diff options
321 files changed, 27559 insertions, 26270 deletions
diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml new file mode 100644 index 0000000..3d1f7f3 --- /dev/null +++ b/.github/workflows/build_cmake.yml @@ -0,0 +1,330 @@ +name: CMake Build for Doxygen + +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.config.name }} + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { + name: "Ubuntu Latest GCC Release", + os: ubuntu-latest, + build_type: "Release", cc: "gcc", cxx: "g++", + build_gen: "Unix Makefiles" + } + - { + name: "Ubuntu Latest GCC Debug", + os: ubuntu-latest, + build_type: "Debug", cc: "gcc", cxx: "g++", + build_gen: "Unix Makefiles" + } + - { + name: "Ubuntu Latest Clang Release", + os: ubuntu-latest, + build_type: "Release", cc: "clang", cxx: "clang++", + build_gen: "Unix Makefiles" + } + - { + name: "Ubuntu Latest Clang Debug", + os: ubuntu-latest, + build_type: "Debug", cc: "clang", cxx: "clang++", + build_gen: "Unix Makefiles" + } + - { + name: "macOS Latest Release", + os: macos-latest, + build_type: "Release", cc: "clang", cxx: "clang++", + build_gen: "Unix Makefiles" + } + - { + name: "macOS Latest Debug", + os: macos-latest, + build_type: "Debug", cc: "clang", cxx: "clang++", + build_gen: "Unix Makefiles" + } + - { + name: "Windows Latest MSVC Debug", + os: windows-latest, + build_type: "Debug", cc: "cl", cxx: "cl", + build_gen: "NMake Makefiles" + } + - { + name: "Windows Latest MSVC Release", + os: windows-latest, + build_type: "Release", cc: "cl", cxx: "cl", + build_gen: "NMake Makefiles" + } + steps: + - uses: actions/checkout@v1 + + - name: Download MikTex (Windows) + run: | + $wc = New-Object System.Net.WebClient; + $maxAttempts=5; + $attemptCount=0; + Do { + $attemptCount++; + Try { + $wc.DownloadFile("https://ctan.math.illinois.edu/systems/win32/miktex/setup/windows-x64/miktexsetup-4.0-x64.zip","miktexsetup-4.0-x64.zip") + } Catch [Exception] { + Write-Host $_.Exception | format-list -force + } + } while (((Test-Path "miktexsetup-x64.zip") -eq $false) -and ($attemptCount -le $maxAttempts)) + shell: pwsh + if: matrix.config.os == 'windows-latest' + + - uses: suisei-cn/actions-download-file@v1 + with: + url: "https://github.com/pffang/libiconv-for-Windows/releases/download/v1.16/libiconv-for-Windows_1.16.7z" + target: . + if: matrix.config.os == 'windows-latest' + + - name: Install LaTeX (Linux) + run: sudo apt-get install texlive texlive-generic-recommended texlive-extra-utils texlive-latex-extra texlive-font-utils + if: matrix.config.os == 'ubuntu-latest' + + - name: Install LaTeX (MacOS) + run: | + brew install --cask mactex; + echo "/Library/TeX/texbin/" >> $GITHUB_PATH + if: matrix.config.os == 'macos-latest' + + - name: Extract MikTex zip (Windows) + shell: bash + run: | + unzip miktexsetup-4.0-x64.zip + if: matrix.config.os == 'windows-latest' + + - name: Download MikTex packages (Windows) + shell: bash + run: | + ./miktexsetup --verbose \ + --local-package-repository=C:/miktex-repository \ + --remote-package-repository="https://ctan.math.illinois.edu/systems/win32/miktex/tm/packages/" \ + --package-set=essential \ + download + if: matrix.config.os == 'windows-latest' + + - name: Install MikTex packages (Windows) + shell: bash + run: | + ./miktexsetup --local-package-repository=C:/miktex-repository \ + --package-set=essential \ + --shared \ + install + if: matrix.config.os == 'windows-latest' + + - name: Setting MikTex paths (Windows) + shell: bash + run: | + echo "C:/Program Files/MiKTeX/miktex/bin/x64/" >> $GITHUB_PATH + export PATH="/c/Program Files/MiKTeX/miktex/bin/x64/:$PATH" + + echo "Configuring MiKTeX to install missing packages on the fly" + initexmf --admin --verbose --set-config-value='[MPM]AutoInstall=1' + if: matrix.config.os == 'windows-latest' + + - name: Install Ghostscript (Linux) + run: sudo apt-get install ghostscript + if: matrix.config.os == 'ubuntu-latest' + + - name: Install Ghostscript (Windows) + run: + choco install ghostscript + if: matrix.config.os == 'windows-latest' + + - name: Setting Ghostscript paths (Windows) + shell: bash + run: | + echo "C:/Program Files (x86)/gs/gs9.53.3/bin/" >> $GITHUB_PATH + echo "C:/Program Files/gs/gs9.53.3/bin/" >> $GITHUB_PATH + export PATH="/c/Program Files (x86)/gs/gs9.53.3/bin/:$PATH" + export PATH="/c/Program Files/gs/gs9.53.3/bin/:$PATH" + if: matrix.config.os == 'windows-latest' + + - name: Install xmllint (Linux) + run: sudo apt-get install libxml2-utils + if: matrix.config.os == 'ubuntu-latest' + + - name: Install xmllint (MacOS) + run: brew install libxml2 + if: matrix.config.os == 'macos-latest' + + - name: Install bison (MacOS) + run: | + brew install bison; + echo "/usr/local/opt/bison/bin" >> $GITHUB_PATH + if: matrix.config.os == 'macos-latest' + + - name: Install bison/flex (Windows) + run: + choco install winflexbison + if: matrix.config.os == 'windows-latest' + + - name: Install Graphviz (Linux) + run: sudo apt-get install graphviz + if: matrix.config.os == 'ubuntu-latest' + + - name: Install Graphviz (MacOS) + run: brew install graphviz + if: matrix.config.os == 'macos-latest' + + - name: Install Graphviz (Windows) + run: + choco install graphviz.portable + if: matrix.config.os == 'windows-latest' + +# - name: Install Perl (Windows) +# run: +# choco install activeperl +# if: matrix.config.os == 'windows-latest' + + - name: Setup VS Environment (Windows) + uses: seanmiddleditch/gha-setup-vsdevenv@master + if: matrix.config.os == 'windows-latest' + + - name: Refresh Env (Windows) + run: + refreshenv + if: matrix.config.os == 'windows-latest' + + - name: Check tool versions (Linux / MacOS) + shell: bash + run: | + echo "=== perl ==="; + perl --version; + echo "=== python ==="; + python --version; + echo "=== cmake ==="; + cmake --version; + echo "=== latex ==="; + latex --version; + echo "=== bibtex ==="; + bibtex --version + echo "=== dvips ==="; + dvips --version + echo "=== bison ==="; + bison --version; + echo "=== flex ==="; + flex --version; + echo "=== dot ==="; + dot -V; + echo "=== ghostscript ==="; + gs --version; + if: matrix.config.os != 'windows-latest' + + - name: Check tool versions (Windows) + shell: bash + run: | + echo "=== perl ==="; + perl --version; + echo "=== python ==="; + python --version; + echo "=== cmake ==="; + cmake --version; + echo "=== latex ==="; + latex --version; + echo "=== bibtex ==="; + bibtex --version + echo "=== dvips ==="; + dvips --version + echo "=== bison ==="; + win_bison --version; + echo "=== flex ==="; + win_flex --version; + echo "=== dot ==="; + dot -V; + echo "=== ghostscript ==="; + gswin64c --version; + if: matrix.config.os == 'windows-latest' + + - name: Configure + shell: cmake -P {0} + run: | + set(ENV{CC} ${{ matrix.config.cc }}) + set(ENV{CXX} ${{ matrix.config.cxx }}) + + execute_process( + COMMAND cmake + -S . + -B build + -D CMAKE_BUILD_TYPE=${{ matrix.config.build_type }} + -G "${{ matrix.config.build_gen }}" + -Dbuild_doc=YES + -Dbuild_app=YES + -Dbuild_parse=YES + -Dbuild_xmlparser=YES + RESULT_VARIABLE result + ) + if (NOT result EQUAL 0) + message(FATAL_ERROR "Bad exit status") + endif() + + - name: Build + shell: cmake -P {0} + run: | + include(ProcessorCount) + ProcessorCount(N) + execute_process( + COMMAND cmake --build build --parallel ${N} + RESULT_VARIABLE result + OUTPUT_VARIABLE output + ERROR_VARIABLE output + ECHO_OUTPUT_VARIABLE ECHO_ERROR_VARIABLE + ) + if (NOT result EQUAL 0) + string(REGEX MATCH "FAILED:.*$" error_message "${output}") + string(REPLACE "\n" "%0A" error_message "${error_message}") + message("::error::${error_message}") + message(FATAL_ERROR "Build failed") + endif() + + - name: Run tests (Linux / MacOS) + shell: cmake -P {0} + run: | + include(ProcessorCount) + ProcessorCount(N) + + set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON") + + execute_process( + COMMAND cmake --build build --target tests TEST_FLAGS="--xml --xmlxsd --xhtml --docbook --rtf" + RESULT_VARIABLE result + ) + if (NOT result EQUAL 0) + message(FATAL_ERROR "Running tests failed!") + endif() + if: matrix.config.os != 'windows-latest' + + - name: Run tests (Windows) + shell: cmake -P {0} + run: | + include(ProcessorCount) + ProcessorCount(N) + + set(ENV{CTEST_OUTPUT_ON_FAILURE} "ON") + + execute_process( + COMMAND cmake --build build --target tests TEST_FLAGS="--xml --xmlxsd" + RESULT_VARIABLE result + ) + if (NOT result EQUAL 0) + message(FATAL_ERROR "Running tests failed!") + endif() + if: matrix.config.os == 'windows-latest' + + - name: Generate documentation + shell: cmake -P {0} + run: | + execute_process( + COMMAND cmake --build build --target docs + RESULT_VARIABLE result + ) + if (NOT result EQUAL 0) + message(FATAL_ERROR "Building documentation failed") + endif() + if: matrix.config.os != 'windows-latest' @@ -15,4 +15,6 @@ /doxygen.tag /build* +tags + .idea diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 733e668..0000000 --- a/.travis.yml +++ /dev/null @@ -1,130 +0,0 @@ -language: cpp -os: linux -dist: xenial -compiler: - - gcc - - clang - -addons: - apt: - update: true - packages: - - texlive - - texlive-generic-recommended - - texlive-extra-utils - - texlive-latex-extra - - texlive-font-utils - - ghostscript - -linux-ppc64le: &linux-ppc64le - os: linux-ppc64le - env: - - OS_NAME="linux-ppc64le" - addons: - apt: - update: true - packages: - - texlive - - texlive-generic-recommended - - texlive-extra-utils - - texlive-latex-extra - - texlive-font-utils - - ghostscript - - libxml2-utils - - cmake - - cmake-data - -linux-s390x: &linux-s390x - os: linux - arch: s390x - dist: bionic - env: - - OS_NAME="linux-s390x" - addons: - apt: - update: true - packages: - - texlive - - texlive-generic-recommended - - texlive-extra-utils - - texlive-latex-extra - - texlive-font-utils - - ghostscript - - libxml2-utils - - cmake - - cmake-data - - qt5-default - -jobs: - include: - - <<: *linux-ppc64le - compiler: gcc - - <<: *linux-ppc64le - compiler: clang - - <<: *linux-s390x - compiler: gcc - - <<: *linux-s390x - compiler: clang -# - os: osx -# compiler: clang -# addons: -# homebrew: -# packages: -# - ghostscript -# - bison -# - flex -# casks: -# - mactex-no-gui - -before_script: - - | - if [ "${TRAVIS_OS_NAME}" == "linux" ] && [ ! "${OS_NAME}" == "linux-ppc64le" ] && [ ! "${OS_NAME}" == "linux-s390x" ]; then - printf "[requires] - libxml2/2.9.9@bincrafters/stable - libiconv/1.15@bincrafters/stable" >> conanfile.txt; - fi; - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then - printf "[requires] - bzip2/1.0.8@bincrafters/stable - libxml2/2.9.9@bincrafters/stable - libiconv/1.15@bincrafters/stable - qt/5.12.0@bincrafters/stable - bison/3.3.2@bincrafters/stable - [options] - qt:shared=True" >> conanfile.txt; - fi; - - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then - pip install --quiet --user conan; - fi; - - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then - pip install --upgrade pip; - pip install --quiet conan; - - curl -O -L http://mirrors.ctan.org/support/epstopdf.zip; - unzip epstopdf.zip; - mkdir -p /Users/travis/Library/TeX/texbin/; - mv epstopdf/epstopdf.pl /Users/travis/Library/TeX/texbin/epstopdf; - chmod a+x /Users/travis/Library/TeX/texbin/epstopdf; - rm -rf epstopdf*; - export CMAKE_INCLUDE_PATH="/usr/local/opt/flex/include;$CMAKE_INCLUDE_PATH"; - export CMAKE_LIBRARY_PATH="/usr/local/opt/flex/lib;/usr/local/opt/bison/lib;$CMAKE_LIBRARY_PATH"; - export PATH="/usr/local/opt/flex/bin:/usr/local/opt/bison/bin:/Users/travis/Library/TeX/texbin:/Library/TeX/texbin:$PATH"; - fi; - - if [ ! "${OS_NAME}" == "linux-ppc64le" ] && [ ! "${OS_NAME}" == "linux-s390x" ]; then - conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan; - conan install . -g virtualrunenv --build missing --update; - source activate_run.sh; - fi; - -script: - - mkdir build - - cd build - - cmake --version; - - cmake -G "Unix Makefiles" -Dbuild_doc=ON -Dbuild_wizard=ON .. - - make - - if [ ! "${TRAVIS_OS_NAME}" == "osx" ] && [ ! "${TRAVIS_COMPILER}" == "clang" ]; then - make tests docs; - fi; - - if [ ! "${TRAVIS_OS_NAME}" == "osx" ] && [ "${TRAVIS_COMPILER}" == "clang" ]; then - make docs; - fi; diff --git a/CMakeLists.txt b/CMakeLists.txt index 35e6a0c..06b9696 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,9 @@ option(enable_coverage "Enable coverage reporting for gcc/clang [development]" O SET(enlarge_lex_buffers "262144" CACHE INTERNAL "Sets the lex input and read buffers to the specified size") -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Sanitizers") -set(TOP "${CMAKE_SOURCE_DIR}") +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Sanitizers") +set(TOP "${PROJECT_SOURCE_DIR}") include(version) set(sqlite3 "0" CACHE INTERNAL "used in settings.h") @@ -51,7 +51,7 @@ if (use_libclang) find_package(LLVM CONFIG REQUIRED) find_package(Clang CONFIG REQUIRED) if (CMAKE_SYSTEM MATCHES "Darwin") - set(MACOS_VERSION_MIN 10.11) + set(MACOS_VERSION_MIN 10.14) endif() endif() @@ -69,9 +69,10 @@ endif() if (WIN32) if ((NOT CMAKE_GENERATOR MATCHES "MinGW Makefiles") AND - (NOT CMAKE_GENERATOR MATCHES "MSYS Makefiles")) + (NOT CMAKE_GENERATOR MATCHES "MSYS Makefiles") AND + (NOT CMAKE_GENERATOR MATCHES "Unix Makefiles")) if (NOT ICONV_DIR) - set(ICONV_DIR "${CMAKE_SOURCE_DIR}/winbuild") + set(ICONV_DIR "${PROJECT_SOURCE_DIR}/winbuild") endif() set(CMAKE_REQUIRED_DEFINITIONS "-DLIBICONV_STATIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") # needed for language.cpp on 64bit @@ -120,10 +121,10 @@ find_package(Iconv REQUIRED) include_directories(${ICONV_INCLUDE_DIR}) -#set(DOXYDOCS ${CMAKE_SOURCE_DIR}/doc CACHE INTERNAL "Path to doxygen docs") +#set(DOXYDOCS ${PROJECT_SOURCE_DIR}/doc CACHE INTERNAL "Path to doxygen docs") set(DOXYDOCS ${PROJECT_BINARY_DIR}/doc) set(ENV{DOXYGEN_DOCDIR} ${DOXYDOCS}) -set(GENERATED_SRC "${CMAKE_BINARY_DIR}/generated_src" CACHE INTERNAL "Stores generated files") +set(GENERATED_SRC "${PROJECT_BINARY_DIR}/generated_src" CACHE INTERNAL "Stores generated files") set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) @@ -135,7 +136,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${EXECUTABLE_OUTPUT_PATH}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${EXECUTABLE_OUTPUT_PATH}) # gather lang codes for translation -file(GLOB lang_files RELATIVE "${CMAKE_SOURCE_DIR}/src" "${CMAKE_SOURCE_DIR}/src/translator_??.h") +file(GLOB lang_files RELATIVE "${PROJECT_SOURCE_DIR}/src" "${PROJECT_SOURCE_DIR}/src/translator_??.h") if (english_only) # user only wants English set(lcodes "ENONLY") else () @@ -328,3 +328,5 @@ DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = NO +DOT_MAX_FOLD = 17 +DOT_UML_DETAILS = NO @@ -1,7 +1,7 @@ DOXYGEN Please read the installation section of the manual -(http://www.doxygen.nl/manual/install.html) for instructions. +(https://www.doxygen.nl/manual/install.html) for instructions. -------- Dimitri van Heesch @@ -31,8 +31,7 @@ The latest binaries and source of Doxygen can be downloaded from: Developers --------- -* Linux & macOS Build Status: <a href="https://travis-ci.org/doxygen/doxygen"><img src="https://secure.travis-ci.org/doxygen/doxygen.png?branch=master"/></a> -* Windows Build Status: <a href="https://ci.appveyor.com/project/doxygen/doxygen"><img src="https://ci.appveyor.com/api/projects/status/github/doxygen/doxygen"/></a> +* Linux & Windows and MacOS Build Status: <a href="https://github.com/doxygen/doxygen/actions"><img alt="Github Actions Build Status" src="https://github.com/doxygen/doxygen/workflows/CMake%20Build%20for%20Doxygen/badge.svg"></a> * Coverity Scan Build Status: <a href="https://scan.coverity.com/projects/2860"> <img alt="Coverity Scan Build Status" src="https://scan.coverity.com/projects/2860/badge.svg"/> </a> @@ -1 +1 @@ -1.8.20 +1.9.0 diff --git a/addon/doxmlparser/examples/metrics/CMakeLists.txt b/addon/doxmlparser/examples/metrics/CMakeLists.txt index 255ae0e..7e99a08 100644 --- a/addon/doxmlparser/examples/metrics/CMakeLists.txt +++ b/addon/doxmlparser/examples/metrics/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories( ../../include + ${PROJECT_SOURCE_DIR}/libversion ) add_executable(doxmlparser_metrics @@ -10,6 +11,7 @@ main.cpp target_link_libraries(doxmlparser_metrics doxmlparser + doxygen_version qtools ${COVERAGE_LINKER_FLAGS} ) diff --git a/addon/doxmlparser/examples/metrics/main.cpp b/addon/doxmlparser/examples/metrics/main.cpp index 1328abe..9e301b1 100644 --- a/addon/doxmlparser/examples/metrics/main.cpp +++ b/addon/doxmlparser/examples/metrics/main.cpp @@ -22,6 +22,7 @@ #include <stdlib.h> #include <string.h> #include <doxmlintf.h> +#include "version.h" bool isDocumented(IDocRoot *brief,IDocRoot *detailed) { @@ -49,9 +50,25 @@ bool isDocumented(IDocRoot *brief,IDocRoot *detailed) int main(int argc,char **argv) { - if (argc!=2) + int locArgc = argc; + + if (locArgc == 2) + { + if (!strcmp(argv[1],"--help")) + { + printf("Usage: %s xml_dir\n",argv[0]); + exit(0); + } + else if (!strcmp(argv[1],"--version")) + { + printf("%s version: %s\n",argv[0],getFullVersion()); + exit(0); + } + } + + if (locArgc!=2) { - printf("Usage: %s xml_output_dir\n",argv[0]); + printf("Usage: %s xml_dir\n",argv[0]); exit(1); } diff --git a/addon/doxmlparser/src/CMakeLists.txt b/addon/doxmlparser/src/CMakeLists.txt index 35f6c83..cbd5811 100644 --- a/addon/doxmlparser/src/CMakeLists.txt +++ b/addon/doxmlparser/src/CMakeLists.txt @@ -1,7 +1,7 @@ include_directories( . ../include - ${CMAKE_SOURCE_DIR}/qtools + ${PROJECT_SOURCE_DIR}/qtools ) add_library(doxmlparser STATIC basehandler.cpp diff --git a/addon/doxmlparser/test/CMakeLists.txt b/addon/doxmlparser/test/CMakeLists.txt index 2d92b72..4caef57 100644 --- a/addon/doxmlparser/test/CMakeLists.txt +++ b/addon/doxmlparser/test/CMakeLists.txt @@ -1,7 +1,8 @@ include_directories( ../include - ${CMAKE_SOURCE_DIR}/qtools + ${PROJECT_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/qtools ) add_executable(doxmlparser_test @@ -11,6 +12,7 @@ main.cpp target_link_libraries(doxmlparser_test doxmlparser + doxygen_version qtools ${COVERAGE_LINKER_FLAGS} ) diff --git a/addon/doxmlparser/test/main.cpp b/addon/doxmlparser/test/main.cpp index 0d1f95e..35fd700 100644 --- a/addon/doxmlparser/test/main.cpp +++ b/addon/doxmlparser/test/main.cpp @@ -17,6 +17,7 @@ #include <stdlib.h> #include <doxmlintf.h> #include <qstring.h> +#include "version.h" /*! Dumps the contents of a hyperlinked text fragment as plain text to the * output. @@ -577,9 +578,25 @@ void DumpParamList(IParamIterator *pli,int indent) int main(int argc,char **argv) { - if (argc!=2) + int locArgc = argc; + + if (locArgc == 2) + { + if (!strcmp(argv[1],"--help")) + { + printf("Usage: %s xml_dir\n",argv[0]); + exit(0); + } + else if (!strcmp(argv[1],"--version")) + { + printf("%s version: %s\n",argv[0],getFullVersion()); + exit(0); + } + } + + if (locArgc!=2) { - printf("Usage: %s xmldir\n",argv[0]); + printf("Usage: %s xml_dir\n",argv[0]); exit(1); } diff --git a/addon/doxyapp/CMakeLists.txt b/addon/doxyapp/CMakeLists.txt index a6a776a..3e58d32 100644 --- a/addon/doxyapp/CMakeLists.txt +++ b/addon/doxyapp/CMakeLists.txt @@ -1,10 +1,10 @@ find_package(Iconv) include_directories( - ${CMAKE_SOURCE_DIR}/src - ${CMAKE_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/libversion ${GENERATED_SRC} - ${CMAKE_SOURCE_DIR}/qtools + ${PROJECT_SOURCE_DIR}/qtools ${ICONV_INCLUDE_DIR} ${CLANG_INCLUDEDIR} ) diff --git a/addon/doxyapp/doxyapp.cpp b/addon/doxyapp/doxyapp.cpp index 97f3755..b89c5d9 100644 --- a/addon/doxyapp/doxyapp.cpp +++ b/addon/doxyapp/doxyapp.cpp @@ -38,6 +38,7 @@ #include "classlist.h" #include "config.h" #include "filename.h" +#include "version.h" class XRefDummyCodeGenerator : public CodeOutputInterface { @@ -62,6 +63,8 @@ class XRefDummyCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *) {} + void endCodeFragment(const char *) {} // here we are presented with the symbols found by the code parser void linkableSymbol(int l, const char *sym,Definition *symDef,Definition *context) @@ -109,19 +112,19 @@ class XRefDummyCodeGenerator : public CodeOutputInterface static void findXRefSymbols(FileDef *fd) { // get the interface to a parser that matches the file extension - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); // get the programming language from the file name SrcLangExt lang = getLanguageFromFileName(fd->name()); // reset the parsers state - intf.resetCodeParserState(); + intf->resetCodeParserState(); // create a new backend object XRefDummyCodeGenerator *xrefGen = new XRefDummyCodeGenerator(fd); // parse the source code - intf.parseCode(*xrefGen, + intf->parseCode(*xrefGen, 0, fileToString(fd->absFilePath()), lang, @@ -146,25 +149,9 @@ static void listSymbol(Definition *d) static void listSymbols() { - QDictIterator<DefinitionIntf> sli(*Doxygen::symbolMap); - DefinitionIntf *di; - for (sli.toFirst();(di=sli.current());++sli) + for (const auto &kv : Doxygen::symbolMap) { - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols - // with same name - { - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - // for each symbol - for (dli.toFirst();(d=dli.current());++dli) - { - listSymbol(d); - } - } - else // single symbol - { - listSymbol((Definition*)di); - } + listSymbol(kv.second); } } @@ -199,9 +186,9 @@ static void lookupSymbol(Definition *d) case Definition::TypeNamespace: { NamespaceDef *nd = dynamic_cast<NamespaceDef*>(d); - printf("Kind: Namespace: contains %d classes and %d namespaces\n", - nd->getClassSDict() ? nd->getClassSDict()->count() : 0, - nd->getNamespaceSDict() ? nd->getNamespaceSDict()->count() : 0); + printf("Kind: Namespace: contains %zu classes and %zu namespaces\n", + nd->getClasses().size(), + nd->getNamespaces().size()); } break; case Definition::TypeMember: @@ -221,25 +208,14 @@ static void lookupSymbols(const QCString &sym) { if (!sym.isEmpty()) { - DefinitionIntf *di = Doxygen::symbolMap->find(sym); - if (di) + auto range = Doxygen::symbolMap.find(sym); + bool found=false; + for (auto it=range.first; it!=range.second; ++it) { - if (di->definitionType()==DefinitionIntf::TypeSymbolList) - { - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - // for each symbol with the given name - for (dli.toFirst();(d=dli.current());++dli) - { - lookupSymbol(d); - } - } - else - { - lookupSymbol((Definition*)di); - } + lookupSymbol(it->second); + found=true; } - else + if (!found) { printf("Unknown symbol\n"); } @@ -250,7 +226,23 @@ int main(int argc,char **argv) { char cmd[256]; - if (argc<2) + int locArgc = argc; + + if (locArgc == 2) + { + if (!strcmp(argv[1],"--help")) + { + printf("Usage: %s [source_file | source_dir]\n",argv[0]); + exit(0); + } + else if (!strcmp(argv[1],"--version")) + { + printf("%s version: %s\n",argv[0],getFullVersion()); + exit(0); + } + } + + if (locArgc!=2) { printf("Usage: %s [source_file | source_dir]\n",argv[0]); exit(1); diff --git a/addon/doxyparse/CMakeLists.txt b/addon/doxyparse/CMakeLists.txt index 8df99ab..fe2f2c2 100644 --- a/addon/doxyparse/CMakeLists.txt +++ b/addon/doxyparse/CMakeLists.txt @@ -1,10 +1,10 @@ find_package(Iconv) include_directories( - ${CMAKE_SOURCE_DIR}/src - ${CMAKE_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/libversion ${GENERATED_SRC} - ${CMAKE_SOURCE_DIR}/qtools + ${PROJECT_SOURCE_DIR}/qtools ${ICONV_INCLUDE_DIR} ${CLANG_INCLUDEDIR} ) diff --git a/addon/doxyparse/README b/addon/doxyparse/README deleted file mode 100644 index 95cce8c..0000000 --- a/addon/doxyparse/README +++ /dev/null @@ -1,40 +0,0 @@ -doxyparse -========= - -This directory contains an "source parsing engine" based on doxyapp code. - -More info and source code repository: https://github.com/analizo/doxygen - -## build dependencies - - apt-get install flex bison cmake build-essential python - -## build - - cmake -G "Unix Makefiles" -Dbuild_parse=ON - make - -## install - - sudo make install - -## release - -* ensure analizo testsuite passing on newer doxyparse version -* update debian/changelog, commit, push -* create git tag, push to github analizo/doxyparse -* build on amd64 and i386 archs, upload tar.gz to github - * tar -zcf doxyparse_<VERSION>_amd64.tar.gz -C bin/ doxyparse - * tar -zcf doxyparse_<VERSION>_i386.tar.gz -C bin/ doxyparse -* build debian packages for amd64 and i386, update analizo.org repository - * (see analizo.github.io/README.md file for updating repository instructions) - * upload the deb files to github release tag also -* check if a alien-doxyparse release is necessary and do it on cpan - -AUTHORS - -Antonio Terceiro <terceiro@softwarelivre.org> -João M. Miranda <joaomm88@gmail.com> -Joenio Costa <joenio@joenio.me> -Paulo Meirelles <paulo@softwarelivre.org> -Vinicius Daros <vkdaros@mercurio.eclipse.ime.usp.br> diff --git a/addon/doxyparse/README.md b/addon/doxyparse/README.md new file mode 100644 index 0000000..2f9c468 --- /dev/null +++ b/addon/doxyparse/README.md @@ -0,0 +1,52 @@ +# Doxyparse + +This directory contains an "source parsing engine" based on doxyapp code. + +Doxyparse modifies the default output of Doxygen and dumps the dependencies +among code elements in a YAML format, instead of output it in a human-readable +format, as Doxygen does Doxyparse's output is intended to produce a +machine-readable output. + +Doxyparse has been used in many software engineering research (as a source-code +static analysis tool) regards on software metrics, quality metrics and so on, +Doxyparse was first used by the [Analizo](http://analizo.org) toolkit, a suite +of source code analysis tools, aimed at being language-independent and +extensible, able to extract and calculate a fair number of source code metrics, +generate dependency graphs, and other software evolution analysis. + +Academic publications citing Doxyparse: +* https://scholar.google.com.br/scholar?q=doxyparse + +## build dependencies + + apt-get install flex bison cmake build-essential python + +## build + + cmake -G "Unix Makefiles" -Dbuild_parse=ON + make + +## install + + sudo make install + +## release + +* ensure analizo testsuite passing on newer doxyparse version +* update debian/changelog, commit, push +* create git tag, push to github analizo/doxyparse +* build on amd64 and i386 archs, upload tar.gz to github + * tar -zcf doxyparse_<VERSION>_amd64.tar.gz -C bin/ doxyparse + * tar -zcf doxyparse_<VERSION>_i386.tar.gz -C bin/ doxyparse +* build debian packages for amd64 and i386, update analizo.org repository + * (see analizo.github.io/README.md file for updating repository instructions) + * upload the deb files to github release tag also +* check if a alien-doxyparse release is necessary and do it on cpan + +## Authors + +* Antonio Terceiro <terceiro@softwarelivre.org> +* João M. Miranda <joaomm88@gmail.com> +* Joenio Costa <joenio@joenio.me> +* Paulo Meirelles <paulo@softwarelivre.org> +* Vinicius Daros <vkdaros@mercurio.eclipse.ime.usp.br> diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp index c06eb1c..df9069b 100644 --- a/addon/doxyparse/doxyparse.cpp +++ b/addon/doxyparse/doxyparse.cpp @@ -49,7 +49,7 @@ class Doxyparse : public CodeOutputInterface { public: - Doxyparse(FileDef *fd) : m_fd(fd) {} + Doxyparse(const FileDef *fd) : m_fd(fd) {} ~Doxyparse() {} // these are just null functions, they can be used to produce a syntax highlighted @@ -70,6 +70,8 @@ class Doxyparse : public CodeOutputInterface void startCodeLine(bool) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *) {} + void endCodeFragment(const char *) {} void linkableSymbol(int l, const char *sym, Definition *symDef, Definition *context) { @@ -82,7 +84,7 @@ class Doxyparse : public CodeOutputInterface } private: - FileDef *m_fd; + const FileDef *m_fd; }; static bool is_c_code = true; @@ -90,25 +92,25 @@ static bool is_c_code = true; static void findXRefSymbols(FileDef *fd) { // get the interface to a parser that matches the file extension - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); // get the programming language from the file name SrcLangExt lang = getLanguageFromFileName(fd->name()); // reset the parsers state - intf.resetCodeParserState(); + intf->resetCodeParserState(); // create a new backend object Doxyparse *parse = new Doxyparse(fd); // parse the source code - intf.parseCode(*parse, 0, fileToString(fd->absFilePath()), lang, FALSE, 0, fd); + intf->parseCode(*parse, 0, fileToString(fd->absFilePath()), lang, FALSE, 0, fd); // dismiss the object. delete parse; } -static bool ignoreStaticExternalCall(MemberDef *context, MemberDef *md) { +static bool ignoreStaticExternalCall(const MemberDef *context, const MemberDef *md) { if (md->isStatic()) { if(md->getFileDef() && context->getFileDef()) { if(md->getFileDef()->getOutputFileBase() == context->getFileDef()->getOutputFileBase()) @@ -142,7 +144,7 @@ static void printInherits() { printf(" inherits:\n"); } static void printInheritance(std::string base_class) { - printf(" - %s\n", base_class.c_str()); + printf(" - \"%s\"\n", base_class.c_str()); } static void printDefines() { printf(" defines:\n"); @@ -161,8 +163,8 @@ static void printPrototypeYes() { static void printNumberOfLines(int lines) { printf(" lines_of_code: %d\n", lines); } -static void printNumberOfArguments(int arguments) { - printf(" parameters: %d\n", arguments); +static void printNumberOfArguments(size_t arguments) { + printf(" parameters: %zu\n", arguments); } static void printUses() { printf(" uses:\n"); @@ -172,11 +174,11 @@ static void printReferenceTo(std::string type, std::string signature, std::strin printf(" type: %s\n", type.c_str()); printf(" defined_in: \"%s\"\n", unescapeCharsInString(defined_in.c_str()).data()); } -static void printNumberOfConditionalPaths(MemberDef* md) { +static void printNumberOfConditionalPaths(const MemberDef* md) { printf(" conditional_paths: %d\n", md->numberOfFlowKeyWords()); } -static int isPartOfCStruct(MemberDef * md) { +static int isPartOfCStruct(const MemberDef * md) { return is_c_code && md->getClassDef() != NULL; } @@ -196,7 +198,7 @@ std::string argumentData(const Argument &argument) { return data; } -std::string functionSignature(MemberDef* md) { +std::string functionSignature(const MemberDef* md) { std::string signature = sanitizeString(md->name().data()); if(md->isFunction()){ const ArgumentList &argList = md->argumentList(); @@ -213,7 +215,7 @@ std::string functionSignature(MemberDef* md) { return signature; } -static void referenceTo(MemberDef* md) { +static void referenceTo(const MemberDef* md) { std::string type = md->memberTypeName().data(); std::string defined_in = ""; std::string signature = ""; @@ -251,17 +253,17 @@ void protectionInformation(Protection protection) { } } -void cModule(ClassDef* cd) { - MemberList* ml = cd->getMemberList(MemberListType_variableMembers); +void cModule(const ClassDef* cd) { + const MemberList* ml = cd->getMemberList(MemberListType_variableMembers); if (ml) { - FileDef *fd = cd->getFileDef(); - MemberList *fd_ml = fd->getMemberList(MemberListType_allMembersList); + const FileDef *fd = cd->getFileDef(); + const MemberList *fd_ml = fd->getMemberList(MemberListType_allMembersList); if (!fd_ml || fd_ml->count() == 0) { printModule(fd->getOutputFileBase().data()); printDefines(); } MemberListIterator mli(*ml); - MemberDef* md; + const MemberDef* md; for (mli.toFirst(); (md=mli.current()); ++mli) { printDefinition("variable", cd->name().data() + std::string("::") + md->name().data(), md->getDefLine()); protectionInformation(md->protection()); @@ -269,7 +271,7 @@ void cModule(ClassDef* cd) { } } -static bool checkOverrideArg(const ArgumentList &argList, MemberDef *md) { +static bool checkOverrideArg(const ArgumentList &argList, const MemberDef *md) { if(!md->isFunction() || argList.empty()){ return false; } @@ -283,7 +285,7 @@ static bool checkOverrideArg(const ArgumentList &argList, MemberDef *md) { return false; } -void functionInformation(MemberDef* md) { +void functionInformation(const MemberDef* md) { std::string temp = ""; int size = md->getEndBodyLine() - md->getStartBodyLine() + 1; printNumberOfLines(size); @@ -299,12 +301,10 @@ void functionInformation(MemberDef* md) { } printNumberOfConditionalPaths(md); - MemberSDict *defDict = md->getReferencesMembers(); - if (defDict) { - MemberSDict::Iterator msdi(*defDict); - MemberDef *rmd; + auto refList = md->getReferencesMembers(); + if (!refList.empty()) { printUses(); - for (msdi.toFirst(); (rmd=msdi.current()); ++msdi) { + for (const auto &rmd : refList) { if (rmd->definitionType() == Definition::TypeMember && !ignoreStaticExternalCall(md, rmd) && !checkOverrideArg(argList, rmd)) { referenceTo(rmd); } @@ -312,15 +312,15 @@ void functionInformation(MemberDef* md) { } } -void prototypeInformation(MemberDef* md) { +void prototypeInformation(const MemberDef* md) { printPrototypeYes(); const ArgumentList &argList = md->argumentList(); printNumberOfArguments(argList.size()); } -static void lookupSymbol(Definition *d) { +static void lookupSymbol(const Definition *d) { if (d->definitionType() == Definition::TypeMember) { - MemberDef *md = dynamic_cast<MemberDef*>(d); + const MemberDef *md = dynamic_cast<const MemberDef*>(d); std::string type = md->memberTypeName().data(); std::string signature = functionSignature(md); printDefinition(type, signature, md->getDefLine()); @@ -334,17 +334,17 @@ static void lookupSymbol(Definition *d) { } } -void listMembers(MemberList *ml) { +void listMembers(const MemberList *ml) { if (ml) { MemberListIterator mli(*ml); - MemberDef *md; + const MemberDef *md; for (mli.toFirst(); (md=mli.current()); ++mli) { lookupSymbol((Definition*) md); } } } -void listAllMembers(ClassDef* cd) { +void listAllMembers(const ClassDef* cd) { // methods listMembers(cd->getMemberList(MemberListType_functionMembers)); // constructors @@ -353,18 +353,15 @@ void listAllMembers(ClassDef* cd) { listMembers(cd->getMemberList(MemberListType_variableMembers)); } -static void classInformation(ClassDef* cd) { +static void classInformation(const ClassDef* cd) { if (is_c_code) { cModule(cd); } else { printModule(cd->name().data()); - BaseClassList* baseClasses = cd->baseClasses(); - if (baseClasses) { + if (!cd->baseClasses().empty()) { printInherits(); - BaseClassListIterator bci(*baseClasses); - BaseClassDef* bcd; - for (bci.toFirst(); (bcd = bci.current()); ++bci) { - printInheritance(bcd->classDef->name().data()); + for (const auto &bcd : cd->baseClasses()) { + printInheritance(sanitizeString(bcd.classDef->name().data())); } } if(cd->isAbstract()) { @@ -416,15 +413,11 @@ static void listSymbols() { listMembers(ml); } - ClassSDict *classes = fd->getClassSDict(); - if (classes) { - ClassSDict::Iterator cli(*classes); - ClassDef *cd; - for (cli.toFirst(); (cd = cli.current()); ++cli) { - if (!cd->isVisited()) { - classInformation(cd); - cd->setVisited(TRUE); - } + ClassDefSet visitedClasses; + for (const auto &cd : fd->getClasses()) { + if (visitedClasses.find(cd)==visitedClasses.end()) { + classInformation(cd); + visitedClasses.insert(cd); } } } @@ -433,15 +426,27 @@ static void listSymbols() { } int main(int argc,char **argv) { - if (argc < 2) { + int locArgc = argc; + + if (locArgc == 2) + { + if (!strcmp(argv[1],"--help")) + { + printf("Usage: %s [source_file | source_dir]\n",argv[0]); + exit(0); + } + else if (!strcmp(argv[1],"--version")) + { + printf("%s version: %s\n",argv[0],getFullVersion()); + exit(0); + } + } + + if (locArgc!=2) + { printf("Usage: %s [source_file | source_dir]\n",argv[0]); exit(1); } - if (qstrcmp(&argv[1][2], "version") == 0) { - QCString versionString = getDoxygenVersion(); - printf("%s\n", versionString.data()); - exit(0); - } // initialize data structures initDoxygen(); diff --git a/addon/doxysearch/CMakeLists.txt b/addon/doxysearch/CMakeLists.txt index 7a1e1c1..d0c8724 100644 --- a/addon/doxysearch/CMakeLists.txt +++ b/addon/doxysearch/CMakeLists.txt @@ -1,13 +1,14 @@ -find_package(Xapian REQUIRED) +find_package(xapian REQUIRED) find_package(ZLIB REQUIRED) if (WIN32) - set(WIN_EXTRA_LIBS "uuid.lib rpcrt4.lib ws2_32.lib") + set(WIN_EXTRA_LIBS uuid.lib rpcrt4.lib ws2_32.lib) endif() include_directories( - ${CMAKE_SOURCE_DIR}/qtools - ${XAPIAN_INCLUDE_DIR} + ${PROJECT_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/qtools + ${XAPIAN_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS} ) add_executable(doxyindexer @@ -16,8 +17,9 @@ add_executable(doxyindexer target_link_libraries(doxyindexer ${XAPIAN_LIBRARIES} ${ZLIB_LIBRARIES} - ${WIN_EXTRA_LIBS} + ${WIN_EXTRA_LIBS} ${COVERAGE_LINKER_FLAGS} + doxygen_version qtools ) @@ -25,9 +27,10 @@ add_executable(doxysearch.cgi doxysearch.cpp ) target_link_libraries(doxysearch.cgi + doxygen_version ${XAPIAN_LIBRARIES} ${ZLIB_LIBRARIES} - ${WIN_EXTRA_LIBS} + ${WIN_EXTRA_LIBS} ) install(TARGETS doxyindexer doxysearch.cgi DESTINATION bin) diff --git a/addon/doxysearch/doxyindexer.cpp b/addon/doxysearch/doxyindexer.cpp index cd31b3d..ae4e046 100644 --- a/addon/doxysearch/doxyindexer.cpp +++ b/addon/doxysearch/doxyindexer.cpp @@ -30,6 +30,8 @@ // Xapian include #include <xapian.h> +#include "version.h" + #define MAX_TERM_LENGTH 245 #if defined(_WIN32) && !defined(__CYGWIN__) @@ -303,10 +305,10 @@ class XMLErrorHandler : public QXmlErrorHandler QString errorMsg; }; -static void usage(const char *name) +static void usage(const char *name, int exitVal = 1) { std::cerr << "Usage: " << name << " [-o output_dir] searchdata.xml [searchdata2.xml ...]" << std::endl; - exit(1); + exit(exitVal); } /** main function to index data */ @@ -340,7 +342,12 @@ int main(int argc,const char **argv) } else if (std::string(argv[i])=="-h" || std::string(argv[i])=="--help") { - usage(argv[0]); + usage(argv[0],0); + } + else if (std::string(argv[i])=="-v" || std::string(argv[i])=="--version") + { + std::cerr << argv[0] << " version: " << getFullVersion() << std::endl; + exit(0); } } diff --git a/addon/doxysearch/doxysearch.cpp b/addon/doxysearch/doxysearch.cpp index 4c4dc72..26517bd 100644 --- a/addon/doxysearch/doxysearch.cpp +++ b/addon/doxysearch/doxysearch.cpp @@ -27,6 +27,8 @@ // Xapian includes #include <xapian.h> +#include "version.h" + #ifdef _WIN32 #include <windows.h> #else @@ -306,31 +308,55 @@ static void showError(const std::string &callback,const std::string &error) exit(0); } +static void usage(const char *name, int exitVal = 1) +{ + std::cerr << "Usage: " << name << "[query_string]" << std::endl; + std::cerr << " " << "alternatively the query string can be given by the environment variable QUERY_STRING" << std::endl; + exit(exitVal); +} + /** Main routine */ int main(int argc,char **argv) { // process inputs that were passed to us via QUERY_STRING - std::cout << "Content-Type:application/javascript;charset=utf-8\r\n\n"; std::string callback; try { - // get input parameters - const char *queryEnv = getenv("QUERY_STRING"); std::string queryString; - if (queryEnv) + if (argc == 1) { - queryString = queryEnv; + const char *queryEnv = getenv("QUERY_STRING"); + if (queryEnv) + { + queryString = queryEnv; + } + else + { + usage(argv[0]); + } } - else if (argc>=2) + else if (argc == 2) { - queryString = argv[1]; + if (std::string(argv[1])=="-h" || std::string(argv[1])=="--help") + { + usage(argv[0],0); + } + else if (std::string(argv[1])=="-v" || std::string(argv[1])=="--version") + { + std::cerr << argv[0] << " version: " << getFullVersion() << std::endl; + exit(0); + } + else + { + queryString = argv[1]; + } } else { - std::cout << "No input!\n"; - exit(1); + usage(argv[0]); } + std::cout << "Content-Type:application/javascript;charset=utf-8\r\n\n"; // parse query string std::vector<std::string> parts = split(queryString,'&'); std::string searchFor,callback; diff --git a/addon/doxywizard/CMakeLists.txt b/addon/doxywizard/CMakeLists.txt index 6aacd8b..a6f65f8 100644 --- a/addon/doxywizard/CMakeLists.txt +++ b/addon/doxywizard/CMakeLists.txt @@ -29,10 +29,10 @@ if (NOT Qt5Core_FOUND) endif() include_directories( - . - ${CMAKE_SOURCE_DIR}/libversion - ${CMAKE_SOURCE_DIR}/qtools - ${GENERATED_SRC} + . + ${PROJECT_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/qtools + ${GENERATED_SRC} ) set(GENERATED_SRC_WIZARD ${GENERATED_SRC}/doxywizard) @@ -58,25 +58,26 @@ set_source_files_properties(${GENERATED_SRC_WIZARD}/settings.h PROPERTIES GENERA # generate version.cpp add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/version.py ${VERSION} > ${GENERATED_SRC_WIZARD}/version.cpp - DEPENDS ${CMAKE_SOURCE_DIR}/VERSION ${CMAKE_SOURCE_DIR}/src/version.py + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/version.py ${VERSION} > ${GENERATED_SRC_WIZARD}/version.cpp + DEPENDS ${PROJECT_SOURCE_DIR}/VERSION ${PROJECT_SOURCE_DIR}/src/version.py OUTPUT ${GENERATED_SRC_WIZARD}/version.cpp ) set_source_files_properties(${GENERATED_SRC_WIZARD}/version.cpp PROPERTIES GENERATED 1) # generate configdoc.cpp add_custom_command( -COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -wiz ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC_WIZARD}/configdoc.cpp -OUTPUT ${GENERATED_SRC_WIZARD}/configdoc.cpp + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/configgen.py -wiz ${PROJECT_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC_WIZARD}/configdoc.cpp + DEPENDS ${PROJECT_SOURCE_DIR}/src/configgen.py ${PROJECT_SOURCE_DIR}/src/config.xml + OUTPUT ${GENERATED_SRC_WIZARD}/configdoc.cpp ) set_source_files_properties(${GENERATED_SRC_WIZARD}/configdoc.cpp PROPERTIES GENERATED 1) -set(LEX_FILES config_doxyw) +set(LEX_FILES config_doxyw) foreach(lex_file ${LEX_FILES}) add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/addon/doxywizard/${lex_file}.l > ${GENERATED_SRC_WIZARD}/${lex_file}.l.h - DEPENDS ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/addon/doxywizard/${lex_file}.l - OUTPUT ${GENERATED_SRC_WIZARD}/${lex_file}.l.h + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l > ${GENERATED_SRC_WIZARD}/${lex_file}.l.h + DEPENDS ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/addon/doxywizard/${lex_file}.l + OUTPUT ${GENERATED_SRC_WIZARD}/${lex_file}.l.h ) set_source_files_properties(${GENERATED_SRC_WIZARD}/${lex_file}.l.h PROPERTIES GENERATED 1) @@ -97,6 +98,7 @@ wizard.h qt_add_resources(doxywizard_RESOURCES_RCC doxywizard.qrc) add_executable(doxywizard WIN32 +config_msg.cpp doxywizard.cpp expert.cpp wizard.cpp diff --git a/addon/doxywizard/config_doxyw.l b/addon/doxywizard/config_doxyw.l index 4018af7..6b487ee 100644 --- a/addon/doxywizard/config_doxyw.l +++ b/addon/doxywizard/config_doxyw.l @@ -3,8 +3,8 @@ * 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. * @@ -24,6 +24,7 @@ #include "config.h" #include "input.h" #include "inputstring.h" +#include "config_msg.h" #include <QString> #include <QVariant> @@ -53,22 +54,22 @@ struct ConfigFileState YY_BUFFER_STATE oldState; YY_BUFFER_STATE newState; QString fileName; -}; +}; static const QHash<QString,Input*> *g_options; static FILE *g_file; static QString g_yyFileName; static QString g_includeName; static QVariant g_includePathList; -static QStack<ConfigFileState*> g_includeStack; +static QStack<ConfigFileState*> g_includeStack; static int g_includeDepth; static QVariant *g_arg; static Input *g_curOption=0; -static QString g_elemStr; +static QByteArray g_str; static QTextCodec *g_codec = QTextCodec::codecForName("UTF-8"); static QString g_codecName = QString::fromLatin1("UTF-8"); -static int g_lastState; -static QByteArray g_tmpString; +static QString g_cmd; +static bool g_isEnum; static const char *stateToString(int state); @@ -77,41 +78,19 @@ static const char *stateToString(int state); #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -static int yyread(char *buf,int maxSize) +static yy_size_t yyread(char *buf,yy_size_t maxSize) { // no file included - if (g_includeStack.isEmpty()) + if (g_includeStack.isEmpty()) { return fread(buf,1,maxSize,g_file); - } - else + } + else { return fread(buf,1,maxSize,g_includeStack.top()->file); } } -static QString warning_str = QString::fromLatin1("warning: "); -static QString error_str = QString::fromLatin1("error: "); - -void config_err(const char *fmt, ...) -{ - QString msg = error_str; - msg.append(QString::fromLatin1(fmt)); - va_list args; - va_start(args, fmt); - vfprintf(stderr, qPrintable(msg), args); - va_end(args); -} -void config_warn(const char *fmt, ...) -{ - QString msg = warning_str; - msg.append(QString::fromLatin1(fmt)); - va_list args; - va_start(args, fmt); - vfprintf(stderr, qPrintable(msg), args); - va_end(args); -} - static void substEnvVarsInStrList(QStringList &sl); static void substEnvVarsInString(QString &s); @@ -129,6 +108,191 @@ static void checkEncoding() } } +static QByteArray stripComment(const QByteArray &s) +{ + // check if there is a comment at the end of the string + bool insideQuote=false; + int l = s.length(); + for (int i=0;i<l;i++) + { + char c = s.at(i); + if (c=='\\') // skip over escaped characters + { + i++; + } + else if (c=='"') // toggle inside/outside quotation + { + insideQuote=!insideQuote; + } + else if (!insideQuote && c=='#') // found start of a comment + { + return s.left(i).trimmed(); + } + } + return s; +} + + +static void processString() +{ + // strip leading and trailing whitespace + QByteArray s = stripComment(g_str.trimmed()); + int l = s.length(); + + // remove surrounding quotes if present (and not escaped) + if (l>=2 && s.at(0)=='"' && s.at(l-1)=='"' && // remove quotes + (s.at(l-2)!='\\' || (s.at(l-2)=='\\' && s.at(l-3)=='\\'))) + { + s=s.mid(1,s.length()-2); + l=s.length(); + } + + // check for invalid and/or escaped quotes + bool warned=false; + QByteArray result; + for (int i=0;i<l;i++) + { + char c = s.at(i); + if (c=='\\') // escaped character + { + if (i<l-1 && s.at(i+1)=='"') // unescape the quote character + { + result+='"'; + } + else // keep other escaped characters in escaped form + { + result+=c; + if (i<l-1) + { + result+=s.at(i+1); + } + } + i++; // skip over the escaped character + } + else if (c=='"') // unescaped quote + { + if (!warned) + { + std::string str = g_str.trimmed().data(); + config_warn("Invalid value for '%s' tag at line %d, file %s: Value '%s' is not properly quoted\n", + qPrintable(g_cmd),yylineno-1,qPrintable(g_yyFileName),str.c_str()); + } + warned=true; + } + else // normal character + { + result+=c; + } + } + + // recode the string + if (g_isEnum) + { + InputString *cur = dynamic_cast<InputString *>(g_curOption); + *g_arg = cur->checkEnumVal(g_codec->toUnicode(result)); + } + else + { + *g_arg = QVariant(g_codec->toUnicode(result)); + } + + // update encoding + checkEncoding(); + + //printf("Processed string '%s'\n",g_string->data()); +} + +static void processList() +{ + bool allowCommaAsSeparator = g_cmd!=QString::fromLatin1("PREDEFINED"); + + const QByteArray s = stripComment(g_str.trimmed()); + int l = s.length(); + + QByteArray elemStr; + + // helper to push elemStr to the list and clear it + auto addElem = [&elemStr]() + { + if (!elemStr.isEmpty()) + { + //printf("Processed list element '%s'\n",e.data()); + *g_arg = QVariant(g_arg->toStringList() << g_codec->toUnicode(elemStr)); + elemStr=""; + } + }; + + bool needsSeparator=false; + int insideQuote=false; + bool warned=false; + for (int i=0;i<l;i++) + { + char c = s.at(i); + if (!needsSeparator && c=='\\') // escaped character + { + if (i<l-1 && s.at(i+1)=='"') // unescape the quote character + { + elemStr+='"'; + } + else // keep other escaped characters in escaped form + { + elemStr+=c; + if (i<l-1) + { + elemStr+=s.at(i+1); + } + } + i++; // skip over the escaped character + } + else if (!needsSeparator && c=='"') // quote character + { + if (!insideQuote) + { + insideQuote=true; + } + else // this quote ends an element + { + insideQuote=false; + needsSeparator=true; + } + } + else if (!insideQuote && ((c==',' && allowCommaAsSeparator) || isspace(c))) // separator + { + needsSeparator=false; + addElem(); + } + else // normal content character + { + if (needsSeparator) + { + if (!warned) + { + std::string str = g_str.trimmed().data(); + config_warn("Invalid value for '%s' tag at line %d, file %s: Values in list '%s' are not properly space %sseparated\n", + qPrintable(g_cmd),yylineno-1,qPrintable(g_yyFileName),str.c_str(),allowCommaAsSeparator?"or comma ":""); + warned=true; + } + needsSeparator=false; + i--; // try the character again as part of a new element + addElem(); + } + else + { + elemStr+=c; + } + } + } + // add last part + addElem(); + if (insideQuote) + { + std::string str = g_str.trimmed().data(); + config_warn("Invalid value for '%s' tag at line %d, file %s: Values in list '%s' are not properly quoted\n", + qPrintable(g_cmd),yylineno-1,qPrintable(g_yyFileName),str.c_str()); + } +} + + static FILE *tryPath(const QString &path,const QString &fileName) { QString absName=!path.isEmpty() ? path+QString::fromLatin1("/")+fileName : fileName; @@ -138,7 +302,7 @@ static FILE *tryPath(const QString &path,const QString &fileName) FILE *f = fopen(absName.toLocal8Bit(),"r"); if (f==NULL) config_err("could not open file %s for reading\n",qPrintable(absName)); - else + else return f; } return NULL; @@ -154,7 +318,7 @@ static FILE *findFile(const QString &fileName) // relative path, try with include paths in the list QStringList sl = g_includePathList.toStringList(); substEnvVarsInStrList(sl); - foreach (QString s, sl) + foreach (QString s, sl) { FILE *f = tryPath(s,fileName); if (f) return f; @@ -165,18 +329,17 @@ static FILE *findFile(const QString &fileName) static void readIncludeFile(const QString &incName) { - if (g_includeDepth==MAX_INCLUDE_DEPTH) + if (g_includeDepth==MAX_INCLUDE_DEPTH) { - config_err("maximum include depth (%d) reached, %s is not included. Aborting...\n", + config_err("maximum include depth (%d) reached, %s is not included.", MAX_INCLUDE_DEPTH,qPrintable(incName)); - exit(1); - } + } QString inc = incName; substEnvVarsInString(inc); inc = inc.trimmed(); uint incLen = inc.length(); - if (inc.at(0)==QChar::fromLatin1('"') && + if (inc.at(0)==QChar::fromLatin1('"') && inc.at(incLen-1)==QChar::fromLatin1('"')) // strip quotes { inc=inc.mid(1,incLen-2); @@ -191,7 +354,7 @@ static void readIncludeFile(const QString &incName) msg("@INCLUDE = %s: parsing...\n",qPrintable(inc)); #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->fileName=g_yyFileName; @@ -203,11 +366,10 @@ static void readIncludeFile(const QString &incName) fs->newState=YY_CURRENT_BUFFER; g_yyFileName=inc; g_includeDepth++; - } + } else { config_err("@INCLUDE = %s: not found!\n",qPrintable(inc)); - exit(1); } } @@ -219,48 +381,46 @@ static void readIncludeFile(const QString &incName) %option yylineno %x Start -%x SkipComment %x SkipInvalid %x GetString %x GetEnum %x GetStrList %x GetQuotedString -%x GetEnvVar %x Include %% <*>\0x0d -<Start,GetString,GetEnum,GetStrList,SkipInvalid>"#" { BEGIN(SkipComment); } -<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { QString cmd = g_codec->toUnicode(yytext); - cmd=cmd.left(cmd.length()-1).trimmed(); - g_curOption = g_options->value(cmd); + + /*-------------- Comments ---------------*/ + +<Start>"#".*\n { /* Skip comment */ } + + /*-------------- TAG start ---------------*/ + +<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { g_cmd = g_codec->toUnicode(yytext); + g_cmd=g_cmd.left(g_cmd.length()-1).trimmed(); + g_curOption = g_options->value(g_cmd); if (g_curOption==0) // oops not known { config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - qPrintable(cmd),yylineno,qPrintable(g_yyFileName)); + qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName)); BEGIN(SkipInvalid); } else // known tag { - //option->setEncoding(encoding); g_arg = &g_curOption->value(); + g_str = QByteArray(); + g_isEnum = false; switch(g_curOption->kind()) { case Input::StrList: - g_elemStr = QString(); *g_arg = QStringList(); BEGIN(GetStrList); break; case Input::String: - if (dynamic_cast<InputString *>(g_curOption)->stringMode() == InputString::StringFixed) - { - BEGIN(GetEnum); - } - else - { - BEGIN(GetString); - } + g_isEnum = dynamic_cast<InputString *>(g_curOption)->stringMode() == InputString::StringFixed; + BEGIN(GetString); break; case Input::Int: BEGIN(GetString); @@ -271,20 +431,20 @@ static void readIncludeFile(const QString &incName) case Input::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", qPrintable(cmd), - yylineno,qPrintable(g_yyFileName)); + "file using \"doxygen -u\"\n", qPrintable(g_cmd), + yylineno,qPrintable(g_yyFileName)); BEGIN(SkipInvalid); break; } } } -<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { QString cmd=g_codec->toUnicode(yytext); - cmd=cmd.left(cmd.length()-2).trimmed(); - g_curOption = g_options->value(cmd); +<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { g_cmd=g_codec->toUnicode(yytext); + g_cmd=g_cmd.left(g_cmd.length()-2).trimmed(); + g_curOption = g_options->value(g_cmd); if (g_curOption==0) // oops not known { config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - yytext,yylineno,qPrintable(g_yyFileName)); + yytext,yylineno,qPrintable(g_yyFileName)); BEGIN(SkipInvalid); } else // known tag @@ -293,31 +453,34 @@ static void readIncludeFile(const QString &incName) { case Input::StrList: g_arg = &g_curOption->value(); - g_elemStr=QString(); + g_str=QByteArray(); BEGIN(GetStrList); break; case Input::String: case Input::Int: case Input::Bool: - config_warn("operator += not supported for '%s'. Ignoring line at line %d, file %s\n", - yytext,yylineno,qPrintable(g_yyFileName)); + config_warn("operator += not supported for '%s'. Ignoring line %d, file %s\n", + qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName)); BEGIN(SkipInvalid); break; case Input::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", - qPrintable(cmd),yylineno,qPrintable(g_yyFileName)); + "file using \"doxygen -u\"\n", + qPrintable(g_cmd),yylineno,qPrintable(g_yyFileName)); BEGIN(SkipInvalid); break; } } } -<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_arg=&g_includePathList; *g_arg = QStringList(); g_elemStr=QString(); } + + /*-------------- INCLUDE* ---------------*/ + +<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_arg=&g_includePathList; *g_arg = QStringList(); g_str=QByteArray(); } /* include a config file */ <Start>"@INCLUDE"[ \t]*"=" { BEGIN(Include);} -<Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { - readIncludeFile(g_codec->toUnicode(yytext)); +<Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { + readIncludeFile(g_codec->toUnicode(yytext)); BEGIN(Start); } <<EOF>> { @@ -336,78 +499,66 @@ static void readIncludeFile(const QString &incName) yy_switch_to_buffer( fs->oldState ); yy_delete_buffer( oldBuf ); g_yyFileName=fs->fileName; - delete fs; + delete fs; g_includeDepth--; } } <Start>[a-z_A-Z0-9]+ { config_warn("ignoring unknown tag '%s' at line %d, file %s\n",yytext,yylineno,qPrintable(g_yyFileName)); } -<GetString,GetEnum,SkipInvalid>\n { BEGIN(Start); } -<GetStrList>\n { - if (!g_elemStr.isEmpty()) - { - //printf("elemStr1='%s'\n",qPrintable(elemStr)); - *g_arg = QVariant(g_arg->toStringList() << g_elemStr); - } - BEGIN(Start); - } -<GetStrList>[ \t]+ { - if (!g_elemStr.isEmpty()) - { - //printf("elemStr2='%s'\n",qPrintable(elemStr)); - *g_arg = QVariant(g_arg->toStringList() << g_elemStr); - } - g_elemStr = QString(); - } -<GetString>[^ \"\t\r\n]+ { - *g_arg = QVariant(g_codec->toUnicode(yytext)); - checkEncoding(); + + /*-------------- GetString ---------------*/ + +<GetString>\n { // end of string + processString(); + BEGIN(Start); } -<GetEnum>[^ \"\t\r\n]+ { - InputString *cur = dynamic_cast<InputString *>(g_curOption); - *g_arg = cur->checkEnumVal(g_codec->toUnicode(yytext)); +<GetString>\\[ \r\t]*\n { // line continuation + g_str+=' '; } -<GetString,GetEnum,GetStrList,SkipInvalid>"\"" { g_lastState=YY_START; - BEGIN(GetQuotedString); - g_tmpString=""; - } -<GetQuotedString>"\""|"\n" { - // we add a bogus space to signal that the string was quoted. This space will be stripped later on. - g_tmpString+=" "; - //printf("Quoted String = '%s'\n",qPrintable(tmpString)); - if (g_lastState==GetString) - { - *g_arg = g_codec->toUnicode(g_tmpString); - checkEncoding(); - } - else if (g_lastState==GetEnum) - { - InputString *cur = dynamic_cast<InputString *>(g_curOption); - *g_arg = cur->checkEnumVal(g_codec->toUnicode(g_tmpString)); - } - else - { - g_elemStr+=g_codec->toUnicode(g_tmpString); - } - if (*yytext=='\n') - { - config_warn("Missing end quote (\") on line %d, file %s\n",yylineno, - qPrintable(g_yyFileName)); - } - BEGIN(g_lastState); - } -<GetQuotedString>"\\\"" { - g_tmpString+='"'; - } -<GetQuotedString>. { g_tmpString+=*yytext; } -<GetStrList>[^ \#\"\t\r\n]+ { - g_elemStr+=g_codec->toUnicode(yytext); - } -<SkipComment>\n { BEGIN(Start); } -<SkipComment>\\[ \r\t]*\n { BEGIN(Start); } +<GetString>"\\" { // escape character + g_str+=yytext; + } +<GetString>[^\n\\]+ { // string part without escape characters + g_str+=yytext; + } + + /*-------------- GetStrList ---------------*/ + +<GetStrList>\n { // end of list + processList(); + BEGIN(Start); + } +<GetStrList>\\[ \r\t]*\n { // line continuation + g_str+=' '; + } +<GetStrList>"\\" { // escape character + g_str+=yytext; + } +<GetStrList>[^\n\\]+ { // string part without escape characters + g_str+=yytext; + } + + /*-------------- SkipInvalid ---------------*/ + +<SkipInvalid>\n { // end of skipped part + BEGIN(Start); + } +<SkipInvalid>\\[ \r\t]*\n { // line continuation + g_str+=' '; + } +<SkipInvalid>"\\" { // escape character + g_str+=yytext; + } +<SkipInvalid>[^\n\\]+ { // string part without escape characters + g_str+=yytext; + } + + /*-------------- fall through -------------*/ + <*>\\[ \r\t]*\n { } +<*>[ \r\t] { } <*>\n -<*>. +<*>. { config_warn("ignoring unknown character '%c' at line %d, file %s\n",yytext[0],yylineno,qPrintable(g_yyFileName)); } %% @@ -442,7 +593,7 @@ static void substEnvVarsInStrList(QStringList &sl) foreach (QString result, sl) { // an argument with quotes will have an extra space at the end, so wasQuoted will be TRUE. - bool wasQuoted = (result.indexOf(QChar::fromLatin1(' '))!=-1) || + bool wasQuoted = (result.indexOf(QChar::fromLatin1(' '))!=-1) || (result.indexOf(QChar::fromLatin1('\t'))!=-1); // here we strip the quote again substEnvVarsInString(result); @@ -452,7 +603,7 @@ static void substEnvVarsInStrList(QStringList &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 + contained multiple elements no further splitting is done to allow quoted items with spaces! */ { int l=result.length(); @@ -463,11 +614,11 @@ static void substEnvVarsInStrList(QStringList &sl) { QChar c=0; // skip until start of new word - while (i<l && ((c=result.at(i))==QChar::fromLatin1(' ') || c==QChar::fromLatin1('\t'))) i++; + while (i<l && ((c=result.at(i))==QChar::fromLatin1(' ') || c==QChar::fromLatin1('\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))!=QChar::fromLatin1(' ') && - c!=QChar::fromLatin1('\t') && + while (i<l && ((c=result.at(i))!=QChar::fromLatin1(' ') && + c!=QChar::fromLatin1('\t') && c!=QChar::fromLatin1('"'))) i++; if (i<l) // not at the end of the string { @@ -481,7 +632,7 @@ static void substEnvVarsInStrList(QStringList &sl) { out += result.mid(p,i-p); p=i+1; - break; + break; } else if (c==QChar::fromLatin1('\\')) // skip escaped stuff { @@ -516,13 +667,15 @@ bool parseConfig( const QHash<QString,Input *> &options ) { + yylineno = 1; + config_open(); QHashIterator<QString, Input*> i(options); g_file = fopen(fileName.toLocal8Bit(),"r"); if (g_file==NULL) return false; // reset all values i.toFront(); - while (i.hasNext()) + while (i.hasNext()) { i.next(); if (i.value()) @@ -542,7 +695,7 @@ bool parseConfig( // update the values in the UI i.toFront(); - while (i.hasNext()) + while (i.hasNext()) { i.next(); if (i.value()) @@ -554,8 +707,9 @@ bool parseConfig( { printf("Invalid option: %s\n",qPrintable(i.key())); } - } + } fclose(g_file); + config_finish(); return true; } @@ -572,29 +726,29 @@ void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s) { if (*p != QChar::fromLatin1('"')) { - while (!(c=*p++).isNull() && !needsEscaping) + while (!(c=*p++).isNull() && !needsEscaping) { - needsEscaping = (c==QChar::fromLatin1(' ') || - c==QChar::fromLatin1('\n') || - c==QChar::fromLatin1('\t') || + needsEscaping = (c==QChar::fromLatin1(' ') || + c==QChar::fromLatin1('\n') || + c==QChar::fromLatin1('\t') || c==QChar::fromLatin1('"')); } p=s.data(); - while (!(c=*p++).isNull() && !needsHashEscaping) + while (!(c=*p++).isNull() && !needsHashEscaping) { needsHashEscaping = (c==QChar::fromLatin1('#')); } } if (needsHashEscaping || needsEscaping) - { + { t << "\""; } if (needsEscaping) - { + { p=s.data(); while (!p->isNull()) { - if (*p ==QChar::fromLatin1(' ') && + if (*p ==QChar::fromLatin1(' ') && *(p+1)==QChar::fromLatin1('\0')) break; // skip inserted space at the end if (*p ==QChar::fromLatin1('"')) t << "\\"; // escape quotes t << *p++; @@ -605,7 +759,7 @@ void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s) t << s; } if (needsHashEscaping || needsEscaping) - { + { t << "\""; } } diff --git a/addon/doxywizard/config_msg.cpp b/addon/doxywizard/config_msg.cpp new file mode 100644 index 0000000..fc84206 --- /dev/null +++ b/addon/doxywizard/config_msg.cpp @@ -0,0 +1,56 @@ +#include <QString> +#include "config_msg.h" +#include "doxywizard.h" + +static QString warning_str = QString::fromLatin1("warning: "); +static QString error_str = QString::fromLatin1("error: "); + +void config_err(const char *fmt, ...) +{ + QString msg = error_str; + + msg.append(QString::fromLatin1(fmt)); + va_list args; + va_start(args, fmt); + char debugOut[1000]; // this size should be sufficient + vsnprintf(debugOut, 1000,qPrintable(msg), args); + MainWindow::instance().outputLogText(QString::fromLatin1(debugOut)); + va_end(args); +} + +void config_term(const char *fmt, ...) +{ + QString msg = error_str; + + msg.append(QString::fromLatin1(fmt)); + va_list args; + va_start(args, fmt); + char debugOut[1000]; // this size should be sufficient + vsnprintf(debugOut, 1000,qPrintable(msg), args); + MainWindow::instance().outputLogText(QString::fromLatin1(debugOut)); + va_end(args); + exit(1); +} + +void config_warn(const char *fmt, ...) +{ + QString msg = warning_str; + + msg.append(QString::fromLatin1(fmt)); + va_list args; + va_start(args, fmt); + char debugOut[1000]; + vsnprintf(debugOut, 1000,qPrintable(msg), args); + MainWindow::instance().outputLogText(QString::fromLatin1(debugOut)); + va_end(args); +} + +void config_open() +{ + MainWindow::instance().outputLogStart(); +} + +void config_finish() +{ + MainWindow::instance().outputLogFinish(); +} diff --git a/addon/doxywizard/config_msg.h b/addon/doxywizard/config_msg.h new file mode 100644 index 0000000..c8f1070 --- /dev/null +++ b/addon/doxywizard/config_msg.h @@ -0,0 +1,10 @@ +#ifndef DOXYW_MSG_H +#define DOXYW_MSG_H + +void config_err(const char *fmt, ...); +void config_term(const char *fmt, ...); +void config_warn(const char *fmt, ...); +void config_open(); +void config_finish(); + +#endif diff --git a/addon/doxywizard/doxywizard.cpp b/addon/doxywizard/doxywizard.cpp index ce22367..c75279b 100755 --- a/addon/doxywizard/doxywizard.cpp +++ b/addon/doxywizard/doxywizard.cpp @@ -3,8 +3,8 @@ * 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. * @@ -22,6 +22,7 @@ #include <QVBoxLayout> #include <QLineEdit> #include <QLabel> +#include <QCheckBox> #include <QTextBrowser> #include <QStatusBar> #include <QProcess> @@ -41,6 +42,9 @@ #define MAX_RECENT_FILES 10 +// globally accessible variables +bool DoxygenWizard::debugFlag = false; + const int messageTimeout = 5000; //!< status bar message timeout in milliseconds. #define APPQT(x) QString::fromLatin1("<qt><pre>") + x + QString::fromLatin1("</pre></qt>") @@ -57,36 +61,39 @@ MainWindow::MainWindow() : m_settings(QString::fromLatin1("Doxygen.org"), QString::fromLatin1("Doxywizard")) { QMenu *file = menuBar()->addMenu(tr("File")); - file->addAction(tr("Open..."), + file->addAction(tr("Open..."), this, SLOT(openConfig()), Qt::CTRL+Qt::Key_O); m_recentMenu = file->addMenu(tr("Open recent")); - file->addAction(tr("Save"), + file->addAction(tr("Save"), this, SLOT(saveConfig()), Qt::CTRL+Qt::Key_S); - file->addAction(tr("Save as..."), + file->addAction(tr("Save as..."), this, SLOT(saveConfigAs()), Qt::SHIFT+Qt::CTRL+Qt::Key_S); - file->addAction(tr("Quit"), + file->addAction(tr("Quit"), this, SLOT(quit()), Qt::CTRL+Qt::Key_Q); QMenu *settings = menuBar()->addMenu(tr("Settings")); - settings->addAction(tr("Reset to factory defaults"), + m_resetDefault = settings->addAction(tr("Reset to factory defaults"), this,SLOT(resetToDefaults())); settings->addAction(tr("Use current settings at startup"), this,SLOT(makeDefaults())); - settings->addAction(tr("Clear recent list"), + m_clearRecent = settings->addAction(tr("Clear recent list"), this,SLOT(clearRecent())); QMenu *help = menuBar()->addMenu(tr("Help")); - help->addAction(tr("Online manual"), + help->addAction(tr("Online manual"), this, SLOT(manual()), Qt::Key_F1); - help->addAction(tr("About"), + help->addAction(tr("About"), this, SLOT(about()) ); m_expert = new Expert; m_wizard = new Wizard(m_expert->modelData()); // ----------- top part ------------------ + QWidget *mainPart = new QWidget; + QVBoxLayout *mainLayout = new QVBoxLayout(mainPart); QWidget *topPart = new QWidget; QVBoxLayout *rowLayout = new QVBoxLayout(topPart); + mainLayout->addWidget(topPart); // select working directory QHBoxLayout *dirLayout = new QHBoxLayout; @@ -107,11 +114,43 @@ MainWindow::MainWindow() m_saveLog = new QPushButton(tr("Save log...")); m_saveLog->setEnabled(false); QPushButton *showSettings = new QPushButton(tr("Show configuration")); - runLayout->addWidget(m_run); - runLayout->addWidget(m_runStatus); + + m_showCondensedSettings = new QCheckBox(this); + m_showCondensedSettings->setText(tr("Condensed")); + m_showCondensedSettings->setChecked(false); + m_showCondensedSettings->setToolTip(tr("Show only configuration settings different from default settings")); + + // select extra run options + m_runOptions = new QLineEdit; + + runTabLayout->addWidget(new QLabel(tr("Specify additional command line options for running doxygen"))); + runTabLayout->addWidget(m_runOptions); + + QVBoxLayout *runVLayout = new QVBoxLayout; + runLayout->addLayout(runVLayout); + QHBoxLayout *runVHLayout = new QHBoxLayout; + runVLayout->addLayout(runVHLayout); + runVHLayout->addWidget(m_run); + runVHLayout->addWidget(m_runStatus); + + QHBoxLayout *runVH2Layout = new QHBoxLayout; + runVLayout->addLayout(runVH2Layout); + m_launchHtml = new QPushButton(tr("Show HTML output")); + runVH2Layout->addWidget(m_launchHtml); + runVH2Layout->addStretch(1); // to have launch button not being stretched + runLayout->addStretch(1); - runLayout->addWidget(showSettings); - runLayout->addWidget(m_saveLog); + + QVBoxLayout *settingsLayout = new QVBoxLayout; + runLayout->addLayout(settingsLayout); + settingsLayout->addWidget(m_showCondensedSettings); + settingsLayout->addWidget(showSettings); + + QVBoxLayout *saveLayout = new QVBoxLayout; + runLayout->addLayout(saveLayout); + saveLayout->addWidget(m_saveLog); + saveLayout->setAlignment(Qt::AlignTop); + // saveLayout->addWidget(new QWidget); // to have the save button at the top // output produced by Doxygen runTabLayout->addLayout(runLayout); @@ -126,12 +165,6 @@ MainWindow::MainWindow() grid->addWidget(m_outputLog,0,0); grid->setColumnStretch(0,1); grid->setRowStretch(0,1); - QHBoxLayout *launchLayout = new QHBoxLayout; - m_launchHtml = new QPushButton(tr("Show HTML output")); - launchLayout->addWidget(m_launchHtml); - - launchLayout->addStretch(1); - grid->addLayout(launchLayout,1,0); runTabLayout->addLayout(grid); m_tabs = new QTabWidget; @@ -139,12 +172,12 @@ MainWindow::MainWindow() m_tabs->addTab(m_expert,tr("Expert")); m_tabs->addTab(runTab,tr("Run")); - rowLayout->addWidget(new QLabel(tr("Step 1: Specify the working directory from which doxygen will run"))); + rowLayout->addWidget(new QLabel(tr("Specify the working directory from which doxygen will run"))); rowLayout->addLayout(dirLayout); - rowLayout->addWidget(new QLabel(tr("Step 2: Configure doxygen using the Wizard and/or Expert tab, then switch to the Run tab to generate the documentation"))); - rowLayout->addWidget(m_tabs); + rowLayout->addWidget(new QLabel(tr("Configure doxygen using the Wizard and/or Expert tab, then switch to the Run tab to generate the documentation"))); + mainLayout->addWidget(m_tabs); - setCentralWidget(topPart); + setCentralWidget(mainPart); statusBar()->showMessage(tr("Welcome to Doxygen"),messageTimeout); m_runProcess = new QProcess; @@ -193,6 +226,10 @@ void MainWindow::quit() { saveSettings(); } + else + { + return; + } QApplication::exit(0); } @@ -220,7 +257,7 @@ void MainWindow::updateWorkingDir() void MainWindow::manual() { - QDesktopServices::openUrl(QUrl(QString::fromLatin1("http://www.doxygen.org/manual/index.html"))); + QDesktopServices::openUrl(QUrl(QString::fromLatin1("https://www.doxygen.org/manual/index.html"))); } void MainWindow::about() @@ -229,7 +266,15 @@ void MainWindow::about() QTextStream t(&msg,QIODevice::WriteOnly); t << QString::fromLatin1("<qt><center>A tool to configure and run doxygen version ")+ QString::fromLatin1(getDoxygenVersion())+ - QString::fromLatin1(" on your source files.</center><p><br>" + QString::fromLatin1(" on your source files.</center>")+ + QString::fromLatin1("<center>(Created with Qt version ")+ + QString::fromLatin1(QT_VERSION_STR); + if (qstrcmp(qVersion(),QT_VERSION_STR)) + { + t << QString::fromLatin1(", running with ")+ + QString::fromLatin1(qVersion()); + } + t << QString::fromLatin1(")</center><p><br>" "<center>Written by<br> Dimitri van Heesch<br>© 2000-2019</center><p>" "</qt>"); QMessageBox::about(this,tr("Doxygen GUI"),msg); @@ -288,7 +333,7 @@ void MainWindow::saveConfig(const QString &fileName) return; } QTextStream t(&f); - m_expert->writeConfig(t,false); + m_expert->writeConfig(t,false,false); updateConfigFileName(fileName); m_modified = false; updateTitle(); @@ -309,7 +354,7 @@ bool MainWindow::saveConfig() bool MainWindow::saveConfigAs() { - QString fileName = QFileDialog::getSaveFileName(this, QString(), + QString fileName = QFileDialog::getSaveFileName(this, QString(), m_workingDir->text()+QString::fromLatin1("/Doxyfile")); if (fileName.isEmpty()) return false; saveConfig(fileName); @@ -343,11 +388,13 @@ void MainWindow::clearRecent() m_recentFiles.clear(); for (int i=0;i<MAX_RECENT_FILES;i++) { - m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i++),QString::fromLatin1("")); + m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i),QString::fromLatin1("")); } + m_clearRecent->setEnabled(false); + m_recentMenu->setEnabled(false); m_settings.sync(); } - + } void MainWindow::resetToDefaults() @@ -362,6 +409,8 @@ void MainWindow::resetToDefaults() m_expert->resetToDefaults(); m_settings.setValue(QString::fromLatin1("wizard/loadsettings"), false); m_settings.sync(); + m_modified = false; + updateTitle(); m_wizard->refresh(); } } @@ -429,7 +478,7 @@ void MainWindow::addRecentFileList(const QString &fileName) { int i=m_recentFiles.indexOf(fileName); if (i!=-1) m_recentFiles.removeAt(i); - + // not found if (m_recentFiles.count() < MAX_RECENT_FILES) // append { @@ -440,12 +489,15 @@ void MainWindow::addRecentFileList(const QString &fileName) m_recentFiles.removeLast(); m_recentFiles.prepend(fileName); } + m_clearRecent->setEnabled(m_recentFiles.count()>0); + m_recentMenu->setEnabled(m_recentFiles.count()>0); + m_settings.sync(); } void MainWindow::updateRecentFile(void) { m_recentMenu->clear(); int i=0; - foreach( QString str, m_recentFiles ) + foreach( QString str, m_recentFiles ) { m_recentMenu->addAction(str); m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i++),str); @@ -454,6 +506,9 @@ void MainWindow::updateRecentFile(void) { m_settings.setValue(QString::fromLatin1("recent/config%1").arg(i),QString::fromLatin1("")); } + m_clearRecent->setEnabled(m_recentFiles.count()>0); + m_recentMenu->setEnabled(m_recentFiles.count()>0); + m_settings.sync(); } void MainWindow::openRecent(QAction *action) @@ -468,18 +523,18 @@ void MainWindow::runDoxygen() { if (!m_running) { - QString doxygenPath; + QString doxygenPath; #if defined(Q_OS_MACX) doxygenPath = qApp->applicationDirPath()+QString::fromLatin1("/../Resources/"); qDebug() << tr("Doxygen path: ") << doxygenPath; - if ( !QFile(doxygenPath + QString::fromLatin1("doxygen")).exists() ) + if ( !QFile(doxygenPath + QString::fromLatin1("doxygen")).exists() ) { // No Doxygen binary in the resources, if there is a system Doxygen binary, use that instead if ( QFile(QString::fromLatin1("/usr/local/bin/doxygen")).exists() ) { doxygenPath = QString::fromLatin1("/usr/local/bin/"); } - else + else { qDebug() << tr("Can't find the doxygen command, make sure it's in your $$PATH"); doxygenPath = QString::fromLatin1(""); @@ -493,11 +548,14 @@ void MainWindow::runDoxygen() m_runProcess->setWorkingDirectory(m_workingDir->text()); QStringList env=QProcess::systemEnvironment(); // set PWD environment variable to m_workingDir - env.replaceInStrings(QRegExp(QString::fromLatin1("^PWD=(.*)"),Qt::CaseInsensitive), + env.replaceInStrings(QRegExp(QString::fromLatin1("^PWD=(.*)"),Qt::CaseInsensitive), QString::fromLatin1("PWD=")+m_workingDir->text()); m_runProcess->setEnvironment(env); QStringList args; + QStringList runOptions = m_runOptions->text().split(QLatin1Char(' '),QString::SkipEmptyParts); + + args << runOptions; args << QString::fromLatin1("-b"); // make stdout unbuffered args << QString::fromLatin1("-"); // read config from stdin @@ -511,7 +569,7 @@ void MainWindow::runDoxygen() return; } QTextStream t(m_runProcess); - m_expert->writeConfig(t,false); + m_expert->writeConfig(t,false,false); m_runProcess->closeWriteChannel(); if (m_runProcess->state() == QProcess::NotRunning) @@ -601,7 +659,7 @@ void MainWindow::showHtmlOutput() void MainWindow::saveLog() { - QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"), + QString fn = QFileDialog::getSaveFileName(this, tr("Save log file"), m_workingDir->text()+ QString::fromLatin1("/doxygen_log.txt")); if (!fn.isEmpty()) @@ -625,7 +683,14 @@ void MainWindow::showSettings() { QString text; QTextStream t(&text); - m_expert->writeConfig(t,true); + if (m_showCondensedSettings->isChecked()) + { + m_expert->writeConfig(t,true,true); + } + else + { + m_expert->writeConfig(t,true,false); + } m_outputLog->clear(); m_outputLog->append(APPQT(text)); m_outputLog->ensureCursorVisible(); @@ -641,6 +706,7 @@ void MainWindow::configChanged() void MainWindow::updateTitle() { QString title = tr("Doxygen GUI frontend"); + m_resetDefault->setEnabled(m_modified); if (m_modified) { title+=QString::fromLatin1(" +"); @@ -685,11 +751,33 @@ bool MainWindow::discardUnsavedChanges(bool saveOption) return true; } +void MainWindow::outputLogStart() +{ + m_outputLogTextCount = 0; + m_outputLog->clear(); +} +void MainWindow::outputLogText(QString text) +{ + m_outputLogTextCount++; + m_outputLog->append(APPQT(text)); +} +void MainWindow::outputLogFinish() +{ + if (m_outputLogTextCount > 0) + { + selectRunTab(); + } + + m_outputLog->ensureCursorVisible(); + m_saveLog->setEnabled(true); +} //----------------------------------------------------------------------- int main(int argc,char **argv) { QApplication a(argc,argv); - if (argc == 2) + int locArgc = argc; + + if (locArgc == 2) { if (!qstrcmp(argv[1],"--help")) { @@ -701,12 +789,25 @@ int main(int argc,char **argv) else if (!qstrcmp(argv[1],"--version")) { QMessageBox msgBox; - msgBox.setText(QString::fromLatin1("Doxywizard version: %1").arg(QString::fromLatin1(getFullVersion()))); + if (!qstrcmp(qVersion(),QT_VERSION_STR)) + { + msgBox.setText(QString::fromLatin1("Doxywizard version: %1, Qt version: %2").arg(QString::fromLatin1(getFullVersion()),QString::fromLatin1(QT_VERSION_STR))); + } + else + { + msgBox.setText(QString::fromLatin1("Doxywizard version: %1, Qt version: created with %2, running with %3").arg(QString::fromLatin1(getFullVersion()),QString::fromLatin1(QT_VERSION_STR),QString::fromLatin1(qVersion()))); + } msgBox.exec(); exit(0); } } - if (argc > 2) + if (!qstrcmp(argv[1],"--debug") && ((locArgc == 2) || (locArgc == 3))) + { + DoxygenWizard::debugFlag = true; + locArgc--; + } + + if (locArgc > 2) { QMessageBox msgBox; msgBox.setText(QString::fromLatin1("Too many arguments specified\n\nUsage: %1 [config file]").arg(QString::fromLatin1(argv[0]))); @@ -716,9 +817,9 @@ int main(int argc,char **argv) else { MainWindow &main = MainWindow::instance(); - if (argc==2 && argv[1][0]!='-') // name of config file as an argument + if (locArgc==2 && argv[argc-1][0]!='-') // name of config file as an argument { - main.loadConfigFromFile(QString::fromLocal8Bit(argv[1])); + main.loadConfigFromFile(QString::fromLocal8Bit(argv[argc-1])); } main.show(); return a.exec(); diff --git a/addon/doxywizard/doxywizard.h b/addon/doxywizard/doxywizard.h index c64941e..ccbd9b0 100755 --- a/addon/doxywizard/doxywizard.h +++ b/addon/doxywizard/doxywizard.h @@ -3,8 +3,8 @@ * 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. * @@ -20,6 +20,7 @@ class Expert; class Wizard; class QLabel; +class QCheckBox; class QLineEdit; class QPushButton; class QTextBrowser; @@ -40,6 +41,10 @@ class MainWindow : public QMainWindow void closeEvent(QCloseEvent *event); QString configFileName() const { return m_fileName; } void updateTitle(); + // access routines for outputLog pane + void outputLogStart(); + void outputLogText(QString text); + void outputLogFinish(); public slots: void manual(); @@ -65,7 +70,7 @@ class MainWindow : public QMainWindow void configChanged(); void clearRecent(); void selectRunTab(); - + private: MainWindow(); void saveConfig(const QString &fileName); @@ -78,9 +83,11 @@ class MainWindow : public QMainWindow bool discardUnsavedChanges(bool saveOption=true); QLineEdit *m_workingDir; + QLineEdit *m_runOptions; QPushButton *m_selWorkingDir; QPushButton *m_run; QPushButton *m_saveLog; + QCheckBox *m_showCondensedSettings; QPushButton *m_launchHtml; QPushButton *m_launchPdf; QTextBrowser *m_outputLog; @@ -91,11 +98,23 @@ class MainWindow : public QMainWindow QSettings m_settings; QMenu *m_recentMenu; QStringList m_recentFiles; + QAction *m_resetDefault; + QAction *m_clearRecent; QProcess *m_runProcess; QTimer *m_timer; QTabWidget *m_tabs; + int m_outputLogTextCount = 0; bool m_running; bool m_modified; }; +/*! \brief This class serves as a namespace for global variables used by the doxygen wizard. + * + * All fields in this class are public and static, so they can be used directly. + */ +class DoxygenWizard +{ + public: + static bool debugFlag; +}; #endif diff --git a/addon/doxywizard/expert.cpp b/addon/doxywizard/expert.cpp index c043994..7fd7df3 100644 --- a/addon/doxywizard/expert.cpp +++ b/addon/doxywizard/expert.cpp @@ -139,10 +139,14 @@ void Expert::createTopics(const QDomElement &rootElem) { // Remove _ from a group name like: Source_Browser QString name = childElem.attribute(SA("name")).replace(SA("_"),SA(" ")); - items.append(new QTreeWidgetItem((QTreeWidget*)0,QStringList(name))); - QWidget *widget = createTopicWidget(childElem); - m_topics[name] = widget; - m_topicStack->addWidget(widget); + QString setting = childElem.attribute(SA("setting")); + if (setting.isEmpty() || IS_SUPPORTED(setting.toLatin1())) + { + items.append(new QTreeWidgetItem((QTreeWidget*)0,QStringList(name))); + QWidget *widget = createTopicWidget(childElem); + m_topics[name] = widget; + m_topicStack->addWidget(widget); + } } childElem = childElem.nextSiblingElement(); } @@ -423,7 +427,7 @@ static QString getDocsForNode(const QDomElement &child) regexp.setPattern(SA("`([^`]+)`")); docs.replace(regexp,SA("<code>\\1</code>")); // \ref key "desc" -> <code>desc</code> - regexp.setPattern(SA("\\\\ref[ ]+[^ ]+[ ]+\"([^ ]+)\"")); + regexp.setPattern(SA("\\\\ref[ ]+[^ ]+[ ]+\"([^\"]+)\"")); docs.replace(regexp,SA("<code>\\1</code> ")); //\ref specials // \ref <key> -> description @@ -752,15 +756,18 @@ void Expert::loadConfig(const QString &fileName) } void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec, - bool brief) + bool brief,bool condensed) { if (!brief) { t << endl; } - t << "#---------------------------------------------------------------------------" << endl; - t << "# " << elem.attribute(SA("docs")) << endl; - t << "#---------------------------------------------------------------------------" << endl; + if (!condensed) + { + t << "#---------------------------------------------------------------------------" << endl; + t << "# " << elem.attribute(SA("docs")) << endl; + t << "#---------------------------------------------------------------------------" << endl; + } // write options... QDomElement childElem = elem.firstChildElement(); while (!childElem.isNull()) @@ -780,24 +787,29 @@ void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec, t << convertToComment(option->templateDocs()); t << endl; } - t << name.leftJustified(MAX_OPTION_LENGTH) << "="; - if (option && !option->isEmpty()) + bool toPrint = true; + if (option && condensed) toPrint = !option->isDefault(); + if (toPrint) { - t << " "; - option->writeValue(t,codec); + t << name.leftJustified(MAX_OPTION_LENGTH) << "="; + if (option && !option->isEmpty()) + { + t << " "; + option->writeValue(t,codec); + } + t << endl; } - t << endl; } } childElem = childElem.nextSiblingElement(); } } -bool Expert::writeConfig(QTextStream &t,bool brief) +bool Expert::writeConfig(QTextStream &t,bool brief, bool condensed) { // write global header t << "# Doxyfile " << getDoxygenVersion() << endl << endl; - if (!brief) + if (!brief && !condensed) { t << convertToComment(m_header); } @@ -817,7 +829,7 @@ bool Expert::writeConfig(QTextStream &t,bool brief) { if (childElem.tagName()==SA("group")) { - saveTopic(t,childElem,codec,brief); + saveTopic(t,childElem,codec,brief,condensed); } childElem = childElem.nextSiblingElement(); } diff --git a/addon/doxywizard/expert.h b/addon/doxywizard/expert.h index f58ef62..7011eb4 100644 --- a/addon/doxywizard/expert.h +++ b/addon/doxywizard/expert.h @@ -38,7 +38,7 @@ class Expert : public QSplitter, public DocIntf void loadSettings(QSettings *); void saveSettings(QSettings *); void loadConfig(const QString &fileName); - bool writeConfig(QTextStream &t,bool brief); + bool writeConfig(QTextStream &t,bool brief,bool condensed); QByteArray saveInnerState () const; bool restoreInnerState ( const QByteArray & state ); const QHash<QString,Input*> &modelData() const { return m_options; } @@ -67,7 +67,7 @@ class Expert : public QSplitter, public DocIntf private: void createTopics(const QDomElement &); - void saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,bool brief); + void saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec,bool brief,bool dondensed); QSplitter *m_splitter; QTextBrowser *m_helper; diff --git a/addon/doxywizard/input.h b/addon/doxywizard/input.h index ff8339a..c1815d0 100644 --- a/addon/doxywizard/input.h +++ b/addon/doxywizard/input.h @@ -40,6 +40,7 @@ class Input virtual void setEnabled(bool) = 0; virtual void updateDependencies() = 0; virtual void reset() = 0; + virtual bool isDefault() = 0; virtual void writeValue(QTextStream &t,QTextCodec *codec) = 0; virtual void setTemplateDocs(const QString &docs) = 0; virtual bool isEmpty() { return false; }; diff --git a/addon/doxywizard/inputbool.cpp b/addon/doxywizard/inputbool.cpp index 63d9998..132658d 100644 --- a/addon/doxywizard/inputbool.cpp +++ b/addon/doxywizard/inputbool.cpp @@ -3,8 +3,8 @@ * 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. * @@ -12,13 +12,14 @@ #include "inputbool.h" #include "helplabel.h" +#include "config_msg.h" #include <QCheckBox> #include <QTextStream> #include <QTextCodec> #include <QGridLayout> -InputBool::InputBool( QGridLayout *layout, int &row, +InputBool::InputBool( QGridLayout *layout, int &row, const QString &id, bool checked, const QString &docs ) : m_default(checked), m_docs(docs), m_id(id) @@ -42,10 +43,10 @@ void InputBool::help() } void InputBool::setEnabled(bool b) -{ +{ m_enabled = b; - m_cb->setEnabled(b); - m_lab->setEnabled(b); + m_cb->setEnabled(b); + m_lab->setEnabled(b); updateDefault(); updateDependencies(); } @@ -60,7 +61,7 @@ void InputBool::updateDependencies() void InputBool::setValue( bool s ) { - if (m_state!=s) + if (m_state!=s) { m_state=s; updateDefault(); @@ -75,7 +76,7 @@ void InputBool::updateDefault() { if (m_state==m_default || !m_lab->isEnabled()) { - m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt")); + m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt>")); } else { @@ -91,9 +92,22 @@ QVariant &InputBool::value() void InputBool::update() { QString v = m_value.toString().toLower(); - m_state = (v==QString::fromLatin1("yes") || - v==QString::fromLatin1("true") || - v==QString::fromLatin1("1")); + if (v==QString::fromLatin1("yes") || v==QString::fromLatin1("true") || + v==QString::fromLatin1("1") || v==QString::fromLatin1("all")) + { + m_state = true; + } + else if (v==QString::fromLatin1("no") || v==QString::fromLatin1("false") || + v==QString::fromLatin1("0") || v==QString::fromLatin1("none")) + { + m_state = false; + } + else + { + config_warn("argument '%s' for option %s is not a valid boolean value." + " Using the default: %s!",qPrintable(m_value.toString()),qPrintable(m_id),m_default?"YES":"NO"); + m_state = m_default; + } m_cb->setChecked( m_state ); updateDefault(); updateDependencies(); @@ -106,9 +120,14 @@ void InputBool::reset() void InputBool::writeValue(QTextStream &t,QTextCodec *codec) { - if (m_state) - t << codec->fromUnicode(QString::fromLatin1("YES")); - else + if (m_state) + t << codec->fromUnicode(QString::fromLatin1("YES")); + else t << codec->fromUnicode(QString::fromLatin1("NO")); } +bool InputBool::isDefault() +{ + return m_state == m_default; +} + diff --git a/addon/doxywizard/inputbool.h b/addon/doxywizard/inputbool.h index 98f7f85..a527e20 100644 --- a/addon/doxywizard/inputbool.h +++ b/addon/doxywizard/inputbool.h @@ -38,6 +38,7 @@ class InputBool : public QObject, public Input void addDependency(Input *option) { m_dependencies+=option; } void setEnabled(bool); void updateDependencies(); + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } diff --git a/addon/doxywizard/inputint.cpp b/addon/doxywizard/inputint.cpp index 2aa019b..ce3fa02 100644 --- a/addon/doxywizard/inputint.cpp +++ b/addon/doxywizard/inputint.cpp @@ -3,8 +3,8 @@ * 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. * @@ -12,6 +12,7 @@ #include "inputint.h" #include "helplabel.h" +#include "config_msg.h" #include <QSpinBox> #include <QGridLayout> @@ -28,7 +29,7 @@ class NoWheelSpinBox : public QSpinBox }; InputInt::InputInt( QGridLayout *layout,int &row, - const QString & id, + const QString & id, int defVal, int minVal,int maxVal, const QString & docs ) : m_default(defVal), m_minVal(minVal), m_maxVal(maxVal), m_docs(docs), m_id(id) @@ -44,7 +45,7 @@ InputInt::InputInt( QGridLayout *layout,int &row, layout->addWidget( m_lab, row, 0 ); layout->addWidget( m_sp, row, 1 ); - connect(m_sp, SIGNAL(valueChanged(int)), + connect(m_sp, SIGNAL(valueChanged(int)), this, SLOT(setValue(int)) ); connect( m_lab, SIGNAL(enter()), SLOT(help()) ); connect( m_lab, SIGNAL(reset()), SLOT(reset()) ); @@ -59,12 +60,19 @@ void InputInt::help() void InputInt::setValue(int val) { - val = qMax(m_minVal,val); - val = qMin(m_maxVal,val); - if (val!=m_val) + int newVal = val; + newVal = qMax(m_minVal,newVal); + newVal = qMin(m_maxVal,newVal); + if (val != newVal) { - m_val = val; - m_sp->setValue(val); + config_warn("argument '%d' for option %s is not a valid number in the range [%d..%d]!" + " Using the default: %d!\n",val,qPrintable(m_id),m_minVal,m_maxVal,m_default); + newVal = m_default; + } + if (newVal!=m_val) + { + m_val = newVal; + m_sp->setValue(newVal); m_value = m_val; updateDefault(); } @@ -75,13 +83,13 @@ void InputInt::updateDefault() { if (m_val==m_default || !m_lab->isEnabled()) { - m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt")); + m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt>")); } else { m_lab->setText(QString::fromLatin1("<qt><font color='red'>")+m_id+QString::fromLatin1("</font></qt>")); } - emit changed(); + emit changed(); } } @@ -92,14 +100,22 @@ void InputInt::setEnabled(bool state) updateDefault(); } -QVariant &InputInt::value() +QVariant &InputInt::value() { return m_value; } void InputInt::update() { - setValue(m_value.toInt()); + bool ok; + int newVal = m_value.toInt(&ok); + if (!ok) + { + config_warn("argument '%s' for option %s is not a valid number in the range [%d..%d]!" + " Using the default: %d!\n",qPrintable(m_value.toString()),qPrintable(m_id),m_minVal,m_maxVal,m_default); + newVal = m_default; + } + setValue(newVal); } void InputInt::reset() @@ -112,3 +128,8 @@ void InputInt::writeValue(QTextStream &t,QTextCodec *) t << m_val; } + +bool InputInt::isDefault() +{ + return m_val == m_default; +} diff --git a/addon/doxywizard/inputint.h b/addon/doxywizard/inputint.h index 10d735e..60d4415 100644 --- a/addon/doxywizard/inputint.h +++ b/addon/doxywizard/inputint.h @@ -41,6 +41,7 @@ class InputInt : public QObject, public Input void addDependency(Input *) { Q_ASSERT(false); } void setEnabled(bool); void updateDependencies() {} + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } diff --git a/addon/doxywizard/inputstring.cpp b/addon/doxywizard/inputstring.cpp index 2f81b5b..ac76342 100644 --- a/addon/doxywizard/inputstring.cpp +++ b/addon/doxywizard/inputstring.cpp @@ -13,6 +13,7 @@ #include "inputstring.h" #include "helplabel.h" #include "doxywizard.h" +#include "config_msg.h" #include "config.h" #include <QComboBox> @@ -130,7 +131,7 @@ void InputString::updateDefault() { if (m_str==m_default || !m_lab->isEnabled()) { - m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt")); + m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt>")); } else { @@ -253,6 +254,11 @@ void InputString::writeValue(QTextStream &t,QTextCodec *codec) writeStringValue(t,codec,m_str); } +bool InputString::isDefault() +{ + return m_str == m_default; +} + QString InputString::checkEnumVal(const QString &value) { QString val = value.trimmed().toLower(); @@ -263,5 +269,7 @@ QString InputString::checkEnumVal(const QString &value) if (enumVal.toLower() == val) return enumVal; } + config_warn("argument '%s' for option %s is not a valid enum value." + " Using the default: %s!",qPrintable(value),qPrintable(m_id),qPrintable(m_default)); return m_default; } diff --git a/addon/doxywizard/inputstring.h b/addon/doxywizard/inputstring.h index 1520584..c22d7a3 100644 --- a/addon/doxywizard/inputstring.h +++ b/addon/doxywizard/inputstring.h @@ -57,6 +57,7 @@ class InputString : public QObject, public Input void addDependency(Input *) { Q_ASSERT(false); } void setEnabled(bool); void updateDependencies() {} + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } bool isEmpty() { return m_str.isEmpty(); } diff --git a/addon/doxywizard/inputstrlist.cpp b/addon/doxywizard/inputstrlist.cpp index dd1ecb2..fae45b5 100644 --- a/addon/doxywizard/inputstrlist.cpp +++ b/addon/doxywizard/inputstrlist.cpp @@ -3,8 +3,8 @@ * 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. * @@ -25,7 +25,7 @@ #include <QTextCodec> InputStrList::InputStrList( QGridLayout *layout,int &row, - const QString & id, + const QString & id, const QStringList &sl, ListMode lm, const QString & docs) : m_default(sl), m_strList(sl), m_docs(docs), m_id(id) @@ -50,7 +50,7 @@ InputStrList::InputStrList( QGridLayout *layout,int &row, m_lb = new QListWidget; //m_lb->setMinimumSize(400,100); foreach (QString s, m_strList) m_lb->addItem(s); - + m_brFile=0; m_brDir=0; if (lm!=ListString) @@ -60,7 +60,7 @@ InputStrList::InputStrList( QGridLayout *layout,int &row, m_brFile = toolBar->addAction(QIcon(QString::fromLatin1(":/images/file.png")),QString(), this,SLOT(browseFiles())); m_brFile->setToolTip(tr("Browse to a file")); - } + } if (lm&ListDir) { m_brDir = toolBar->addAction(QIcon(QString::fromLatin1(":/images/folder.png")),QString(), @@ -78,9 +78,9 @@ InputStrList::InputStrList( QGridLayout *layout,int &row, m_value = m_strList; - connect(m_le, SIGNAL(returnPressed()), + connect(m_le, SIGNAL(returnPressed()), this, SLOT(addString()) ); - connect(m_lb, SIGNAL(currentTextChanged(const QString &)), + connect(m_lb, SIGNAL(currentTextChanged(const QString &)), this, SLOT(selectText(const QString &))); connect( m_lab, SIGNAL(enter()), SLOT(help()) ); connect( m_lab, SIGNAL(reset()), SLOT(reset()) ); @@ -154,7 +154,7 @@ void InputStrList::browseFiles() QString path = QFileInfo(MainWindow::instance().configFileName()).path(); QStringList fileNames = QFileDialog::getOpenFileNames(); - if (!fileNames.isEmpty()) + if (!fileNames.isEmpty()) { QStringList::Iterator it; for ( it= fileNames.begin(); it != fileNames.end(); ++it ) @@ -184,7 +184,7 @@ void InputStrList::browseDir() QString path = QFileInfo(MainWindow::instance().configFileName()).path(); QString dirName = QFileDialog::getExistingDirectory(); - if (!dirName.isNull()) + if (!dirName.isNull()) { QDir dir(path); if (!MainWindow::instance().configFileName().isEmpty() && dir.exists()) @@ -228,9 +228,9 @@ void InputStrList::update() void InputStrList::updateDefault() { - if (m_strList==m_default || !m_lab->isEnabled()) + if (isDefault() || !m_lab->isEnabled()) { - m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt")); + m_lab->setText(QString::fromLatin1("<qt>")+m_id+QString::fromLatin1("</qt>")); } else { @@ -246,9 +246,9 @@ void InputStrList::reset() void InputStrList::writeValue(QTextStream &t,QTextCodec *codec) { bool first=true; - foreach (QString s, m_strList) + foreach (QString s, m_strList) { - if (!first) + if (!first) { t << " \\" << endl; t << " "; @@ -258,6 +258,50 @@ void InputStrList::writeValue(QTextStream &t,QTextCodec *codec) } } +#include <QMessageBox> +bool InputStrList::isDefault() +{ + bool isEq = m_strList==m_default; + + if (!isEq) + { + isEq = true; + + auto it1 = m_strList.begin(); + auto it2 = m_default.begin(); + while (it1!=m_strList.end() && it2!=m_default.end()) + { + // skip over empty values + while (it1!=m_strList.end() && (*it1).isEmpty()) + { + ++it1; + } + while (it2!=m_default.end() && (*it2).isEmpty()) + { + ++it2; + } + if ((it1!=m_strList.end()) && (it2!=m_default.end())) + { + if ((*it1).trimmed()!= (*it2).trimmed()) // difference so not the default + { + isEq=false; + break; + } + ++it1; + ++it2; + } + else if ((it1!=m_strList.end()) || (it2!=m_default.end())) + { + // one list empty so cannot be the default + isEq=false; + break; + } + } + } + + return isEq; +} + bool InputStrList::isEmpty() { foreach (QString s, m_strList) diff --git a/addon/doxywizard/inputstrlist.h b/addon/doxywizard/inputstrlist.h index adb0fb0..d2e713d 100644 --- a/addon/doxywizard/inputstrlist.h +++ b/addon/doxywizard/inputstrlist.h @@ -51,6 +51,7 @@ class InputStrList : public QObject, public Input void addDependency(Input *) { Q_ASSERT(false); } void setEnabled(bool); void updateDependencies() {} + bool isDefault(); void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } bool isEmpty(); diff --git a/addon/doxywizard/wizard.cpp b/addon/doxywizard/wizard.cpp index c3c1b57..6be752f 100644..100755 --- a/addon/doxywizard/wizard.cpp +++ b/addon/doxywizard/wizard.cpp @@ -3,8 +3,8 @@ * 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. * @@ -47,6 +47,7 @@ #define STR_OPTIMIZE_OUTPUT_JAVA QString::fromLatin1("OPTIMIZE_OUTPUT_JAVA") #define STR_OPTIMIZE_FOR_FORTRAN QString::fromLatin1("OPTIMIZE_FOR_FORTRAN") #define STR_OPTIMIZE_OUTPUT_VHDL QString::fromLatin1("OPTIMIZE_OUTPUT_VHDL") +#define STR_OPTIMIZE_OUTPUT_SLICE QString::fromLatin1("OPTIMIZE_OUTPUT_SLICE") #define STR_CPP_CLI_SUPPORT QString::fromLatin1("CPP_CLI_SUPPORT") #define STR_HIDE_SCOPE_NAMES QString::fromLatin1("HIDE_SCOPE_NAMES") #define STR_EXTRACT_ALL QString::fromLatin1("EXTRACT_ALL") @@ -56,6 +57,7 @@ #define STR_GENERATE_MAN QString::fromLatin1("GENERATE_MAN") #define STR_GENERATE_RTF QString::fromLatin1("GENERATE_RTF") #define STR_GENERATE_XML QString::fromLatin1("GENERATE_XML") +#define STR_GENERATE_DOCBOOK QString::fromLatin1("GENERATE_DOCBOOK") #define STR_GENERATE_HTMLHELP QString::fromLatin1("GENERATE_HTMLHELP") #define STR_GENERATE_TREEVIEW QString::fromLatin1("GENERATE_TREEVIEW") #define STR_USE_PDFLATEX QString::fromLatin1("USE_PDFLATEX") @@ -74,7 +76,7 @@ #define STR_HTML_COLORSTYLE_SAT QString::fromLatin1("HTML_COLORSTYLE_SAT") #define STR_HTML_COLORSTYLE_GAMMA QString::fromLatin1("HTML_COLORSTYLE_GAMMA") -static bool g_optimizeMapping[6][6] = +static bool g_optimizeMapping[7][7] = { // A: OPTIMIZE_OUTPUT_FOR_C // B: OPTIMIZE_OUTPUT_JAVA @@ -82,23 +84,26 @@ static bool g_optimizeMapping[6][6] = // D: OPTIMIZE_OUTPUT_VHDL // E: CPP_CLI_SUPPORT // F: HIDE_SCOPE_NAMES - // A B C D E F - { false,false,false,false,false,false }, // 0: C++ - { false,false,false,false,true, false }, // 1: C++/CLI - { false,true, false,false,false,false }, // 2: C#/Java - { true, false,false,false,false,true }, // 3: C/PHP - { false,false,true, false,false,false }, // 4: Fortran - { false,false,false,true, false,false }, // 5: VHDL + // G: OPTIMIZE_OUTPUT_SLICE + // A B C D E F G + { false,false,false,false,false,false,false }, // 0: C++ + { false,false,false,false,true, false,false }, // 1: C++/CLI + { false,true, false,false,false,false,false }, // 2: C#/Java + { true, false,false,false,false,true, false }, // 3: C/PHP + { false,false,true, false,false,false,false }, // 4: Fortran + { false,false,false,true, false,false,false }, // 5: VHDL + { false,false,false,false,false,false,true }, // 6: SLICE }; -static QString g_optimizeOptionNames[6] = +static QString g_optimizeOptionNames[7] = { STR_OPTIMIZE_OUTPUT_FOR_C, STR_OPTIMIZE_OUTPUT_JAVA, STR_OPTIMIZE_FOR_FORTRAN, STR_OPTIMIZE_OUTPUT_VHDL, STR_CPP_CLI_SUPPORT, - STR_HIDE_SCOPE_NAMES + STR_HIDE_SCOPE_NAMES, + STR_OPTIMIZE_OUTPUT_SLICE }; //========================================================================== @@ -107,7 +112,7 @@ static bool stringVariantToBool(const QVariant &v) { QString s = v.toString().toLower(); return s==QString::fromLatin1("yes") || s==QString::fromLatin1("true") || s==QString::fromLatin1("1"); -} +} static bool getBoolOption( const QHash<QString,Input*>&model,const QString &name) @@ -115,7 +120,7 @@ static bool getBoolOption( Input *option = model[name]; Q_ASSERT(option!=0); return stringVariantToBool(option->value()); -} +} static int getIntOption( const QHash<QString,Input*>&model,const QString &name) @@ -123,7 +128,7 @@ static int getIntOption( Input *option = model[name]; Q_ASSERT(option!=0); return option->value().toInt(); -} +} static QString getStringOption( const QHash<QString,Input*>&model,const QString &name) @@ -343,19 +348,19 @@ void ColorPicker::paintEvent(QPaintEvent*) QRect r(0, foff, w, height() - 2*foff); int wi = r.width() - 2; int hi = r.height() - 2; - if (!m_pix || m_pix->height() != hi || m_pix->width() != wi) + if (!m_pix || m_pix->height() != hi || m_pix->width() != wi) { delete m_pix; QImage img(wi, hi, QImage::Format_RGB32); int y; uint *pixel = (uint *) img.scanLine(0); - for (y = 0; y < hi; y++) + for (y = 0; y < hi; y++) { const uint *end = pixel + wi; int yh = y2hue(y+coff); int ys = y2sat(y+coff); int yg = y2gam(y+coff); - while (pixel < end) + while (pixel < end) { QColor c; c.setHsv(yh, ys, (int)(255*pow(0.7,yg/100.0))); @@ -372,7 +377,7 @@ void ColorPicker::paintEvent(QPaintEvent*) p.setPen(g.windowText().color()); p.setBrush(g.windowText()); QPolygon a; - int y = m_mode==Hue ? hue2y(m_hue) : + int y = m_mode==Hue ? hue2y(m_hue) : m_mode==Saturation ? sat2y(m_sat) : gam2y(m_gam); a.setPoints(3, w, y, w+5, y+5, w+5, y-5); @@ -382,14 +387,14 @@ void ColorPicker::paintEvent(QPaintEvent*) void ColorPicker::mouseMoveEvent(QMouseEvent *m) { - if (m_mode==Hue) setHue(y2hue(m->y())); + if (m_mode==Hue) setHue(y2hue(m->y())); else if (m_mode==Saturation) setSat(y2sat(m->y())); else setGam(y2gam(m->y())); } void ColorPicker::mousePressEvent(QMouseEvent *m) { - if (m_mode==Hue) setHue(y2hue(m->y())); + if (m_mode==Hue) setHue(y2hue(m->y())); else if (m_mode==Saturation) setSat(y2sat(m->y())); else setGam(y2gam(m->y())); } @@ -530,7 +535,7 @@ Step1::Step1(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(w QFrame *f = new QFrame( this ); f->setFrameStyle( QFrame::HLine | QFrame::Sunken ); layout->addWidget(f); - + l = new QLabel(this); l->setText(tr("Specify the directory to scan for source code")); layout->addWidget(l); @@ -602,7 +607,7 @@ void Step1::selectProjectIcon() else { QFile Fout(iconName); - if(!Fout.exists()) + if(!Fout.exists()) { m_projIconLab->setText(tr("Sorry, cannot find file(")+iconName+QString::fromLatin1(");")); } @@ -711,7 +716,7 @@ void Step1::init() if (!iconName.isEmpty()) { QFile Fout(iconName); - if(!Fout.exists()) + if(!Fout.exists()) { m_projIconLab->setText(tr("Sorry, cannot find file(")+iconName+QString::fromLatin1(");")); } @@ -745,7 +750,7 @@ void Step1::init() //========================================================================== -Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) +Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(wizard), m_modelData(modelData) { QRadioButton *r; @@ -770,7 +775,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // m_crossRef -> SOURCE_BROWSER = YES/NO gbox->addWidget(m_crossRef,3,0); layout->addWidget(m_extractMode); - + //--------------------------------------------------- QFrame *f = new QFrame( this ); f->setFrameStyle( QFrame::HLine | QFrame::Sunken ); @@ -779,8 +784,8 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) m_optimizeLangGroup = new QButtonGroup(this); m_optimizeLang = new QGroupBox(this); m_optimizeLang->setTitle(tr("Select programming language to optimize the results for")); - gbox = new QGridLayout( m_optimizeLang ); - + gbox = new QGridLayout( m_optimizeLang ); + r = new QRadioButton(m_optimizeLang); r->setText(tr("Optimize for C++ output")); r->setChecked(true); @@ -791,6 +796,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,0,0); r = new QRadioButton(tr("Optimize for C++/CLI output")); gbox->addWidget(r,1,0); @@ -801,6 +807,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = YES // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO r = new QRadioButton(tr("Optimize for Java or C# output")); m_optimizeLangGroup->addButton(r, 2); // 2 -> OPTIMIZE_OUTPUT_FOR_C = NO @@ -809,6 +816,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,2,0); r = new QRadioButton(tr("Optimize for C or PHP output")); m_optimizeLangGroup->addButton(r, 3); @@ -818,6 +826,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = YES + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,3,0); r = new QRadioButton(tr("Optimize for Fortran output")); m_optimizeLangGroup->addButton(r, 4); @@ -827,6 +836,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = NO // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,4,0); r = new QRadioButton(tr("Optimize for VHDL output")); m_optimizeLangGroup->addButton(r, 5); @@ -836,7 +846,18 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) // OPTIMIZE_OUTPUT_VHDL = YES // CPP_CLI_SUPPORT = NO // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = NO gbox->addWidget(r,5,0); + r = new QRadioButton(tr("Optimize for SLICE output")); + m_optimizeLangGroup->addButton(r, 6); + // 5 -> OPTIMIZE_OUTPUT_FOR_C = NO + // OPTIMIZE_OUTPUT_JAVA = NO + // OPTIMIZE_FOR_FORTRAN = NO + // OPTIMIZE_OUTPUT_VHDL = NO + // CPP_CLI_SUPPORT = NO + // HIDE_SCOPE_NAMES = NO + // OPTIMIZE_OUTPUT_SLICE = YES + gbox->addWidget(r,6,0); layout->addWidget(m_optimizeLang); layout->addStretch(1); @@ -852,7 +873,7 @@ Step2::Step2(Wizard *wizard,const QHash<QString,Input*> &modelData) void Step2::optimizeFor(int choice) { - for (int i=0;i<6;i++) + for (int i=0;i<7;i++) { updateBoolOption(m_modelData, g_optimizeOptionNames[i], @@ -882,12 +903,13 @@ void Step2::init() else if (getBoolOption(m_modelData,STR_OPTIMIZE_OUTPUT_FOR_C)) x=3; else if (getBoolOption(m_modelData,STR_OPTIMIZE_FOR_FORTRAN)) x=4; else if (getBoolOption(m_modelData,STR_OPTIMIZE_OUTPUT_VHDL)) x=5; + else if (getBoolOption(m_modelData,STR_OPTIMIZE_OUTPUT_SLICE)) x=6; m_optimizeLangGroup->button(x)->setChecked(true); } //========================================================================== -Step3::Step3(Wizard *wizard,const QHash<QString,Input*> &modelData) +Step3::Step3(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(wizard), m_modelData(modelData) { QVBoxLayout *vbox = 0; @@ -957,16 +979,20 @@ Step3::Step3(Wizard *wizard,const QHash<QString,Input*> &modelData) // GENERATE_RTF m_xmlEnabled=new QCheckBox(tr("XML")); // GENERATE_XML + m_docbookEnabled=new QCheckBox(tr("Docbook")); + // GENERATE_DOCBOOK gbox->addWidget(m_manEnabled,3,0); gbox->addWidget(m_rtfEnabled,4,0); gbox->addWidget(m_xmlEnabled,5,0); + gbox->addWidget(m_docbookEnabled,6,0); - gbox->setRowStretch(6,1); + gbox->setRowStretch(7,1); connect(m_htmlOptions,SIGNAL(toggled(bool)),SLOT(setHtmlEnabled(bool))); connect(m_texOptions,SIGNAL(toggled(bool)),SLOT(setLatexEnabled(bool))); connect(m_manEnabled,SIGNAL(stateChanged(int)),SLOT(setManEnabled(int))); connect(m_rtfEnabled,SIGNAL(stateChanged(int)),SLOT(setRtfEnabled(int))); connect(m_xmlEnabled,SIGNAL(stateChanged(int)),SLOT(setXmlEnabled(int))); + connect(m_docbookEnabled,SIGNAL(stateChanged(int)),SLOT(setDocbookEnabled(int))); connect(m_searchEnabled,SIGNAL(stateChanged(int)),SLOT(setSearchEnabled(int))); connect(m_htmlOptionsGroup,SIGNAL(buttonClicked(int)), SLOT(setHtmlOptions(int))); @@ -1014,6 +1040,11 @@ void Step3::setXmlEnabled(int state) updateBoolOption(m_modelData,STR_GENERATE_XML,state==Qt::Checked); } +void Step3::setDocbookEnabled(int state) +{ + updateBoolOption(m_modelData,STR_GENERATE_DOCBOOK,state==Qt::Checked); +} + void Step3::setSearchEnabled(int state) { updateBoolOption(m_modelData,STR_SEARCHENGINE,state==Qt::Checked); @@ -1064,6 +1095,7 @@ void Step3::init() m_manEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_MAN)); m_rtfEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_RTF)); m_xmlEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_XML)); + m_docbookEnabled->setChecked(getBoolOption(m_modelData,STR_GENERATE_DOCBOOK)); m_searchEnabled->setChecked(getBoolOption(m_modelData,STR_SEARCHENGINE)); if (getBoolOption(m_modelData,STR_GENERATE_HTMLHELP)) { @@ -1093,7 +1125,7 @@ void Step3::init() //========================================================================== -Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData) +Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData) : m_wizard(wizard), m_modelData(modelData) { m_diagramModeGroup = new QButtonGroup(this); @@ -1116,7 +1148,7 @@ Step4::Step4(Wizard *wizard,const QHash<QString,Input*> &modelData) m_dotGroup = new QGroupBox(tr("Dot graphs to generate")); QVBoxLayout *vbox = new QVBoxLayout; - m_dotClass=new QCheckBox(tr("Class diagrams")); + m_dotClass=new QCheckBox(tr("Class graphs")); // CLASS_GRAPH m_dotCollaboration=new QCheckBox(tr("Collaboration diagrams")); // COLLABORATION_GRAPH @@ -1250,7 +1282,7 @@ void Step4::init() //========================================================================== -Wizard::Wizard(const QHash<QString,Input*> &modelData, QWidget *parent) : +Wizard::Wizard(const QHash<QString,Input*> &modelData, QWidget *parent) : QSplitter(parent), m_modelData(modelData) { m_treeWidget = new QTreeWidget; @@ -1303,7 +1335,7 @@ void Wizard::activateTopic(QTreeWidgetItem *item,QTreeWidgetItem *) { if (item) { - + QString label = item->text(0); if (label==tr("Project")) { diff --git a/addon/doxywizard/wizard.h b/addon/doxywizard/wizard.h index 8b877e1..d4fbba3 100644 --- a/addon/doxywizard/wizard.h +++ b/addon/doxywizard/wizard.h @@ -162,6 +162,7 @@ class Step3 : public QWidget void setManEnabled(int); void setRtfEnabled(int); void setXmlEnabled(int); + void setDocbookEnabled(int); void setSearchEnabled(int); void setHtmlOptions(int); void setLatexOptions(int); @@ -177,6 +178,7 @@ class Step3 : public QWidget QCheckBox *m_manEnabled = 0; QCheckBox *m_rtfEnabled = 0; QCheckBox *m_xmlEnabled = 0; + QCheckBox *m_docbookEnabled = 0; QCheckBox *m_searchEnabled = 0; QPushButton *m_tuneColor = 0; Wizard *m_wizard = 0; diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 7969be0..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,60 +0,0 @@ -image: Visual Studio 2017 - -configuration: - - Release - - Debug - -platform: - - x64 - - Win32 - -environment: - # VS VERSION IN CMAKE STYLE - matrix: - - VSVERSION: "15 2017" - - VSVERSION: "14 2015" - -cache: - - C:\Users\Appveyor\.conan -> appveyor.yml - - c:\.conan -> appveyor.yml - - '%LOCALAPPDATA%\pip\Cache -> appveyor.yml' - - C:\miktex-repository -> appveyor.yml - - -init: - - cmake --version - - perl --version - - msbuild /version - -install: - # Static url: https://github.com/MiKTeX/miktex/issues/321#issuecomment-496286866 - # The setup is small enough, and does not need to be cached - - appveyor-retry appveyor DownloadFile https://miktex.org/download/win/miktexsetup-x64.zip - - 7z e miktexsetup-x64.zip - - appveyor-retry miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential download - - miktexsetup.exe --local-package-repository=C:\miktex-repository --package-set=essential --shared install - - refreshenv - - pip install conan - - ps: | - "[requires] - libxml2/2.9.8@bincrafters/stable - winflexbison/2.5.16@bincrafters/stable" | Out-File -Encoding ASCII -FilePath conanfile.txt - - conan install . -g virtualrunenv --build missing - - activate_run.bat - -before_build: - - if "%platform%"=="Win32" ( set "CMAKE_GENERATOR_NAME=Visual Studio %VSVERSION%" ) - - if "%platform%"=="x64" ( set "CMAKE_GENERATOR_NAME=Visual Studio %VSVERSION% Win64") - - mkdir build - - cd build - - cmake -G "%CMAKE_GENERATOR_NAME%" .. - -build: - project: "build\\PACKAGE.vcxproj" - parallel: false - -test_script: - - msbuild "testing\tests.vcxproj" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" -# Disabled building document due to unreliable MikTeX installation -# - cmake -G "%CMAKE_GENERATOR_NAME%" -D build_doc=ON .. -# - msbuild "doc\docs.vcxproj" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" diff --git a/cmake/Coverage.cmake b/cmake/Coverage.cmake index 31f8341..ce7d431 100644 --- a/cmake/Coverage.cmake +++ b/cmake/Coverage.cmake @@ -7,23 +7,23 @@ if(enable_coverage) CACHE INTERNAL "") add_custom_target(coverage-clean COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --zerocounters - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ) add_custom_target(coverage COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --capture --output-file cov.info COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --remove cov.info '*/c++/*' '*/_ctype.h' '*/generated_src/*' --output-file cov.info.cleaned - COMMAND ${CMAKE_COMMAND} -Dsearch=${CMAKE_BINARY_DIR} - -Dreplace=${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -Dsearch=${PROJECT_BINARY_DIR} + -Dreplace=${PROJECT_SOURCE_DIR} -Dsrc=cov.info.cleaned -Ddst=cov.info.final - -P ${CMAKE_SOURCE_DIR}/cmake/SearchReplace.cmake + -P ${PROJECT_SOURCE_DIR}/cmake/SearchReplace.cmake COMMAND ${GENHTML_PATH} --rc genhtml_branch_coverage=1 --function-coverage --branch-coverage --title "Doxygen Coverage Report" --num-spaces 2 - --legend --prefix ${CMAKE_SOURCE_DIR} --demangle-cpp + --legend --prefix ${PROJECT_SOURCE_DIR} --demangle-cpp --output-directory cov_output cov.info.final COMMAND ${CMAKE_COMMAND} -E remove cov.info cov.info.cleaned cov.info.final - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} ) add_custom_command(TARGET coverage POST_BUILD COMMAND ; diff --git a/cmake/FindXapian.cmake b/cmake/Findxapian.cmake index 6109d7f..33726cf 100644 --- a/cmake/FindXapian.cmake +++ b/cmake/Findxapian.cmake @@ -1,4 +1,4 @@ -# Find Xapian search engine library +# Find xapian search engine library # # XAPIAN_FOUND - system has Xapian # XAPIAN_INCLUDE_DIR - the Xapian include directory @@ -11,7 +11,7 @@ if(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES) # Already in cache, be silent - set(Xapian_FIND_QUIETLY TRUE) + set(xapian_FIND_QUIETLY TRUE) endif(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES) FIND_PATH(XAPIAN_INCLUDE_DIR xapian/version.h) @@ -25,16 +25,16 @@ ELSE(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES) ENDIF(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES) IF(XAPIAN_FOUND) - IF(NOT Xapian_FIND_QUIETLY) - MESSAGE(STATUS "Found Xapian: ${XAPIAN_LIBRARIES}") - ENDIF(NOT Xapian_FIND_QUIETLY) + IF(NOT xapian_FIND_QUIETLY) + MESSAGE(STATUS "Found xapian: ${XAPIAN_LIBRARIES}") + ENDIF(NOT xapian_FIND_QUIETLY) ELSE(XAPIAN_FOUND) - IF(Xapian_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find Xapian") - ENDIF(Xapian_FIND_REQUIRED) - IF(NOT Xapian_FIND_QUIETLY) - MESSAGE(STATUS "Could not find Xapian") - ENDIF(NOT Xapian_FIND_QUIETLY) + IF(xapian_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find xapian") + ENDIF(xapian_FIND_REQUIRED) + IF(NOT xapian_FIND_QUIETLY) + MESSAGE(STATUS "Could not find xapian") + ENDIF(NOT xapian_FIND_QUIETLY) ENDIF(XAPIAN_FOUND) # show the XAPIAN_INCLUDE_DIR and XAPIAN_LIBRARIES variables only in the advanced view diff --git a/cmake/doxygen_version.cmake b/cmake/doxygen_version.cmake index 2433889..0797cac 100644 --- a/cmake/doxygen_version.cmake +++ b/cmake/doxygen_version.cmake @@ -40,7 +40,7 @@ endmacro() CHECK_REQUIRED_VARIABLE(PRE_CONFIGURE_DOXYGEN_VERSION_FILE) CHECK_REQUIRED_VARIABLE(POST_CONFIGURE_DOXYGEN_VERSION_FILE) -CHECK_OPTIONAL_VARIABLE(DOXY_STATE_FILE "${CMAKE_SOURCE_DIR}/VERSION") +CHECK_OPTIONAL_VARIABLE(DOXY_STATE_FILE "${PROJECT_SOURCE_DIR}/VERSION") # Function: DoxygenStateChangedAction # Description: this function is executed when the diff --git a/cmake/git_watcher.cmake b/cmake/git_watcher.cmake index ac34c1d..da1a68f 100644 --- a/cmake/git_watcher.cmake +++ b/cmake/git_watcher.cmake @@ -64,7 +64,7 @@ CHECK_REQUIRED_VARIABLE(PRE_CONFIGURE_GIT_VERSION_FILE) CHECK_REQUIRED_VARIABLE(POST_CONFIGURE_GIT_VERSION_FILE) CHECK_OPTIONAL_VARIABLE(GIT_STATE_FILE "${GENERATED_SRC}/git_state") #CHECK_REQUIRED_VARIABLE(GIT_STATE_FILE) -CHECK_OPTIONAL_VARIABLE(GIT_WORKING_DIR "${CMAKE_SOURCE_DIR}") +CHECK_OPTIONAL_VARIABLE(GIT_WORKING_DIR "${PROJECT_SOURCE_DIR}") # Check the optional git variable. # If it's not set, we'll try to find it using the CMake packaging system. diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index a094c57..f2d177e 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -44,14 +44,27 @@ set(DOC_FILES doxygen_manual.css doxygen_usage.doc doxywizard_expert.png - doxywizard.gif doxywizard_main.png - doxywizard_menu.png + doxywizard_menu_file.png + doxywizard_menu_settings.png + doxywizard_menu_help.png doxywizard_page1.png doxywizard_page2.png doxywizard_page3.png doxywizard_page4.png + doxywizard_run.png doxywizard_usage.doc + expert_bool.png + expert_enum.png + expert_int.png + expert_list_dir.png + expert_list_file.png + expert_list_filedir.png + expert_list_string.png + expert_string_dir.png + expert_string_file.png + expert_string_image.png + expert_string_string.png external.doc extsearch.doc extsearch_flow.dot @@ -88,6 +101,14 @@ set(DOC_FILES doxygen_logo.svg ) +set(DOC_FILES_IMAGES + add.png + del.png + file.png + folder.png + refresh.png +) + if (build_doc_chm) set(DOC_FILES_CHM Doxyfile_chm @@ -103,37 +124,47 @@ endif() file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/man ${PROJECT_BINARY_DIR}/src - ${PROJECT_BINARY_DIR}/doc) + ${PROJECT_BINARY_DIR}/doc + ${PROJECT_BINARY_DIR}/doc/images) foreach (f ${DOC_FILES}) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f} - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/ - DEPENDS ${CMAKE_SOURCE_DIR}/doc/${f} + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/ + DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f} ) set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1) list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/${f}") endforeach() +foreach (f ${DOC_FILES_IMAGES}) +add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/images/${f} + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f} ${PROJECT_BINARY_DIR}/doc/images/ + DEPENDS ${PROJECT_SOURCE_DIR}/addon/doxywizard/images/${f} + ) +set_source_files_properties(${PROJECT_BINARY_DIR}/doc/images/${f} PROPERTIES GENERATED 1) +list(APPEND OUT_DOC_FILES "${PROJECT_BINARY_DIR}/doc/images/${f}") +endforeach() + foreach (f ${DOC_FILES_CHM}) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/doc/${f} - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/ - DEPENDS ${CMAKE_SOURCE_DIR}/doc/${f} + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/${f} ${PROJECT_BINARY_DIR}/doc/ + DEPENDS ${PROJECT_SOURCE_DIR}/doc/${f} ) set_source_files_properties(${PROJECT_BINARY_DIR}/doc/${f} PROPERTIES GENERATED 1) list(APPEND OUT_DOC_CHM_FILES "${PROJECT_BINARY_DIR}/doc/${f}") endforeach() -configure_file(${CMAKE_SOURCE_DIR}/doc/manual.sty ${PROJECT_BINARY_DIR}/doc/manual.sty) -configure_file(${CMAKE_SOURCE_DIR}/doc/doxygen_manual.tex ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex) -configure_file(${CMAKE_SOURCE_DIR}/doc/doxygen.1 ${PROJECT_BINARY_DIR}/man/doxygen.1) -configure_file(${CMAKE_SOURCE_DIR}/doc/doxywizard.1 ${PROJECT_BINARY_DIR}/man/doxywizard.1) -configure_file(${CMAKE_SOURCE_DIR}/doc/doxysearch.1 ${PROJECT_BINARY_DIR}/man/doxysearch.1) -configure_file(${CMAKE_SOURCE_DIR}/doc/doxyindexer.1 ${PROJECT_BINARY_DIR}/man/doxyindexer.1) +configure_file(${PROJECT_SOURCE_DIR}/doc/manual.sty ${PROJECT_BINARY_DIR}/doc/manual.sty) +configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen_manual.tex ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex) +configure_file(${PROJECT_SOURCE_DIR}/doc/doxygen.1 ${PROJECT_BINARY_DIR}/man/doxygen.1) +configure_file(${PROJECT_SOURCE_DIR}/doc/doxywizard.1 ${PROJECT_BINARY_DIR}/man/doxywizard.1) +configure_file(${PROJECT_SOURCE_DIR}/doc/doxysearch.1 ${PROJECT_BINARY_DIR}/man/doxysearch.1) +configure_file(${PROJECT_SOURCE_DIR}/doc/doxyindexer.1 ${PROJECT_BINARY_DIR}/man/doxyindexer.1) # doc/language.doc (see tag Doxyfile:INPUT) add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} translator.py ${CMAKE_SOURCE_DIR} - DEPENDS ${CMAKE_SOURCE_DIR}/doc/maintainers.txt ${CMAKE_SOURCE_DIR}/doc/language.tpl ${PROJECT_BINARY_DIR}/doc/translator.py ${LANG_FILES} + COMMAND ${PYTHON_EXECUTABLE} translator.py ${PROJECT_SOURCE_DIR} + DEPENDS ${PROJECT_SOURCE_DIR}/doc/maintainers.txt ${PROJECT_SOURCE_DIR}/doc/language.tpl ${PROJECT_BINARY_DIR}/doc/translator.py ${LANG_FILES} OUTPUT language.doc WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/doc ) @@ -163,7 +194,7 @@ add_custom_target(doxygen_pdf COMMAND ${CMAKE_COMMAND} -E remove refman.tex COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/doxygen_manual.tex . COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/doc/manual.sty . - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/doc/doxygen_logo.pdf . + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/doc/doxygen_logo.pdf . COMMAND ${PDFLATEX} -shell-escape doxygen_manual.tex COMMAND ${MAKEINDEX} doxygen_manual.idx COMMAND ${PDFLATEX} -shell-escape doxygen_manual.tex diff --git a/doc/Doxyfile b/doc/Doxyfile index dd67958..caf6229 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -32,7 +32,7 @@ HTML_COLORSTYLE_SAT = 0 ENABLED_SECTIONS = logo_on ENABLE_PREPROCESSING = NO CASE_SENSE_NAMES = NO -IMAGE_PATH = . +IMAGE_PATH = . images INPUT = index.doc install.doc starting.doc docblocks.doc markdown.doc \ lists.doc grouping.doc formulas.doc tables.doc diagrams.doc preprocessing.doc \ autolink.doc output.doc searching.doc extsearch.doc customize.doc custcmd.doc \ @@ -53,6 +53,8 @@ HTML_STYLESHEET = doxygen_manual.css HTML_EXTRA_FILES = doxygen_logo.svg ALIASES = LaTeX="\f$\mbox{\LaTeX}\f$" ALIASES += TeX="\f$\mbox{\TeX}\f$" +ALIASES += forceNewPage="\latexonly \newpage \endlatexonly" LATEX_BATCHMODE = YES LATEX_EXTRA_STYLESHEET = manual.sty LATEX_EMOJI_DIRECTORY = ../doc +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/doc/arch.doc b/doc/arch.doc index 104b3e3..eb39d70 100644 --- a/doc/arch.doc +++ b/doc/arch.doc @@ -209,12 +209,12 @@ if (!-e "../src/${file}.l") exit 1; } system("touch ../src/${file}.l"); -unless (rename "src/CMakeFiles/_doxygen.dir/build.make","src/CMakeFiles/_doxygen.dir/build.make.old") { - print STDERR "Error: cannot rename src/CMakeFiles/_doxygen.dir/build.make!\n"; +unless (rename "src/CMakeFiles/doxymain.dir/build.make","src/CMakeFiles/doxymain.dir/build.make.old") { + print STDERR "Error: cannot rename src/CMakeFiles/doxymain.dir/build.make!\n"; exit 1; } -if (open(F,"<src/CMakeFiles/_doxygen.dir/build.make.old")) { - unless (open(G,">src/CMakeFiles/_doxygen.dir/build.make")) { +if (open(F,"<src/CMakeFiles/doxymain.dir/build.make.old")) { + unless (open(G,">src/CMakeFiles/doxymain.dir/build.make")) { print STDERR "Error: opening file build.make for writing\n"; exit 1; } @@ -229,10 +229,10 @@ if (open(F,"<src/CMakeFiles/_doxygen.dir/build.make.old")) { print G "$_"; } close F; - unlink "src/CMakeFiles/_doxygen.dir/build.make.old"; + unlink "src/CMakeFiles/doxymain.dir/build.make.old"; } else { - print STDERR "Warning file src/CMakeFiles/_doxygen.dir/build.make does not exist!\n"; + print STDERR "Warning file src/CMakeFiles/doxymain.dir/build.make does not exist!\n"; } # touch the file diff --git a/doc/changelog.doc b/doc/changelog.doc index b5ea41a..0af6fd7 100755..100644 --- a/doc/changelog.doc +++ b/doc/changelog.doc @@ -1,5 +1,275 @@ /** \page changelog Changelog \tableofcontents{html,latex} +\section log_1_9 1.9 Series + +\subsection log_1_9_0 Release 1.9.0 +\htmlonly +<b>(release date 27-12-2020)</b> +</p> +<h3>Bug fixes</h3> +<ul> +<li>issue #697: Test 32 reference to bell signal (XHTML, LaTeX) [<a href="https://github.com/doxygen/doxygen/commit/06eb8c6edcb0df79717f9cf3afb4061b57157382">view</a>]</li> +<li>issue #7976: bug_786382 Unmatched single quote in C++ source breaks aliases [<a href="https://github.com/doxygen/doxygen/commit/942fcfaf391d1213bee26e43249fea8da723d714">view</a>]</li> +<li>issue #6442: C++: Trailing return type syntax + void [<a href="https://github.com/doxygen/doxygen/commit/74d43fa25c5db5c1b0fc6ed45a725aaee972b1b7">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/d6567641ef09bc125e3b722db7a202c12bf27913">view</a>]</li> +<li>issue #6471: Out-of-line documentation of scoped enums [<a href="https://github.com/doxygen/doxygen/commit/9bf7658013e49dabaafb818a639b5ca62f845538">view</a>]</li> +<li>issue #7471: [1.8.16 regression] multiple use of page label [<a href="https://github.com/doxygen/doxygen/commit/ae4e0e0e55bbadc6621ba25a095eb90458ae818e">view</a>]</li> +<li>issue #7547: Fix permodgen issue [<a href="https://github.com/doxygen/doxygen/commit/d75a287f2c5fc37cde07006bec7d027453d9827b">view</a>]</li> +<li>issue #7556: ANSI-C anonymous (unnamed) struct/unions duplicated names [<a href="https://github.com/doxygen/doxygen/commit/7bd775a7d8c4d74ce075ba3bb399c5dbff08b325">view</a>]</li> +<li>issue #7706: Md5 hash does not match for two different runs [<a href="https://github.com/doxygen/doxygen/commit/c3d98a0794c8bd8246e06a21b41cd594bcdb3725">view</a>]</li> +<li>issue #7872: A define containing a doxygen start of comment breaks the parser [<a href="https://github.com/doxygen/doxygen/commit/f2de7e59db40daf9efde55bba111e9f4a98ef59f">view</a>]</li> +<li>issue #7927: PREDEFINED fails to replace argument [<a href="https://github.com/doxygen/doxygen/commit/075771fd46ee7e6e4c7572b84cff194e887eddf4">view</a>]</li> +<li>issue #7977: Broken ref for enum entry (doxygen 1.8.18 -> 1.8.19) [<a href="https://github.com/doxygen/doxygen/commit/63dc5b9b1b3e8fb875304a954e4df934b249034b">view</a>]</li> +<li>issue #7979: C++ enums being defined in multiple files after b265433 (multi-thread input processing) [<a href="https://github.com/doxygen/doxygen/commit/9d9d08582ccea7ef90000acebfd09f8c8acc577a">view</a>]</li> +<li>issue #7981: bug_647654 Special command \fn fails when first argument of PHP function is call-by-reference [<a href="https://github.com/doxygen/doxygen/commit/1d8610c90ba279bb207f0d45f96cef3054ff34eb">view</a>]</li> +<li>issue #7991: bug 789318 c# expression-bodied property is not rendered correctly [<a href="https://github.com/doxygen/doxygen/commit/e8c1817bdd8341da752f31259953d21e9d36418f">view</a>]</li> +<li>issue #7995: Doxygen doesn't handle very simple example in the .md file [<a href="https://github.com/doxygen/doxygen/commit/7c429806b072dd8bf777d93035ffda817976adc0">view</a>], and [<a href="https://github.com/doxygen/doxygen/commit/d3d9dd8540ec159de080859c8f34a2581c4147f0">view</a>]</li> +<li>issue #7996: \ref commands broken in markdown tables [<a href="https://github.com/doxygen/doxygen/commit/fa32d44f237ca9ebeaf0d4da6545c977c50ca34c">view</a>]</li> +<li>issue #8015: Special command \skip and \until no longer functional in ALIASES [<a href="https://github.com/doxygen/doxygen/commit/17d14c68608808e2688df8073294aec2094bf1fd">view</a>]</li> +<li>issue #8017: C++: mishandling of brackets used in trailing return types [<a href="https://github.com/doxygen/doxygen/commit/8cabc84a0f7b741e84aabe45c97f7aeca0eb53e0">view</a>]</li> +<li>issue #8022: Different results on 64 and 32 bit [<a href="https://github.com/doxygen/doxygen/commit/1fda77f54a2eacba32658001329bd9084f4df1e7">view</a>]</li> +<li>issue #8023: Add option to exit with non-zero exit code on warnings even if WARN_AS_ERROR is OFF [<a href="https://github.com/doxygen/doxygen/commit/b88e8097acdb30175c024ed47258739cec30f903">view</a>]</li> +<li>issue #8034: doxygen crashes [<a href="https://github.com/doxygen/doxygen/commit/d067baf495d0415283ce724ad32cb9a08dc17c83">view</a>]</li> +<li>issue #8037: Links using @ref stopped working in doxygen 1.8.19 [<a href="https://github.com/doxygen/doxygen/commit/dfc82af001c56254c6fde0affd009f80e19b1548">view</a>]</li> +<li>issue #8050: Artificial classDef confuses getCanonicalTypeForIdentifier() [<a href="https://github.com/doxygen/doxygen/commit/c5ffcd673f5fca4f9af96f92a0184ce287599a0f">view</a>], and [<a href="https://github.com/doxygen/doxygen/commit/d936554037ac9c46184cb55d118d0007144b6bd9">view</a>]</li> +<li>issue #8051: Consider documenting debug options of doxygen [<a href="https://github.com/doxygen/doxygen/commit/6d59324e04641955edfc2ba2001bd597afc5163a">view</a>]</li> +<li>issue #8053: error: Attribute target redefined in SVG [<a href="https://github.com/doxygen/doxygen/commit/ff021223c89995bf2abc4f33befddb1c97cab1d8">view</a>]</li> +<li>issue #8063: Failed to build current "master" branch [<a href="https://github.com/doxygen/doxygen/commit/b3720aec2c0251d246544c2b30d15b092c9c7c25">view</a>]</li> +<li>issue #8066: Doxygen crashes in ClangTUParser [<a href="https://github.com/doxygen/doxygen/commit/02b8dea10813606db4a013799a3e354368d0280f">view</a>]</li> +<li>issue #8070: C++: \var don't document enum class values [<a href="https://github.com/doxygen/doxygen/commit/4e75d77f60bd173019247177686376ce36ace90b">view</a>]</li> +<li>issue #8078: Warning and extra text when using Markdown as mainpage [<a href="https://github.com/doxygen/doxygen/commit/a05a7ae2e65b9e438327d4a50c81df18f2b49a4d">view</a>]</li> +<li>issue #8091: [C++] Newer doxygen versions add a lot of bogus warnings about undocumented entities [<a href="https://github.com/doxygen/doxygen/commit/01ded6f6963d4798ce1338246d6d946dbc3922d9">view</a>]</li> +<li>issue #8093: Some URLs in fresh/updated Doxyfile are split over two lines [<a href="https://github.com/doxygen/doxygen/commit/b1b9d28cdc4e43668df70d67f36d12c3d4e16d88">view</a>]</li> +<li>issue #8098: Python Decorator written below @brief tag and above the function leads to documentation error [<a href="https://github.com/doxygen/doxygen/commit/e31d4c8092bcac54b4b820b9d995fce8cd5a78c5">view</a>]</li> +<li>issue #8102: [C++] Reference relations are not generated for constructors using list initialization [<a href="https://github.com/doxygen/doxygen/commit/96378244a8b1874df95dd5983702e87f69b31a48">view</a>]</li> +<li>issue #8103: C++ Table of content, namespace list does not contains namespace without class [<a href="https://github.com/doxygen/doxygen/commit/e847d5dc322740b0097f56fc19311c8c74a44a55">view</a>], and [<a href="https://github.com/doxygen/doxygen/commit/33b0f4d25dff25b0e50d62eff68155106e88d58d">view</a>]</li> +<li>issue #8105: How do add (multiple files without extension) directory in INPUT field of doxygen configuration file [<a href="https://github.com/doxygen/doxygen/commit/6e14ace91c407293662c78ad88df1b91aebe9769">view</a>]</li> +<li>issue #8127: Java: xml output of preformatted (`<pre>`) block adds para-block for blank lines (hindering certain manual parsing) [<a href="https://github.com/doxygen/doxygen/commit/70abd648fd67d3588bc9d6e64f5eeaab575f515f">view</a>]</li> +<li>issue #8129: Image path is now case sensitive [<a href="https://github.com/doxygen/doxygen/commit/7bd4455f4fb17075eb23f5f24a5735913cde3e16">view</a>], and [<a href="https://github.com/doxygen/doxygen/commit/2b5a4541fb6f806c02a1f6e65a1ff2610f29751f">view</a>]</li> +<li>issue #8130: Markdown relative links - not working for other folders [<a href="https://github.com/doxygen/doxygen/commit/f674f5bbe7fdec97d8567b7256312d24a49ed924">view</a>]</li> +<li>issue #8132: Markdown inclusion of images broken after 39db9f48 [<a href="https://github.com/doxygen/doxygen/commit/add763fc5caf6d2be2316ee8c8270fa56940136a">view</a>]</li> +<li>issue #8137: Whitespace/Separator required to recognize custom command argument [<a href="https://github.com/doxygen/doxygen/commit/8b7993630f08ae499ebca0eb894451c89180199f">view</a>]</li> +<li>issue #8139: Segfault after a8bf5d3 [<a href="https://github.com/doxygen/doxygen/commit/e63311276e13bbd8ac304ba914bf14022fc1af40">view</a>]</li> +<li>issue #8142: UTF-8 in URL in source generates truncated URL in HTML [<a href="https://github.com/doxygen/doxygen/commit/c9ae8635949850562efe5ffc1524c84cb2b705cf">view</a>]</li> +<li>issue #8148: copydoc broken in private sections [<a href="https://github.com/doxygen/doxygen/commit/648b7f6f097e70d097405f6c9fc9e1111ce0d929">view</a>]</li> +<li>issue #8156: Markdown anchors do not work with special symbols [<a href="https://github.com/doxygen/doxygen/commit/eaf691cc82cb2c819bf61a48265d334464f2d831">view</a>]</li> +<li>issue #8160: Example in documentation of ALIASES shows using `\n` instead of `^^` [<a href="https://github.com/doxygen/doxygen/commit/9fb944fc99c2963fd010963a7e9f17a994195c6f">view</a>]</li> +<li>issue #8177: Incorrect inheritance with forward declared templated classes [<a href="https://github.com/doxygen/doxygen/commit/fa65bb38f81457d00f9c900bb57eb68bea59b1b4">view</a>]</li> +<li>issue #8184: Bad parsing of CMakeLists.txt [<a href="https://github.com/doxygen/doxygen/commit/5cc7fed36c8d3b45eec19b7333b494c1c649902f">view</a>]</li> +<li>issue #8186: Path resolving breaks on included @ sign [<a href="https://github.com/doxygen/doxygen/commit/ff27d22910eeec1861bea3c7cf9201a25e509f94">view</a>]</li> +<li>issue #8192: Excluded inline namespace broken after a5792da8 [<a href="https://github.com/doxygen/doxygen/commit/61f8521f768165e02a5f28df3fb442e3b91d170b">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/b2d009555ebce4a6802ac0255c056e880bdb45bd">view</a>]</li> +<li>Issue #8206: Incorrect XHTML results [<a href="https://github.com/doxygen/doxygen/commit/a292601d5d06cf5993247f2f7a6bc7306997da23">view</a>]</li> +<li>issue #8246: The prefix &#Ñ…202А; for files is displayed incorrectly in the file names. [<a href="https://github.com/doxygen/doxygen/commit/b4d2fccacc226f22f9e2ae0ed016895aceb92053">view</a>]</li> +<li>issue #8247: declaration different in cpp and h file of qstrncmp [<a href="https://github.com/doxygen/doxygen/commit/c5733d2e19f5de783e776dce05bd48f1a9e99c90">view</a>]</li> +<li>issue #8251: Macro stopped working in 1.8,.19 [<a href="https://github.com/doxygen/doxygen/commit/7b2e841b3a3d7d787458f236e2447c890cfbf590">view</a>]</li> +<li>issue #8269: Make failed when building layout.cpp [<a href="https://github.com/doxygen/doxygen/commit/e00dfd2d0ac20c4e25f6452242f65cd82faf9538">view</a>]</li> +<li>issue #8274: List entries for file & namespace enums (part 2) [<a href="https://github.com/doxygen/doxygen/commit/4a627283263247deccc125d072f23d93057b8a65">view</a>], and [<a href="https://github.com/doxygen/doxygen/commit/eb8b6f40d863a8d7d2798a95cbde4200e27d4945">view</a>]</li> +<li>issue #8143: copydoc in excluded namespace broken after d03e8d9 [<a href="https://github.com/doxygen/doxygen/commit/42d60bd97de0d1fbf85fdc9117e8dd46a026db1b">view</a>]</li> +<li>issue #8169: "\emoji heavy_check_mark" produces ✓ instead of ✔️ [<a href="https://github.com/doxygen/doxygen/commit/89e7f7c484af0a5a8cb4083a71958c3a16b0a951">view</a>]</li> +<li>Added missing protocols [<a href="https://github.com/doxygen/doxygen/commit/acc4b7e99cd05a78d1adbfdab1abc58db342c396">view</a>]</li> +<li>Avoid duplicate entry in the LaTeX output for inlined namespace [<a href="https://github.com/doxygen/doxygen/commit/f673a99a492397b3647ce07eb9537b8d1522a541">view</a>]</li> +<li>Concatenation of \param text and \details text [<a href="https://github.com/doxygen/doxygen/commit/ec5c07362270f6c088b831c2560f69b122c1ab5e">view</a>]</li> +<li>Confusing message for extension mapping for extension with starting dot. [<a href="https://github.com/doxygen/doxygen/commit/e2aae77981716d5234af8aa2d9aac68db8a161ed">view</a>]</li> +<li>Consistency for use class graphs / class diagrams [<a href="https://github.com/doxygen/doxygen/commit/eeedb6c479665095f69033eab23ab0d8b4d981b5">view</a>]</li> +<li>Create possibility to show in doxywizard "condensed" settings [<a href="https://github.com/doxygen/doxygen/commit/9f68f7f9932b349d65b6af6059807af55d2e535a">view</a>]</li> +<li>Creating link to not defined label in case of groups [<a href="https://github.com/doxygen/doxygen/commit/98fa1e02eb69d6738376bb2c5febd0078ca795b5">view</a>]</li> +<li>Default doxygen search mechanism doesn't work when using with XHTML output [<a href="https://github.com/doxygen/doxygen/commit/3655a0164951b5bce015196381267d2b878ab901">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/506a794bf146c0d9f46aac831170700822cb7675">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/bc3349e52752dafef47565c54c4145e43885f0d2">view</a>]</li> +<li>Docbook missing in doxywizard Wizard-Output page [<a href="https://github.com/doxygen/doxygen/commit/c1946161454322b92a3e2837c12a02f1a1de3a4a">view</a>]</li> +<li>Documentation correction for CASE_SENSE_NAMES [<a href="https://github.com/doxygen/doxygen/commit/1a7d56df56b4f93b539117c4f76c566da0f6e019">view</a>]</li> +<li>Don't start dvips when latex fails for formulas [<a href="https://github.com/doxygen/doxygen/commit/5b9a140ded861438b6b630b08f846dd73a60c585">view</a>]</li> +<li>Double "->" in warning in case of trailing return type [<a href="https://github.com/doxygen/doxygen/commit/8d976817a0a71411452f213e7c73ee9db1ba8d71">view</a>]</li> +<li>Doxygen crashes on Fortran [<a href="https://github.com/doxygen/doxygen/commit/7171bbba9259bc7d22e09454ca9d7381d13c94e2">view</a>]</li> +<li>Doxygen manual top rule is in uppercase. [<a href="https://github.com/doxygen/doxygen/commit/7a3d77897eafcd213197c9229c68429bb4396bbb">view</a>]</li> +<li>Doxygen's own documentation doesn't build with recent LaTeX version [<a href="https://github.com/doxygen/doxygen/commit/8d45cd1895ca7a9a53f9a02cdf7d66c239bdc504">view</a>]</li> +<li>Doxywizard expert page without settings [<a href="https://github.com/doxygen/doxygen/commit/169f7f0f02541f97ed080634df232e8cc8f3ded8">view</a>]</li> +<li>Enabling both ALLEXTERNALS and BUILTIN_STL_SUPPORT caused artificial STL classes to appear in the class hierarchy. [<a href="https://github.com/doxygen/doxygen/commit/169d71426d1a42ec294c451af5f901620e6d89e5">view</a>]</li> +<li>Exclude markdown mapped documentation files from Files list [<a href="https://github.com/doxygen/doxygen/commit/8a20dd6c10c08424dd0ead6e58c2f34d2f90c509">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/92e67d8955dc6360759abfc6debf6aae78ac539f">view</a>]</li> +<li>Expand non-recursive preprocessor macros [<a href="https://github.com/doxygen/doxygen/commit/6392703db8037e8a501e42d87c1c450c5c2ae95c">view</a>]</li> +<li>Fix for broken LaTeX output. [<a href="https://github.com/doxygen/doxygen/commit/502e03dad20b333748d73fdea4cf6d7cb0ab31a8">view</a>]</li> +<li>Fix too aggressive hyphenation of abbr. words. (#8026) [<a href="https://github.com/doxygen/doxygen/commit/58895b1763fbc2d09a180204c831cf204adb5e1c">view</a>]</li> +<li>Fixed marker replacement for a placeholder at the end of the command [<a href="https://github.com/doxygen/doxygen/commit/cbfc7f9e6a2532f58e736c2049b32bd231efade8">view</a>]</li> +<li>Fixed more issues handling Java nested generic classes [<a href="https://github.com/doxygen/doxygen/commit/c65daff57d905a2b89bde059e7ccf5ed26584116">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/d590014ca419847f932fc7074794e0a1f1e18110">view</a>]</li> +<li>Fixed scope resolution problem for nested Java generics [<a href="https://github.com/doxygen/doxygen/commit/04fe3c5dffa6d5fb530311d5763a1310dd1260cc">view</a>]</li> +<li>Fixed small issue computing indentation for inline line breaks [<a href="https://github.com/doxygen/doxygen/commit/03e0f54b86285e0e6eba07cbdbf407a0522b517d">view</a>]</li> +<li>Flush warnings file (#8069) [<a href="https://github.com/doxygen/doxygen/commit/21bc8b5077ff95c823f9633f81c0738c271219bd">view</a>]</li> +<li>Fortran comments with C comments inside (#8000) [<a href="https://github.com/doxygen/doxygen/commit/1206a9b9b49cdd904c1b5f003c874acd94472806">view</a>]</li> +<li>Handling Enable / Disable menu items (doxywizard) [<a href="https://github.com/doxygen/doxygen/commit/6deb25ba0cb0286f879071d0aaa069c1776fe06f">view</a>]</li> +<li>Handling commands for backslash and at-sign in ALIASES [<a href="https://github.com/doxygen/doxygen/commit/a4b4398ff7b14f0b5fdccac6bb6334da38ef581d">view</a>]</li> +<li>Handling of "Cancel" during "Quit" in doxywizard [<a href="https://github.com/doxygen/doxygen/commit/f01df99914ebd405bb76f117b64a12fca620dcb9">view</a>]</li> +<li>Improve handling of inline namespace members in LateX/RTF output [<a href="https://github.com/doxygen/doxygen/commit/4372054e0b7af9c0cd1c1390859d8fef3581d8bb">view</a>]</li> +<li>Improved sorting of class list/hierarchy [<a href="https://github.com/doxygen/doxygen/commit/459a66a0f6a8073fce07e3f54858d1d078c3a8d3">view</a>]</li> +<li>Improvements of reading the configuration file [<a href="https://github.com/doxygen/doxygen/commit/f573b414b482a01e87869a277cdb913d173fc925">view</a>]</li> +<li>Incorrect checking between default and used values for strList in doxywizard [<a href="https://github.com/doxygen/doxygen/commit/d610c552dbc23f0c036f20ddb1ab8dc64c08e9dc">view</a>]</li> +<li>Incorrect duplicate code for Fortran fixed/free recognition [<a href="https://github.com/doxygen/doxygen/commit/a88b298bee89f001072c80e32e04dfd855d05c58">view</a>]</li> +<li>Incorrect end tag in doxywizard [<a href="https://github.com/doxygen/doxygen/commit/99583eeb36711c2ed4261488c2157da0d425fa67">view</a>]</li> +<li>Incorrect handling of UTF-8 characters in latex reference statement [<a href="https://github.com/doxygen/doxygen/commit/2421a8bb57aad7bbd43dd992d385a59006004f42">view</a>]</li> +<li>Incorrect handling of string with spaces and no quotes [<a href="https://github.com/doxygen/doxygen/commit/9cfb5e58a6a55b2f87027e7b378001f3f3768423">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/ef91bacb7a69bbf7bccb4a864698cc003aabac66">view</a>]</li> +<li>Incorrect label / name in case regeneration of HTML without regeneration of dot files [<a href="https://github.com/doxygen/doxygen/commit/939eca311ced62d9cb41d8e3c1acc207c99e09ed">view</a>]</li> +<li>Incorrect line count in case of an error in msc input [<a href="https://github.com/doxygen/doxygen/commit/a51a6d4845f8a8220700883db7c786a0007f1094">view</a>]</li> +<li>Incorrect recognition as RCS tag [<a href="https://github.com/doxygen/doxygen/commit/64f6dd32f9c0d0d98bb70dac76af684c608d7dda">view</a>]</li> +<li>Incorrect sorting of reflist items [<a href="https://github.com/doxygen/doxygen/commit/9b59748f682e5d5cec5faea91a57b8b7291c7105">view</a>]</li> +<li>Incorrect specification of irc as URL protocol [<a href="https://github.com/doxygen/doxygen/commit/ea5650c7354d57a18ef245b48fdf4bc351524db6">view</a>]</li> +<li>Join sequences of the same type of xref items together in a single paragraph (restores 1.8.16 behavior) [<a href="https://github.com/doxygen/doxygen/commit/38e56645b7527ce70a90f4fcf1bd046fafc50248">view</a>]</li> +<li>Lowercase Findxapian module (same casing as upstream xapian-core) [<a href="https://github.com/doxygen/doxygen/commit/af3bb09cfeb60aeda554754f13a939d14e4bbd4e">view</a>]</li> +<li>Marked the section with definitions regarding numbers more clearly [<a href="https://github.com/doxygen/doxygen/commit/cbefa43c62ed5b19bf82a66dbaf1a4136faac9bd">view</a>]</li> +<li>Minor tweaks [<a href="https://github.com/doxygen/doxygen/commit/0b54d06d4449d91a0890e589ba48daaf41794284">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/143a69238cfec5a031a4f7fd3ac43ce0ae66f40a">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/7e9ac9f80784eef31fd84c3892115cffb1630f95">view</a>]</li> +<li>Fixed line number counting issue with test case cc.h [<a href="https://github.com/doxygen/doxygen/commit/f011af81523bd44dc4c446df6e2976d9c1786609">view</a>]</li> +<li>Fixed various line counting issues resulting in warnings refering to the wrong line number: +[<a href="https://github.com/doxygen/doxygen/commit/927af4b61fc3bac384aeca0d04ef321c854b3ef0">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/33c29dccd16d96b3a5c29fa476e8e9ce376134cd">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/a5ff8649247c2d79c04f068e91987aecbf01c05b">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/75c5c2837a9652cfa94e349c334d5a8f67b91d60">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/c69542e495a01aca1cb20013d91fda78730d2153">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/53d1bbc3bd7686fccdf61e8212137ebad65c1ece">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/8be6d4ec55738b074a5b0ee225cbde05067222a5">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/b1c78ad5a0f15ae67a70d9d7a36e907ac89734cd">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/39db9f48e6376b62f28c9b85320dd62f76547765">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/b5e77b66a4cea0fbfc011f90993a098bd6651e09">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/9c572e72b1070c5d8b58f7d4b6f72fdaede6e8ed">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/17390b669f7a1017fa937410880da38a540dfa35">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/559fa499528fdbca05c05e0a39ccabd46c9edfc2">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/e9d1556252ceea914f7ca98b85a365cd4af594fe">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/e12fd6904e8cc0785f1e3a7dc48fd87ed522f715">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/f3baca79549205c19cde6712a93982f971b58da5">view</a>], +[<a href="https://github.com/doxygen/doxygen/commit/254d1106e52f89fc69620dded9a670358818e8e6">view</a>], and +[<a href="https://github.com/doxygen/doxygen/commit/85fba651ec2a6062e5ab21f06783770ab6fede3b">view</a>] +</li> +<li>Missing \noop in list with commands starting with "\n" for escaping in aliases [<a href="https://github.com/doxygen/doxygen/commit/c56443a8f133c8a04aecf3ecae823af75fb348e1">view</a>]</li> +<li>Missing footer on first page of each chapter in LaTeX [<a href="https://github.com/doxygen/doxygen/commit/24db478285843d3e6afa32af734e29a316f42d62">view</a>]</li> +<li>Multiple anchors with member-group [<a href="https://github.com/doxygen/doxygen/commit/fada71a46966a83a06df17d220d8ee08a5a927b1">view</a>]</li> +<li>No warning for unbalanced brackets in markdown [<a href="https://github.com/doxygen/doxygen/commit/6b13bce96c7845c139b7e481c49d5d540f6633d7">view</a>]</li> +<li>Not always linking in map as maps use name instead if id [<a href="https://github.com/doxygen/doxygen/commit/175b94528ee0f2b51b631a262a053ec15f497738">view</a>]</li> +<li>Optimization for Slice missing in doxywizard Wizard-Mode page [<a href="https://github.com/doxygen/doxygen/commit/7ca670edb21bc9755045bacb775c95c4a755c706">view</a>]</li> +<li>Optimized the escape function and made it more generic [<a href="https://github.com/doxygen/doxygen/commit/c48c5eb3c68a9b5f3f82d1d186a6695ed1d30db5">view</a>]</li> +<li>Prettify the HTML output when enabling SEPARATE_MEMBER_PAGES [<a href="https://github.com/doxygen/doxygen/commit/07767300c3d5bfe256d14ec5bc5a03f5f6d88e4f">view</a>]</li> +<li>Problem with `\\` at end of an ALIASES in the configuration file [<a href="https://github.com/doxygen/doxygen/commit/47c34e3d3ec7143ce69f53ef3a2c1ddcf6ab8065">view</a>]</li> +<li>Proposed fix for Internal search engine produce ".html" pages instead of using HTML_FILE_EXTENSION [<a href="https://github.com/doxygen/doxygen/commit/49ed5387d6a80bbbff3544293cd30c0184abd1ec">view</a>]</li> +<li>Protect mutable access to members in code generators with mutexes [<a href="https://github.com/doxygen/doxygen/commit/f651a0ac32060907b43eb6ccc7f1472986034270">view</a>]</li> +<li>Readability of warning message [<a href="https://github.com/doxygen/doxygen/commit/e1f55871fa67b5d88330a45b4b7d06ac492f0266">view</a>]</li> +<li>Recent file list of doxywizard not cleared properly [<a href="https://github.com/doxygen/doxygen/commit/97d0ba731e46d2e79d40dc34a2a43c96d6951969">view</a>]</li> +<li>Redundant storage of `VhdlParser_adj.cc`, it can be regenerated [<a href="https://github.com/doxygen/doxygen/commit/b4ac6562a715711128720adbeec89ac7125317e9">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/e0468ef6f19af8f320db49004e875f482e606c28">view</a>]</li> +<li>Renamed EXTRACT_ANON_ARGUMENTS to RESOLVE_UNNAMED_PARAMS and enabled it by default [<a href="https://github.com/doxygen/doxygen/commit/09b04bcb61a0e127cf502bc0533cd9bce9293406">view</a>]</li> +<li>Silently ignoring unexpected characters in configuration [<a href="https://github.com/doxygen/doxygen/commit/d2c98cdbc5a66a95fd4a1d68ff21c371d31288a4">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/e1dfd05428008ba61acbb083d7903413b52a8c12">view</a>]</li> +<li>Simplified escaping for latex URLs [<a href="https://github.com/doxygen/doxygen/commit/736557cabb38a37f12cb630adca9ef693646a980">view</a>]</li> +<li>Some further simplications and modernisations [<a href="https://github.com/doxygen/doxygen/commit/539b3bbef61dc7dec8cd5987dc2dbb7a2a956a83">view</a>]</li> +<li>Some tweaks & fixes [<a href="https://github.com/doxygen/doxygen/commit/0006f830184ea30abdd9eb13e79ca2587004a63d">view</a>]</li> +<li>Space around images in LaTeX output is sometimes a bit large [<a href="https://github.com/doxygen/doxygen/commit/89c4556edfc7ca5cac9c2e0171e3be9441990a91">view</a>]</li> +<li>Split into separate rules [<a href="https://github.com/doxygen/doxygen/commit/7b57fa9934130b78e0a70b2406b3627a6d4dce1b">view</a>]</li> +<li>Split lexer rules [<a href="https://github.com/doxygen/doxygen/commit/7eeef98f103a9e62ef1ec44153fbdb630925a2a1">view</a>]</li> +<li>Support commented out argument names in declarations controlled by new cofig EXTRACT_ANON_ARGUMENTS. [<a href="https://github.com/doxygen/doxygen/commit/970b3469a3beaf7041a2efce8d81515077003232">view</a>]</li> +<li>Translation function trCompoundListDescription no entry for SLICE [<a href="https://github.com/doxygen/doxygen/commit/e813676ad74eeab4f469bfbb3ff3977a3a2239cf">view</a>]</li> +<li>Typo in namespacedef.h [<a href="https://github.com/doxygen/doxygen/commit/64c096935496bc513c6b85dca1d526b50f9fed5f">view</a>]</li> +<li>Unclear description of QHG_LOCATION [<a href="https://github.com/doxygen/doxygen/commit/bd6e1b03fc85086abcd920a9d4cee0291d8bf56f">view</a>]</li> +<li>Unified the routine to get the next UTF8 character from a UTF8 stream [<a href="https://github.com/doxygen/doxygen/commit/0404d8ba32b97193822b5d72db2788aff8c3ac9f">view</a>]</li> +<li>Update CMakeLists.txt [<a href="https://github.com/doxygen/doxygen/commit/7eff1f27f6edd509f2c5c472cd76d13691cd437a">view</a>]</li> +<li>Update config.xml [<a href="https://github.com/doxygen/doxygen/commit/9bbd3f5b9b63133e925c30e8acb7615fdbe8c297">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/a29a2efd84101509aaebc61ecfa9139a45fb5e15">view</a>]</li> +<li>Update markdown.cpp [<a href="https://github.com/doxygen/doxygen/commit/b035a11197f69770db5c7ebfb50cb42afc22468d">view</a>]</li> +<li>Usage of version and help in addons [<a href="https://github.com/doxygen/doxygen/commit/b320b14cdfee48a90a732304d6398eb388b1c975">view</a>]</li> +<li>Use correct #include [<a href="https://github.com/doxygen/doxygen/commit/5f34e8ae667c24900e61c72e7dfc213d53a7cb05">view</a>]</li> +<li>Using f() instead f(void) in C++ , consistency [<a href="https://github.com/doxygen/doxygen/commit/7fdd68ca7cbf107a76c233d0e3a9c4c38bd90f90">view</a>]</li> +<li>Warning about duplicate figure numbers in LaTeX [<a href="https://github.com/doxygen/doxygen/commit/1084519cd410bacb997b1ddd705800412450241b">view</a>]</li> +<li>Warning about end of list in brief description after alias `^^` replacement [<a href="https://github.com/doxygen/doxygen/commit/5be9f2b42ec02735712aa68198da1d5056d08ef6">view</a>]</li> +<li>Warning about possible loss of data [<a href="https://github.com/doxygen/doxygen/commit/aad2c7ae4db355c68d1b87ad29e9bf47f8b7652e">view</a>]</li> +<li>Warning in internal documentation [<a href="https://github.com/doxygen/doxygen/commit/a4a7f0a5494c5232c61859dc4e17d0043a31693c">view</a>]</li> +<li>Warnings during compilation of doctokinizer [<a href="https://github.com/doxygen/doxygen/commit/9075fef193e6909b25e67ec9e6aa8dde1503c255">view</a>]</li> +<li>Warnings in generated VhdlParser.cc [<a href="https://github.com/doxygen/doxygen/commit/32c7576977f44c054591f0cb7b75f9b7f81689d2">view</a>]</li> +<li>When instantiating templates also instantiate nested classes [<a href="https://github.com/doxygen/doxygen/commit/a945d52a62b73b23674f6dc0948e22011e278cf9">view</a>]</li> +<li>XHML: div tag not possible as part of a p tag. [<a href="https://github.com/doxygen/doxygen/commit/1525b66e12ed8dba34e12786500422a74387cd29">view</a>]</li> +<li>extend the max lenght befor a sting is folded [<a href="https://github.com/doxygen/doxygen/commit/e97b0c6f1ced61c18621fb4f0d5fe90e11d982ce">view</a>]</li> +<li>quotes added surrounding inheritance tokens on doxyparse output [<a href="https://github.com/doxygen/doxygen/commit/77b4c3bc7cba2d06fa2c03fbf55f5da4f71eb72c">view</a>]</li> +</ul> +<h3>Features</h3> +<ul> +<li>Show QT version in doxywizard [<a href="https://github.com/doxygen/doxygen/commit/b26ec711d6b13578c283ab41ef6d46523ec77777">view</a>]</li> +<li>Adding possibility to add command line options when running doxygen from doxygen wizard [<a href="https://github.com/doxygen/doxygen/commit/70e5213d3646460ce3a31a9afbcb498cdaa2b5b9">view</a>], [<a href="http://github.com/doxygen/doxygen/commit/e78c2e47afa40408dc95de50451e997d0ab357c0">view</a>]</li> +<li>Add param validation to typedef function pointers [<a href="https://github.com/doxygen/doxygen/commit/d34236ba40379847ad4ee3140366bee37b652615">view</a>]</li> +<li>Allow building doxygen as a subproject [<a href="https://github.com/doxygen/doxygen/commit/e7311a036e16cf56692862103be37df95853a1dc">view</a>]</li> +<li>Layout changes doxywizard [<a href="https://github.com/doxygen/doxygen/commit/1113c6fb614de24fae90afbffc05259b89d1d300">view</a>]</li> +<li>Show configuration warnings unconditionally in the doxywizard [<a href="https://github.com/doxygen/doxygen/commit/92f9149ecf34dd1a7f19204ae7aff39c08dacc93">view</a>]</li> +<li>Enable UML diagrams without member fields [<a href="https://github.com/doxygen/doxygen/commit/cea53616cee27e1fe597421a7cb7b2bf8bcb2b7f">view</a>]</li> +<li>add variable for the fold length of UML diagrams (DOT_WRAP_THRESHOLD) [<a href="https://github.com/doxygen/doxygen/commit/78f57f623c45c92f4fb2740300b44b9b68c42bcc">view</a>]</li> +<li>use boolean to add or remove uml details (DOT_UML_DETAILS) [<a href="https://github.com/doxygen/doxygen/commit/a49a5d4c687742a6eaf516d79d2dff399aad12dc">view</a>] and [<a href="https://github.com/doxygen/doxygen/commit/3175b34cc09c59300d5ad2868ab6aba6f4ad0646">view</a>]</li> +<li>add suggestion #7686 to show type and parameters [<a href="https://github.com/doxygen/doxygen/commit/1263d3085da9e2c8fb8f42ea98c107347efb529f">view</a>]</li> +</ul> +<h3>Refactoring and cleanup</h3> +<ul> +<li>Position of layout_default.xml [<a href="https://github.com/doxygen/doxygen/commit/cb351b9cfc13ea5f4049182a2b922ea667f06045">view</a>]</li> +<li>Fix some issues in reporting warnings for Doxywizard's config parser [<a href="https://github.com/doxygen/doxygen/commit/479c58af242b7754775dca646e6ed74a92d58f76">view</a>]</li> +<li>Introduce ScopedTypeVariant [<a href="https://github.com/doxygen/doxygen/commit/0bf6993635a859867db545c89a0712ba94e6c217">view</a>]</li> +<li>Introduce immutable and mutable interfaces [<a href="https://github.com/doxygen/doxygen/commit/075229e586b391c3ec7ad79597aaeae392ca64e5">view</a>]</li> +<li>Modernise DotGfxHierarchyTable [<a href="https://github.com/doxygen/doxygen/commit/fce7c2f8af2ccd04137c7db163333d0110241835">view</a>]</li> +<li>Modernise diagram.h/diagram.cpp [<a href="https://github.com/doxygen/doxygen/commit/2442e7c5c2c8ac2879486a8d01ce8cdf8a6965bb">view</a>]</li> +<li>Modernise BaseClassList [<a href="https://github.com/doxygen/doxygen/commit/86904d5b9752d35ff83bab14969314913f945d5b">view</a>]</li> +<li>OutputList & OutputGen [<a href="https://github.com/doxygen/doxygen/commit/0815bb7d5c99fccdbdba24fb933f9e7fce29bbc6">view</a>]</li> +<li>Re-added sorting for namespaces [<a href="https://github.com/doxygen/doxygen/commit/e89966fc9be09a6cfa6cd39204445059d52f6ca3">view</a>]</li> +<li>Remove unused DefinitionIntf and DefinitionList classes [<a href="https://github.com/doxygen/doxygen/commit/e22e89c0ed1c4fbf22021f4446a2900c65214cf2">view</a>]</li> +<li>Remove use of globals/statics in isAccessibleFrom* [<a href="https://github.com/doxygen/doxygen/commit/8a93f4e00b6922526935909312dabbd9a566d5cc">view</a>]</li> +<li>Better processing of (un)quoted values for tags in the configuration file [<a href="https://github.com/doxygen/doxygen/commit/eb3d1eb5ad85c94d6f2c32934fce2b8630331d6c">view</a>]</li> +<li>Better processing of (un)quoted values for tags in the configuration file (part 2) [<a href="https://github.com/doxygen/doxygen/commit/e0c4e9f3a5416d53aa4da381ce6804022106fa83">view</a>]</li> +<li>Introduce SymbolResolver to group symbol lookup routines [<a href="https://github.com/doxygen/doxygen/commit/0c0889e331305ea5b4f5c7a58c4a0e82da6111cd">view</a>]</li> +<li>Make setAnchors() a member of MemberList [<a href="https://github.com/doxygen/doxygen/commit/a95ab819972148fef8287353e13089fd8cacebb8">view</a>]</li> +<li>Making fortrancode.l reentrant [<a href="https://github.com/doxygen/doxygen/commit/99ca73d04ac162741fb63403c5bfb8cb9809ff1c">view</a>]</li> +<li>Making pycode.l reentrant [<a href="https://github.com/doxygen/doxygen/commit/05547d571d1f5c32e7577ef26c830a240505d0aa">view</a>]</li> +<li>Making sqlcode.l reentrant [<a href="https://github.com/doxygen/doxygen/commit/5162dab5a4254ef65e2de972f07a00ff52e7734c">view</a>]</li> +<li>Making vhdlcode.l reentrant [<a href="https://github.com/doxygen/doxygen/commit/e801f129218e6f9ab11dc165b0e1607fc64cd645">view</a>]</li> +<li>Making xmlcode.l reentrant [<a href="https://github.com/doxygen/doxygen/commit/0fc06d657d596adcc289a5f228973ea268efd66d">view</a>]</li> +<li>Modernised the remaining containers in code.l [<a href="https://github.com/doxygen/doxygen/commit/0aaa71ab96fe055fe08567bea9cc59a6e33b7bb4">view</a>]</li> +<li>Modernize Doxygen::symbolMap [<a href="https://github.com/doxygen/doxygen/commit/1c889cca680b79ca55a69b6dfef2f387f120e2d3">view</a>]</li> +<li>Modernize TooltipManager class and source reference lists [<a href="https://github.com/doxygen/doxygen/commit/d03e8d9411ab3e983fc3413c147fba1a5e5c9dad">view</a>]</li> +<li>Modernize class index [<a href="https://github.com/doxygen/doxygen/commit/59372719ef31d7a76e2cfb64ab4628a315ccaf3a">view</a>]</li> +<li>Modernize getUsedClasses() method [<a href="https://github.com/doxygen/doxygen/commit/daeba94e228802e374eea260b8ba8f6157f91dbd">view</a>]</li> +<li>Modernized the getUsedNamespaces() method [<a href="https://github.com/doxygen/doxygen/commit/4c0557e8261a6753a19de293e8cc7cdd3beb90ca">view</a>]</li> +<li>Move ClassDefSet to the classdef header [<a href="https://github.com/doxygen/doxygen/commit/62e55b73b0762251bdcf51e2f4c7b8f4cdcb4ddb">view</a>]</li> +<li>Move addDocCrossReference to memberdef.cpp/.h [<a href="https://github.com/doxygen/doxygen/commit/65e57b55cfa22e3ccc2b281f1af974d410263e2a">view</a>]</li> +<li>Prepare output generators for multi-threaded use [<a href="https://github.com/doxygen/doxygen/commit/cfdabb54c5bcea38629eb0ec8f207d1306ff0939">view</a>]</li> +<li>Remove isVisited/setVisited from context [<a href="https://github.com/doxygen/doxygen/commit/6728e04f215353429aec7b468448fa3eaeaa499d">view</a>]</li> +<li>Remove isVisited/setVisited from index [<a href="https://github.com/doxygen/doxygen/commit/b82f069a2a11f6bc82c81ee2cda8d30725e95313">view</a>]</li> +<li>Remove unused Doxygen::genericsSDict [<a href="https://github.com/doxygen/doxygen/commit/48096bb6c5d7a2879327c82cc0144eef8e6d8ac8">view</a>]</li> +<li>Removed macros used for getting the value of settings [<a href="https://github.com/doxygen/doxygen/commit/d3ffd31e89c05d0afa3245ccc68604baeae837a4">view</a>]</li> +<li>Removed some dead code [<a href="https://github.com/doxygen/doxygen/commit/c73dccc6af02de46485b66caef63253aeb9fd5fe">view</a>]</li> +<li>Removing setVisited/isVisited members [<a href="https://github.com/doxygen/doxygen/commit/a5792da8b4bf88a9d93cfd0582cec469747de3b2">view</a>]</li> +<li>Replace ClassSDict by ClassLinkedMap/ClassLinkedRefMap [<a href="https://github.com/doxygen/doxygen/commit/963caeef1c24d66a51376f77d8692f1a3c5d4a62">view</a>]</li> +<li>Replace NamespaceSDict by NamespaceLinkedMap [<a href="https://github.com/doxygen/doxygen/commit/11f0c2e3735e4736a5ade8468a356ebc2fc2840d">view</a>]</li> +<li>Replace QDict by std::set for classifying keywords in vhdldocgen [<a href="https://github.com/doxygen/doxygen/commit/f0621abcd0db27a362e9c6eec5ea1a8d85e83beb">view</a>]</li> +<li>Replace QMap with std::map in fortranscanner.l [<a href="https://github.com/doxygen/doxygen/commit/525b87e93dfedc9d98fc00def60c987b4e8d80d9">view</a>]</li> +<li>Replace QXml by own XML processor [<a href="https://github.com/doxygen/doxygen/commit/644997f85f327d3f8456f1c5cf0cde78a3bd1d28">view</a>]</li> +<li>Replaced QCache by STL based LRU cache implementation. [<a href="https://github.com/doxygen/doxygen/commit/bb783fb795f9c0d077fa201ed673be93825486ce">view</a>]</li> +<li>Replaced QStack by std::stack for scopeStack [<a href="https://github.com/doxygen/doxygen/commit/62dabb22779acb023b74329b6ab515f187cd4ff3">view</a>]</li> +<li>Replaced codeClassSDict by codeClassMap in code.l [<a href="https://github.com/doxygen/doxygen/commit/250f6fe440773eb8202bf234b3a4b81c44044f5a">view</a>]</li> +<li>Replaced getNamespaceSDict() by getNamespaces() [<a href="https://github.com/doxygen/doxygen/commit/bf5c2ac20e42f440ae0199d4d809b9d5e7e22191">view</a>]</li> +<li>Replacing dynamic_cast by static_cast to improve performance [<a href="https://github.com/doxygen/doxygen/commit/784313b82442747843145429d39e5d257256b7b0">view</a>]</li> +<li>Simplify vhdldocgen code a bit [<a href="https://github.com/doxygen/doxygen/commit/a159f53f032b04064df0c9ad9d7d02f0622f0529">view</a>]</li> +<li>Modernize search index [<a href="https://github.com/doxygen/doxygen/commit/33a334ce77e6dd0c81e97edc4bfba1fe50d947fa">view</a>]</li> +<li>Update used links in test examples [<a href="https://github.com/doxygen/doxygen/commit/3c9eeae58ca98a000c75d75ed21bbe4a625cd2c8">view</a>]</li> +<li>Updated minimum MacOS requirements to version 10.14 [<a href="https://github.com/doxygen/doxygen/commit/4b997ee2519c1032da6f1a9caf2638d17202fea7">view</a>]</li> +<li>Updated test for enums based on recently fixed issues [<a href="https://github.com/doxygen/doxygen/commit/62b368644dec14d1d916c778461f6d4d32e2182e">view</a>]</li> +<li>Make layout parser use the new XML parser [<a href="https://github.com/doxygen/doxygen/commit/22f6dcc3cedf1bf4360c452db40949e3c156f41b">view</a>]</li> +<li>Make tagreader use the new XML parser [<a href="https://github.com/doxygen/doxygen/commit/714f89d30cf04ad972df84a6a398258b751d3553">view</a>]</li> +<li>Make testsqlite3.py python script running with python 3 [<a href="https://github.com/doxygen/doxygen/commit/6383a72200df27b0515b6e3d09bfad8934eb5c76">view</a>]</li> +<li>Remove duplicate pages for classes inside inline namespaces (LaTeX/RTF/DocBook) [<a href="https://github.com/doxygen/doxygen/commit/63d7b19df11eb55a30e4af8fa492ee464ff353f5">view</a>]</li> +<li>Remove double usepackage / RequirePackage from LaTeX [<a href="https://github.com/doxygen/doxygen/commit/f3f23cbe43e9fd43fb42b65b0b01002962f6af0e">view</a>]</li> +</ul> +<h3>Documentation updates</h3> +<ul> +<li>Correction of spelling errors [<a href="https://github.com/doxygen/doxygen/commit/5ebf938be4d3b185fa1e1319ebeefafd090605f8">view</a>]</li> +<li>Incomplete documentation in respect to hyphens for horizontal rulers [<a href="https://github.com/doxygen/doxygen/commit/4aa74abe0835b2430e51dc628c10f2e04b9b894b">view</a>]</li> +<li>Mismatch documentation and build system [<a href="https://github.com/doxygen/doxygen/commit/b42ee5fc78f3c5b08d5f96347c9c912fd1a07c3e">view</a>]</li> +<li>Update of doxywizard documetation [<a href="https://github.com/doxygen/doxygen/commit/a4d254f92f7c892a7dc1ce3a83b0894dbe3870f1">view</a>]</li> +<li>Update of testing README.txt [<a href="https://github.com/doxygen/doxygen/commit/d6afc494c14f683ed80f929a9f9fd311ef7fd500">view</a>]</li> +<li>Incorrect link in doxygen documentation [<a href="https://github.com/doxygen/doxygen/commit/1928b428c3948dfffcabf328d77692e6ba14ec5e">view</a>]</li> +<li>Making the use of DOT_CLEANUP more transparent [<a href="https://github.com/doxygen/doxygen/commit/773d0aafb4f603b6924d86a60a2828bd44a16756">view</a>]</li> +<li>Syntax for faq about use in Windows Powershell [<a href="https://github.com/doxygen/doxygen/commit/819529338768bf791a58416fc67d291cf4271087">view</a>]</li> +<li>Consistency in documentation of used Python versions [<a href="https://github.com/doxygen/doxygen/commit/48fcee6e1bcce7bfe295f3143c4ee2d93c4b3904">view</a>]</li> +<li>better description of Doxyparse on README doc [<a href="https://github.com/doxygen/doxygen/commit/abab1ca40750c038b69f112f94f591cc3ea07648">view</a>]</li> +<li>Missing commands in list of commands documentation [<a href="https://github.com/doxygen/doxygen/commit/938e868b438dd49d1b366a739eb2aba57f0f5b55">view</a>]</li> +<li>Small layout improvement in documentation of CLANG_DATABASE_PATH [<a href="https://github.com/doxygen/doxygen/commit/b2cf46c4b8a74163526e1d3334ce60026b0198bc">view</a>]</li> +</ul> +<p> +\endhtmlonly + + + + + \section log_1_8 1.8 Series \subsection log_1_8_20 Release 1.8.20 diff --git a/doc/commands.doc b/doc/commands.doc index 631f5c7..1465a1e 100644 --- a/doc/commands.doc +++ b/doc/commands.doc @@ -144,6 +144,7 @@ documentation: \refitem cmdn \\n \refitem cmdname \\name \refitem cmdnamespace \\namespace +\refitem cmdnoop \\noop \refitem cmdnosubgrouping \\nosubgrouping \refitem cmdnote \\note \refitem cmdoverload \\overload @@ -193,6 +194,7 @@ documentation: \refitem cmdsnippet \\snippet \refitem cmdsnippetdoc \\snippetdoc \refitem cmdsnippetlineno \\snippetlineno +\refitem cmdstatic \\static \refitem cmdstartuml \\startuml \refitem cmdstruct \\struct \refitem cmdsubpage \\subpage @@ -2798,6 +2800,10 @@ only copy the detailed documentation, not the brief description. The nodes of a graph can be made clickable by using the URL attribute. By using the command \ref cmdref "\\ref" inside the URL value you can conveniently link to an item inside doxygen. Here is an example: + + \note doxygen creates a temporary file that is automatically removed unless + the \ref cfg_dot_cleanup "DOT_CLEANUP" tag is set to `NO`. + \code /*! class B */ class B {}; @@ -2861,6 +2867,8 @@ See also the \ref emojisup "emoji support page" for details. within the <code>msc {...}</code> block (this is different from \ref cmdmscfile "\\mscfile"). \note mscgen is now built in into doxygen + \note doxygen creates a temporary file that is automatically removed unless + the \ref cfg_dot_cleanup "DOT_CLEANUP" tag is set to `NO`. Here is an example of the use of the \c \\msc command. \code @@ -2903,7 +2911,7 @@ class Receiver \addindex \\startuml Starts a text fragment which should contain a valid description of a - PlantUML diagram. See http://plantuml.com/ for examples. + PlantUML diagram. See https://plantuml.com/ for examples. The text fragment ends with \ref cmdenduml "\\enduml". \note You need to install Java and the PlantUML's jar file, if you want to use this command. The location of the jar file should be specified @@ -2931,6 +2939,9 @@ class Receiver \ref image_sizeindicator "Size indication" with the \ref cmdimage "\\image" command. + \note doxygen creates a temporary file that is automatically removed unless + the \ref cfg_dot_cleanup "DOT_CLEANUP" tag is set to `NO`. + Here is an example of the use of the \c \\startuml command. \code /** Sender class. Can be used to send a command to the server. diff --git a/doc/custcmd.doc b/doc/custcmd.doc index c6be4c4..0cc1d4d 100644 --- a/doc/custcmd.doc +++ b/doc/custcmd.doc @@ -34,7 +34,7 @@ The simplest form of an alias is a simple substitution of the form \endverbatim For example defining the following alias: \verbatim - ALIASES += sideeffect="\par Side Effects:\n" + ALIASES += sideeffect="\par Side Effects:^^" \endverbatim will allow you to put the command `\sideeffect` (or `@sideeffect`) in the documentation, which diff --git a/doc/docblocks.doc b/doc/docblocks.doc index 96a2621..ac81bec 100644 --- a/doc/docblocks.doc +++ b/doc/docblocks.doc @@ -431,7 +431,9 @@ using structural commands: a case where the \\fn command is redundant and will only lead to problems. When you place a comment block in a file with one of the following extensions - `.dox`, `.txt`, or `.doc` then doxygen will hide this file from the file list. + `.dox`, `.txt`, `.doc`, `.md` or `.markdown` or when the extension maps to + `md` by means of the \ref cfg_extension_mapping "EXTENSION_MAPPING" + then doxygen will hide this file from the file list. If you have a file that doxygen cannot parse but still would like to document it, you can show it as-is using \ref cmdverbinclude "\\verbinclude", e.g. diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex index 0148379..7d8e889 100644 --- a/doc/doxygen_manual.tex +++ b/doc/doxygen_manual.tex @@ -122,6 +122,7 @@ \usepackage{etoc} \etocsettocstyle{\doxytocparskip}{\doxynormalparskip} \begin{document} +\raggedbottom \pagenumbering{alph} \begin{titlepage} \includegraphics[width=\textwidth]{doxygen_logo} @@ -171,83 +172,84 @@ Written by Dimitri van Heesch\\[2ex] \chapter{Perl Module Output}\label{perlmod}\hypertarget{perlmod}{}\input{perlmod} \chapter{Doxygen's internals}\label{arch}\hypertarget{arch}{}\input{arch} \renewcommand{\thepart}{} +\renewcommand{\partname}{} \part{Appendices} \appendix %mean that subinputfrom requires a / at the end of the path \chapter{Autolink Example}\label{autolink_example}\hypertarget{autolink_example}{} -\subinputfrom{../html/examples/autolink/latex/}{refman_doc} +\subinputfrom{examples/autolink/latex/}{refman_doc} \chapter{Resolving Typedef Example}\label{restypedef_example}\hypertarget{restypedef_example}{} -\subinputfrom{../html/examples/restypedef/latex/}{refman_doc} +\subinputfrom{examples/restypedef/latex/}{refman_doc} -\IfFileExists{../html/examples/diagrams/latex/refman_doc.tex} +\IfFileExists{examples/diagrams/latex/refman_doc.tex} { \chapter{Diagrams Example}\label{diagrams_example}\hypertarget{diagrams_example}{} - \subinputfrom{../html/examples/diagrams/latex/}{refman_doc} + \subinputfrom{examples/diagrams/latex/}{refman_doc} }{} \chapter{Modules Example}\label{modules_example}\hypertarget{modules_example}{} -\subinputfrom{../html/examples/group/latex/}{refman_doc} +\subinputfrom{examples/group/latex/}{refman_doc} \chapter{Member Groups Example}\label{memgrp_example}\hypertarget{memgrp_example}{} -\subinputfrom{../html/examples/memgrp/latex/}{refman_doc} +\subinputfrom{examples/memgrp/latex/}{refman_doc} \chapter{Style Examples} \doxysection{After Block Example}\label{afterdoc_example}\hypertarget{afterdoc_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/afterdoc/latex/}{refman_doc} + \subinputfrom{examples/afterdoc/latex/}{refman_doc} \end{DoxygenSubAppendix} \doxysection{QT Style Example}\label{qtstyle_example}\hypertarget{qtstyle_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/qtstyle/latex/}{refman_doc} + \subinputfrom{examples/qtstyle/latex/}{refman_doc} \end{DoxygenSubAppendix} \doxysection{Javadoc Style Example}\label{jdstyle_example}\hypertarget{jdstyle_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/jdstyle/latex/}{refman_doc} + \subinputfrom{examples/jdstyle/latex/}{refman_doc} \end{DoxygenSubAppendix} \doxysection{Javadoc Banner Example}\label{javadoc_banner_example}\hypertarget{javadoc_banner_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/javadoc-banner/latex/}{refman_doc} + \subinputfrom{examples/javadoc-banner/latex/}{refman_doc} \end{DoxygenSubAppendix} \chapter{Structural Commands Example}\label{structcmd_example}\hypertarget{structcmd_example}{} -\subinputfrom{../html/examples/structcmd/latex/}{refman_doc} +\subinputfrom{examples/structcmd/latex/}{refman_doc} \chapter{Language Examples} \doxysection{Python Docstring Example}\label{python_example}\hypertarget{python_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/docstring/latex/}{refman_doc} + \subinputfrom{examples/docstring/latex/}{refman_doc} \end{DoxygenSubAppendix} \doxysection{Python Example}\label{py_example}\hypertarget{py_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/pyexample/latex/}{refman_doc} + \subinputfrom{examples/pyexample/latex/}{refman_doc} \end{DoxygenSubAppendix} \doxysection{VHDL Example}\label{vhdl_example}\hypertarget{vhdl_example}{} \begin{DoxygenSubAppendix} - \subinputfrom{../html/examples/mux/latex/}{refman_doc} + \subinputfrom{examples/mux/latex/}{refman_doc} \end{DoxygenSubAppendix} \chapter{Class Example}\label{class_example}\hypertarget{class_example}{} -\subinputfrom{../html/examples/class/latex/}{refman_doc} +\subinputfrom{examples/class/latex/}{refman_doc} \chapter{Define Example}\label{define_example}\hypertarget{define_example}{} -\subinputfrom{../html/examples/define/latex/}{refman_doc} +\subinputfrom{examples/define/latex/}{refman_doc} \chapter{Enum Example}\label{enum_example}\hypertarget{enum_example}{} -\subinputfrom{../html/examples/enum/latex/}{refman_doc} +\subinputfrom{examples/enum/latex/}{refman_doc} \chapter{Example Example}\label{example_example}\hypertarget{example_example}{} -\subinputfrom{../html/examples/example/latex/}{refman_doc} +\subinputfrom{examples/example/latex/}{refman_doc} \chapter{Extends/Implements Example}\label{extends_example}\hypertarget{extends_example}{} -\subinputfrom{../html/examples/manual/latex/}{refman_doc} +\subinputfrom{examples/manual/latex/}{refman_doc} \chapter{File Example}\label{file_example}\hypertarget{file_example}{} -\subinputfrom{../html/examples/file/latex/}{refman_doc} +\subinputfrom{examples/file/latex/}{refman_doc} \chapter{Fn Example}\label{fn_example}\hypertarget{fn_example}{} -\subinputfrom{../html/examples/func/latex/}{refman_doc} +\subinputfrom{examples/func/latex/}{refman_doc} \chapter{Overload Example}\label{overload_example}\hypertarget{overload_example}{} -\subinputfrom{../html/examples/overload/latex/}{refman_doc} +\subinputfrom{examples/overload/latex/}{refman_doc} \chapter{Page Example}\label{page_example}\hypertarget{page_example}{} -\subinputfrom{../html/examples/page/latex/}{refman_doc} +\subinputfrom{examples/page/latex/}{refman_doc} \chapter{Relates Example}\label{relates_example}\hypertarget{relates_example}{} -\subinputfrom{../html/examples/relates/latex/}{refman_doc} +\subinputfrom{examples/relates/latex/}{refman_doc} \chapter{Author Example}\label{author_example}\hypertarget{author_example}{} -\subinputfrom{../html/examples/author/latex/}{refman_doc} +\subinputfrom{examples/author/latex/}{refman_doc} \chapter{Par Example}\label{par_example}\hypertarget{par_example}{} -\subinputfrom{../html/examples/par/latex/}{refman_doc} +\subinputfrom{examples/par/latex/}{refman_doc} \chapter{Include Example}\label{include_example}\hypertarget{include_example}{} -\subinputfrom{../html/examples/include/latex/}{refman_doc} +\subinputfrom{examples/include/latex/}{refman_doc} \printindex diff --git a/doc/doxywizard.gif b/doc/doxywizard.gif Binary files differdeleted file mode 100644 index 80bb636..0000000 --- a/doc/doxywizard.gif +++ /dev/null diff --git a/doc/doxywizard_expert.png b/doc/doxywizard_expert.png Binary files differindex 5eb14d4..d07152f 100644 --- a/doc/doxywizard_expert.png +++ b/doc/doxywizard_expert.png diff --git a/doc/doxywizard_main.png b/doc/doxywizard_main.png Binary files differindex b170e15..1c4ee1b 100644 --- a/doc/doxywizard_main.png +++ b/doc/doxywizard_main.png diff --git a/doc/doxywizard_menu.png b/doc/doxywizard_menu.png Binary files differdeleted file mode 100644 index 7f37192..0000000 --- a/doc/doxywizard_menu.png +++ /dev/null diff --git a/doc/doxywizard_menu_file.png b/doc/doxywizard_menu_file.png Binary files differnew file mode 100644 index 0000000..e3c6092 --- /dev/null +++ b/doc/doxywizard_menu_file.png diff --git a/doc/doxywizard_menu_help.png b/doc/doxywizard_menu_help.png Binary files differnew file mode 100644 index 0000000..4d6812b --- /dev/null +++ b/doc/doxywizard_menu_help.png diff --git a/doc/doxywizard_menu_settings.png b/doc/doxywizard_menu_settings.png Binary files differnew file mode 100644 index 0000000..c22e361 --- /dev/null +++ b/doc/doxywizard_menu_settings.png diff --git a/doc/doxywizard_page1.png b/doc/doxywizard_page1.png Binary files differindex 3e008d0..7834573 100644 --- a/doc/doxywizard_page1.png +++ b/doc/doxywizard_page1.png diff --git a/doc/doxywizard_page2.png b/doc/doxywizard_page2.png Binary files differindex 8343902..ec5ce51 100644 --- a/doc/doxywizard_page2.png +++ b/doc/doxywizard_page2.png diff --git a/doc/doxywizard_page3.png b/doc/doxywizard_page3.png Binary files differindex 0201981..dff15e7 100644 --- a/doc/doxywizard_page3.png +++ b/doc/doxywizard_page3.png diff --git a/doc/doxywizard_page4.png b/doc/doxywizard_page4.png Binary files differindex 1068e6c..8378a5c 100644 --- a/doc/doxywizard_page4.png +++ b/doc/doxywizard_page4.png diff --git a/doc/doxywizard_run.png b/doc/doxywizard_run.png Binary files differnew file mode 100644 index 0000000..156fc9d --- /dev/null +++ b/doc/doxywizard_run.png diff --git a/doc/doxywizard_usage.doc b/doc/doxywizard_usage.doc index 310c358..8b9e428 100644 --- a/doc/doxywizard_usage.doc +++ b/doc/doxywizard_usage.doc @@ -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,134 +14,272 @@ */ /*! \page doxywizard_usage Doxywizard usage -Doxywizard is a GUI front-end for configuring and running doxygen. +Doxywizard is a GUI front-end for configuring and running doxygen. -Note it is possible to start the doxywizard with as argument the configuration file to be used. +When starting doxywizard one can specify an existing configuration file to use as argument, +otherwise the default settings will be used as a starting point. -When you start doxywizard it will display the main window -(the actual look depends on the OS used). +When you start doxywizard it will display the main window +(the actual look depends on the platform used). \image html doxywizard_main.png "Main window" \image latex doxywizard_main.png "Main window" width=15cm -The windows shows the steps to take to configure and run doxygen. -The first step is to choose one of the ways to configure doxygen. +The user interface consists of the following sections: <dl> -<dt>Wizard<dd>Click this button to quickly configure the most important - settings and leave the rest of the options to their defaults. -<dt>Expert<dd>Click this button to gain access to the - \ref config "full range of configuration options". -<dt>Load<dd>Click this button to load an existing configuration file - from disk. +<dt>\ref dw_menu +<dd> In the menu bar the following parts are available: +\ref dw_menu_file, \ref dw_menu_settings and \ref dw_menu_help. + +<dt>Specify the working directory from which doxygen will run +<dd> +Using the <tt>Select...</tt> button a directory can be selected. +When doxywizard is started with a configuration file or one is loaded using the open command +(see: \ref dw_menu_file) the directory of this settings file used as the working directory. + +<dt>Configure doxygen using the Wizard and/or Expert tab... +<dd> + <dl> + <dt>\ref dw_wizard <dd>with this tab it is possible to quickly configure the most + important settings and leave the rest of the options to + their defaults. + <dt>\ref dw_expert <dd>with this tab one gains access to the \ref config + "full set of configuration options". + <dt>\ref dw_run <dd>with this tab it is possible to run doxygen and view the used settings. + </dl> + +Switching between these tabs is possible, e.g you could start with the wizard tab +and then fine tune some settings by switching to the expert tab. + </dl> -Note that you can select multiple buttons in a row, for instance to first -configure doxygen using the Wizard and then fine tune the settings via -the Expert. -After doxygen is configured you need to save the configuration as a file -to disk. This second step allows doxygen to use the configuration -and has the additional advantage that the configuration can be reused -to run doxygen with the same settings at a later point in time. +After doxygen is configured you need to save (see: \ref dw_menu_file) the configuration as a file +to disk. This allows doxygen to use the configuration +and also allows running doxygen again with the same settings at a later point in time. -Since some configuration options may use relative paths, the next step is -to select a directory from which to run doxygen. This is typically the root -of the source tree and will most of the time already be filled in correctly. +Since some configuration options may use relative paths, be sure to +select a working directory that is root of those paths. +This is often the root of the source tree and will typically be correctly filled in +if the configuration file is stored at this location as well. Once the configuration file is saved and the working directory is set, you -can run doxygen based on the selected settings. Do this by pressing the -"Start" button. Once doxygen runs you can cancel it by clicking the same -button again. The output produced by doxygen is captured and shown in a log -window. Once doxygen finishes, the log can be saved as a text file. +can run doxygen based on the selected settings. Do this by switching to the +\ref dw_run "Run" tab, and click the "Run doxygen" button. + +Once doxygen runs you can cancel it by clicking the same +button again. The output produced by doxygen is captured and shown in the "Output produced by doxygen" +pane. Once doxygen finishes, the log can be saved as a text file. -<h3>The Wizard Dialog</h3> +\section dw_wizard Wizard tab + +The Wizard tab is divided into two panes +<dl> +<dt>Left pane<dd>The main topics for easy setting up doxygen. +By clicking on a topic the corresponding settings will appear in the Right +pane. +<dt>Right pane<dd>The wizard's settings pane, in this pane you will find the +settings that are available for the selected topic. +</dl> -If you select the Wizard button in step 1, then a dialog with -a number of tabs will appear. +The wizard only gives the possibility to quickly setup doxygen, for full control +one should use the \ref dw_expert. -\image html doxywizard_page1.png "Wizard dialog: Project settings" -\image latex doxywizard_page1.png "Wizard dialog: Project settings" width=13cm +\forceNewPage +\subsection dw_wizard_project Project settings -The fields in the project tab speak for themselves. Once doxygen has finished +The fields in the Project pane speak for themselves. Once doxygen has finished the Destination directory is where to look for the results. Doxygen will -put each output format in a separate sub-directory. +put each output format in a separate sub-directory by default. + +\image html doxywizard_page1.png "Wizard tab: Project settings" +\image latex doxywizard_page1.png "Wizard tab: Project settings" width=15cm + +\forceNewPage +\subsection dw_wizard_mode Mode of operating + +The Mode pane allows you to select how doxygen will look at your sources. +The default is to only look for things that have been documented. Furthermore, the +terminology used in the output can be changed to better match the main programming language used +(this doesn't affect the way doxygen parses your source code). -\image html doxywizard_page2.png "Wizard dialog: Mode of operating" -\image latex doxywizard_page2.png "Wizard dialog: Mode of operating" width=13cm +\image html doxywizard_page2.png "Wizard tab: Mode of operating" +\image latex doxywizard_page2.png "Wizard tab: Mode of operating" width=15cm -The mode tab allows you to select how doxygen will look at your sources. -The default is to only look for things that have been documented. +\forceNewPage +\subsection dw_wizard_output Output to produce -You can also select how doxygen should present the results. -The latter does not affect the way doxygen parses your source code. +The Output pane allows you to select what kinds of output doxygen will produce. +For HTML and \LaTeX there are additional options available. -\image html doxywizard_page3.png "Wizard dialog: Output to produce" -\image latex doxywizard_page3.png "Wizard dialog: Output to produce" width=13cm +\image html doxywizard_page3.png "Wizard tab: Output to produce" +\image latex doxywizard_page3.png "Wizard tab: Output to produce" width=15cm -You can select one or more of the output formats that doxygen should -produce. For HTML and \LaTeX there are additional options. +\forceNewPage +\subsection dw_wizard_diagrams Diagrams to generate -\image html doxywizard_page4.png "Wizard dialog: Diagrams to generate" -\image latex doxywizard_page4.png "Wizard dialog: Diagrams to generate" width=13cm +Doxygen can produce a number of diagrams. Using the Diagrams pane you +can select which ones to generate. For most diagrams the +`dot` tool of the <a href="http://www.graphviz.org">GraphViz</a> package +is needed. This needs to be installed separately. -Doxygen can produce a number of diagrams. Using the diagrams tab you -can select which ones to generate. For most diagrams the -dot tool of the <a href="http://www.graphviz.org">GraphViz</a> package -is needed (if you use the binary packages for MacOSX this -tool is already included). +\image html doxywizard_page4.png "Wizard tab: Diagrams to generate" +\image latex doxywizard_page4.png "Wizard tab: Diagrams to generate" width=15cm -<h3>Expert dialog</h3> +\section dw_expert Expert tab -The Expert dialog has a number of tab fields, one -for each section in the configuration file. Each tab-field -contains a number of lines, one for each configuration option in -that section. +The Expert tab is divided into a number of panes: +<dl> +<dt>Top left pane<dd>The Topics pane (i.e. sections in the +configuration file) that are available. By clicking on a topic the +corresponding settings will appear in the Right pane. +<dt>Bottom left pane<dd>The help pane, this will be updated when one +hovers over the name of a setting in the Right pane. +<dt>Right pane<dd>The Settings pane, in this pane you will find the +settings that are available for the selected topic. In case the name for a setting is colored +red, the setting has a non-default value. +In case a setting is grayed out, the setting is depending on another setting that is disabled. +Which setting it depends on is indicated in the help pane on the bottom left. +</dl> -The kind of input widget depends on the type of the configuration option. +\image html doxywizard_expert.png "Some options from the Expert tab" +\image latex doxywizard_expert.png "Some options from the Expert tab" width=15cm + +The representation of the input field depends on the type of the configuration option. <ul> -<li>For each boolean option (those options that are answered with YES or - NO in the configuration file) there is a check-box. -<li>For items taking one of a fixed set of values (like +<li>For each boolean option (those options that are answered with `YES` or + `NO` in the configuration file) there is a check-box. A typical field + looks like:<br> + \image{inline} html expert_bool.png + \image{inline} latex expert_bool.png width=4.6cm +<li>For items taking one of a fixed set of values (like \ref cfg_output_language "OUTPUT_LANGUAGE") a combo box is used. + A typical field looks like:<br> + \image{inline} html expert_enum.png + \image{inline} latex expert_enum.png width=7.3cm <li>For items taking an integer value from a range, a spinbox is used. -<li>For free form string-type options there is a one line edit field -<li>For options taking a lists of strings, a one line edit field is - available, with a `+' button to add this string to the list and - a `-' button to remove the selected string from the list. There - is also a `*' button that, when pressed, - replaces the selected item in the list with the string entered in the - edit field. -<li>For file and folder entries, there are special buttons - that start a file selection dialog. + A typical field looks like:<br> + \image{inline} html expert_int.png + \image{inline} latex expert_int.png width=10.1cm +<li>For free form string-type options there is a one line edit field. + A typical field looks like:<br> + \image{inline} html expert_string_string.png + \image{inline} latex expert_string_string.png width=12.3cm + <br>Additionally, when the string field should contain a file or a folder name, there are the special buttons + \image{inline} html images/file.png height=14px \ilinebr \image{inline} latex images/file.png height=\DoxyInlineHeightChar + and + \image{inline} html images/folder.png height=14px \ilinebr \image{inline} latex images/folder.png height=\DoxyInlineHeightChar + that start a file / folder selection dialog. + A typical field for a file looks like:<br> + \image{inline} html expert_string_file.png + \image{inline} latex expert_string_file.png width=11.0cm + <br>and a folder looks like:<br> + \image{inline} html expert_string_dir.png + \image{inline} latex expert_string_dir.png width=11.0cm + <br>In case a file represents an image, doxygen also tries to display the selected image. + Then a typical field looks like:<br> + \image{inline} html expert_string_image.png + \image{inline} latex expert_string_image.png width=11.8cm +<li>For options taking a list of strings, an editor field is + shown with a non-editable list below it. The + \image{inline} html images/add.png height=14px \ilinebr \image{inline} latex images/add.png height=\DoxyInlineHeightChar + button adds the string in the editor field to the list and a the + \image{inline} html images/del.png height=14px \ilinebr \image{inline} latex images/del.png height=\DoxyInlineHeightChar + button removes the selected string from the list. The + \image{inline} html images/refresh.png height=14px \ilinebr \image{inline} latex images/refresh.png height=\DoxyInlineHeightChar + button can be clicked to replace the selected item in the list with the string entered in the editor field. + A typical field looks like:<br> + \image{inline} html expert_list_string.png + \image{inline} latex expert_list_string.png width=11.2cm + <br>additionally when the list contains file and / or folder names, there are special buttons + \image{inline} html images/file.png height=14px \ilinebr \image{inline} latex images/file.png height=\DoxyInlineHeightChar + and + \image{inline} html images/folder.png height=14px \ilinebr \image{inline} latex images/folder.png height=\DoxyInlineHeightChar + that start a file / folder selection dialog. + A typical field would for a file looks like:<br> + \image{inline} html expert_list_file.png + \image{inline} latex expert_list_file.png width=11.2cm + <br>and for a folder it looks like<br> + \image{inline} html expert_list_dir.png + \image{inline} latex expert_list_dir.png width=11.2cm + <br>and in case both files and folders are allowed, the look is:<br> + \image{inline} html expert_list_filedir.png + \image{inline} latex expert_list_filedir.png width=11.9cm </ul> -\image html doxywizard_expert.png "Some options from the Expert dialog" -\image latex doxywizard_expert.png "Some options from the Expert dialog" width=15cm +\section dw_run Run tab -The get additional information about the meaning of an option, click -on the "Help" button at the bottom right of the dialog and then on the -item. A tooltip with additional information will appear. +The run tab gives the possibility to run doxygen with the given settings, see the HTML results, +see the settings used and save the output as displayed in the output pane. -<h3>Menu options</h3> +\image html doxywizard_run.png "Run tab" +\image latex doxywizard_run.png "Run tab" width=15cm -The GUI front-end has a menu with a couple of useful items +<dl> +<dt>Specify additional command line options for running doxygen<dd>Field to +specify extra options used when running doxygen, e.g. for debugging purposes. +<dt>Run doxygen<dd>When clicked will start running doxygen. +The "Output produced by doxygen" pane shows the messages produced by doxygen while it is running. +Before being able to run doxygen the settings have to be saved. +<dt>Show HTML output<dd>Clicking this button will open the main HTML output page in the default browser. +The button will be enabled after doxygen has finished. +<dt>Show configuration<dd>Clicking this button shows the configuration settings that are used when running +doxygen. The results will be shown in the "Output produced by doxygen" pane in compact textual form. +<dt>Condensed<dd>When checked the "Show configuration" button will only list the configuration +settings that differ from the default settings (analogous to `doxygen -x`). +<dt>Save Log ...<dd>Will save the information from the "Output produced by doxygen" +pane in a file as specified by the user. +</dl> + +\section dw_menu Menu options + +\subsection dw_menu_file File menu + +The file menu with a couple of useful items for loading and saving settings. -\image html doxywizard_menu.png "File menu" -\image latex doxywizard_menu.png "File menu" width=15cm +\image html doxywizard_menu_file.png "File menu" +\image latex doxywizard_menu_file.png "File menu" width=12.0cm <dl> -<dt>Open...<dd>This is the same as the "Load" button in the main window - and allows to open a configuration file from disk. -<dt>Save as..<dd>This is the same as the "Save" button in the main window - and can be used to save the current configuration settings to disk. -<dt>Recent configurations<dd>Allow to quickly load a recently saved - configuration. -<dt>Set as default...<dd>Stores the current configuration settings as the +<dt>Open...<dd>Load a configuration file from disk, based on a file + selection dialog. In case unsaved settings exist you will be asked to + confirm the action. +<dt>Open recent<dd>Quickly load a recently saved configuration file. + In case unsaved settings exist you will be asked to confirm the action. + This menu item is only accessible when there are recent files in the list. +<dt>Save<dd>Saves a configuration file to disk. In case the configuration + file has already been set this file name is used otherwise a selection dialog + will appear. In case the file already exists a confirmation is required. +<dt>Save as..<dd>Saves the current configuration settings to disk with + a specific name. This file name will become the currently set file name. +<dt>Quit<dd>Leave doxywizard, in case unsaved settings exist you will be asked to + confirm the action. +</dl> + +\subsection dw_menu_settings Settings menu + +\image html doxywizard_menu_settings.png "Settings menu" +\image latex doxywizard_menu_settings.png "Settings menu" width=6.7cm + +<dl> +<dt>Reset to factory defaults<dd>Restores the factory defaults as the default settings to use. + You will be asked to confirm the action. This menu item is only accessible when the current + settings differ from the default settings. +<dt>Use current settings at startup<dd>Stores the current configuration settings as the default to use next time the GUI is started. You will be asked to confirm the action. -<dt>Reset...<dd>Restores the factory defaults as the default settings to use. - You will be asked to confirm the action. +<dt>Clear recent list<dd>Clears the "Open recent" list in the \ref dw_menu_file. This menu + item is only accessible when there are recent files in the "Open recent" list. </dl> +\subsection dw_menu_help Help menu + +\image html doxywizard_menu_help.png "Help menu" +\image latex doxywizard_menu_help.png "Help menu" width=7.0cm + +<dl> +<dt>Online Manual<dd>Opens the doxygen manual from the doxygen home page in the system defined default HTML browser. +<dt>About<dd>Shows an About dialog with version information. +</dl> \htmlonly Go to the <a href="config.html">next</a> section or return to the diff --git a/doc/emojisup.doc b/doc/emojisup.doc index 0175780..2b8a16c 100644 --- a/doc/emojisup.doc +++ b/doc/emojisup.doc @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2018 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. * @@ -105,8 +105,8 @@ When invoking it with the `-d image_dir` option the images will by downloaded in By means of the doxygen configuration parameter \ref cfg_latex_emoji_directory "LATEX_EMOJI_DIRECTORY" the requested directory can be selected. -For convenience a zip with the result of running the script can also be downloaded from -http://www.doxygen.nl/dl/github_emojis.zip +For convenience a zip with the result of running the script can also be downloaded from +https://www.doxygen.nl/dl/github_emojis.zip For an overview of the supported emoji one can issue the command:<br> `doxygen -f emoji <outputFileName>` @@ -117,4 +117,4 @@ Go to the <a href="langhowto.html">next</a> section or return to the \endhtmlonly */ - + diff --git a/doc/expert_bool.png b/doc/expert_bool.png Binary files differnew file mode 100644 index 0000000..c2081e0 --- /dev/null +++ b/doc/expert_bool.png diff --git a/doc/expert_enum.png b/doc/expert_enum.png Binary files differnew file mode 100644 index 0000000..4672080 --- /dev/null +++ b/doc/expert_enum.png diff --git a/doc/expert_int.png b/doc/expert_int.png Binary files differnew file mode 100644 index 0000000..e5048f8 --- /dev/null +++ b/doc/expert_int.png diff --git a/doc/expert_list_dir.png b/doc/expert_list_dir.png Binary files differnew file mode 100644 index 0000000..6089dd1 --- /dev/null +++ b/doc/expert_list_dir.png diff --git a/doc/expert_list_file.png b/doc/expert_list_file.png Binary files differnew file mode 100644 index 0000000..2d5a99b --- /dev/null +++ b/doc/expert_list_file.png diff --git a/doc/expert_list_filedir.png b/doc/expert_list_filedir.png Binary files differnew file mode 100644 index 0000000..08681ec --- /dev/null +++ b/doc/expert_list_filedir.png diff --git a/doc/expert_list_string.png b/doc/expert_list_string.png Binary files differnew file mode 100644 index 0000000..9e5d96e --- /dev/null +++ b/doc/expert_list_string.png diff --git a/doc/expert_string_dir.png b/doc/expert_string_dir.png Binary files differnew file mode 100644 index 0000000..61479ca --- /dev/null +++ b/doc/expert_string_dir.png diff --git a/doc/expert_string_file.png b/doc/expert_string_file.png Binary files differnew file mode 100644 index 0000000..a4a61ae --- /dev/null +++ b/doc/expert_string_file.png diff --git a/doc/expert_string_image.png b/doc/expert_string_image.png Binary files differnew file mode 100644 index 0000000..c5cc9a0 --- /dev/null +++ b/doc/expert_string_image.png diff --git a/doc/expert_string_string.png b/doc/expert_string_string.png Binary files differnew file mode 100644 index 0000000..5d680ae --- /dev/null +++ b/doc/expert_string_string.png diff --git a/doc/faq.doc b/doc/faq.doc index 8a3aee8..95de571 100644 --- a/doc/faq.doc +++ b/doc/faq.doc @@ -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. * @@ -32,7 +32,7 @@ You should use the \ref cmdmainpage "\\mainpage" command inside a comment block * \section install_sec Installation * * \subsection step1 Step 1: Opening the box - * + * * etc... */ \endverbatim @@ -41,13 +41,13 @@ You should use the \ref cmdmainpage "\\mainpage" command inside a comment block Check the following: <ol> - <li>Is your class / file / namespace documented? If not, it will not + <li>Is your class / file / namespace documented? If not, it will not be extracted from the sources unless \ref cfg_extract_all "EXTRACT_ALL" is set to \c YES in the configuration file. <li>Are the members private? If so, you must set \ref cfg_extract_private "EXTRACT_PRIVATE" to \c YES to make them appear in the documentation. - <li>Is there a function macro in your class that does not end with a - semicolon (e.g. MY_MACRO())? If so then you have to instruct + <li>Is there a function macro in your class that does not end with a + semicolon (e.g. MY_MACRO())? If so then you have to instruct doxygen's preprocessor to remove it. This typically boils down to the following settings in the configuration file: @@ -61,14 +61,14 @@ PREDEFINED = MY_MACRO()= Please read the \ref preprocessing "preprocessing" section of the manual for more information. - </ol> + </ol> \section faq_extract_all When I set EXTRACT_ALL to NO none of my functions are shown in the documentation. -In order for global functions, variables, enums, typedefs, and defines +In order for global functions, variables, enums, typedefs, and defines to be documented you should document the file in which these commands are -located using a comment block containing a \ref cmdfile "\\file" (or \ref cmdfile "\@file") -command. +located using a comment block containing a \ref cmdfile "\\file" (or \ref cmdfile "\@file") +command. Alternatively, you can put all members in a group (or module) using the \ref cmdingroup "\\ingroup" command and then document the group using a comment @@ -76,28 +76,28 @@ block containing the \ref cmddefgroup "\\defgroup" command. For member functions or functions that are part of a namespace you should document either the class or namespace. - + \section faq_ext_mapping My file with a custom extension is not parsed (properly) (anymore). Doxygen only parses files that are specified as input (via the \ref cfg_input "INPUT" tag) and that match a specified extension (mentioned in \ref cfg_file_patterns "FILE_PATTERNS") -The list of files is then reduced by excluding files listed as \ref cfg_exclude "EXCLUDE" or +The list of files is then reduced by excluding files listed as \ref cfg_exclude "EXCLUDE" or files that match the patterns set by \ref cfg_exclude_patterns "EXCLUDE_PATTERNS". In the past doxygen parsed all files with an unknown extension as C files which could lead to undesired results. Since version 1.8.8, doxygen requires that you specify a mapping that tells -for a certain file extension, which parser to use. +for a certain file extension, which parser to use. This mapping is specified using the \ref cfg_extension_mapping "EXTENSION_MAPPING" tag. If no mapping is specified the file's contents will be ignored. \section faq_code How can I make doxygen ignore some code fragment? -The new and easiest way is to add one comment block -with a \ref cmdcond "\\cond" command at the start and one comment block +The new and easiest way is to add one comment block +with a \ref cmdcond "\\cond" command at the start and one comment block with a \ref cmdendcond "\\endcond" command at the end of the piece of code that should be ignored. This should be within the same file of course. -But you can also use doxygen's preprocessor for this: +But you can also use doxygen's preprocessor for this: If you put \verbatim #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -115,7 +115,7 @@ as \ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" is set to `YES`. \section faq_code_inc How can I change what is after the \#include in the class documentation? -In most cases you can use \ref cfg_strip_from_inc_path "STRIP_FROM_INC_PATH" +In most cases you can use \ref cfg_strip_from_inc_path "STRIP_FROM_INC_PATH" to strip a user defined part of a path. You can also document your class as follows @@ -132,7 +132,7 @@ To make doxygen put <br><br> \#include \<path/include.h\> </code> -in the documentation of the class MyClassName regardless of the name of the actual +in the documentation of the class MyClassName regardless of the name of the actual header file in which the definition of MyClassName is contained. If you want doxygen to show that the include file should be included using @@ -146,14 +146,14 @@ quotes instead of angle brackets you should type: \section faq_chm How can I use tag files in combination with compressed HTML? -If you want to refer from one compressed HTML file -\c a.chm to another compressed HTML file +If you want to refer from one compressed HTML file +\c a.chm to another compressed HTML file called \c b.chm, the link in \c a.chm must have the following format: \verbatim <a href="b.chm::/file.html"> \endverbatim -Unfortunately this only works if both compressed HTML files are in the same +Unfortunately this only works if both compressed HTML files are in the same directory. As a result you must rename the generated \c index.chm files for all projects @@ -161,7 +161,7 @@ into something unique and put all <code>.chm</code> files in one directory. Suppose you have a project \e a referring to a project \e b using tag file \c b.tag, then you could rename the \c index.chm for project \e a into -\c a.chm and the \c index.chm for project \e b into \c b.chm. In the +\c a.chm and the \c index.chm for project \e b into \c b.chm. In the configuration file for project \e a you write: \verbatim TAGFILES = b.tag=b.chm:: @@ -175,7 +175,7 @@ put in your own header file by writing your own header and feed that to \section faq_html_header The overall HTML output looks different, while I only wanted to use my own html header file -You probably forgot to include the stylesheet <code>doxygen.css</code> that +You probably forgot to include the stylesheet <code>doxygen.css</code> that doxygen generates. You can include this by putting \verbatim <LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css"> @@ -184,11 +184,11 @@ in the HEAD section of the HTML page. \section faq_use_qt Why does doxygen use Qt? -The most important reason is to have a platform abstraction for most -Unices and Windows by means of the QFile, QFileInfo, QDir, QDate, -QTime and QIODevice classes. -Another reason is for the nice and bug free utility classes, like QList, -QDict, QString, QArray, QTextStream, QRegExp, QXML etc. +The most important reason is to have a platform abstraction for most +Unices and Windows by means of the QFile, QFileInfo, QDir, QDate, +QTime and QIODevice classes. +Another reason is for the nice and bug free utility classes, like QList, +QDict, QString, QArray, QTextStream, QRegExp, QXML etc. The GUI front-end doxywizard uses Qt for... well... the GUI! @@ -207,32 +207,32 @@ remove the % and keep the word unlinked. \section faq_pgm_X My favorite programming language is X. Can I still use doxygen? -No, not as such; doxygen needs to understand the structure of what it reads. +No, not as such; doxygen needs to understand the structure of what it reads. If you don't mind spending some time on it, there are several options: - If the grammar of X is close to C or C++, then it is probably not too hard to tweak \c src/scanner.l a bit so the language is supported. This is done - for all other languages directly supported by doxygen + for all other languages directly supported by doxygen (i.e. Java, IDL, C#, PHP). - If the grammar of X is somewhat different than you can write an input filter that translates X into something similar enough to C/C++ for doxygen to understand (this approach is taken for VB, Object Pascal, and - JavaScript, see http://www.doxygen.org/download.html#helpers). -- If the grammar is completely different one could write a parser for X and - write a backend that produces a similar syntax tree as is done by + JavaScript, see https://www.doxygen.org/download.html#helpers). +- If the grammar is completely different one could write a parser for X and + write a backend that produces a similar syntax tree as is done by \c src/scanner.l (and also by \c src/tagreader.cpp while reading tag files). \section faq_lex Help! I get the cryptic message "input buffer overflow, can't enlarge buffer because scanner uses REJECT" This error happens when doxygen's lexical scanner has a rule that matches -more than 256K of input characters in one go. I've seen this happening -on a very large generated file (\>256K lines), where the built-in preprocessor +more than 256K of input characters in one go. I've seen this happening +on a very large generated file (\>256K lines), where the built-in preprocessor converted it into an empty file (with \>256K of newlines). Another case where this might happen is if you have lines in your code with more than -256K characters. +256K characters. If you have run into such a case and want me to fix it, you should send me a code fragment that triggers the message. To work around -the problem, put some line-breaks into your file, split it up into smaller +the problem, put some line-breaks into your file, split it up into smaller parts, or exclude it from the input using EXCLUDE. Another way to work around this problem is to use the cmake command with the option: @@ -244,17 +244,17 @@ In case this option is not given the default value of 262144 (i.e. 256K) will be \section faq_latex When running make in the latex directory I get "TeX capacity exceeded". Now what? -You can edit the texmf.cfg file to increase the default values of the +You can edit the texmf.cfg file to increase the default values of the various buffers and then run "texconfig init". \section faq_stl Why are dependencies via STL classes not shown in the dot graphs? -Doxygen is unaware of the STL classes, unless the +Doxygen is unaware of the STL classes, unless the option \ref cfg_builtin_stl_support "BUILTIN_STL_SUPPORT" is turned on. \section faq_search I have problems getting the search engine to work with PHP5 and/or windows -Please read <a href="searching.html">this</a> for hints on where to look. +Please read <a href="searching.html">this</a> for hints on where to look. \section faq_cmdline Can I configure doxygen from the command line? @@ -266,18 +266,23 @@ in a configuration file from the command line (assuming a UNIX like environment) ( cat Doxyfile ; echo "PROJECT_NUMBER=1.0" ) | doxygen - \endverbatim -For Windows the following would do the same: +For Windows command line the following would do the same: \verbatim ( type Doxyfile & echo PROJECT_NUMBER=1.0 ) | doxygen.exe - \endverbatim -If multiple options with the same name are specified then doxygen will use +For Windows Powershell (checked with version 5.1) the following would do the same: +\verbatim +&{ type Doxyfile ; echo "PROJECT_NUMBER=1.0" } | doxygen - +\endverbatim + +If multiple options with the same name are specified then doxygen will use the last one. To append to an existing option you can use the += operator. \section faq_name How did doxygen get its name? -Doxygen got its name from playing with the words +Doxygen got its name from playing with the words documentation and generator. \verbatim @@ -286,19 +291,19 @@ generator -> gen \endverbatim At the time I was looking into \c lex and \c yacc, where a lot of things start with -"yy", so the "y" slipped in and made things pronounceable +"yy", so the "y" slipped in and made things pronounceable (the proper pronouncement is Docs-ee-gen, so with a long "e"). \section faq_why What was the reason to develop doxygen? I once wrote a GUI widget based on the Qt library (it is still available at -https://sourceforge.net/projects/qdbttabular/ but hasn't been updated since 2002). -Qt had nicely generated documentation (using an internal tool which -<a href="http://rant.gulbrandsen.priv.no/udoc/history">they didn't want to release</a>) -and I wrote similar docs by hand. +https://sourceforge.net/projects/qdbttabular/ but hasn't been updated since 2002). +Qt had nicely generated documentation (using an internal tool which +<a href="https://rant.gulbrandsen.priv.no/udoc/history">they didn't want to release</a>) +and I wrote similar docs by hand. This was a nightmare to maintain, so I wanted a similar tool. I looked at Doc++ but that just wasn't good enough (it didn't support signals and -slots and did not have the Qt look and feel I had grown to like), +slots and did not have the Qt look and feel I had grown to like), so I started to write my own tool... \htmlonly diff --git a/doc/features.doc b/doc/features.doc index 461caef..e746ac3 100644 --- a/doc/features.doc +++ b/doc/features.doc @@ -100,7 +100,7 @@ Although doxygen can now be used in any project written in a language that is supported by doxygen, initially it was specifically designed to be used for projects that make use of Qt Software's -<A HREF="https://www.qt.io/developers/">Qt toolkit</A>. I have tried to +<A HREF="https://www.qt.io/developers">Qt toolkit</A>. I have tried to make doxygen `Qt-compatible'. That is: Doxygen can read the documentation contained in the Qt source code and create a class browser that looks quite similar to the one that is generated by Qt Software. Doxygen understands the C++ extensions diff --git a/doc/index.doc b/doc/index.doc index 60f4497..ae46087 100644 --- a/doc/index.doc +++ b/doc/index.doc @@ -62,7 +62,7 @@ This manual is divided into three parts, each of which is divided into several s The first part forms a user manual: <ul> <li>Section \ref install discusses how to - <a href="http://www.doxygen.org/download.html">download</a>, compile and install + <a href="https://www.doxygen.org/download.html">download</a>, compile and install doxygen for your platform. <li>Section \ref starting tells you how to generate your first piece of documentation quickly. @@ -140,11 +140,11 @@ input used in their production; they are not affected by this license. Doxygen supports a number of \ref output "output formats" where HTML is the most popular one. I've gathered -<a href="http://www.doxygen.org/results.html">some nice examples</a> +<a href="https://www.doxygen.org/results.html">some nice examples</a> of real-life projects using doxygen. These are part of a larger -<a href="http://www.doxygen.org/projects.html">list of projects</a> +<a href="https://www.doxygen.org/projects.html">list of projects</a> that use doxygen. If you know other projects, let <a href="mailto:doxygen@gmail.com?subject=New%20project%20using%20Doxygen">me</a> know and I'll add them. diff --git a/doc/install.doc b/doc/install.doc index 97a0d7a..99cecc6 100644 --- a/doc/install.doc +++ b/doc/install.doc @@ -20,7 +20,7 @@ \tableofcontents{html,latex} First go to the -<a href="http://www.doxygen.org/download.html">download</a> page +<a href="https://www.doxygen.org/download.html">download</a> page to get the latest distribution, if you have not downloaded doxygen already. \section install_src_unix Compiling from source on UNIX @@ -46,7 +46,7 @@ tools should be installed. <ul> <li>Qt Software's GUI toolkit - <a href="https://www.qt.io/developers/">Qt</A> + <a href="https://www.qt.io/developers">Qt</A> \addindex Qt version 4.3 or higher (including Qt 5). This is needed to build the GUI front-end doxywizard. @@ -178,7 +178,7 @@ The next step is to install modern versions of \c bison and \c flex (see https://sourceforge.net/projects/winflexbison/. After installation and adding them to your `path` rename `win_flex.exe` to `flex.exe` and `win_bison.exe` to `bison.exe`) \addindex python -Furthermore you have to install \c python (version 2.6 or higher, see https://www.python.org). +Furthermore you have to install \c python (version 2.7 or higher, see https://www.python.org). These packages are needed during the compilation process. Download doxygen's source tarball and put it somewhere (e.g. use <code>c:\\tools</code>) @@ -211,7 +211,7 @@ nmake \endverbatim Note that compiling Doxywizard requires Qt 4.3 or newer -(see https://www.qt.io/developers/). +(see https://www.qt.io/developers). Also read the next section for additional tools you may need to install to run doxygen with certain features enabled. diff --git a/doc/manual.sty b/doc/manual.sty index 643bd40..12f3911 100644 --- a/doc/manual.sty +++ b/doc/manual.sty @@ -8,33 +8,43 @@ % Setup fancy headings \RequirePackage{fancyhdr} -\pagestyle{fancyplain} \newcommand{\clearemptydoublepage}{% \newpage{\pagestyle{empty}\cleardoublepage}% } +% Used by @image +% (only if inline is specified) +\newlength{\DoxyInlineHeightChar} +\settoheight{\DoxyInlineHeightChar}{H} +\renewenvironment{DoxyInlineImage}{% +\settoheight{\DoxyInlineHeightChar}{H} +}{% +} + +% Headers & footers +\pagestyle{fancyplain} +\renewcommand{\footrulewidth}{0.4pt} +% +\fancypagestyle{fancyplain}{ +\fancyhf{} +\fancyhead[LE, RO]{\bfseries\thepage} +\fancyhead[LO]{\bfseries\rightmark} +\fancyhead[RE]{\bfseries\leftmark} +\fancyfoot[LO, RE]{\bfseries\scriptsize Generated by Doxygen @VERSION@ } +} +% +\fancypagestyle{plain}{ +\fancyhf{} +\fancyfoot[LO, RE]{\bfseries\scriptsize Generated by Doxygen @VERSION@ } +\renewcommand{\headrulewidth}{0pt}} +% +\pagestyle{fancyplain} \renewcommand{\chaptermark}[1]{% \markboth{#1}{}% } \renewcommand{\sectionmark}[1]{% \markright{\thesection\ #1}% } -\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}} -\fancyhead[CE]{\fancyplain{}{}} -\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}} -\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}} -\fancyhead[CO]{\fancyplain{}{}} -\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}} -\fancyfoot[LE]{\fancyplain{}{}} -\fancyfoot[CE]{\fancyplain{}{}} -\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen @VERSION@ }} -\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen @VERSION@ }} -\fancyfoot[CO]{\fancyplain{}{}} -\fancyfoot[RO]{\fancyplain{}{}} - -% Define caption that is also suitable in a table -\makeatletter -\def\doxyfigcaption{% -\refstepcounter{figure}% -\@dblarg{\@caption{figure}}} -\makeatother +% +\usepackage{xpatch} +\xpatchcmd{\part}{plain}{empty}{}{} diff --git a/doc/markdown.doc b/doc/markdown.doc index 883e831..eba9431 100644 --- a/doc/markdown.doc +++ b/doc/markdown.doc @@ -155,7 +155,10 @@ Examples: ______ Note that using asterisks in comment blocks does not work. See -\ref mddox_stars for details. +\ref mddox_stars for details.<br> +Note that when using hyphens and the previous line is not empty you have to +use at least one whitespace in the sequence of hyphens otherwise it might be +seen as a level 2 header (see \ref md_headers). \subsection md_emphasis Emphasis diff --git a/doc/starting.doc b/doc/starting.doc index 4c9823c..3ae2692 100644 --- a/doc/starting.doc +++ b/doc/starting.doc @@ -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. * @@ -17,12 +17,12 @@ /*! \page starting Getting started \tableofcontents{html,latex} -The executable \c doxygen is the main program that parses the sources and +The executable \c doxygen is the main program that parses the sources and generates the documentation. See section \ref doxygen_usage for more detailed usage information. -Optionally, the executable \c doxywizard can be used, which is a -\ref doxywizard_usage "graphical front-end" for editing the configuration file +Optionally, the executable \c doxywizard can be used, which is a +\ref doxywizard_usage "graphical front-end" for editing the configuration file that is used by doxygen and for running doxygen in a graphical environment. For Mac OS X doxywizard will be started by clicking on the doxygen application icon. @@ -31,7 +31,7 @@ The following figure shows the relation between the tools and the flow of information between them (it looks complex but that's only because it tries to be complete): -\image html infoflow.png "Doxygen information flow" +\image html infoflow.png "Doxygen information flow" \image latex infoflow.eps "Doxygen information flow" width=14cm \section step0 Step 0: Check if doxygen supports your programming language @@ -40,20 +40,20 @@ First, assure that your programming language has a reasonable chance of being recognized by doxygen. These languages are supported by default: C, C++, C#, Objective-C, IDL, Java, VHDL, PHP, Python, Fortran and D. It is possible to configure certain file type extensions to use certain parsers: -see the \ref cfg_extension_mapping "Configuration/ExtensionMappings" for details. -Also, completely different languages can be supported by using preprocessor -programs: see the <a href="http://www.doxygen.org/helpers.html">Helpers page</a> +see the \ref cfg_extension_mapping "Configuration/ExtensionMappings" for details. +Also, completely different languages can be supported by using preprocessor +programs: see the <a href="https://www.doxygen.org/helpers.html">Helpers page</a> for details. \section step1 Step 1: Creating a configuration file Doxygen uses a configuration file to determine all of its settings. Each project should get its own configuration file. A project can consist -of a single source file, but can also be an entire source tree that is +of a single source file, but can also be an entire source tree that is recursively scanned. -To simplify the creation of a configuration file, doxygen can create a -template configuration file for you. To do this call \c doxygen +To simplify the creation of a configuration file, doxygen can create a +template configuration file for you. To do this call \c doxygen from the command line with the \c -g option: \verbatim doxygen -g <config-file> @@ -61,48 +61,49 @@ doxygen -g <config-file> where \<config-file\> is the name of the configuration file. If you omit the file name, a file named \c Doxyfile will be created. If a file with the -name \<config-file\> already exists, doxygen will rename it to +name \<config-file\> already exists, doxygen will rename it to \<config-file\>.bak before generating the configuration template. -If you use <code>-</code> (i.e. the minus sign) as the file name then -doxygen will try to read the configuration file from standard +If you use <code>-</code> (i.e. the minus sign) as the file name then +doxygen will try to read the configuration file from standard input (<code>stdin</code>), which can be useful for scripting. -The configuration file has a format that is similar to that of a (simple) +The configuration file has a format that is similar to that of a (simple) Makefile. It consists of a number of assignments (tags) of the form: <tt>TAGNAME = VALUE</tt> or <br> <tt>TAGNAME = VALUE1 VALUE2 ... </tt><br> -You can probably leave the values of most tags in a generated template -configuration file to their default value. See section \ref config for -more details about the configuration file. +You can probably leave the values of most tags in a generated template +configuration file to their default value. See section \ref config for +more details about the configuration file. -If you do not wish to edit the configuration file with a text editor, you should -have a look at \ref doxywizard_usage "doxywizard", which is a GUI -front-end that can create, read and write doxygen configuration files, +If you do not wish to edit the configuration file with a text editor, you should +have a look at \ref doxywizard_usage "doxywizard", which is a GUI +front-end that can create, read and write doxygen configuration files, and allows setting configuration options by entering them via dialogs. -For a small project consisting of a few C and/or C++ source +For a small project consisting of a few C and/or C++ source and header files, you can leave \ref cfg_input "INPUT" tag empty and doxygen will search for sources in -the current directory. - -If you have a larger project consisting of a source directory or tree -you should assign the root directory or -directories to the \ref cfg_input "INPUT" tag, and add one or more file -patterns to the \ref cfg_file_patterns "FILE_PATTERNS" tag -(for instance `*.cpp *.h`). Only files that match one of the -patterns will be parsed (if the patterns are omitted a list of +the current directory. + +If you have a larger project consisting of a source directory or tree +you should assign the root directory or +directories to the \ref cfg_input "INPUT" tag, and add one or more file +patterns to the \ref cfg_file_patterns "FILE_PATTERNS" tag +(for instance `*.cpp *.h`). Only files that match one of the +patterns will be parsed (if the patterns are omitted a list of typical patterns is used for the types of files doxygen supports). -For recursive parsing of a source tree you must set -the \ref cfg_recursive "RECURSIVE" tag to \c YES. To further fine-tune the -list of files that is parsed the \ref cfg_exclude "EXCLUDE" and +For recursive parsing of a source tree you must set +the \ref cfg_recursive "RECURSIVE" tag to \c YES. To further fine-tune the +list of files that is parsed the \ref cfg_exclude "EXCLUDE" and \ref cfg_exclude_patterns "EXCLUDE_PATTERNS" tags can be used. To omit all \c test directories from a source tree for instance, one could use: -\verbatim EXCLUDE_PATTERNS = */test/* +\verbatim EXCLUDE_PATTERNS = */test/* \endverbatim +\anchor default_file_extension_mapping Doxygen looks at the file's extension to determine how to parse a file, using the following table: @@ -130,27 +131,30 @@ Extension | Language | Extension | Language | Extension | Language .mm |C / C++ | | | | | .txt |C / C++ | | | | | -Any other extension is not parsed unless it is added to -\ref cfg_file_patterns "FILE_PATTERNS" and the appropriate +Please note that the above list might contain more items than that by default set +in the \ref cfg_file_patterns "FILE_PATTERNS". + +Any extension that is not parsed can be set by adding it to +\ref cfg_file_patterns "FILE_PATTERNS" and when the appropriate \ref cfg_extension_mapping "EXTENSION_MAPPING" is set. \anchor extract_all -If you start using doxygen for an existing project (thus without any +If you start using doxygen for an existing project (thus without any documentation that doxygen is aware of), you can still get an idea of -what the structure is and how the documented result would look like. -To do so, you must set -the \ref cfg_extract_all "EXTRACT_ALL" tag in the configuration file -to \c YES. Then, doxygen will pretend everything in your sources is documented. -Please note that as a consequence warnings about undocumented members -will not be generated as long as \ref cfg_extract_all "EXTRACT_ALL" is +what the structure is and how the documented result would look like. +To do so, you must set +the \ref cfg_extract_all "EXTRACT_ALL" tag in the configuration file +to \c YES. Then, doxygen will pretend everything in your sources is documented. +Please note that as a consequence warnings about undocumented members +will not be generated as long as \ref cfg_extract_all "EXTRACT_ALL" is set to \c YES. -To analyze an existing piece of software it is useful to cross-reference +To analyze an existing piece of software it is useful to cross-reference a (documented) entity with its definition in the source files. Doxygen will -generate such cross-references if you set -the \ref cfg_source_browser "SOURCE_BROWSER" tag to \c YES. +generate such cross-references if you set +the \ref cfg_source_browser "SOURCE_BROWSER" tag to \c YES. It can also include the sources directly into the documentation by setting -\ref cfg_inline_sources "INLINE_SOURCES" to \c YES (this can be handy for +\ref cfg_inline_sources "INLINE_SOURCES" to \c YES (this can be handy for code reviews for instance). \section step2 Step 2: Running doxygen @@ -160,168 +164,168 @@ To generate the documentation you can now enter: doxygen <config-file> \endverbatim -Depending on your settings doxygen will create \c html, \c rtf, -\c latex, \c xml, \c man, and/or docbook directories inside the output directory. +Depending on your settings doxygen will create \c html, \c rtf, +\c latex, \c xml, \c man, and/or docbook directories inside the output directory. As the names suggest these directories contain the generated documentation in HTML, RTF, \LaTeX, XML, Unix-Man page, and DocBook format. The default output directory is the directory in which \c doxygen -is started. The root directory to which the output is written can be changed +is started. The root directory to which the output is written can be changed using the \ref cfg_output_directory "OUTPUT_DIRECTORY". The format specific directory within the output directory can be selected using the \ref cfg_html_output "HTML_OUTPUT", \ref cfg_rtf_output "RTF_OUTPUT", \ref cfg_latex_output "LATEX_OUTPUT", \ref cfg_xml_output "XML_OUTPUT", \ref cfg_man_output "MAN_OUTPUT", and \ref cfg_docbook_output "DOCBOOK_OUTPUT". -tags of the configuration file. If the output directory does not exist, +tags of the configuration file. If the output directory does not exist, \c doxygen will try to create it for you (but it will \e not try to create -a whole path recursively, like <code>mkdir -p</code> does). +a whole path recursively, like <code>mkdir -p</code> does). \subsection html_out HTML output \addindex browser The generated HTML documentation can be viewed by pointing a HTML browser to the \c index.html file in the \c html directory. For the best results a browser that supports cascading style sheets (CSS) should be used -(I'm using Mozilla Firefox, Google Chrome, Safari, and sometimes -IE8, IE9, and Opera to test the generated output). +(I'm using Mozilla Firefox, Google Chrome, Safari, and sometimes +IE8, IE9, and Opera to test the generated output). -Some of the features the HTML section (such as -\ref cfg_generate_treeview "GENERATE_TREEVIEW" or the search engine) -require a browser that supports Dynamic HTML and JavaScript enabled. +Some of the features the HTML section (such as +\ref cfg_generate_treeview "GENERATE_TREEVIEW" or the search engine) +require a browser that supports Dynamic HTML and JavaScript enabled. \subsection latex_out LaTeX output \addindex LaTeX -The generated \LaTeX documentation must first be compiled by +The generated \LaTeX documentation must first be compiled by a \LaTeX compiler (I use a recent teTeX distribution for Linux -and MacOSX and MikTex for Windows). +and MacOSX and MikTex for Windows). To simplify the process of compiling the generated documentation, \c doxygen writes a \c Makefile into the \c latex directory -(on the Windows platform also a \c make.bat batch file is generated). +(on the Windows platform also a \c make.bat batch file is generated). The contents and targets in the \c Makefile depend on the setting of \ref cfg_use_pdflatex "USE_PDFLATEX". If it is disabled (set to \c NO), then typing \c make in the \c latex directory a \c dvi file called \c refman.dvi -will be generated. This file can then be viewed using \c xdvi or -converted into a PostScript file \c refman.ps by -typing `make ps` (this requires `dvips`). +will be generated. This file can then be viewed using \c xdvi or +converted into a PostScript file \c refman.ps by +typing `make ps` (this requires `dvips`). To put 2 pages on one physical page use `make ps_2on1` instead. The resulting PostScript file can be send to a PostScript -printer. If you do not have a PostScript printer, you can try to use +printer. If you do not have a PostScript printer, you can try to use ghostscript to convert PostScript into something your printer understands. Conversion to PDF is also possible if you have installed the ghostscript -interpreter; just type `make pdf` (or `make pdf_2on1`). +interpreter; just type `make pdf` (or `make pdf_2on1`). -To get the best results for PDF output you should set -the \ref cfg_pdf_hyperlinks "PDF_HYPERLINKS" -and \ref cfg_use_pdflatex "USE_PDFLATEX" tags to \c YES. -In this case the \c Makefile will only contain a target to build +To get the best results for PDF output you should set +the \ref cfg_pdf_hyperlinks "PDF_HYPERLINKS" +and \ref cfg_use_pdflatex "USE_PDFLATEX" tags to \c YES. +In this case the \c Makefile will only contain a target to build \c refman.pdf directly. \subsection rtf_out RTF output \addindex RTF Doxygen combines the RTF output to a single file called refman.rtf. This file is optimized for importing into the Microsoft Word. Certain information -is encoded using so called fields. To show the actual value you need to +is encoded using so called fields. To show the actual value you need to select all (Edit - select all) and then toggle fields (right click and select the option from the drop down menu). \subsection xml_out XML output \addindex XML -The XML output consists of a structured "dump" of the information gathered -by doxygen. Each compound (class/namespace/file/...) has its own XML file -and there is also an index file called `index.xml`. +The XML output consists of a structured "dump" of the information gathered +by doxygen. Each compound (class/namespace/file/...) has its own XML file +and there is also an index file called `index.xml`. A file called `combine.xslt` -XSLT script is also generated and can be used to combine all XML files -into a single file. +XSLT script is also generated and can be used to combine all XML files +into a single file. Doxygen also generates two XML schema files `index.xsd` (for the index file) and `compound.xsd` (for the compound files). -This schema file describes the possible elements, their attributes and -how they are structured, i.e. it the describes the grammar of the XML +This schema file describes the possible elements, their attributes and +how they are structured, i.e. it the describes the grammar of the XML files and can be used for validation or to steer XSLT scripts. In the `addon/doxmlparser` directory you can find a parser library for reading -the XML output produced by doxygen in an incremental way +the XML output produced by doxygen in an incremental way (see `addon/doxmlparser/include/doxmlintf.h` for the interface of the library) \subsection man_out Man page output \addindex man The generated man pages can be viewed using the \c man program. You do need to make sure the man directory is in the man path (see the \c MANPATH -environment variable). Note that there are some limitations to the -capabilities of the man page format, so some information +environment variable). Note that there are some limitations to the +capabilities of the man page format, so some information (like class diagrams, cross references and formulas) will be lost. \subsection docbook_out DocBook output \addindex docbook -Doxygen can also generate output in the +Doxygen can also generate output in the <a href="https://docbook.org/">DocBook</a> format. How to process the DocBook output is beyond the scope of this manual. \section step3 Step 3: Documenting the sources -Although documenting the sources is presented as step 3, in a new project +Although documenting the sources is presented as step 3, in a new project this should of course be step 1. Here I assume -you already have some code and you want doxygen to generate a nice document +you already have some code and you want doxygen to generate a nice document describing the API and maybe the internals and some related design documentation as well. -If the \ref cfg_extract_all "EXTRACT_ALL" option is set to \c NO in the -configuration file (the default), then doxygen will only generate -documentation for \e documented entities. So -how do you document these? For members, classes and namespaces there are +If the \ref cfg_extract_all "EXTRACT_ALL" option is set to \c NO in the +configuration file (the default), then doxygen will only generate +documentation for \e documented entities. So +how do you document these? For members, classes and namespaces there are basically two options: 1. Place a \e special documentation block in front of the declaration or definition of the member, class or namespace. For file, class and namespace - members it is also allowed to place the documentation directly after the - member. - - See section \ref specialblock to learn more about special + members it is also allowed to place the documentation directly after the + member. + + See section \ref specialblock to learn more about special documentation blocks. -2. Place a special documentation block somewhere else (another file or - another location) \e and put a <em>structural command</em> in the - documentation block. A structural command links a documentation block - to a certain entity that can be documented (e.g. a member, class, - namespace or file). - - See section \ref structuralcommands to learn more +2. Place a special documentation block somewhere else (another file or + another location) \e and put a <em>structural command</em> in the + documentation block. A structural command links a documentation block + to a certain entity that can be documented (e.g. a member, class, + namespace or file). + + See section \ref structuralcommands to learn more about structural commands. The advantage of the first option is that you do not have to repeat the name of the entity. Files can only be documented using the second option, since there is -no way to put a documentation block before a file. Of course, file members -(functions, variables, typedefs, defines) do not need an explicit -structural command; just putting a special documentation block in front or -behind them will work fine. +no way to put a documentation block before a file. Of course, file members +(functions, variables, typedefs, defines) do not need an explicit +structural command; just putting a special documentation block in front or +behind them will work fine. The text inside a special documentation block is parsed before it is written to the HTML and/or \LaTeX output files. \addindex parsing During parsing the following steps take place: -- Markdown formatting is replaced by corresponding HTML or special +- Markdown formatting is replaced by corresponding HTML or special commands. - The special commands inside the documentation are executed. See section \ref commands for an overview of all commands. -- If a line starts with some whitespace followed by one or more asterisks - (`*`) and then optionally more whitespace, +- If a line starts with some whitespace followed by one or more asterisks + (`*`) and then optionally more whitespace, then all whitespace and asterisks are removed. - All resulting blank lines are treated as a paragraph separators. - This saves you from placing new-paragraph commands yourself + This saves you from placing new-paragraph commands yourself in order to make the generated documentation readable. - Links are created for words corresponding to documented classes (unless the word is preceded by a \%; then the word will not be linked and - the \% sign is removed). + the \% sign is removed). - Links to members are created when certain patterns are found in the text. See section \ref autolink for more information on how the automatic link generation works. -- HTML tags that are in the documentation are interpreted and converted - to \LaTeX equivalents for the \LaTeX output. +- HTML tags that are in the documentation are interpreted and converted + to \LaTeX equivalents for the \LaTeX output. See section \ref htmlcmds for an overview of all supported HTML tags. \htmlonly diff --git a/doc/translator.py b/doc/translator.py index c4c75ef..af1ec4c 100644 --- a/doc/translator.py +++ b/doc/translator.py @@ -2002,11 +2002,11 @@ class TrManager: if __name__ == '__main__':
- # The Python 2.6+ or 3.3+ is required.
+ # The Python 2.7+ or 3.3+ is required.
major = sys.version_info[0]
minor = sys.version_info[1]
- if (major == 2 and minor < 6) or (major == 3 and minor < 0):
- print('Python 2.6+ or Python 3.0+ are required for the script')
+ if (major == 2 and minor < 7) or (major == 3 and minor < 0):
+ print('Python 2.7+ or Python 3.0+ are required for the script')
sys.exit(1)
# The translator manager builds the Transl objects, parses the related
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3f1c79b..194b427 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,7 @@ file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/examples - ${PROJECT_BINARY_DIR}/html/examples) -file(GLOB EXAMPLE_FILES RELATIVE ${CMAKE_SOURCE_DIR}/examples "*") + ${PROJECT_BINARY_DIR}/html/examples + ${PROJECT_BINARY_DIR}/latex/examples) +file(GLOB EXAMPLE_FILES RELATIVE ${PROJECT_SOURCE_DIR}/examples "*") if (DOT) set(DIAGRAM_EXAMPLE ${PROJECT_BINARY_DIR}/html/examples/diagrams/html/index.html) @@ -8,8 +9,8 @@ endif() foreach (f ${EXAMPLE_FILES}) add_custom_command( - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/examples/${f}" "${PROJECT_BINARY_DIR}/examples/" - DEPENDS "${CMAKE_SOURCE_DIR}/examples/${f}" + COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/examples/${f}" "${PROJECT_BINARY_DIR}/examples/" + DEPENDS "${PROJECT_SOURCE_DIR}/examples/${f}" OUTPUT "${PROJECT_BINARY_DIR}/examples/${f}" ) set_source_files_properties("${PROJECT_BINARY_DIR}/examples/${f}" PROPERTIES GENERATED 1) @@ -50,10 +51,12 @@ foreach (f_inp ${BASIC_EXAMPLES}) string(REGEX REPLACE ".*:" "" f_ext ${f_inp}) string(REGEX REPLACE ":.*" "" f ${f_inp}) add_custom_command( + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/html/examples/${f} + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/latex/examples/${f} COMMAND ${EXECUTABLE_OUTPUT_PATH}/doxygen ${f}.cfg - COMMAND ${PYTHON_EXECUTABLE} ${TOP}/examples/strip_example.py < ${PROJECT_BINARY_DIR}/html/examples/${f}/latex/refman.tex > ${PROJECT_BINARY_DIR}/html/examples/${f}/latex/refman_doc.tex + COMMAND ${PYTHON_EXECUTABLE} ${TOP}/examples/strip_example.py < ${PROJECT_BINARY_DIR}/latex/examples/${f}/latex/refman.tex > ${PROJECT_BINARY_DIR}/latex/examples/${f}/latex/refman_doc.tex DEPENDS doxygen ${f}.${f_ext} ${f}.cfg ${TOP}/examples/strip_example.py - OUTPUT ${PROJECT_BINARY_DIR}/html/examples/${f}/html/index.html ${PROJECT_BINARY_DIR}/html/examples/${f}/latex/refman_doc.tex + OUTPUT ${PROJECT_BINARY_DIR}/html/examples/${f}/html/index.html ${PROJECT_BINARY_DIR}/latex/examples/${f}/latex/refman_doc.tex ) set(EXAMPLES_RES ${EXAMPLES_RES} "" ${PROJECT_BINARY_DIR}/html/examples/${f}/html/index.html) endforeach() @@ -67,9 +70,11 @@ add_custom_target(examples if (DOT) add_custom_command( + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/html/examples/diagrams + COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/latex/examples/diagrams COMMAND ${EXECUTABLE_OUTPUT_PATH}/doxygen diagrams.cfg - COMMAND ${PYTHON_EXECUTABLE} ${TOP}/examples/strip_example.py < ${PROJECT_BINARY_DIR}/html/examples/diagrams/latex/refman.tex > ${PROJECT_BINARY_DIR}/html/examples/diagrams/latex/refman_doc.tex + COMMAND ${PYTHON_EXECUTABLE} ${TOP}/examples/strip_example.py < ${PROJECT_BINARY_DIR}/latex/examples/diagrams/latex/refman.tex > ${PROJECT_BINARY_DIR}/latex/examples/diagrams/latex/refman_doc.tex DEPENDS doxygen diagrams_a.h diagrams_b.h diagrams_c.h diagrams_d.h diagrams_e.h diagrams.cfg ${TOP}/examples/strip_example.py - OUTPUT ${PROJECT_BINARY_DIR}/html/examples/diagrams/html/index.html ${PROJECT_BINARY_DIR}/html/examples/diagrams/latex/refman_doc.tex + OUTPUT ${PROJECT_BINARY_DIR}/html/examples/diagrams/html/index.html ${PROJECT_BINARY_DIR}/latex/examples/diagrams/latex/refman_doc.tex ) endif(DOT) diff --git a/examples/afterdoc.cfg b/examples/afterdoc.cfg index 0542929..71c2a88 100644 --- a/examples/afterdoc.cfg +++ b/examples/afterdoc.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "AfterDocs" -OUTPUT_DIRECTORY = ../html/examples/afterdoc +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/afterdoc/html +LATEX_OUTPUT = latex/examples/afterdoc/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/author.cfg b/examples/author.cfg index 2fafbfe..1107e2c 100644 --- a/examples/author.cfg +++ b/examples/author.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Author Command" -OUTPUT_DIRECTORY = ../html/examples/author +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/author/html +LATEX_OUTPUT = latex/examples/author/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/autolink.cfg b/examples/autolink.cfg index 68e5192..25607eb 100644 --- a/examples/autolink.cfg +++ b/examples/autolink.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Automatic link generation" -OUTPUT_DIRECTORY = ../html/examples/autolink +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/autolink/html +LATEX_OUTPUT = latex/examples/autolink/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/class.cfg b/examples/class.cfg index 5d75373..c8c8bdc 100644 --- a/examples/class.cfg +++ b/examples/class.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Class Command" -OUTPUT_DIRECTORY = ../html/examples/class +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/class/html +LATEX_OUTPUT = latex/examples/class/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/define.cfg b/examples/define.cfg index 61c0f52..63662c5 100644 --- a/examples/define.cfg +++ b/examples/define.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Define Command" -OUTPUT_DIRECTORY = ../html/examples/define +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/define/html +LATEX_OUTPUT = latex/examples/define/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -12,3 +14,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/diagrams.cfg b/examples/diagrams.cfg index c2e637d..04d972c 100644 --- a/examples/diagrams.cfg +++ b/examples/diagrams.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Diagrams" -OUTPUT_DIRECTORY = ../html/examples/diagrams +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/diagrams/html +LATEX_OUTPUT = latex/examples/diagrams/latex HAVE_DOT = YES EXTRACT_ALL = YES GENERATE_LATEX = YES @@ -15,3 +17,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/docstring.cfg b/examples/docstring.cfg index 60b089e..2e18b0a 100644 --- a/examples/docstring.cfg +++ b/examples/docstring.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Python" -OUTPUT_DIRECTORY = ../html/examples/docstring +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/docstring/html +LATEX_OUTPUT = latex/examples/docstring/latex EXTRACT_ALL = YES GENERATE_LATEX = YES GENERATE_MAN = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/enum.cfg b/examples/enum.cfg index e5540bd..8439b6f 100644 --- a/examples/enum.cfg +++ b/examples/enum.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Enum Command" -OUTPUT_DIRECTORY = ../html/examples/enum +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/enum/html +LATEX_OUTPUT = latex/examples/enum/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/example.cfg b/examples/example.cfg index 22266d4..1f8809d 100644 --- a/examples/example.cfg +++ b/examples/example.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Example Command" -OUTPUT_DIRECTORY = ../html/examples/example +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/example/html +LATEX_OUTPUT = latex/examples/example/latex GENERATE_TAGFILE = example.tag GENERATE_LATEX = YES GENERATE_MAN = NO @@ -12,3 +14,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/file.cfg b/examples/file.cfg index ef67ae6..1137fec 100644 --- a/examples/file.cfg +++ b/examples/file.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "File Command" -OUTPUT_DIRECTORY = ../html/examples/file +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/file/html +LATEX_OUTPUT = latex/examples/file/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/func.cfg b/examples/func.cfg index 2f455d9..a46a02d 100644 --- a/examples/func.cfg +++ b/examples/func.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Fn Command" -OUTPUT_DIRECTORY = ../html/examples/func +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/func/html +LATEX_OUTPUT = latex/examples/func/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/group.cfg b/examples/group.cfg index 83911b8..3d357fc 100644 --- a/examples/group.cfg +++ b/examples/group.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Grouping" -OUTPUT_DIRECTORY = ../html/examples/group +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/group/html +LATEX_OUTPUT = latex/examples/group/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/include.cfg b/examples/include.cfg index abaecc6..0a88b8b 100644 --- a/examples/include.cfg +++ b/examples/include.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Include Command" -OUTPUT_DIRECTORY = ../html/examples/include +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/include/html +LATEX_OUTPUT = latex/examples/include/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/javadoc-banner.cfg b/examples/javadoc-banner.cfg index d650dbc..06afc88 100644 --- a/examples/javadoc-banner.cfg +++ b/examples/javadoc-banner.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Javadoc Banner" -OUTPUT_DIRECTORY = ../html/examples/javadoc-banner +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/javadoc-banner/html +LATEX_OUTPUT = latex/examples/javadoc-banner/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -13,3 +15,4 @@ SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES EXTRACT_ALL = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/jdstyle.cfg b/examples/jdstyle.cfg index d94089d..7594b78 100644 --- a/examples/jdstyle.cfg +++ b/examples/jdstyle.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Javadoc Style" -OUTPUT_DIRECTORY = ../html/examples/jdstyle +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/jdstyle/html +LATEX_OUTPUT = latex/examples/jdstyle/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/manual.cfg b/examples/manual.cfg index 07040d9..aac6d2c 100644 --- a/examples/manual.cfg +++ b/examples/manual.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Manual inheritance and membership" -OUTPUT_DIRECTORY = ../html/examples/manual +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/manual/html +LATEX_OUTPUT = latex/examples/manual/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -16,3 +18,4 @@ REFERENCES_RELATION = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/memgrp.cfg b/examples/memgrp.cfg index d609778..ac68e69 100644 --- a/examples/memgrp.cfg +++ b/examples/memgrp.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Member Grouping" -OUTPUT_DIRECTORY = ../html/examples/memgrp +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/memgrp/html +LATEX_OUTPUT = latex/examples/memgrp/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/mux.cfg b/examples/mux.cfg index 861f2f6..bfc3472 100644 --- a/examples/mux.cfg +++ b/examples/mux.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = Mux -OUTPUT_DIRECTORY = ../html/examples/mux +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/mux/html +LATEX_OUTPUT = latex/examples/mux/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -16,3 +18,4 @@ ENABLE_PREPROCESSING = NO EXTRACT_PACKAGE = YES COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/overload.cfg b/examples/overload.cfg index 71ebcc5..2950b71 100644 --- a/examples/overload.cfg +++ b/examples/overload.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Overloaded Command" -OUTPUT_DIRECTORY = ../html/examples/overload +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/overload/html +LATEX_OUTPUT = latex/examples/overload/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/page.cfg b/examples/page.cfg index 972368a..f5a1540 100644 --- a/examples/page.cfg +++ b/examples/page.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Page Command" -OUTPUT_DIRECTORY = ../html/examples/page +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/page/html +LATEX_OUTPUT = latex/examples/page/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/par.cfg b/examples/par.cfg index fe4be84..977cd07 100644 --- a/examples/par.cfg +++ b/examples/par.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Par Command" -OUTPUT_DIRECTORY = ../html/examples/par +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/par/html +LATEX_OUTPUT = latex/examples/par/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/pyexample.cfg b/examples/pyexample.cfg index 4569425..edbaeac 100644 --- a/examples/pyexample.cfg +++ b/examples/pyexample.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Python" -OUTPUT_DIRECTORY = ../html/examples/pyexample +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/pyexample/html +LATEX_OUTPUT = latex/examples/pyexample/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/qtstyle.cfg b/examples/qtstyle.cfg index 1516c7e..6c9f67a 100644 --- a/examples/qtstyle.cfg +++ b/examples/qtstyle.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Qt Style" -OUTPUT_DIRECTORY = ../html/examples/qtstyle +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/qtstyle/html +LATEX_OUTPUT = latex/examples/qtstyle/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/relates.cfg b/examples/relates.cfg index 89f46da..9c05def 100644 --- a/examples/relates.cfg +++ b/examples/relates.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Relates Command" -OUTPUT_DIRECTORY = ../html/examples/relates +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/relates/html +LATEX_OUTPUT = latex/examples/relates/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/restypedef.cfg b/examples/restypedef.cfg index 63d2ea5..76c07e4 100644 --- a/examples/restypedef.cfg +++ b/examples/restypedef.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Resolving Typedefs" -OUTPUT_DIRECTORY = ../html/examples/restypedef +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/restypedef/html +LATEX_OUTPUT = latex/examples/restypedef/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/structcmd.cfg b/examples/structcmd.cfg index f926ddf..7521516 100644 --- a/examples/structcmd.cfg +++ b/examples/structcmd.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Structural commands" -OUTPUT_DIRECTORY = ../html/examples/structcmd +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/structcmd/html +LATEX_OUTPUT = latex/examples/structcmd/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/tag.cfg b/examples/tag.cfg index 12b3c5b..db0f621 100644 --- a/examples/tag.cfg +++ b/examples/tag.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Tag Files" -OUTPUT_DIRECTORY = ../html/examples/tag +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/tag/html +LATEX_OUTPUT = latex/examples/tag/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -11,3 +13,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/examples/templ.cfg b/examples/templ.cfg index c34633f..3dbf4a5 100644 --- a/examples/templ.cfg +++ b/examples/templ.cfg @@ -1,5 +1,7 @@ PROJECT_NAME = "Template Test" -OUTPUT_DIRECTORY = ../html/examples/templ +OUTPUT_DIRECTORY = .. +HTML_OUTPUT = html/examples/templ/html +LATEX_OUTPUT = latex/examples/templ/latex GENERATE_LATEX = YES GENERATE_MAN = NO GENERATE_RTF = NO @@ -10,3 +12,4 @@ JAVADOC_AUTOBRIEF = YES SEARCHENGINE = NO COMPACT_LATEX = YES LATEX_HIDE_INDICES = YES +WARN_AS_ERROR = FAIL_ON_WARNINGS diff --git a/libmscgen/CMakeLists.txt b/libmscgen/CMakeLists.txt index 079fcfc..0a23900 100644 --- a/libmscgen/CMakeLists.txt +++ b/libmscgen/CMakeLists.txt @@ -1,14 +1,14 @@ include_directories( - ${CMAKE_SOURCE_DIR}/liblodepng - ${CMAKE_SOURCE_DIR}/libmscgen + ${PROJECT_SOURCE_DIR}/liblodepng + ${PROJECT_SOURCE_DIR}/libmscgen ${GENERATED_SRC} ) set(LEX_FILES mscgen_lexer) foreach(lex_file ${LEX_FILES}) add_custom_command( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/libmscgen/${lex_file}.l > ${GENERATED_SRC}/${lex_file}.l.h - DEPENDS ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/libmscgen/${lex_file}.l + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/libmscgen/${lex_file}.l > ${GENERATED_SRC}/${lex_file}.l.h + DEPENDS ${PROJECT_SOURCE_DIR}/src/scan_states.py ${PROJECT_SOURCE_DIR}/libmscgen/${lex_file}.l OUTPUT ${GENERATED_SRC}/${lex_file}.l.h ) set_source_files_properties(${GENERATED_SRC}/${lex_file}.l.h PROPERTIES GENERATED 1) diff --git a/libmscgen/mscgen_language.y b/libmscgen/mscgen_language.y index 02b36bb..52dedb3 100644 --- a/libmscgen/mscgen_language.y +++ b/libmscgen/mscgen_language.y @@ -209,6 +209,7 @@ Msc MscParse(FILE *in) yyin = in; + lex_resetparser(); /* Parse, and check that no errors are found */ if(yyparse((void *)&m) != 0) { diff --git a/libmscgen/mscgen_lexer.h b/libmscgen/mscgen_lexer.h index 0cbb21f..bba38c1 100644 --- a/libmscgen/mscgen_lexer.h +++ b/libmscgen/mscgen_lexer.h @@ -56,6 +56,7 @@ Boolean lex_getutf8(void); unsigned long lex_getlinenum(void); char *lex_getline(void); void lex_destroy(void); +void lex_resetparser(void); #endif /* MSCGEN_LEXER_H */ diff --git a/libmscgen/mscgen_lexer.l b/libmscgen/mscgen_lexer.l index 52f5e05..ea812f9 100644 --- a/libmscgen/mscgen_lexer.l +++ b/libmscgen/mscgen_lexer.l @@ -234,5 +234,12 @@ Boolean lex_getutf8(void) return lex_utf8; } +void lex_resetparser() +{ + lex_linenum = 1; + lex_line = NULL; + lex_utf8 = FALSE; +} + #include "mscgen_lexer.l.h" /* END OF FILE */ diff --git a/libversion/CMakeLists.txt b/libversion/CMakeLists.txt index 009c236..9bd87c3 100644 --- a/libversion/CMakeLists.txt +++ b/libversion/CMakeLists.txt @@ -1,16 +1,16 @@ # vim:ts=4:sw=4:expandtab:autoindent: # setup information for doxygen version handling -set(PRE_CONFIGURE_DOXYGEN_VERSION_FILE "${CMAKE_SOURCE_DIR}/libversion/doxyversion.cpp.in") +set(PRE_CONFIGURE_DOXYGEN_VERSION_FILE "${PROJECT_SOURCE_DIR}/libversion/doxyversion.cpp.in") set(POST_CONFIGURE_DOXYGEN_VERSION_FILE "${GENERATED_SRC}/doxyversion.cpp") # setup information for git version handling -set(PRE_CONFIGURE_GIT_VERSION_FILE "${CMAKE_SOURCE_DIR}/libversion/gitversion.cpp.in") +set(PRE_CONFIGURE_GIT_VERSION_FILE "${PROJECT_SOURCE_DIR}/libversion/gitversion.cpp.in") set(POST_CONFIGURE_GIT_VERSION_FILE "${GENERATED_SRC}/gitversion.cpp") set(GIT_STATE_FILE "${GENERATED_SRC}/git_state") -include(${CMAKE_SOURCE_DIR}/cmake/git_watcher.cmake) -include(${CMAKE_SOURCE_DIR}/cmake/doxygen_version.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/git_watcher.cmake) +include(${PROJECT_SOURCE_DIR}/cmake/doxygen_version.cmake) include_directories( . diff --git a/qtools/CMakeLists.txt b/qtools/CMakeLists.txt index a7082c7..d49ca47 100644 --- a/qtools/CMakeLists.txt +++ b/qtools/CMakeLists.txt @@ -10,12 +10,10 @@ qdir.cpp qfile.cpp qfileinfo.cpp qgarray.cpp -qgcache.cpp qgdict.cpp qglist.cpp qglobal.cpp qgstring.cpp -qgvector.cpp qiodevice.cpp qregexp.cpp qstring.cpp diff --git a/qtools/qcache.h b/qtools/qcache.h deleted file mode 100644 index 87f9866..0000000 --- a/qtools/qcache.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** -** Definition of QCache template class -** -** Created : 950209 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#ifndef QCACHE_H -#define QCACHE_H - -#ifndef QT_H -#include "qgcache.h" -#endif // QT_H - -template<class type> class Q_EXPORT QCache : public QGCache -{ -public: - QCache( const QCache<type> &c ) : QGCache(c) {} - QCache( int maxCost=100, uint size=17, bool caseSensitive=TRUE ) - : QGCache( maxCost, size, AsciiKey, caseSensitive, TRUE ) {} - ~QCache() { clear(); } - QCache<type> &operator=( const QCache<type> &c ) - { return (QCache<type>&)QGCache::operator=(c); } - int maxCost() const { return QGCache::maxCost(); } - int totalCost() const { return QGCache::totalCost(); } - void setMaxCost( int m ) { QGCache::setMaxCost(m); } - uint count() const { return QGCache::count(); } - uint size() const { return QGCache::size(); } - bool isEmpty() const { return QGCache::count() == 0; } - void clear() { QGCache::clear(); } - bool insert( const char *k, const type *d, int c=1, int p=0 ) - { return QGCache::insert_other(k,(Item)d,c,p);} - bool remove( const char *k ) - { return QGCache::remove_other(k); } - type *take( const char *k ) - { return (type *)QGCache::take_other(k); } - type *find( const char *k, bool ref=TRUE ) const - { return (type *)QGCache::find_other(k,ref);} - type *operator[]( const char *k ) const - { return (type *)QGCache::find_other(k);} - void statistics() const { QGCache::statistics(); } - int hits() const { return QGCache::hits(); } - int misses() const { return QGCache::misses(); } -private: - void deleteItem( Item d ) { if ( del_item ) delete (type *)d; } -}; - - - -template<class type> class Q_EXPORT QCacheIterator : public QGCacheIterator -{ -public: - QCacheIterator( const QCache<type> &c ):QGCacheIterator((QGCache &)c) {} - QCacheIterator( const QCacheIterator<type> &ci) - : QGCacheIterator( (QGCacheIterator &)ci ) {} - QCacheIterator<type> &operator=(const QCacheIterator<type>&ci) - { return ( QCacheIterator<type>&)QGCacheIterator::operator=( ci ); } - uint count() const { return QGCacheIterator::count(); } - bool isEmpty() const { return QGCacheIterator::count() == 0; } - bool atFirst() const { return QGCacheIterator::atFirst(); } - bool atLast() const { return QGCacheIterator::atLast(); } - type *toFirst() { return (type *)QGCacheIterator::toFirst(); } - type *toLast() { return (type *)QGCacheIterator::toLast(); } - operator type *() const { return (type *)QGCacheIterator::get(); } - type *current() const { return (type *)QGCacheIterator::get(); } - const char *currentKey() const{ return QGCacheIterator::getKeyAscii(); } - type *operator()() { return (type *)QGCacheIterator::operator()();} - type *operator++() { return (type *)QGCacheIterator::operator++(); } - type *operator+=(uint j) { return (type *)QGCacheIterator::operator+=(j);} - type *operator--() { return (type *)QGCacheIterator::operator--(); } - type *operator-=(uint j) { return (type *)QGCacheIterator::operator-=(j);} -}; - - -#endif // QCACHE_H diff --git a/qtools/qcollection.h b/qtools/qcollection.h index a169b7c..c187569 100644 --- a/qtools/qcollection.h +++ b/qtools/qcollection.h @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** Definition of base class for all collection classes ** @@ -43,7 +43,6 @@ #endif // QT_H -class QGVector; class QGList; class QGDict; diff --git a/qtools/qcstring.h b/qtools/qcstring.h index 0f3f932..75bdf29 100644 --- a/qtools/qcstring.h +++ b/qtools/qcstring.h @@ -58,7 +58,7 @@ inline char *cstrcpy( char *dst, const char *src ) inline char *qstrcpy( char *dst, const char *src ) { return src ? strcpy(dst, src) : 0; } -char * qstrncpy(char *src,const char *dst, uint len); +char * qstrncpy(char *dst,const char *src, uint len); inline int cstrcmp( const char *str1, const char *str2 ) { return strcmp(str1,str2); } diff --git a/qtools/qgcache.cpp b/qtools/qgcache.cpp deleted file mode 100644 index 230823c..0000000 --- a/qtools/qgcache.cpp +++ /dev/null @@ -1,878 +0,0 @@ -/**************************************************************************** -** -** -** Implementation of QGCache and QGCacheIterator classes -** -** Created : 950208 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#include "qgcache.h" -#include "qinternallist.h" -#include "qdict.h" -#include "qstring.h" - - -// NOT REVISED -/*! - \class QGCache qgcache.h - - \brief The QGCache class is an internal class for implementing QCache template classes. - - QGCache is a strictly internal class that acts as a base class for the - \link collection.html collection classes\endlink QCache and QIntCache. -*/ - - -/***************************************************************************** - QGCacheItem class (internal cache item) - *****************************************************************************/ - -struct QCacheItem -{ - QCacheItem( void *k, QCollection::Item d, int c, short p ) - : priority(p), skipPriority(p), cost(c), key(k), data(d), node(0) {} - short priority; - short skipPriority; - int cost; - void *key; - QCollection::Item data; - QLNode *node; -}; - - -/***************************************************************************** - QCList class (internal list of cache items) - *****************************************************************************/ - -class QCList : private QInternalList<QCacheItem> -{ -friend class QGCacheIterator; -friend class QCListIt; -public: - QCList() {} - ~QCList(); - - void insert( QCacheItem * ); // insert according to priority - void insert( int, QCacheItem * ); - void take( QCacheItem * ); - void reference( QCacheItem * ); - - void setAutoDelete( bool del ) { QCollection::setAutoDelete(del); } - - bool removeFirst() { return QInternalList<QCacheItem>::removeFirst(); } - bool removeLast() { return QInternalList<QCacheItem>::removeLast(); } - - QCacheItem *first() { return QInternalList<QCacheItem>::first(); } - QCacheItem *last() { return QInternalList<QCacheItem>::last(); } - QCacheItem *prev() { return QInternalList<QCacheItem>::prev(); } - QCacheItem *next() { return QInternalList<QCacheItem>::next(); } - -#if defined(DEBUG) - int inserts; // variables for statistics - int insertCosts; - int insertMisses; - int finds; - int hits; - int hitCosts; - int dumps; - int dumpCosts; -#endif -}; - - -QCList::~QCList() -{ -#if defined(DEBUG) - ASSERT( count() == 0 ); -#endif -} - - -void QCList::insert( QCacheItem *ci ) -{ - QCacheItem *item = first(); - while( item && item->skipPriority > ci->priority ) { - item->skipPriority--; - item = next(); - } - if ( item ) - QInternalList<QCacheItem>::insert( at(), ci ); - else - append( ci ); -#if defined(DEBUG) - ASSERT( ci->node == 0 ); -#endif - ci->node = currentNode(); -} - -inline void QCList::insert( int i, QCacheItem *ci ) -{ - QInternalList<QCacheItem>::insert( i, ci ); -#if defined(DEBUG) - ASSERT( ci->node == 0 ); -#endif - ci->node = currentNode(); -} - - -void QCList::take( QCacheItem *ci ) -{ - if ( ci ) { -#if defined(DEBUG) - ASSERT( ci->node != 0 ); -#endif - takeNode( ci->node ); - ci->node = 0; - } -} - - -inline void QCList::reference( QCacheItem *ci ) -{ -#if defined(DEBUG) - ASSERT( ci != 0 && ci->node != 0 ); -#endif - ci->skipPriority = ci->priority; - relinkNode( ci->node ); // relink as first item -} - - -class QCListIt: public QInternalListIterator<QCacheItem> -{ -public: - QCListIt( const QCList *p ): QInternalListIterator<QCacheItem>( *p ) {} - QCListIt( const QCListIt *p ): QInternalListIterator<QCacheItem>( *p ) {} -}; - - -/***************************************************************************** - QCDict class (internal dictionary of cache items) - *****************************************************************************/ - -// -// Since we need to decide if the dictionary should use an int or const -// char * key (the "bool trivial" argument in the constructor below) -// we cannot use the macro/template dict, but inherit directly from QGDict. -// - -class QCDict : public QGDict -{ -public: - QCDict( uint size, uint kt, bool caseSensitive, bool copyKeys ) - : QGDict( size, (KeyType)kt, caseSensitive, copyKeys ) {} - - QCacheItem *find_string(const QCString &key) const - { return (QCacheItem*)((QCDict*)this)->look_string(key, 0, 0); } - QCacheItem *find_ascii(const char *key) const - { return (QCacheItem*)((QCDict*)this)->look_ascii(key, 0, 0); } - QCacheItem *find_int(long key) const - { return (QCacheItem*)((QCDict*)this)->look_int(key, 0, 0); } - - QCacheItem *take_string(const QCString &key) - { return (QCacheItem*)QGDict::take_string(key); } - QCacheItem *take_ascii(const char *key) - { return (QCacheItem*)QGDict::take_ascii(key); } - QCacheItem *take_int(long key) - { return (QCacheItem*)QGDict::take_int(key); } - - bool insert_string( const QCString &key, const QCacheItem *ci ) - { return QGDict::look_string(key,(Item)ci,1)!=0;} - bool insert_ascii( const char *key, const QCacheItem *ci ) - { return QGDict::look_ascii(key,(Item)ci,1)!=0;} - bool insert_int( long key, const QCacheItem *ci ) - { return QGDict::look_int(key,(Item)ci,1)!=0;} - - bool remove_string( QCacheItem *item ) - { return QGDict::remove_string(*((QCString*)(item->key)),item); } - bool remove_ascii( QCacheItem *item ) - { return QGDict::remove_ascii((const char *)item->key,item); } - bool remove_int( QCacheItem *item ) - { return QGDict::remove_int((intptr_t)item->key,item);} - - void statistics() { QGDict::statistics(); } -}; - - -/***************************************************************************** - QGDict member functions - *****************************************************************************/ - -/*! - \internal - Constructs a cache. -*/ - -QGCache::QGCache( int maxCost, uint size, KeyType kt, bool caseSensitive, - bool copyKeys ) -{ - keytype = kt; - lruList = new QCList; - CHECK_PTR( lruList ); - lruList->setAutoDelete( TRUE ); - copyk = ((keytype == AsciiKey) && copyKeys); - dict = new QCDict( size, kt, caseSensitive, FALSE ); - CHECK_PTR( dict ); - mCost = maxCost; - tCost = 0; -#if defined(DEBUG) - lruList->inserts = 0; - lruList->insertCosts = 0; - lruList->insertMisses = 0; - lruList->finds = 0; - lruList->hits = 0; - lruList->hitCosts = 0; - lruList->dumps = 0; - lruList->dumpCosts = 0; -#endif -} - -/*! - \internal - Cannot copy a cache. -*/ - -QGCache::QGCache( const QGCache & ) - : QCollection() -{ -#if defined(CHECK_NULL) - qFatal( "QGCache::QGCache(QGCache &): Cannot copy a cache" ); -#endif -} - -/*! - \internal - Removes all items from the cache and destroys it. -*/ - -QGCache::~QGCache() -{ - clear(); // delete everything first - delete dict; - delete lruList; -} - -/*! - \internal - Cannot assign a cache. -*/ - -QGCache &QGCache::operator=( const QGCache & ) -{ -#if defined(CHECK_NULL) - qFatal( "QGCache::operator=: Cannot copy a cache" ); -#endif - return *this; // satisfy the compiler -} - - -/*! - \fn uint QGCache::count() const - \internal - Returns the number of items in the cache. -*/ - -/*! - \fn uint QGCache::size() const - \internal - Returns the size of the hash array. -*/ - -/*! - \fn int QGCache::maxCost() const - \internal - Returns the maximum cache cost. -*/ - -/*! - \fn int QGCache::totalCost() const - \internal - Returns the total cache cost. -*/ - -/*! - \internal - Sets the maximum cache cost. -*/ - -void QGCache::setMaxCost( int maxCost ) -{ - if ( maxCost < tCost ) { - if ( !makeRoomFor(tCost - maxCost) ) // remove excess cost - return; - } - mCost = maxCost; -} - - -/*! - \internal - Inserts an item into the cache. - - \warning If this function returns FALSE, you must delete \a data - yourself. Additionally, be very careful about using \a data after - calling this function, as any other insertions into the cache, from - anywhere in the application, or within Qt itself, could cause the - data to be discarded from the cache, and the pointer to become - invalid. -*/ - -bool QGCache::insert_string( const QCString &key, QCollection::Item data, - int cost, int priority) -{ - if ( tCost + cost > mCost ) { - if ( !makeRoomFor(tCost + cost - mCost, priority) ) { -#if defined(DEBUG) - lruList->insertMisses++; -#endif - return FALSE; - } - } -#if defined(DEBUG) - ASSERT( keytype == StringKey ); - lruList->inserts++; - lruList->insertCosts += cost; -#endif - if ( priority < -32768 ) - priority = -32768; - else if ( priority > 32767 ) - priority = 32677; - QCacheItem *ci = new QCacheItem( new QCString(key), newItem(data), - cost, (short)priority ); - CHECK_PTR( ci ); - lruList->insert( 0, ci ); - dict->insert_string( key, ci ); - tCost += cost; - return TRUE; -} - - -/*! \internal */ - -bool QGCache::insert_other( const char *key, QCollection::Item data, - int cost, int priority) -{ - if ( tCost + cost > mCost ) { - if ( !makeRoomFor(tCost + cost - mCost, priority) ) { -#if defined(DEBUG) - lruList->insertMisses++; -#endif - return FALSE; - } - } -#if defined(DEBUG) - ASSERT( keytype != StringKey ); - lruList->inserts++; - lruList->insertCosts += cost; -#endif - if ( keytype == AsciiKey && copyk ) - key = qstrdup( key ); - if ( priority < -32768 ) - priority = -32768; - else if ( priority > 32767 ) - priority = 32677; - QCacheItem *ci = new QCacheItem( (void*)key, newItem(data), cost, - (short)priority ); - CHECK_PTR( ci ); - lruList->insert( 0, ci ); - if ( keytype == AsciiKey ) - dict->insert_ascii( key, ci ); - else - dict->insert_int( (intptr_t)key, ci ); - tCost += cost; - return TRUE; -} - - -/*! - \internal - Removes an item from the cache. -*/ - -bool QGCache::remove_string( const QCString &key ) -{ - Item d = take_string( key ); - if ( d ) - deleteItem( d ); - return d != 0; -} - - -/*! \internal */ - -bool QGCache::remove_other( const char *key ) -{ - Item d = take_other( key ); - if ( d ) - deleteItem( d ); - return d != 0; -} - - -/*! - \internal - Takes an item out of the cache (no delete). -*/ - -QCollection::Item QGCache::take_string( const QCString &key ) -{ - QCacheItem *ci = dict->take_string( key ); // take from dict - Item d; - if ( ci ) { - d = ci->data; - tCost -= ci->cost; - lruList->take( ci ); // take from list - delete (QCString*)ci->key; - delete ci; - } else { - d = 0; - } - return d; -} - -/*! - \internal - Takes an item out of the cache (no delete). -*/ - -QCollection::Item QGCache::take_other( const char *key ) -{ - QCacheItem *ci; - if ( keytype == AsciiKey ) - ci = dict->take_ascii( key ); - else - ci = dict->take_int( (intptr_t)key ); - Item d; - if ( ci ) { - d = ci->data; - tCost -= ci->cost; - lruList->take( ci ); // take from list - if ( copyk ) - delete [] (char *)ci->key; - delete ci; - } else { - d = 0; - } - return d; -} - - -/*! - \internal - Clears the cache. -*/ - -void QGCache::clear() -{ - QCacheItem *ci; - while ( (ci = lruList->first()) ) { - switch ( keytype ) { - case StringKey: - dict->remove_string( ci ); - delete (QCString*)ci->key; - break; - case AsciiKey: - dict->remove_ascii( ci ); - if ( copyk ) - delete [] (char*)ci->key; - break; - case IntKey: - dict->remove_int( ci ); - break; - case PtrKey: // unused - break; - } - deleteItem( ci->data ); // delete data - lruList->removeFirst(); // remove from list - } - tCost = 0; -} - - -/*! - \internal - Finds an item in the cache. -*/ - -QCollection::Item QGCache::find_string( const QCString &key, bool ref ) const -{ - QCacheItem *ci = dict->find_string( key ); -#if defined(DEBUG) - lruList->finds++; -#endif - if ( ci ) { -#if defined(DEBUG) - lruList->hits++; - lruList->hitCosts += ci->cost; -#endif - if ( ref ) - lruList->reference( ci ); - return ci->data; - } - return 0; -} - - -/*! - \internal - Finds an item in the cache. -*/ - -QCollection::Item QGCache::find_other( const char *key, bool ref ) const -{ - QCacheItem *ci = keytype == AsciiKey ? dict->find_ascii(key) - : dict->find_int((intptr_t)key); -#if defined(DEBUG) - lruList->finds++; -#endif - if ( ci ) { -#if defined(DEBUG) - lruList->hits++; - lruList->hitCosts += ci->cost; -#endif - if ( ref ) - lruList->reference( ci ); - return ci->data; - } - return 0; -} - - -/*! - \internal - Allocates cache space for one or more items. -*/ - -bool QGCache::makeRoomFor( int cost, int priority ) -{ - if ( cost > mCost ) // cannot make room for more - return FALSE; // than maximum cost - if ( priority == -1 ) - priority = 32767; - QCacheItem *ci = lruList->last(); - int cntCost = 0; - int dumps = 0; // number of items to dump - while ( cntCost < cost && ci && ci->skipPriority <= priority ) { - cntCost += ci->cost; - ci = lruList->prev(); - dumps++; - } - if ( cntCost < cost ) // can enough cost be dumped? - return FALSE; // no -#if defined(DEBUG) - ASSERT( dumps > 0 ); -#endif - while ( dumps-- ) { - ci = lruList->last(); -#if defined(DEBUG) - lruList->dumps++; - lruList->dumpCosts += ci->cost; -#endif - switch ( keytype ) { - case StringKey: - dict->remove_string( ci ); - delete (QCString*)ci->key; - break; - case AsciiKey: - dict->remove_ascii( ci ); - if ( copyk ) - delete [] (char *)ci->key; - break; - case IntKey: - dict->remove_int( ci ); - break; - case PtrKey: // unused - break; - } - deleteItem( ci->data ); // delete data - lruList->removeLast(); // remove from list - } - tCost -= cntCost; - return TRUE; -} - - -/*! - \internal - Outputs debug statistics. -*/ - -void QGCache::statistics() const -{ -#if defined(DEBUG) - QCString line; - line.fill( '*', 80 ); - qDebug( "%s",line.data() ); - qDebug( "CACHE STATISTICS:" ); - qDebug( "cache contains %d item%s, with a total cost of %d", - count(), count() != 1 ? "s" : "", tCost ); - qDebug( "maximum cost is %d, cache is %d%% full.", - mCost, (200*tCost + mCost) / (mCost*2) ); - qDebug( "find() has been called %d time%s", - lruList->finds, lruList->finds != 1 ? "s" : "" ); - qDebug( "%d of these were hits, items found had a total cost of %d.", - lruList->hits,lruList->hitCosts ); - qDebug( "%d item%s %s been inserted with a total cost of %d.", - lruList->inserts,lruList->inserts != 1 ? "s" : "", - lruList->inserts != 1 ? "have" : "has", lruList->insertCosts ); - qDebug( "%d item%s %s too large or had too low priority to be inserted.", - lruList->insertMisses, lruList->insertMisses != 1 ? "s" : "", - lruList->insertMisses != 1 ? "were" : "was" ); - qDebug( "%d item%s %s been thrown away with a total cost of %d.", - lruList->dumps, lruList->dumps != 1 ? "s" : "", - lruList->dumps != 1 ? "have" : "has", lruList->dumpCosts ); - qDebug( "Statistics from internal dictionary class:" ); - dict->statistics(); - qDebug( "%s",line.data() ); -#endif -} - -int QGCache::hits() const -{ - return lruList->hits; -} - -int QGCache::misses() const -{ - return lruList->finds - lruList->hits; -} - - -/***************************************************************************** - QGCacheIterator member functions - *****************************************************************************/ - -/*! - \class QGCacheIterator qgcache.h - - \brief An internal class for implementing QCacheIterator and QIntCacheIterator. - - QGCacheIterator is a strictly internal class that does the heavy work for - QCacheIterator and QIntCacheIterator. -*/ - -/*! - \internal - Constructs an iterator that operates on the cache \e c. -*/ - -QGCacheIterator::QGCacheIterator( const QGCache &c ) -{ - it = new QCListIt( c.lruList ); -#if defined(DEBUG) - ASSERT( it != 0 ); -#endif -} - -/*! - \internal - Constructs an iterator that operates on the same cache as \e ci. -*/ - -QGCacheIterator::QGCacheIterator( const QGCacheIterator &ci ) -{ - it = new QCListIt( ci.it ); -#if defined(DEBUG) - ASSERT( it != 0 ); -#endif -} - -/*! - \internal - Destroys the iterator. -*/ - -QGCacheIterator::~QGCacheIterator() -{ - delete it; -} - -/*! - \internal - Assigns the iterator \e ci to this cache iterator. -*/ - -QGCacheIterator &QGCacheIterator::operator=( const QGCacheIterator &ci ) -{ - *it = *ci.it; - return *this; -} - -/*! - \internal - Returns the number of items in the cache. -*/ - -uint QGCacheIterator::count() const -{ - return it->count(); -} - -/*! - \internal - Returns TRUE if the iterator points to the first item. -*/ - -bool QGCacheIterator::atFirst() const -{ - return it->atFirst(); -} - -/*! - \internal - Returns TRUE if the iterator points to the last item. -*/ - -bool QGCacheIterator::atLast() const -{ - return it->atLast(); -} - -/*! - \internal - Sets the list iterator to point to the first item in the cache. -*/ - -QCollection::Item QGCacheIterator::toFirst() -{ - QCacheItem *item = it->toFirst(); - return item ? item->data : 0; -} - -/*! - \internal - Sets the list iterator to point to the last item in the cache. -*/ - -QCollection::Item QGCacheIterator::toLast() -{ - QCacheItem *item = it->toLast(); - return item ? item->data : 0; -} - -/*! - \internal - Returns the current item. -*/ - -QCollection::Item QGCacheIterator::get() const -{ - QCacheItem *item = it->current(); - return item ? item->data : 0; -} - -/*! - \internal - Returns the key of the current item. -*/ - -QCString QGCacheIterator::getKeyString() const -{ - QCacheItem *item = it->current(); - return item ? *((QCString*)item->key) : QCString(); -} - -/*! - \internal - Returns the key of the current item, as a \0-terminated C string. -*/ - -const char *QGCacheIterator::getKeyAscii() const -{ - QCacheItem *item = it->current(); - return item ? (const char *)item->key : 0; -} - -/*! - \internal - Returns the key of the current item, as a long. -*/ - -intptr_t QGCacheIterator::getKeyInt() const -{ - QCacheItem *item = it->current(); - return item ? (intptr_t)item->key : 0; -} - -/*! - \internal - Moves to the next item (postfix). -*/ - -QCollection::Item QGCacheIterator::operator()() -{ - QCacheItem *item = it->operator()(); - return item ? item->data : 0; -} - -/*! - \internal - Moves to the next item (prefix). -*/ - -QCollection::Item QGCacheIterator::operator++() -{ - QCacheItem *item = it->operator++(); - return item ? item->data : 0; -} - -/*! - \internal - Moves \e jumps positions forward. -*/ - -QCollection::Item QGCacheIterator::operator+=( uint jump ) -{ - QCacheItem *item = it->operator+=(jump); - return item ? item->data : 0; -} - -/*! - \internal - Moves to the previous item (prefix). -*/ - -QCollection::Item QGCacheIterator::operator--() -{ - QCacheItem *item = it->operator--(); - return item ? item->data : 0; -} - -/*! - \internal - Moves \e jumps positions backward. -*/ - -QCollection::Item QGCacheIterator::operator-=( uint jump ) -{ - QCacheItem *item = it->operator-=(jump); - return item ? item->data : 0; -} diff --git a/qtools/qgcache.h b/qtools/qgcache.h deleted file mode 100644 index 5d8a243..0000000 --- a/qtools/qgcache.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** -** Definition of QGCache and QGCacheIterator classes -** -** Created : 950208 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#ifndef QGCACHE_H -#define QGCACHE_H - -#ifndef QT_H -#include "qcollection.h" -#include "qglist.h" -#include "qgdict.h" -#endif // QT_H - - -class QCList; // internal classes -class QCListIt; -class QCDict; - - -class Q_EXPORT QGCache : public QCollection // generic LRU cache -{ -friend class QGCacheIterator; -protected: - enum KeyType { StringKey, AsciiKey, IntKey, PtrKey }; - // identical to QGDict's, but PtrKey is not used at the moment - - QGCache( int maxCost, uint size, KeyType kt, bool caseSensitive, - bool copyKeys ); - QGCache( const QGCache & ); // not allowed, calls fatal() - ~QGCache(); - QGCache &operator=( const QGCache & ); // not allowed, calls fatal() - - uint count() const { return ((QGDict*)dict)->count(); } - uint size() const { return ((QGDict*)dict)->size(); } - int maxCost() const { return mCost; } - int totalCost() const { return tCost; } - void setMaxCost( int maxCost ); - void clear(); - - bool insert_string( const QCString &key, QCollection::Item, - int cost, int priority ); - bool insert_other( const char *key, QCollection::Item, - int cost, int priority ); - bool remove_string( const QCString &key ); - bool remove_other( const char *key ); - QCollection::Item take_string( const QCString &key ); - QCollection::Item take_other( const char *key ); - - QCollection::Item find_string( const QCString &key, bool ref=TRUE ) const; - QCollection::Item find_other( const char *key, bool ref=TRUE ) const; - - void statistics() const; - int hits() const; - int misses() const; - -private: - bool makeRoomFor( int cost, int priority = -1 ); - KeyType keytype; - QCList *lruList; - QCDict *dict; - int mCost; - int tCost; - bool copyk; -}; - - -class Q_EXPORT QGCacheIterator // generic cache iterator -{ -protected: - QGCacheIterator( const QGCache & ); - QGCacheIterator( const QGCacheIterator & ); - ~QGCacheIterator(); - QGCacheIterator &operator=( const QGCacheIterator & ); - - uint count() const; - bool atFirst() const; - bool atLast() const; - QCollection::Item toFirst(); - QCollection::Item toLast(); - - QCollection::Item get() const; - QCString getKeyString() const; - const char *getKeyAscii() const; - intptr_t getKeyInt() const; - - QCollection::Item operator()(); - QCollection::Item operator++(); - QCollection::Item operator+=( uint ); - QCollection::Item operator--(); - QCollection::Item operator-=( uint ); - -protected: - QCListIt *it; // iterator on cache list -}; - - -#endif // QGCACHE_H diff --git a/qtools/qglist.cpp b/qtools/qglist.cpp index 8197db5..878aa04 100644 --- a/qtools/qglist.cpp +++ b/qtools/qglist.cpp @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** Implementation of QGList and QGListIterator classes ** @@ -36,7 +36,6 @@ **********************************************************************/ #include "qglist.h" -#include "qgvector.h" #include "qdatastream.h" @@ -243,10 +242,10 @@ bool QGList::operator==( const QGList &list ) const { if ( count() != list.count() ) return FALSE; - + if ( count() == 0 ) return TRUE; - + QLNode *n1 = firstNode; QLNode *n2 = list.firstNode; while ( n1 && n2 ) { @@ -256,7 +255,7 @@ bool QGList::operator==( const QGList &list ) const n1 = n1->next; n2 = n2->next; } - + return TRUE; } @@ -866,25 +865,6 @@ QCollection::Item QGList::prev() } -/*! - \internal - Converts the list to a vector. -*/ - -void QGList::toVector( QGVector *vector ) const -{ - vector->clear(); - if ( !vector->resize( count() ) ) - return; - QLNode *n = firstNode; - uint i = 0; - while ( n ) { - vector->insert( i, n->data ); - n = n->next; - i++; - } -} - void QGList::heapSortPushDown( QCollection::Item* heap, int first, int last ) { int r = first; diff --git a/qtools/qglist.h b/qtools/qglist.h index f400b64..0f30594 100644 --- a/qtools/qglist.h +++ b/qtools/qglist.h @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** Definition of QGList and QGListIterator classes ** @@ -68,7 +68,6 @@ private: class Q_EXPORT QGList : public QCollection // doubly linked generic list { friend class QGListIterator; -friend class QGVector; // needed by QGVector::toList public: uint count() const; // return number of nodes @@ -122,8 +121,6 @@ protected: QCollection::Item next(); // set next item in list curr QCollection::Item prev(); // set prev item in list curr - void toVector( QGVector * ) const; // put items in vector - virtual int compareItems( QCollection::Item, QCollection::Item ); #ifndef QT_NO_DATASTREAM diff --git a/qtools/qgvector.cpp b/qtools/qgvector.cpp deleted file mode 100644 index 2d08ede..0000000 --- a/qtools/qgvector.cpp +++ /dev/null @@ -1,638 +0,0 @@ -/**************************************************************************** -** -** -** Implementation of QGVector class -** -** Created : 930907 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#define QGVECTOR_CPP -#include "qgvector.h" -#include "qglist.h" -#include "qstring.h" -#include "qdatastream.h" -#include <stdlib.h> - -#define USE_MALLOC // comment to use new/delete - -#undef NEW -#undef DELETE - -#if defined(USE_MALLOC) -#define NEW(type,size) ((type*)malloc(size*sizeof(type))) -#define DELETE(array) (free((char*)array)) -#else -#define NEW(type,size) (new type[size]) -#define DELETE(array) (delete[] array) -#define DONT_USE_REALLOC // comment to use realloc() -#endif - -// NOT REVISED - -/*! - \class QGVector qgvector.h - - \brief The QGVector class is an internal class for implementing Qt - collection classes. - - QGVector is a strictly internal class that acts as a base class for - the QVector collection class. - - QGVector has some virtual functions that may be reimplemented in - subclasses to customize behavior. - - <ul> - <li> compareItems() compares two collection/vector items. - <li> read() reads a collection/vector item from a QDataStream. - <li> write() writes a collection/vector item to a QDataStream. - </ul> -*/ - -/***************************************************************************** - Default implementation of virtual functions - *****************************************************************************/ - -/*! - This virtual function compares two list items. - - Returns: - <ul> - <li> 0 if \a item1 == \a item2 - <li> non-zero if \a item1 != \a item2 - </ul> - - This function returns \e int rather than \e bool so that - reimplementations can return one of three values and use it to sort - by: - - <ul> - <li> 0 if \e item1 == \e item2 - <li> \> 0 (positive integer) if \a item1 \> \a item2 - <li> \< 0 (negative integer) if \a item1 \< \a item2 - </ul> - - The QVector::sort() and QVector::bsearch() functions require that - compareItems() is implemented as described here. - - This function should not modify the vector because some const - functions call compareItems(). -*/ - -int QGVector::compareItems( Item d1, Item d2 ) -{ - return d1 != d2; // compare pointers -} - -#ifndef QT_NO_DATASTREAM -/*! - Reads a collection/vector item from the stream \a s and returns a reference - to the stream. - - The default implementation sets \e item to 0. - - \sa write() -*/ - -QDataStream &QGVector::read( QDataStream &s, Item &d ) -{ // read item from stream - d = 0; - return s; -} - -/*! - Writes a collection/vector item to the stream \a s and returns a reference - to the stream. - - The default implementation does nothing. - - \sa read() -*/ - -QDataStream &QGVector::write( QDataStream &s, Item ) const -{ // write item to stream - return s; -} -#endif // QT_NO_DATASTREAM - -/***************************************************************************** - QGVector member functions - *****************************************************************************/ - -/*! - \internal -*/ - -QGVector::QGVector() // create empty vector -{ - vec = 0; - len = numItems = 0; -} - -/*! - \internal -*/ -QGVector::QGVector( uint size ) // create vectors with nullptrs -{ - len = size; - numItems = 0; - if ( len == 0 ) { // zero length - vec = 0; - return; - } - vec = NEW(Item,len); - CHECK_PTR( vec ); - memset( (void*)vec, 0, len*sizeof(Item) ); // fill with nulls -} - -/*! - \internal -*/ - -QGVector::QGVector( const QGVector &a ) // make copy of other vector - : QCollection( a ) -{ - len = a.len; - numItems = a.numItems; - vec = NEW(Item,len); - CHECK_PTR( vec ); - for ( uint i=0; i<len; i++ ) { - vec[i] = a.vec[i] ? newItem( a.vec[i] ) : 0; - CHECK_PTR( vec[i] ); - } -} - -/*! - \internal -*/ - -QGVector::~QGVector() -{ - clear(); -} - - -/*! - \internal -*/ - -QGVector& QGVector::operator=( const QGVector &v ) -{ // assign from other vector - clear(); // first delete old vector - len = v.len; - numItems = v.numItems; - vec = NEW(Item,len); // create new vector - CHECK_PTR( vec ); - for ( uint i=0; i<len; i++ ) { // copy elements - vec[i] = v.vec[i] ? newItem( v.vec[i] ) : 0; - CHECK_PTR( vec[i] ); - } - return *this; -} - - -/*! - \fn Item *QGVector::data() const - \internal -*/ - -/*! - \fn uint QGVector::size() const - \internal -*/ - -/*! - \fn uint QGVector::count() const - \internal -*/ - -/*! - \fn Item QGVector::at( uint index ) const - \internal -*/ - -/*! - \internal -*/ - -bool QGVector::insert( uint index, Item d ) // insert item at index -{ -#if defined(CHECK_RANGE) - if ( index >= len ) { // range error - qWarning( "QGVector::insert: Index %d out of range", index ); - return FALSE; - } -#endif - if ( vec[index] ) { // remove old item - deleteItem( vec[index] ); - numItems--; - } - if ( d ) { - vec[index] = newItem( d ); - CHECK_PTR( vec[index] ); - numItems++; - return vec[index] != 0; - } else { - vec[index] = 0; // reset item - } - return TRUE; -} - -/*! - \internal -*/ - -bool QGVector::remove( uint index ) // remove item at index -{ -#if defined(CHECK_RANGE) - if ( index >= len ) { // range error - qWarning( "QGVector::remove: Index %d out of range", index ); - return FALSE; - } -#endif - if ( vec[index] ) { // valid item - deleteItem( vec[index] ); // delete it - vec[index] = 0; // reset pointer - numItems--; - } - return TRUE; -} - -/*! - \internal -*/ - -QCollection::Item QGVector::take( uint index ) // take out item -{ -#if defined(CHECK_RANGE) - if ( index >= len ) { // range error - qWarning( "QGVector::take: Index %d out of range", index ); - return 0; - } -#endif - Item d = vec[index]; // don't delete item - if ( d ) - numItems--; - vec[index] = 0; - return d; -} - - -/*! - \internal -*/ - -void QGVector::clear() // clear vector -{ - if ( vec ) { - for ( uint i=0; i<len; i++ ) { // delete each item - if ( vec[i] ) - deleteItem( vec[i] ); - } - DELETE(vec); - vec = 0; - len = numItems = 0; - } -} - -/*! - \internal -*/ - -bool QGVector::resize( uint newsize ) // resize array -{ - if ( newsize == len ) // nothing to do - return TRUE; - if ( vec ) { // existing data - if ( newsize < len ) { // shrink vector - uint i = newsize; - while ( i < len ) { // delete lost items - if ( vec[i] ) { - deleteItem( vec[i] ); - numItems--; - } - i++; - } - } - if ( newsize == 0 ) { // vector becomes empty - DELETE(vec); - vec = 0; - len = numItems = 0; - return TRUE; - } -#if defined(DONT_USE_REALLOC) - Item *newvec = NEW(Item,newsize); // manual realloc - memcpy( newvec, vec, (len < newsize ? len : newsize)*sizeof(Item) ); - DELETE(vec); - vec = newvec; -#else - vec = (Item*)realloc( (char *)vec, newsize*sizeof(Item) ); -#endif - } else { // create new vector - vec = NEW(Item,newsize); - len = numItems = 0; - } - CHECK_PTR( vec ); - if ( !vec ) // no memory - return FALSE; - if ( newsize > len ) // init extra space added - memset( (void*)&vec[len], 0, (newsize-len)*sizeof(Item) ); - len = newsize; - return TRUE; -} - - -/*! - \internal -*/ - -bool QGVector::fill( Item d, int flen ) // resize and fill vector -{ - if ( flen < 0 ) - flen = len; // default: use vector length - else if ( !resize( flen ) ) - return FALSE; - for ( uint i=0; i<(uint)flen; i++ ) // insert d at every index - insert( i, d ); - return TRUE; -} - - -static QGVector *sort_vec=0; // current sort vector - - -#if defined(Q_C_CALLBACKS) -extern "C" { -#endif - -static int cmp_vec( const void *n1, const void *n2 ) -{ - return sort_vec->compareItems( *((QCollection::Item*)n1), *((QCollection::Item*)n2) ); -} - -#if defined(Q_C_CALLBACKS) -} -#endif - - -/*! - \internal -*/ - -void QGVector::sort() // sort vector -{ - if ( count() == 0 ) // no elements - return; - Item *start = &vec[0]; - Item *end = &vec[len-1]; - Item tmp; - while ( TRUE ) { // put all zero elements behind - while ( start < end && *start != 0 ) - start++; - while ( end > start && *end == 0 ) - end--; - if ( start < end ) { - tmp = *start; - *start = *end; - *end = tmp; - } else { - break; - } - } - sort_vec = (QGVector*)this; - qsort( vec, count(), sizeof(Item), cmp_vec ); - sort_vec = 0; -} - -/*! - \internal -*/ - -int QGVector::bsearch( Item d ) const // binary search; when sorted -{ - if ( !len ) - return -1; - if ( !d ) { -#if defined(CHECK_NULL) - qWarning( "QGVector::bsearch: Cannot search for null object" ); -#endif - return -1; - } - int n1 = 0; - int n2 = len - 1; - int mid = 0; - bool found = FALSE; - while ( n1 <= n2 ) { - int res; - mid = (n1 + n2)/2; - if ( vec[mid] == 0 ) // null item greater - res = -1; - else - res = ((QGVector*)this)->compareItems( d, vec[mid] ); - if ( res < 0 ) - n2 = mid - 1; - else if ( res > 0 ) - n1 = mid + 1; - else { // found it - found = TRUE; - break; - } - } - if ( !found ) - return -1; - // search to first of equal items - while ( (mid - 1 >= 0) && !((QGVector*)this)->compareItems(d, vec[mid-1]) ) - mid--; - return mid; -} - - -/*! - \internal -*/ - -int QGVector::findRef( Item d, uint index) const // find exact item in vector -{ -#if defined(CHECK_RANGE) - if ( index >= len ) { // range error - qWarning( "QGVector::findRef: Index %d out of range", index ); - return -1; - } -#endif - for ( uint i=index; i<len; i++ ) { - if ( vec[i] == d ) - return i; - } - return -1; -} - -/*! - \internal -*/ - -int QGVector::find( Item d, uint index ) const // find equal item in vector -{ -#if defined(CHECK_RANGE) - if ( index >= len ) { // range error - qWarning( "QGVector::find: Index %d out of range", index ); - return -1; - } -#endif - for ( uint i=index; i<len; i++ ) { - if ( vec[i] == 0 && d == 0 ) // found null item - return i; - if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 ) - return i; - } - return -1; -} - -/*! - \internal -*/ - -uint QGVector::containsRef( Item d ) const // get number of exact matches -{ - uint count = 0; - for ( uint i=0; i<len; i++ ) { - if ( vec[i] == d ) - count++; - } - return count; -} - -/*! - \internal -*/ - -uint QGVector::contains( Item d ) const // get number of equal matches -{ - uint count = 0; - for ( uint i=0; i<len; i++ ) { - if ( vec[i] == 0 && d == 0 ) // count null items - count++; - if ( vec[i] && ((QGVector*)this)->compareItems( vec[i], d ) == 0 ) - count++; - } - return count; -} - - -/*! - \internal -*/ - -bool QGVector::insertExpand( uint index, Item d )// insert and grow if necessary -{ - if ( index >= len ) { - if ( !resize( index+1 ) ) // no memory - return FALSE; - } - insert( index, d ); - return TRUE; -} - - -/*! - \internal -*/ - -void QGVector::toList( QGList *list ) const // store items in list -{ - list->clear(); - for ( uint i=0; i<len; i++ ) { - if ( vec[i] ) - list->append( vec[i] ); - } -} - - -void QGVector::warningIndexRange( uint i ) -{ -#if defined(CHECK_RANGE) - qWarning( "QGVector::operator[]: Index %d out of range", i ); -#else - Q_UNUSED( i ) -#endif -} - - -/***************************************************************************** - QGVector stream functions - *****************************************************************************/ -#ifndef QT_NO_DATASTREAM -QDataStream &operator>>( QDataStream &s, QGVector &vec ) -{ // read vector - return vec.read( s ); -} - -QDataStream &operator<<( QDataStream &s, const QGVector &vec ) -{ // write vector - return vec.write( s ); -} - -/*! - \internal -*/ - -QDataStream &QGVector::read( QDataStream &s ) // read vector from stream -{ - uint num; - s >> num; // read number of items - clear(); // clear vector - resize( num ); - for (uint i=0; i<num; i++) { // read all items - Item d; - read( s, d ); - CHECK_PTR( d ); - if ( !d ) // no memory - break; - vec[i] = d; - } - return s; -} - -/*! - \internal -*/ - -QDataStream &QGVector::write( QDataStream &s ) const -{ // write vector to stream - uint num = count(); - s << num; // number of items to write - num = size(); - for (uint i=0; i<num; i++) { // write non-null items - if ( vec[i] ) - write( s, vec[i] ); - } - return s; -} -#endif // QT_NO_DATASTREAM diff --git a/qtools/qgvector.h b/qtools/qgvector.h deleted file mode 100644 index 6a7999d..0000000 --- a/qtools/qgvector.h +++ /dev/null @@ -1,120 +0,0 @@ -/**************************************************************************** -** -** -** Definition of QGVector class -** -** Created : 930907 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#ifndef QGVECTOR_H -#define QGVECTOR_H - -#ifndef QT_H -#include "qcollection.h" -#endif // QT_H - - -class Q_EXPORT QGVector : public QCollection // generic vector -{ -friend class QGList; // needed by QGList::toVector -public: -#ifndef QT_NO_DATASTREAM - QDataStream &read( QDataStream & ); // read vector from stream - QDataStream &write( QDataStream & ) const; // write vector to stream -#endif - virtual int compareItems( Item, Item ); - -protected: - QGVector(); // create empty vector - QGVector( uint size ); // create vector with nullptrs - QGVector( const QGVector &v ); // make copy of other vector - ~QGVector(); - - QGVector &operator=( const QGVector &v ); // assign from other vector - - Item *data() const { return vec; } - uint size() const { return len; } - uint count() const { return numItems; } - - bool insert( uint index, Item ); // insert item at index - bool remove( uint index ); // remove item - Item take( uint index ); // take out item - - void clear(); // clear vector - bool resize( uint newsize ); // resize vector - - bool fill( Item, int flen ); // resize and fill vector - - void sort(); // sort vector - int bsearch( Item ) const; // binary search (when sorted) - - int findRef( Item, uint index ) const; // find exact item in vector - int find( Item, uint index ) const; // find equal item in vector - uint containsRef( Item ) const; // get number of exact matches - uint contains( Item ) const; // get number of equal matches - - Item at( uint index ) const // return indexed item - { -#if defined(CHECK_RANGE) - if ( index >= len ) - warningIndexRange( index ); -#endif - return vec[index]; - } - - bool insertExpand( uint index, Item ); // insert, expand if necessary - - void toList( QGList * ) const; // put items in list - -#ifndef QT_NO_DATASTREAM - virtual QDataStream &read( QDataStream &, Item & ); - virtual QDataStream &write( QDataStream &, Item ) const; -#endif -private: - Item *vec; - uint len; - uint numItems; - - static void warningIndexRange( uint ); -}; - - -/***************************************************************************** - QGVector stream functions - *****************************************************************************/ - -#ifndef QT_NO_DATASTREAM -Q_EXPORT QDataStream &operator>>( QDataStream &, QGVector & ); -Q_EXPORT QDataStream &operator<<( QDataStream &, const QGVector & ); -#endif - -#endif // QGVECTOR_H diff --git a/qtools/qinternallist.h b/qtools/qinternallist.h index 09dbfce..b1cc64e 100644 --- a/qtools/qinternallist.h +++ b/qtools/qinternallist.h @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** Definition of QList template/macro class ** @@ -88,7 +88,6 @@ public: type *last() { return (type *)QGList::last(); } type *next() { return (type *)QGList::next(); } type *prev() { return (type *)QGList::prev(); } - void toVector( QGVector *vec )const{ QGList::toVector(vec); } private: void deleteItem( QCollection::Item d ); }; diff --git a/qtools/qlist.doc b/qtools/qlist.doc index 4f97e35..d28d662 100644 --- a/qtools/qlist.doc +++ b/qtools/qlist.doc @@ -1,5 +1,5 @@ /**************************************************************************** -** +** ** ** QList and QListIterator class documentation ** @@ -681,15 +681,6 @@ \sa first(), last(), next(), current() */ -/*! - \fn void QList::toVector( QGVector *vec ) const - Stores all list items in the vector \e vec. - - The vector must be have the same item type, otherwise the result - will be undefined. -*/ - - /***************************************************************************** QListIterator documentation *****************************************************************************/ diff --git a/qtools/qtools.pro.in b/qtools/qtools.pro.in deleted file mode 100644 index 21d26cc..0000000 --- a/qtools/qtools.pro.in +++ /dev/null @@ -1,88 +0,0 @@ -TEMPLATE = lib -CONFIG = warn_on staticlib $extraopts -HEADERS = qarray.h \ - qbuffer.h \ - qcache.h \ - qgcache.h \ - qcollection.h \ - qconfig.h \ - qcstring.h \ - qdatastream.h \ - qdatetime.h \ - qdict.h \ - qdir.h \ - qfeatures.h \ - qfile.h \ - qfiledefs_p.h \ - qfileinfo.h \ - qgarray.h \ - qfeatures.h \ - qgdict.h \ - qgeneric.h \ - qglist.h \ - qglobal.h \ - qgstring.h \ - qgvector.h \ - qintdict.h \ - qiodevice.h \ - qinternallist.h \ - qptrdict.h \ - qqueue.h \ - qregexp.h \ - qshared.h \ - qsortedlist.h \ - qstack.h \ - qstring.h \ - qstringlist.h \ - qstrlist.h \ - qstrvec.h \ - qtextstream.h \ - qtl.h \ - qvaluelist.h \ - qvector.h \ - qxml.h \ - qvaluestack.h \ - qmap.h \ - qmodules.h \ - qutfcodec.h - -SOURCES = qbuffer.cpp \ - qcollection.cpp \ - qcstring.cpp \ - qdatastream.cpp \ - qdatetime.cpp \ - qdir.cpp \ - qfile.cpp \ - qfileinfo.cpp \ - qgarray.cpp \ - qgcache.cpp \ - qgdict.cpp \ - qglist.cpp \ - qglobal.cpp \ - qgstring.cpp \ - qgvector.cpp \ - qiodevice.cpp \ - qregexp.cpp \ - qstring.cpp \ - qtextstream.cpp \ - qtextcodec.cpp \ - qstringlist.cpp \ - qxml.cpp \ - qmap.cpp \ - qutfcodec.cpp - -unix:SOURCES += qfile_unix.cpp \ - qdir_unix.cpp \ - qfileinfo_unix.cpp - -win32:SOURCES += qfile_win32.cpp \ - qdir_win32.cpp \ - qfileinfo_win32.cpp - -INCLUDEPATH = . -#TMAKE_CXXFLAGS += -DQT_NO_CODECS -DQT_LITE_UNICODE -TMAKE_CXXFLAGS += -DQT_LITE_UNICODE -win32:TMAKE_CXXFLAGS += -DQT_NODLL -win32-g++:TMAKE_CXXFLAGS += -D__CYGWIN__ -DALL_STATIC -OBJECTS_DIR = ../objects/qtools -DESTDIR = ../lib diff --git a/qtools/qvector.doc b/qtools/qvector.doc deleted file mode 100644 index 2acf567..0000000 --- a/qtools/qvector.doc +++ /dev/null @@ -1,344 +0,0 @@ -/**************************************************************************** -** -** -** QVector class documentation -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - - -/***************************************************************************** - QVector documentation - *****************************************************************************/ - -// BEING REVISED: ettrich -/*! - \class QVector qvector.h - - \brief The QVector class is a template collection class that - provides a vector (array). - - \ingroup tools - - QVector is implemented as a template class. Define a template - instance QVector\<X\> to create a vector that contains pointers to - X, or X*. - - A vector is the same as an array. The main difference between - QVector and QArray is that QVector stores pointers to the elements, - while QArray stores the elements themselves (i.e. QArray is - value-based). - - Unless where otherwise stated, all functions that remove items from - the vector will also delete the element pointed to if auto-deletion - is enabled - see setAutoDelete(). By default, auto-deletion is - disabled. This behaviour can be changed in a subclass by - reimplementing the virtual method deleteItem(). - - Functions that compares items, e.g. find() and sort(), will do so - using the virtual function compareItems(). The default - implementation of this function will only compare the absolute - pointer values. Reimplement compareItems() in a subclass to get - searching and sorting based on the item contents. - - \sa \link collection.html Collection Classes\endlink, QArray -*/ - -/*! - \fn QVector::QVector() - - Constructs a null vector. - - \sa isNull() -*/ - -/*! - \fn QVector::QVector( uint size ) - - Constructs an vector with room for \a size items. Makes a null - vector if \a size == 0. - - All \a size positions in the vector are initialized to 0. - - \sa size(), resize(), isNull() -*/ - -/*! - \fn QVector::QVector( const QVector<type> &v ) - - Constructs a copy of \a v. Only the pointers are copied (i.e. shallow copy). -*/ - -/*! - \fn QVector::~QVector() - - Removes all items from the vector, and destroys the vector itself. - - \sa clear() -*/ - -/*! - \fn QVector<type> &QVector::operator=( const QVector<type> &v ) - - Assigns \a v to this vector and returns a reference to this vector. - - This vector is first cleared, then all the items from \a v is copied - into this vector. Only the pointers are copied (i.e. shallow copy). - - \sa clear() -*/ - -/*! - \fn type **QVector::data() const - Returns a pointer to the actual vector data, which is an array of type*. - - The vector is a null vector if data() == 0 (null pointer). - - \sa isNull() -*/ - -/*! - \fn uint QVector::size() const - - Returns the size of the vector, i.e. the number of vector - positions. This is also the maximum number of items the vector can - hold. - - The vector is a null vector if size() == 0. - - \sa isNull(), resize(), count() -*/ - -/*! - \fn uint QVector::count() const - - Returns the number of items in the vector. The vector is empty if - count() == 0. - - \sa isEmpty(), size() -*/ - -/*! - \fn bool QVector::isEmpty() const - - Returns TRUE if the vector is empty, i.e. count() == 0, otherwise FALSE. - - \sa count() -*/ - -/*! - \fn bool QVector::isNull() const - - Returns TRUE if the vector is null, otherwise FALSE. - - A null vector has size() == 0 and data() == 0. - - \sa size() -*/ - -/*! - \fn bool QVector::resize( uint size ) - Resizes (expands or shrinks) the vector to \a size elements. The array - becomes a null array if \a size == 0. - - Any items in position \a size or beyond in the vector are removed. - New positions are initialized 0. - - Returns TRUE if successful, or FALSE if the memory cannot be allocated. - - \sa size(), isNull() -*/ - -/*! - \fn bool QVector::insert( uint i, const type *d ) - - Sets position \a i in the vector to contain the item \a d. \a i must - be less than size(). Any previous element in position \a i is removed. - - \sa at() -*/ - -/*! - \fn bool QVector::remove( uint i ) - - Removes the item at position \a i in the vector, if there is one. - \a i must be less than size(). - - Returns TRUE unless \a i is out of range. - - \sa take(), at() -*/ - -/*! - \fn type* QVector::take( uint i ) - - Returns the item at position \a i in the vector, and removes that - item from the vector. \a i must be less than size(). If there is no - item at position \a i, 0 is returned. - - In contrast to remove(), this function does \e not call deleteItem() - for the removed item. - - \sa remove(), at() -*/ - -/*! - \fn void QVector::clear() - - Removes all items from the vector, and destroys the vector - itself. - - The vector becomes a null vector. - - \sa isNull() -*/ - -/*! - \fn bool QVector::fill( const type *d, int size ) - - Inserts item \a d in all positions in the vector. Any existing items - are removed. If \a d is 0, the vector becomes empty. - - If \a size >= 0, the vector is first resized to \a size. By default, - \a size is -1. - - Returns TRUE if successful, or FALSE if the memory cannot be allocated - (only if a resize has been requested). - - \sa resize(), insert(), isEmpty() -*/ - -/*! - \fn void QVector::sort() - - Sorts the items in ascending order. Any empty positions will be put - last. - - Compares items using the virtual function compareItems(). - - \sa bsearch() -*/ - -/*! - \fn int QVector::bsearch( const type* d ) const - - In a sorted array, finds the first occurrence of \a d using binary - search. For a sorted array, this is generally much faster than - find(), which does a linear search. - - Returns the position of \a d, or -1 if \a d could not be found. \a d - may not be 0. - - Compares items using the virtual function compareItems(). - - \sa sort(), find() -*/ - - -/*! - \fn int QVector::findRef( const type *d, uint i ) const - - Finds the first occurrence of the item pointer \a d in the vector, - using linear search. The search starts at position \a i, which must - be less than size(). \a i is by default 0; i.e. the search starts at - the start of the vector. - - Returns the position of \a d, or -1 if \a d could not be found. - - This function does \e not use compareItems() to compare items. - - \sa find(), bsearch() -*/ - -/*! - \fn int QVector::find( const type *d, uint i ) const - - Finds the first occurrence of item \a d in the vector, using linear - search. The search starts at position \a i, which must be less than - size(). \a i is by default 0; i.e. the search starts at the start of - the vector. - - Returns the position of \e v, or -1 if \e v could not be found. - - Compares items using the virtual function compareItems(). - - \sa findRef(), bsearch() -*/ - - -/*! - \fn uint QVector::containsRef( const type *d ) const - - Returns the number of occurrences of the item pointer \a d in the - vector. - - This function does \e not use compareItems() to compare items. - - \sa findRef() -*/ - -/*! - \fn uint QVector::contains( const type *d ) const - - Returns the number of occurrences of item \a d in the vector. - - Compares items using the virtual function compareItems(). - - \sa containsRef() -*/ - -/*! - \fn type *QVector::operator[]( int i ) const - - Returns the item at position \a i, or 0 if there is no item at - that position. \a i must be less than size(). - - Equivalent to at( \a i ). - - \sa at() -*/ - -/*! - \fn type *QVector::at( uint i ) const - - Returns the item at position \a i, or 0 if there is no item at - that position. \a i must be less than size(). -*/ - - -/*! - \fn void QVector::toList( QGList *list ) const - - Copies all items in this vector to the list \a list. First, \a list - is cleared, then all items are appended to \a list. - - \sa QList, QStack, QQueue -*/ - diff --git a/qtools/qvector.h b/qtools/qvector.h deleted file mode 100644 index 36f0be7..0000000 --- a/qtools/qvector.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** -** Definition of QVector template/macro class -** -** Created : 930907 -** -** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. -** -** This file is part of the tools module of the Qt GUI Toolkit. -** -** This file may be distributed under the terms of the Q Public License -** as defined by Trolltech AS of Norway and appearing in the file -** LICENSE.QPL included in the packaging of this file. -** -** This file may be distributed and/or modified under the terms of the -** GNU General Public License version 2 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. -** -** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition -** licenses may use this file in accordance with the Qt Commercial License -** Agreement provided with the Software. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for -** information about Qt Commercial License Agreements. -** See http://www.trolltech.com/qpl/ for QPL licensing information. -** See http://www.trolltech.com/gpl/ for GPL licensing information. -** -** Contact info@trolltech.com if any conditions of this licensing are -** not clear to you. -** -**********************************************************************/ - -#ifndef QVECTOR_H -#define QVECTOR_H - -#ifndef QT_H -#include "qgvector.h" -#endif // QT_H - - -template<class type> class QVector : public QGVector -{ -public: - QVector() {} - QVector( uint size ) : QGVector(size) {} - QVector( const QVector<type> &v ) : QGVector(v) {} - ~QVector() { clear(); } - QVector<type> &operator=(const QVector<type> &v) - { return (QVector<type>&)QGVector::operator=(v); } - type **data() const { return (type **)QGVector::data(); } - uint size() const { return QGVector::size(); } - uint count() const { return QGVector::count(); } - bool isEmpty() const { return QGVector::count() == 0; } - bool isNull() const { return QGVector::size() == 0; } - bool resize( uint size ) { return QGVector::resize(size); } - bool insert( uint i, const type *d){ return QGVector::insert(i,(Item)d); } - bool remove( uint i ) { return QGVector::remove(i); } - type *take( uint i ) { return (type *)QGVector::take(i); } - void clear() { QGVector::clear(); } - bool fill( const type *d, int size=-1 ) - { return QGVector::fill((Item)d,size);} - void sort() { QGVector::sort(); } - int bsearch( const type *d ) const{ return QGVector::bsearch((Item)d); } - int findRef( const type *d, uint i=0 ) const - { return QGVector::findRef((Item)d,i);} - int find( const type *d, uint i= 0 ) const - { return QGVector::find((Item)d,i); } - uint containsRef( const type *d ) const - { return QGVector::containsRef((Item)d); } - uint contains( const type *d ) const - { return QGVector::contains((Item)d); } - type *operator[]( int i ) const { return (type *)QGVector::at(i); } - type *at( uint i ) const { return (type *)QGVector::at(i); } - void toList( QGList *list ) const { QGVector::toList(list); } -private: - void deleteItem( Item d ) { if ( del_item ) delete (type *)d; } -}; - - -#endif // QVECTOR_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb28911..5004a95 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,13 +1,13 @@ # vim:ts=4:sw=4:expandtab:autoindent: include_directories( - ${CMAKE_SOURCE_DIR}/qtools - ${CMAKE_SOURCE_DIR}/libmd5 - ${CMAKE_SOURCE_DIR}/liblodepng - ${CMAKE_SOURCE_DIR}/libmscgen - ${CMAKE_SOURCE_DIR}/libversion - ${CMAKE_SOURCE_DIR}/vhdlparser - ${CMAKE_SOURCE_DIR}/src + ${PROJECT_SOURCE_DIR}/qtools + ${PROJECT_SOURCE_DIR}/libmd5 + ${PROJECT_SOURCE_DIR}/liblodepng + ${PROJECT_SOURCE_DIR}/libmscgen + ${PROJECT_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/vhdlparser + ${PROJECT_SOURCE_DIR}/src ${CLANG_INCLUDEDIR} ${GENERATED_SRC} ) @@ -78,7 +78,7 @@ set_source_files_properties(${GENERATED_SRC}/ce_parse.h PROPERTIES GENERATED 1) # lang_cfg.h add_custom_command( COMMENT "Generating ${GENERATED_SRC}/lang_cfg.h" - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/lang_cfg.cmake ${GENERATED_SRC}/lang_cfg.h ${LANG_CODES} + COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/lang_cfg.cmake ${GENERATED_SRC}/lang_cfg.h ${LANG_CODES} DEPENDS ${LANGUAGE_FILES} OUTPUT ${GENERATED_SRC}/lang_cfg.h ) @@ -86,28 +86,20 @@ set_source_files_properties(${GENERATED_SRC}/lang_cfg.h PROPERTIES GENERATED 1) # all resource files 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/*/*) + file(GLOB RESOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/templates/*/*) else() - file(GLOB RESOURCES ${CMAKE_SOURCE_DIR}/templates/*/*) + file(GLOB RESOURCES ${PROJECT_SOURCE_DIR}/templates/*/*) endif() # resources.cpp add_custom_command( COMMENT "Generating ${GENERATED_SRC}/resources.cpp" - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py ${CMAKE_SOURCE_DIR}/templates ${GENERATED_SRC}/resources.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py ${PROJECT_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_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) - set(LEX_FILES scanner code pyscanner @@ -122,6 +114,7 @@ set(LEX_FILES scanner commentcnv commentscan constexp + xml xmlcode sqlcode configimpl) @@ -138,9 +131,9 @@ foreach(lex_file ${LEX_FILES}) 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 + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/${lex_file}.l ${PROJECT_BINARY_DIR}/src/${lex_file}.l + DEPENDS ${PROJECT_SOURCE_DIR}/src/${lex_file}.l + OUTPUT ${PROJECT_BINARY_DIR}/src/${lex_file}.l ) FLEX_TARGET(${lex_file} @@ -156,9 +149,9 @@ BISON_TARGET(constexp 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 + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/constexp.y ${PROJECT_BINARY_DIR}/src + DEPENDS ${PROJECT_SOURCE_DIR}/src/constexp.y + OUTPUT ${PROJECT_BINARY_DIR}/src/constexp.y ) add_library(doxycfg STATIC @@ -197,6 +190,7 @@ add_library(doxymain STATIC ${GENERATED_SRC}/scanner.l.h ${GENERATED_SRC}/sqlcode.l.h ${GENERATED_SRC}/vhdlcode.l.h + ${GENERATED_SRC}/xml.l.h ${GENERATED_SRC}/xmlcode.l.h ${GENERATED_SRC}/code.cpp ${GENERATED_SRC}/commentcnv.cpp @@ -212,12 +206,12 @@ add_library(doxymain STATIC ${GENERATED_SRC}/scanner.cpp ${GENERATED_SRC}/sqlcode.cpp ${GENERATED_SRC}/vhdlcode.cpp + ${GENERATED_SRC}/xml.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 # @@ -240,6 +234,7 @@ add_library(doxymain STATIC docgroup.cpp docparser.cpp docsets.cpp + docvisitor.cpp dot.cpp dotcallgraph.cpp dotclassgraph.cpp @@ -295,6 +290,7 @@ add_library(doxymain STATIC searchindex.cpp sqlite3gen.cpp stlsupport.cpp + symbolresolver.cpp tagreader.cpp template.cpp textdocvisitor.cpp @@ -327,7 +323,6 @@ 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(doxymain PRIVATE cxx_alignof) target_compile_features(doxygen PRIVATE cxx_alignof) if (use_libc++) diff --git a/src/cache.h b/src/cache.h new file mode 100644 index 0000000..5f7c834 --- /dev/null +++ b/src/cache.h @@ -0,0 +1,162 @@ +/***************************************************************************** + * + * 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 CACHE_H +#define CACHE_H + +#include <list> +#include <unordered_map> +#include <mutex> +#include <ctype.h> + +/*! Fixed size cache for value type V using keys of type K. + * + * When the maximum capacity has reached, the least recently used value is removed from the cache + * (LRU strategy). + */ +template<typename K,typename V> +class Cache +{ + public: + using kv_pair = std::pair<K,V>; + using iterator = typename std::list<kv_pair>::iterator; + using const_iterator = typename std::list<kv_pair>::const_iterator; + + //! creates a cache that can hold \a capacity elements + Cache(size_t capacity) : m_capacity(capacity) + { + } + + //! Inserts \a value under \a key in the cache + V *insert(const K &key,V &&value) + { + // remove item if it already exists + remove(key); + // store new item + m_cacheItemList.push_front(kv_pair(key,std::move(value))); + V *result = &m_cacheItemList.front().second; + m_cacheItemMap[key] = m_cacheItemList.begin(); + // remove least recently used item if cache is full + resize(); + return result; + } + + //! Inserts \a value under \a key in the cache + V *insert(const K &key,const V &value) + { + // remove item if it already exists + remove(key); + // store new item + m_cacheItemList.push_front(kv_pair(key,value)); + V *result = &m_cacheItemList.front().second; + m_cacheItemMap[key] = m_cacheItemList.begin(); + // remove least recently used item if cache is full + resize(); + return result; + } + + //! Removes entry \a key from the cache. + //! \note this invalidates any iterators + void remove(const K &key) + { + // remove item if it already exists + auto it = m_cacheItemMap.find(key); + if (it != m_cacheItemMap.end()) + { + m_cacheItemList.erase(it->second); + m_cacheItemMap.erase(it); + } + } + + //! Finds a value in the cache given the corresponding \a key. + //! @returns a pointer to the value or nullptr if the key is not found in the cache + //! @note The hit and miss counters are updated, see hits() and misses(). + V *find(const K &key) + { + auto it = m_cacheItemMap.find(key); + if (it != m_cacheItemMap.end()) + { + // move the item to the front of the list + m_cacheItemList.splice(m_cacheItemList.begin(), + m_cacheItemList, + it->second); + m_hits++; + // return the value + return &it->second->second; + } + else + { + m_misses++; + } + return nullptr; + } + + //! Returns the number of values stored in the cache. + size_t size() const + { + return m_cacheItemMap.size(); + } + + //! Returns the maximum number of values that can be stored in the cache. + size_t capacity() const + { + return m_capacity; + } + + //! Returns how many of the find() calls did find a value in the cache. + uint64_t hits() const + { + return m_hits; + } + + //! Returns how many of the find() calls did not found a value in the cache. + uint64_t misses() const + { + return m_misses; + } + + //! Clears all values in the cache. + void clear() + { + m_cacheItemMap.clear(); + m_cacheItemList.clear(); + } + + iterator begin() { return m_cacheItemList.begin(); } + iterator end() { return m_cacheItemList.end(); } + const_iterator begin() const { return m_cacheItemList.cbegin(); } + const_iterator end() const { return m_cacheItemList.cend(); } + + private: + void resize() + { + if (m_cacheItemMap.size() > m_capacity) + { + auto last_it = m_cacheItemList.end(); + --last_it; + m_cacheItemMap.erase(last_it->first); + m_cacheItemList.pop_back(); + } + } + size_t m_capacity; + // list of items in the cache, sorted by most to least recently used. + std::list<kv_pair> m_cacheItemList; + // mapping for each key to a place in the list where item is found + std::unordered_map<K,iterator> m_cacheItemMap; + uint64_t m_hits=0; + uint64_t m_misses=0; +}; + +#endif diff --git a/src/cite.cpp b/src/cite.cpp index 03bdb02..e02641a 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -368,7 +368,7 @@ void CitationManager::generatePage() //printf("doc=[%s]\n",doc.data()); // 7. add it as a page - addRelatedPage(fileName(),theTranslator->trCiteReferences(),doc,fileName(),1); + addRelatedPage(fileName(),theTranslator->trCiteReferences(),doc,fileName(),1,1); // 8. for latex we just copy the bib files to the output and let // latex do this work. diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 1ac9138..934da31 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -25,7 +25,7 @@ //-------------------------------------------------------------------------- -std::mutex g_clangMutex; +static std::mutex g_clangMutex; ClangParser *ClangParser::instance() { @@ -39,6 +39,8 @@ ClangParser *ClangParser::s_instance = 0; //-------------------------------------------------------------------------- #if USE_LIBCLANG +static std::mutex g_docCrossReferenceMutex; + enum class DetectedLang { Cpp, ObjC, ObjCpp }; static QCString detab(const QCString &s) @@ -129,7 +131,7 @@ class ClangTUParser::Private std::vector<CXUnsavedFile> ufs; std::vector<CXCursor> cursors; std::unordered_map<std::string,uint> fileMapping; - CXTranslationUnit tu; + CXTranslationUnit tu = 0; CXToken *tokens = 0; uint numTokens = 0; StringVector filesInSameTU; @@ -572,7 +574,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, const char *text) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -695,7 +697,8 @@ void ClangTUParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, p->currentMemberDef && d->definitionType()==Definition::TypeMember && (p->currentMemberDef!=d || p->currentLine<line)) // avoid self-reference { - addDocCrossReference(p->currentMemberDef,dynamic_cast<MemberDef *>(d)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(p->currentMemberDef),toMemberDefMutable(d)); } writeMultiLineCodeLink(ol,fd,line,column,d,text); } @@ -858,7 +861,7 @@ class ClangParser::Private 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) + if (!clangCompileDatabase.isEmpty() && 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(), @@ -884,6 +887,7 @@ ClangParser::~ClangParser() std::unique_ptr<ClangTUParser> ClangParser::createTUParser(const FileDef *fd) const { + //printf("ClangParser::createTUParser()\n"); return std::make_unique<ClangTUParser>(*this,fd); } diff --git a/src/clangparser.h b/src/clangparser.h index 8ee1bdb..f948c33 100644 --- a/src/clangparser.h +++ b/src/clangparser.h @@ -30,7 +30,7 @@ class ClangTUParser void parse(); /** Switches to another file within the translation unit started with start(). - * @param[in] fileName The name of the file to switch to. + * @param[in] fd The file definition with the name of the file to switch to. */ void switchToFile(FileDef *fd); diff --git a/src/classdef.cpp b/src/classdef.cpp index c3cd3ee..b3eb353 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -50,12 +50,110 @@ #include "namespacedef.h" #include "membergroup.h" #include "definitionimpl.h" +#include "symbolresolver.h" + +//----------------------------------------------------------------------------- + +static QCString makeQualifiedNameWithTemplateParameters(const ClassDef *cd, + const ArgumentLists *actualParams,uint *actualParamIndex) +{ + //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); + bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES); + //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); + QCString scName; + const Definition *d=cd->getOuterScope(); + if (d) + { + if (d->definitionType()==Definition::TypeClass) + { + const ClassDef *ocd=toClassDef(d); + scName = ocd->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); + } + else if (!hideScopeNames) + { + scName = d->qualifiedName(); + } + } + + SrcLangExt lang = cd->getLanguage(); + QCString scopeSeparator = getLanguageSpecificSeparator(lang); + if (!scName.isEmpty()) scName+=scopeSeparator; + + bool isSpecialization = cd->localName().find('<')!=-1; + + QCString clName = cd->className(); + scName+=clName; + if (!cd->templateArguments().empty()) + { + if (actualParams && *actualParamIndex<actualParams->size()) + { + const ArgumentList &al = actualParams->at(*actualParamIndex); + if (!isSpecialization) + { + scName+=tempArgListToString(al,lang); + } + (*actualParamIndex)++; + } + else + { + if (!isSpecialization) + { + scName+=tempArgListToString(cd->templateArguments(),lang); + } + } + } + //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data()); + return scName; +} + +static QCString makeDisplayName(const ClassDef *cd,bool includeScope) +{ + //static bool optimizeOutputForJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); + SrcLangExt lang = cd->getLanguage(); + //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + QCString n; + if (lang==SrcLangExt_VHDL) + { + n = VhdlDocGen::getClassName(cd); + } + else + { + if (includeScope) + { + n=cd->qualifiedNameWithTemplateParameters(); + } + else + { + n=cd->className(); + } + } + if (cd->isAnonymous()) + { + n = removeAnonymousScopes(n); + } + QCString sep=getLanguageSpecificSeparator(lang); + if (sep!="::") + { + n=substitute(n,"::",sep); + } + if (cd->compoundType()==ClassDef::Protocol && n.right(2)=="-p") + { + n="<"+n.left(n.length()-2)+">"; + } + //else if (n.right(2)=="-g") + //{ + // n = n.left(n.length()-2); + //} + //printf("ClassDefImpl::displayName()=%s\n",n.data()); + return n; +} + //----------------------------------------------------------------------------- /** Implementation of the ClassDef interface */ -class ClassDefImpl : public DefinitionImpl, public ClassDef +class ClassDefImpl : public DefinitionMixin<ClassDefMutable> { public: ClassDefImpl(const char *fileName,int startLine,int startColumn, @@ -73,7 +171,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString getReference() const; virtual bool isReference() const; virtual bool isLocal() const; - virtual ClassSDict *getClassSDict() const; + virtual ClassLinkedRefMap getClasses() const; virtual bool hasDocumentation() const; virtual bool hasDetailedDescription() const; virtual QCString collaborationGraphFileName() const; @@ -81,8 +179,10 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString displayName(bool includeScope=TRUE) const; virtual CompoundType compoundType() const; virtual QCString compoundTypeString() const; - virtual BaseClassList *baseClasses() const; - virtual BaseClassList *subClasses() const; + virtual BaseClassList baseClasses() const; + virtual void updateBaseClasses(const BaseClassList &bcd); + virtual BaseClassList subClasses() const; + virtual void updateSubClasses(const BaseClassList &bcd); virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const; virtual Protection protection() const; virtual bool isLinkableInProject() const; @@ -105,7 +205,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual UsesClassDict *usedInterfaceClasses() const; virtual ConstraintClassDict *templateTypeConstraints() const; virtual bool isTemplateArgument() const; - virtual Definition *findInnerCompound(const char *name) const; + virtual const Definition *findInnerCompound(const char *name) const; virtual ArgumentLists getTemplateParameterLists() const; virtual QCString qualifiedNameWithTemplateParameters( const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const; @@ -130,12 +230,9 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString anchor() const; virtual bool isEmbeddedInOuterScope() const; virtual bool isSimple() const; - virtual const ClassList *taggedInnerClasses() const; - virtual ClassDef *tagLessReference() const; + virtual const ClassDef *tagLessReference() const; virtual MemberDef *isSmartPointer() const; virtual bool isJavaEnum() const; - virtual bool isGeneric() const; - virtual const ClassSDict *innerClasses() const; virtual QCString title() const; virtual QCString generatedFromFiles() const; virtual const FileList &usedFiles() const; @@ -172,12 +269,11 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef 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 addMembersToTemplateInstance(const ClassDef *cd,const ArgumentList &templateArguments,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 setTagLessReference(const ClassDef *cd); virtual void setName(const char *name); virtual void setMetaData(const char *md); virtual void findSectionsInDocumentation(); @@ -196,7 +292,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef 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 reclassifyMember(MemberDefMutable *md,MemberType t); virtual void writeInlineDocumentation(OutputList &ol) const; virtual void writeDeclarationLink(OutputList &ol,bool &found, const char *header,bool localNames) const; @@ -209,8 +305,6 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef const ClassDef *inheritedFrom,const QCString &inheritId) const; virtual void writeTagFile(FTextStream &); - virtual void setVisited(bool visited) const { m_visited = visited; } - virtual bool isVisited() const { return m_visited; } virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const; virtual int countInheritanceNodes() const; virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, @@ -221,7 +315,6 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef QPtrDict<void> *visitedClasses=0) const; private: - mutable bool m_visited; void addUsedInterfaceClasses(MemberDef *md,const char *typeStr); void showUsedFiles(OutputList &ol) const; @@ -270,7 +363,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef IMPL *m_impl = 0; }; -ClassDef *createClassDef( +ClassDefMutable *createClassDef( const char *fileName,int startLine,int startColumn, const char *name,ClassDef::CompoundType ct, const char *ref,const char *fName, @@ -280,14 +373,15 @@ ClassDef *createClassDef( } //----------------------------------------------------------------------------- -class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef +class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef> { public: - ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd) : DefinitionAliasImpl(newScope,cd) {} - virtual ~ClassDefAliasImpl() {} + ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd) + : DefinitionAliasMixin(newScope,cd) { init(); } + virtual ~ClassDefAliasImpl() { deinit(); } virtual DefType definitionType() const { return TypeClass; } - const ClassDef *getCdAlias() const { return dynamic_cast<const ClassDef*>(getAlias()); } + const ClassDef *getCdAlias() const { return toClassDef(getAlias()); } virtual ClassDef *resolveAlias() { return const_cast<ClassDef*>(getCdAlias()); } virtual QCString getOutputFileBase() const @@ -302,8 +396,8 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->isReference(); } virtual bool isLocal() const { return getCdAlias()->isLocal(); } - virtual ClassSDict *getClassSDict() const - { return getCdAlias()->getClassSDict(); } + virtual ClassLinkedRefMap getClasses() const + { return getCdAlias()->getClasses(); } virtual bool hasDocumentation() const { return getCdAlias()->hasDocumentation(); } virtual bool hasDetailedDescription() const @@ -313,14 +407,14 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef virtual QCString inheritanceGraphFileName() const { return getCdAlias()->inheritanceGraphFileName(); } virtual QCString displayName(bool includeScope=TRUE) const - { return getCdAlias()->displayName(includeScope); } + { return makeDisplayName(this,includeScope); } virtual CompoundType compoundType() const { return getCdAlias()->compoundType(); } virtual QCString compoundTypeString() const { return getCdAlias()->compoundTypeString(); } - virtual BaseClassList *baseClasses() const + virtual BaseClassList baseClasses() const { return getCdAlias()->baseClasses(); } - virtual BaseClassList *subClasses() const + virtual BaseClassList subClasses() const { return getCdAlias()->subClasses(); } virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const { return getCdAlias()->memberNameInfoLinkedMap(); } @@ -366,13 +460,13 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->templateTypeConstraints(); } virtual bool isTemplateArgument() const { return getCdAlias()->isTemplateArgument(); } - virtual Definition *findInnerCompound(const char *name) const + virtual const Definition *findInnerCompound(const char *name) const { return getCdAlias()->findInnerCompound(name); } virtual ArgumentLists getTemplateParameterLists() const { return getCdAlias()->getTemplateParameterLists(); } virtual QCString qualifiedNameWithTemplateParameters( const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const - { return getCdAlias()->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); } + { return makeQualifiedNameWithTemplateParameters(this,actualParams,actualParamIndex); } virtual bool isAbstract() const { return getCdAlias()->isAbstract(); } virtual bool isObjectiveC() const @@ -415,18 +509,12 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->isEmbeddedInOuterScope(); } virtual bool isSimple() const { return getCdAlias()->isSimple(); } - virtual const ClassList *taggedInnerClasses() const - { return getCdAlias()->taggedInnerClasses(); } - virtual ClassDef *tagLessReference() const + virtual const ClassDef *tagLessReference() const { return getCdAlias()->tagLessReference(); } virtual MemberDef *isSmartPointer() const { return getCdAlias()->isSmartPointer(); } virtual bool isJavaEnum() const { return getCdAlias()->isJavaEnum(); } - virtual bool isGeneric() const - { return getCdAlias()->isGeneric(); } - virtual const ClassSDict *innerClasses() const - { return getCdAlias()->innerClasses(); } virtual QCString title() const { return getCdAlias()->title(); } virtual QCString generatedFromFiles() const @@ -447,72 +535,7 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->isSliceLocal(); } virtual bool hasNonReferenceSuperClass() const { return getCdAlias()->hasNonReferenceSuperClass(); } - virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, - const QCString &templSpec,bool &freshInstance) const - { return getCdAlias()->insertTemplateInstance(fileName,startLine,startColumn,templSpec,freshInstance); } - 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 *,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() {} - virtual void addTypeConstraints() {} - virtual void computeAnchors() {} - virtual void mergeMembers() {} - virtual void sortMemberLists() {} - virtual void distributeMemberGroupDocumentation() {} - 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 *) {} - virtual void setAnonymousEnumType() {} - virtual void countMembers() {} - 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; } - virtual bool isVisited() const { return m_visited; } virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const { return getCdAlias()->countMembersIncludingGrouped(lt,inheritedFrom,additional); } virtual int countInheritanceNodes() const @@ -520,17 +543,27 @@ 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 &,MemberListType,const QCString &, - const char *,bool,const ClassDef *, int,bool,bool, QPtrDict<void> *) const {} - private: - mutable bool m_visited = false; + virtual void writeDeclarationLink(OutputList &ol,bool &found, + const char *header,bool localNames) const + { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); } + virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, + const QCString &templSpec,bool &freshInstance) const + { return getCdAlias()->insertTemplateInstance(fileName,startLine,startColumn,templSpec,freshInstance); } + + virtual void updateBaseClasses(const BaseClassList &) {} + virtual void updateSubClasses(const BaseClassList &) {} }; + ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd) { - return new ClassDefAliasImpl(newScope,cd); + ClassDef *acd = new ClassDefAliasImpl(newScope,cd); + //printf("cd name=%s localName=%s qualifiedName=%s qualifiedNameWith=%s displayName()=%s\n", + // acd->name().data(),acd->localName().data(),acd->qualifiedName().data(), + // acd->qualifiedNameWithTemplateParameters().data(),acd->displayName().data()); + return acd; } //----------------------------------------------------------------------------- @@ -567,11 +600,11 @@ class ClassDefImpl::IMPL /*! List of base class (or super-classes) from which this class derives * directly. */ - BaseClassList *inherits = 0; + BaseClassList inherits; /*! List of sub-classes that directly derive from this class */ - BaseClassList *inheritedBy = 0; + BaseClassList inheritedBy; /*! Namespace this class is part of * (this is the inner most namespace in case of nested namespaces) @@ -608,7 +641,7 @@ class ClassDefImpl::IMPL /*! The inner classes contained in this class. Will be 0 if there are * no inner classes. */ - ClassSDict *innerClasses = 0; + ClassLinkedRefMap innerClasses; /* classes for the collaboration diagram */ UsesClassDict *usesImplClassDict = 0; @@ -678,14 +711,11 @@ class ClassDefImpl::IMPL /** Does this class overloaded the -> operator? */ MemberDef *arrowOperator = 0; - ClassList *taggedInnerClasses = 0; - ClassDef *tagLessRef = 0; + const ClassDef *tagLessRef = 0; /** Does this class represent a Java style enum? */ bool isJavaEnum = false; - bool isGeneric = false; - uint64 spec = 0; QCString metaData; @@ -703,8 +733,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, fileName=ctStr+name; } exampleSDict = 0; - inherits = 0; - inheritedBy = 0; incInfo=0; prot=Public; nspace=0; @@ -714,7 +742,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, usesIntfClassDict=0; constraintClassDict=0; memberGroupSDict = 0; - innerClasses = 0; subGrouping=Config_getBool(SUBGROUPING); templateInstances = 0; variableInstances = 0; @@ -728,7 +755,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, usedOnly = FALSE; isSimple = Config_getBool(INLINE_SIMPLE_STRUCTS); arrowOperator = 0; - taggedInnerClasses = 0; tagLessRef = 0; spec=0; //QCString ns; @@ -746,7 +772,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, { isLocal=FALSE; } - isGeneric = (lang==SrcLangExt_CSharp || lang==SrcLangExt_Java) && QCString(name).find('<')!=-1; } ClassDefImpl::IMPL::IMPL() : vhdlSummaryTitles(17) @@ -756,8 +781,6 @@ ClassDefImpl::IMPL::IMPL() : vhdlSummaryTitles(17) ClassDefImpl::IMPL::~IMPL() { - delete inherits; - delete inheritedBy; delete exampleSDict; delete usesImplClassDict; delete usedByImplClassDict; @@ -765,11 +788,9 @@ ClassDefImpl::IMPL::~IMPL() delete constraintClassDict; delete incInfo; delete memberGroupSDict; - delete innerClasses; delete templateInstances; delete variableInstances; delete templBaseClassNames; - delete taggedInnerClasses; } //------------------------------------------------------------------------------------------- @@ -780,9 +801,8 @@ ClassDefImpl::ClassDefImpl( const char *nm,CompoundType ct, const char *lref,const char *fName, bool isSymbol,bool isJavaEnum) - : DefinitionImpl(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),0,0,isSymbol) + : DefinitionMixin(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),0,0,isSymbol) { - m_visited=FALSE; setReference(lref); m_impl = new ClassDefImpl::IMPL; m_impl->compType = ct; @@ -810,44 +830,7 @@ QCString ClassDefImpl::getMemberListFileName() const QCString ClassDefImpl::displayName(bool includeScope) const { - //static bool optimizeOutputForJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); - SrcLangExt lang = getLanguage(); - //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - QCString n; - if (lang==SrcLangExt_VHDL) - { - n = VhdlDocGen::getClassName(this); - } - else - { - if (includeScope) - { - n=qualifiedNameWithTemplateParameters(); - } - else - { - n=className(); - } - } - if (isAnonymous()) - { - n = removeAnonymousScopes(n); - } - QCString sep=getLanguageSpecificSeparator(lang); - if (sep!="::") - { - n=substitute(n,"::",sep); - } - if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p") - { - n="<"+n.left(n.length()-2)+">"; - } - //else if (n.right(2)=="-g") - //{ - // n = n.left(n.length()-2); - //} - //printf("ClassDefImpl::displayName()=%s\n",n.data()); - return n; + return makeDisplayName(this,includeScope); } // inserts a base/super class in the inheritance list @@ -855,13 +838,7 @@ void ClassDefImpl::insertBaseClass(ClassDef *cd,const char *n,Protection p, Specifier s,const char *t) { //printf("*** insert base class %s into %s\n",cd->name().data(),name().data()); - //inherits->inSort(new BaseClassDef(cd,p,s,t)); - if (m_impl->inherits==0) - { - m_impl->inherits = new BaseClassList; - m_impl->inherits->setAutoDelete(TRUE); - } - m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t)); + m_impl->inherits.push_back(BaseClassDef(cd,n,p,s,t)); m_impl->isSimple = FALSE; } @@ -872,12 +849,7 @@ void ClassDefImpl::insertSubClass(ClassDef *cd,Protection p, //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data()); static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (!extractPrivate && cd->protection()==Private) return; - if (m_impl->inheritedBy==0) - { - m_impl->inheritedBy = new BaseClassList; - m_impl->inheritedBy->setAutoDelete(TRUE); - } - m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); + m_impl->inheritedBy.push_back(BaseClassDef(cd,0,p,s,t)); m_impl->isSimple = FALSE; } @@ -1218,7 +1190,7 @@ void ClassDefImpl::computeAnchors() { if ((ml->listType()&MemberListType_detailedLists)==0) { - setAnchors(ml); + ml->setAnchors(); } } @@ -1248,6 +1220,7 @@ void ClassDefImpl::distributeMemberGroupDocumentation() void ClassDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); if (m_impl->memberGroupSDict) { @@ -1281,27 +1254,31 @@ void ClassDefImpl::insertUsedFile(FileDef *fd) ClassDef *cd; for (qdi.toFirst();(cd=qdi.current());++qdi) { - cd->insertUsedFile(fd); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->insertUsedFile(fd); + } } } } -static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) +static void writeInheritanceSpecifier(OutputList &ol,const BaseClassDef &bcd) { - if (bcd->prot!=Public || bcd->virt!=Normal) + if (bcd.prot!=Public || bcd.virt!=Normal) { ol.startTypewriter(); ol.docify(" ["); - QStrList sl; - if (bcd->prot==Protected) sl.append("protected"); - else if (bcd->prot==Private) sl.append("private"); - if (bcd->virt==Virtual) sl.append("virtual"); - const char *s=sl.first(); - while (s) + StringVector sl; + if (bcd.prot==Protected) sl.push_back("protected"); + else if (bcd.prot==Private) sl.push_back("private"); + if (bcd.virt==Virtual) sl.push_back("virtual"); + bool first=true; + for (const auto &s : sl) { - ol.docify(s); - s=sl.next(); - if (s) ol.docify(", "); + if (!first) ol.docify(", "); + ol.docify(s.c_str()); + first=false; } ol.docify("]"); ol.endTypewriter(); @@ -1358,7 +1335,7 @@ static void searchTemplateSpecs(/*in*/ const Definition *d, { searchTemplateSpecs(d->getOuterScope(),result,name,lang); } - const ClassDef *cd=dynamic_cast<const ClassDef *>(d); + const ClassDef *cd=toClassDef(d); if (!name.isEmpty()) name+="::"; QCString clName = d->localName(); if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p") @@ -1659,24 +1636,15 @@ void ClassDefImpl::showUsedFiles(OutputList &ol) const int ClassDefImpl::countInheritanceNodes() const { int count=0; - BaseClassDef *ibcd; - if (m_impl->inheritedBy) + for (const auto &ibcd : m_impl->inheritedBy) { - BaseClassListIterator it(*m_impl->inheritedBy); - for (;(ibcd=it.current());++it) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - } + const ClassDef *icd=ibcd.classDef; + if ( icd->isVisibleInHierarchy()) count++; } - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - for (;(ibcd=it.current());++it) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - } + const ClassDef *icd=ibcd.classDef; + if ( icd->isVisibleInHierarchy()) count++; } return count; } @@ -1726,12 +1694,12 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.disableAllBut(OutputGenerator::Man); } - if (m_impl->inherits && m_impl->inherits->count()>0) + if (!m_impl->inherits.empty()) { ol.startParagraph(); //parseText(ol,theTranslator->trInherits()+" "); - QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits->count()); + QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits.size()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1740,15 +1708,15 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.parseText(inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inherits->at(entryIndex); - if (ok && bcd) + BaseClassDef &bcd=m_impl->inherits.at(entryIndex); + if (ok) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; // use the class name but with the template arguments as given // in the inheritance relation QCString displayName = insertTemplateSpecifierInScope( - cd->displayName(),bcd->templSpecifiers); + cd->displayName(),bcd.templSpecifiers); if (cd->isLinkable()) { @@ -1773,10 +1741,10 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } // write subclasses - if (m_impl->inheritedBy && m_impl->inheritedBy->count()>0) + if (!m_impl->inheritedBy.empty()) { ol.startParagraph(); - QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy->count()); + QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1785,10 +1753,10 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.parseText(inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); - if (ok && bcd) + BaseClassDef &bcd=m_impl->inheritedBy.at(entryIndex); + if (ok) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; if (cd->isLinkable()) { ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName()); @@ -1934,35 +1902,30 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const ol.docify("class "); } ol.docify(stripScope(name())); - if (m_impl->inherits) + if (!m_impl->inherits.empty()) { if (m_impl->spec & (Entry::Interface|Entry::Exception)) { ol.docify(" extends "); - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (;(ibcd=it.current());++it) + bool first=true; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + if (!first) ol.docify(", "); + ClassDef *icd = ibcd.classDef; ol.docify(icd->name()); - if (!it.atLast()) - { - ol.docify(", "); - } + first=false; } } else { // Must be a class. - bool implements = FALSE; - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (;(ibcd=it.current());++it) + bool implements = false; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + ClassDef *icd = ibcd.classDef; if (icd->isInterface()) { - implements = TRUE; + implements = true; } else { @@ -1973,20 +1936,14 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const if (implements) { ol.docify(" implements "); - bool first = TRUE; - for (ibcd=it.toFirst();(ibcd=it.current());++it) + bool first = true; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + ClassDef *icd = ibcd.classDef; if (icd->isInterface()) { - if (!first) - { - ol.docify(", "); - } - else - { - first = FALSE; - } + if (!first) ol.docify(", "); + first = false; ol.docify(icd->name()); } } @@ -2070,18 +2027,12 @@ void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) const void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title) const { // nested classes - if (m_impl->innerClasses) - { - m_impl->innerClasses->writeDeclaration(ol,0,title,TRUE); - } + m_impl->innerClasses.writeDeclaration(ol,0,title,TRUE); } void ClassDefImpl::writeInlineClasses(OutputList &ol) const { - if (m_impl->innerClasses) - { - m_impl->innerClasses->writeDocumentation(ol,this); - } + m_impl->innerClasses.writeDocumentation(ol,this); } void ClassDefImpl::startMemberDocumentation(OutputList &ol) const @@ -2152,8 +2103,7 @@ void ClassDefImpl::writeSummaryLinks(OutputList &ol) const for (eli.toFirst();(lde=eli.current());++eli) { if (lde->kind()==LayoutDocEntry::ClassNestedClasses && - m_impl->innerClasses && - m_impl->innerClasses->declVisible() + m_impl->innerClasses.declVisible() ) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; @@ -2222,32 +2172,27 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile) { tagFile << " <templarg>" << convertToXML(a.name) << "</templarg>" << endl; } - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *cd=ibcd.classDef; + if (cd && cd->isLinkable()) { - ClassDef *cd=ibcd->classDef; - if (cd && cd->isLinkable()) + if (!Config_getString(GENERATE_TAGFILE).isEmpty()) { - if (!Config_getString(GENERATE_TAGFILE).isEmpty()) + tagFile << " <base"; + if (ibcd.prot==Protected) { - tagFile << " <base"; - if (ibcd->prot==Protected) - { - tagFile << " protection=\"protected\""; - } - else if (ibcd->prot==Private) - { - tagFile << " protection=\"private\""; - } - if (ibcd->virt==Virtual) - { - tagFile << " virtualness=\"virtual\""; - } - tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; + tagFile << " protection=\"protected\""; } + else if (ibcd.prot==Private) + { + tagFile << " protection=\"private\""; + } + if (ibcd.virt==Virtual) + { + tagFile << " virtualness=\"virtual\""; + } + tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; } } } @@ -2260,20 +2205,15 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile) { case LayoutDocEntry::ClassNestedClasses: { - if (m_impl->innerClasses) + for (const auto &innerCd : m_impl->innerClasses) { - ClassSDict::Iterator cli(*m_impl->innerClasses); - ClassDef *innerCd; - for (cli.toFirst();(innerCd=cli.current());++cli) + if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && + protectionLevelVisible(innerCd->protection()) && + !innerCd->isEmbeddedInOuterScope() + ) { - if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && - protectionLevelVisible(innerCd->protection()) && - !innerCd->isEmbeddedInOuterScope() - ) - { - tagFile << " <class kind=\"" << innerCd->compoundTypeString() << - "\">" << convertToXML(innerCd->name()) << "</class>" << endl; - } + tagFile << " <class kind=\"" << innerCd->compoundTypeString() << + "\">" << convertToXML(innerCd->name()) << "</class>" << endl; } } } @@ -2897,25 +2837,25 @@ void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current const MemberDef *md=mi->memberDef(); if (md->getClassDef()==this && md->isLinkable() && !md->isEnumValue()) { - ol.writeString(" <tr><td class=\"navtab\">"); if (md->isLinkableInProject()) { if (md==currentMd) // selected item => highlight { - ol.writeString("<a class=\"qindexHL\" "); + ol.writeString(" <tr><td class=\"navtabHL\">"); } else { - ol.writeString("<a class=\"qindex\" "); + ol.writeString(" <tr><td class=\"navtab\">"); } + ol.writeString("<a class=\"navtab\" "); 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"); } - ol.writeString("</td></tr>\n"); } } } @@ -2930,22 +2870,22 @@ void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) const { // write inner classes after the parent, so the tag files contain // the definition in proper order! - if (m_impl->innerClasses) + for (const auto &innerCd : m_impl->innerClasses) { - ClassSDict::Iterator cli(*m_impl->innerClasses); - ClassDef *innerCd; - for (cli.toFirst();(innerCd=cli.current());++cli) + ClassDefMutable *innerCdm = toClassDefMutable(innerCd); + if (innerCdm) { - if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && + if ( + innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && protectionLevelVisible(innerCd->protection()) && - !innerCd->isEmbeddedInOuterScope() + !innerCd->isEmbeddedInOuterScope() ) { msg("Generating docs for nested compound %s...\n",qPrint(innerCd->name())); - innerCd->writeDocumentation(ol); - innerCd->writeMemberList(ol); + innerCdm->writeDocumentation(ol); + innerCdm->writeMemberList(ol); } - innerCd->writeDocumentationForInnerClasses(ol); + innerCdm->writeDocumentationForInnerClasses(ol); } } } @@ -3266,13 +3206,21 @@ void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCStri //printf("addTypeConstraint(%s,%s)\n",type.data(),typeConstraint.data()); static bool hideUndocRelation = Config_getBool(HIDE_UNDOC_RELATIONS); if (typeConstraint.isEmpty() || type.isEmpty()) return; - ClassDef *cd = const_cast<ClassDef*>(getResolvedClass(this,getFileDef(),typeConstraint)); + SymbolResolver resolver(getFileDef()); + ClassDefMutable *cd = resolver.resolveClassMutable(this,typeConstraint); if (cd==0 && !hideUndocRelation) { - cd = new ClassDefImpl(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class); + cd = toClassDefMutable( + Doxygen::hiddenClassLinkedMap->add(typeConstraint, + std::unique_ptr<ClassDef>( + new ClassDefImpl( + getDefFileName(),getDefLine(), + getDefColumn(), + typeConstraint, + ClassDef::Class)))); + cd->setUsedOnly(TRUE); cd->setLanguage(getLanguage()); - Doxygen::hiddenClasses->append(typeConstraint,cd); //printf("Adding undocumented constraint '%s' to class %s on type %s\n", // typeConstraint.data(),name().data(),type.data()); } @@ -3337,29 +3285,29 @@ bool ClassDefImpl::hasNonReferenceSuperClass() const { return TRUE; // we're done if this class is not a reference } - if (m_impl->inheritedBy) + for (const auto &ibcd : m_impl->inheritedBy) { - BaseClassListIterator bcli(*m_impl->inheritedBy); - for ( ; bcli.current() && !found ; ++bcli ) // for each super class + ClassDef *bcd=ibcd.classDef; + // recurse into the super class branch + found = found || bcd->hasNonReferenceSuperClass(); + if (!found) { - ClassDef *bcd=bcli.current()->classDef; - // recurse into the super class branch - found = found || bcd->hasNonReferenceSuperClass(); - if (!found) + // look for template instances that might have non-reference super classes + QDict<ClassDef> *cil = bcd->getTemplateInstances(); + if (cil) { - // look for template instances that might have non-reference super classes - QDict<ClassDef> *cil = bcd->getTemplateInstances(); - if (cil) + QDictIterator<ClassDef> tidi(*cil); + for ( ; tidi.current() && !found ; ++tidi) // for each template instance { - QDictIterator<ClassDef> tidi(*cil); - for ( ; tidi.current() && !found ; ++tidi) // for each template instance - { - // recurse into the template instance branch - found = found || tidi.current()->hasNonReferenceSuperClass(); - } + // recurse into the template instance branch + found = found || tidi.current()->hasNonReferenceSuperClass(); } } } + else + { + break; + } } return found; } @@ -3455,16 +3403,14 @@ bool ClassDefImpl::isLinkable() const /*! the class is visible in a class diagram, or class hierarchy */ bool ClassDefImpl::isVisibleInHierarchy() const { - static bool allExternals = Config_getBool(ALLEXTERNALS); - static bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES); - static bool extractStatic = Config_getBool(EXTRACT_STATIC); + bool allExternals = Config_getBool(ALLEXTERNALS); + bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES); + bool extractStatic = Config_getBool(EXTRACT_STATIC); return // show all classes or a subclass is visible - (allExternals || hasNonReferenceSuperClass()) && + ((allExternals && !isArtificial()) || hasNonReferenceSuperClass()) && // and not an anonymous compound !isAnonymous() && - // not an artificially introduced class - /*!isArtificial() &&*/ // 1.8.2: allowed these to appear // and not privately inherited protectionLevelVisible(m_impl->prot) && // documented or shown anyway or documentation is external @@ -3479,7 +3425,7 @@ bool ClassDefImpl::isVisibleInHierarchy() const bool ClassDefImpl::hasDocumentation() const { - return DefinitionImpl::hasDocumentation(); + return DefinitionMixin::hasDocumentation(); } //---------------------------------------------------------------------- @@ -3496,21 +3442,12 @@ bool ClassDefImpl::isBaseClass(const ClassDef *bcd, bool followInstances,int lev err("Possible recursive class relation while inside %s and looking for base class %s\n",qPrint(name()),qPrint(bcd->name())); return FALSE; } - if (baseClasses()) + for (const auto &bclass : baseClasses()) { - // Beware: trying to optimise the iterator away using ->first() & ->next() - // causes bug 625531 - BaseClassListIterator bcli(*baseClasses()); - for ( ; bcli.current() && !found ; ++bcli) - { - const ClassDef *ccd=bcli.current()->classDef; - if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); - //printf("isBaseClass() baseclass %s\n",ccd->name().data()); - if (ccd==bcd) - found=TRUE; - else - found=ccd->isBaseClass(bcd,followInstances,level+1); - } + const ClassDef *ccd = bclass.classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + found = (ccd==bcd) || ccd->isBaseClass(bcd,followInstances,level+1); + if (found) break; } return found; } @@ -3525,17 +3462,11 @@ bool ClassDefImpl::isSubClass(ClassDef *cd,int level) const err("Possible recursive class relation while inside %s and looking for derived class %s\n",qPrint(name()),qPrint(cd->name())); return FALSE; } - if (subClasses()) + for (const auto &iscd : subClasses()) { - BaseClassListIterator bcli(*subClasses()); - for ( ; bcli.current() && !found ; ++bcli) - { - ClassDef *ccd=bcli.current()->classDef; - if (ccd==cd) - found=TRUE; - else - found=ccd->isSubClass(cd,level+1); - } + ClassDef *ccd=iscd.classDef; + found = (ccd==cd) || ccd->isSubClass(cd,level+1); + if (found) break; } return found; } @@ -3568,15 +3499,11 @@ void ClassDefImpl::mergeMembers() //printf(" mergeMembers for %s\n",name().data()); static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); - if (baseClasses()) + for (const auto &bcd : baseClasses()) { - //printf(" => has base classes!\n"); - BaseClassListIterator bcli(*baseClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + ClassDefMutable *bClass=toClassDefMutable(bcd.classDef); + if (bClass) { - ClassDef *bClass=bcd->classDef; - // merge the members in the base class of this inheritance branch first bClass->mergeMembers(); @@ -3610,8 +3537,8 @@ void ClassDefImpl::mergeMembers() if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) // member is in the same or a base class { - ArgumentList &srcAl = srcMd->argumentList(); - ArgumentList &dstAl = dstMd->argumentList(); + ArgumentList &srcAl = const_cast<ArgumentList&>(srcMd->argumentList()); + ArgumentList &dstAl = const_cast<ArgumentList&>(dstMd->argumentList()); found=matchArguments2( srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl, dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl, @@ -3683,8 +3610,8 @@ void ClassDefImpl::mergeMembers() 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; + if (bcd.prot==Protected && prot==Public) prot=bcd.prot; + else if (bcd.prot==Private) prot=bcd.prot; if (inlineInheritedMembers) { @@ -3696,7 +3623,7 @@ void ClassDefImpl::mergeMembers() } Specifier virt=srcMi->virt(); - if (virt==Normal && bcd->virt!=Normal) virt=bcd->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()); @@ -3742,22 +3669,22 @@ void ClassDefImpl::mergeMembers() if (!mi->memberDef()->isFriend()) // don't inherit friends { Protection prot = mi->prot(); - if (bcd->prot==Protected) + if (bcd.prot==Protected) { if (prot==Public) prot=Protected; } - else if (bcd->prot==Private) + else if (bcd.prot==Private) { prot=Private; } - //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", + //printf("%s::%s: prot=%d bcd.prot=%d result=%d\n", // name().data(),mi->memberDef->name().data(),mi->prot, - // bcd->prot,prot); + // bcd.prot,prot); if (prot!=Private || extractPrivate) { Specifier virt=mi->virt(); - if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt; if (inlineInheritedMembers) { @@ -3787,105 +3714,113 @@ void ClassDefImpl::mergeMembers() /*! Merges the members of a Objective-C category into this class. */ -void ClassDefImpl::mergeCategory(ClassDef *category) +void ClassDefImpl::mergeCategory(ClassDef *cat) { - static bool extractLocalMethods = Config_getBool(EXTRACT_LOCAL_METHODS); - bool makePrivate = category->isLocal(); - // in case extract local methods is not enabled we don't add the methods - // of the category in case it is defined in the .m file. - if (makePrivate && !extractLocalMethods) return; - bool isExtension = category->isExtension(); - - category->setCategoryOf(this); - if (isExtension) + ClassDefMutable *category = toClassDefMutable(cat); + if (category) { - category->setArtificial(TRUE); + static bool extractLocalMethods = Config_getBool(EXTRACT_LOCAL_METHODS); + bool makePrivate = category->isLocal(); + // in case extract local methods is not enabled we don't add the methods + // of the category in case it is defined in the .m file. + if (makePrivate && !extractLocalMethods) return; + bool isExtension = category->isExtension(); - // copy base classes/protocols from extension - if (category->baseClasses()) + category->setCategoryOf(this); + if (isExtension) { - BaseClassListIterator bcli(*category->baseClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + category->setArtificial(TRUE); + + // copy base classes/protocols from extension + for (const auto &bcd : category->baseClasses()) { - insertBaseClass(bcd->classDef,bcd->usedName,bcd->prot,bcd->virt,bcd->templSpecifiers); - // correct bcd->classDef so that they do no longer derive from + insertBaseClass(bcd.classDef,bcd.usedName,bcd.prot,bcd.virt,bcd.templSpecifiers); + // correct bcd.classDef so that they do no longer derive from // category, but from this class! - if (bcd->classDef->subClasses()) + BaseClassList scl = bcd.classDef->subClasses(); + for (auto &scd : scl) { - BaseClassListIterator scli(*bcd->classDef->subClasses()); - BaseClassDef *scd; - for ( ; (scd=scli.current()) ; ++scli ) + if (scd.classDef==category) { - if (scd->classDef==category) - { - scd->classDef=this; - } + scd.classDef=this; } } + bcd.classDef->updateSubClasses(scl); } } - } - // make methods private for categories defined in the .m file - //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); + // make methods private for categories defined in the .m file + //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); - const MemberNameInfoLinkedMap &srcMnd = category->memberNameInfoLinkedMap(); - MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; + const MemberNameInfoLinkedMap &srcMnd = category->memberNameInfoLinkedMap(); + MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; - for (auto &srcMni : srcMnd) - { - MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName()); - if (dstMni) // method is already defined in the class + for (auto &srcMni : srcMnd) { - //printf("Existing member %s\n",srcMni->memberName()); - auto &dstMi = dstMni->front(); - auto &srcMi = srcMni->front(); - if (srcMi && dstMi) + MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName()); + if (dstMni) // method is already defined in the class { - combineDeclarationAndDefinition(srcMi->memberDef(),dstMi->memberDef()); - dstMi->memberDef()->setCategory(category); - dstMi->memberDef()->setCategoryRelation(srcMi->memberDef()); - srcMi->memberDef()->setCategoryRelation(dstMi->memberDef()); + //printf("Existing member %s\n",srcMni->memberName()); + auto &dstMi = dstMni->front(); + auto &srcMi = srcMni->front(); + if (srcMi && dstMi) + { + MemberDefMutable *smdm = toMemberDefMutable(srcMi->memberDef()); + MemberDefMutable *dmdm = toMemberDefMutable(dstMi->memberDef()); + if (smdm && dmdm) + { + combineDeclarationAndDefinition(smdm,dmdm); + dmdm->setCategory(category); + dmdm->setCategoryRelation(smdm); + smdm->setCategoryRelation(dmdm); + } + } } - } - 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) + else // new method name { - //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("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("Copying member %s\n",mi->memberDef->name().data()); - newMd->moveTo(this); + //printf("Adding '%s'\n",mi->memberDef->name().data()); + Protection prot = mi->prot(); + //if (makePrivate) prot = Private; + std::unique_ptr<MemberDefMutable> newMd { toMemberDefMutable(mi->memberDef()->deepCopy()) }; + if (newMd) + { + //printf("Copying member %s\n",mi->memberDef->name().data()); + newMd->moveTo(this); - 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)); + 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 - QCString name = newMd->name(); - MemberName *mn = Doxygen::memberNameLinkedMap->add(name); + QCString name = newMd->name(); + MemberName *mn = Doxygen::memberNameLinkedMap->add(name); - newMd->setCategory(category); - newMd->setCategoryRelation(mi->memberDef()); - mi->memberDef()->setCategoryRelation(newMd.get()); - if (makePrivate || isExtension) - { - newMd->makeImplementationDetail(); + if (newMd) + { + newMd->setCategory(category); + newMd->setCategoryRelation(mi->memberDef()); + } + MemberDefMutable *mdm = toMemberDefMutable(mi->memberDef()); + if (mdm) + { + mdm->setCategoryRelation(newMd.get()); + } + if (newMd && (makePrivate || isExtension)) + { + newMd->makeImplementationDetail(); + } + internalInsertMember(newMd.get(),prot,FALSE); + mn->push_back(std::move(newMd)); } - internalInsertMember(newMd.get(),prot,FALSE); - mn->push_back(std::move(newMd)); } } } @@ -4047,7 +3982,7 @@ QCString ClassDefImpl::getSourceFileBase() const } else { - return DefinitionImpl::getSourceFileBase(); + return DefinitionMixin::getSourceFileBase(); } } @@ -4059,11 +3994,14 @@ void ClassDefImpl::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pr { for (auto &mi : *mni) { - MemberDef *md=mi->memberDef(); - md->setGroupDef(gd,pri,fileName,startLine,hasDocs); - gd->insertMember(md,TRUE); - ClassDef *innerClass = md->getClassDefOfAnonymousType(); - if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs); + MemberDefMutable *md = toMemberDefMutable(mi->memberDef()); + if (md) + { + md->setGroupDef(gd,pri,fileName,startLine,hasDocs); + gd->insertMember(md,TRUE); + ClassDefMutable *innerClass = toClassDefMutable(md->getClassDefOfAnonymousType()); + if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs); + } } } } @@ -4074,23 +4012,13 @@ void ClassDefImpl::addInnerCompound(const Definition *d) if (d->definitionType()==Definition::TypeClass) // only classes can be // nested in classes. { - if (m_impl->innerClasses==0) - { - m_impl->innerClasses = new ClassSDict(17); - } - m_impl->innerClasses->inSort(d->localName(),dynamic_cast<const ClassDef *>(d)); + m_impl->innerClasses.add(d->localName(),toClassDef(d)); } } -Definition *ClassDefImpl::findInnerCompound(const char *name) const +const Definition *ClassDefImpl::findInnerCompound(const char *name) const { - Definition *result=0; - if (name==0) return 0; - if (m_impl->innerClasses) - { - result = m_impl->innerClasses->find(name); - } - return result; + return m_impl->innerClasses.find(name); } ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, @@ -4101,18 +4029,40 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, { m_impl->templateInstances = new QDict<ClassDef>(17); } - ClassDef *templateClass=m_impl->templateInstances->find(templSpec); + ClassDefMutable *templateClass=toClassDefMutable(m_impl->templateInstances->find(templSpec)); if (templateClass==0) { - Debug::print(Debug::Classes,0," New template instance class '%s''%s'\n",qPrint(name()),qPrint(templSpec)); QCString tcname = removeRedundantWhiteSpace(localName()+templSpec); - templateClass = new ClassDefImpl( - fileName,startLine,startColumn,tcname,ClassDef::Class); - templateClass->setTemplateMaster(this); - templateClass->setOuterScope(getOuterScope()); - templateClass->setHidden(isHidden()); - m_impl->templateInstances->insert(templSpec,templateClass); - freshInstance=TRUE; + Debug::print(Debug::Classes,0," New template instance class '%s''%s' inside '%s' hidden=%d\n",qPrint(name()),qPrint(templSpec),qPrint(name()),isHidden()); + + templateClass = toClassDefMutable(Doxygen::classLinkedMap->find(tcname)); + if (templateClass==0) + { + templateClass = + toClassDefMutable( + Doxygen::classLinkedMap->add(tcname, + std::unique_ptr<ClassDef>( + new ClassDefImpl(fileName,startLine,startColumn,tcname,ClassDef::Class)))); + templateClass->setTemplateMaster(this); + templateClass->setOuterScope(getOuterScope()); + templateClass->setHidden(isHidden()); + m_impl->templateInstances->insert(templSpec,templateClass); + + // also add nested classes + for (const auto &innerCd : m_impl->innerClasses) + { + QCString innerName = tcname+"::"+innerCd->localName(); + ClassDefMutable *innerClass = + toClassDefMutable( + Doxygen::classLinkedMap->add(innerName, + std::unique_ptr<ClassDef>( + new ClassDefImpl(fileName,startLine,startColumn,innerName,ClassDef::Class)))); + templateClass->addInnerCompound(innerClass); + innerClass->setOuterScope(templateClass); + innerClass->setHidden(isHidden()); + } + freshInstance=TRUE; + } } return templateClass; } @@ -4124,14 +4074,14 @@ ClassDef *ClassDefImpl::getVariableInstance(const char *templSpec) const m_impl->variableInstances = new QDict<ClassDef>(17); m_impl->variableInstances->setAutoDelete(TRUE); } - ClassDef *templateClass=m_impl->variableInstances->find(templSpec); + ClassDefMutable *templateClass=toClassDefMutable(m_impl->variableInstances->find(templSpec)); if (templateClass==0) { Debug::print(Debug::Classes,0," New template variable instance class '%s' '%s'\n",qPrint(name()),qPrint(templSpec)); QCString tcname = removeRedundantWhiteSpace(name()+templSpec); templateClass = new ClassDefImpl("<code>",1,1,tcname, ClassDef::Class,0,0,FALSE); - templateClass->addMembersToTemplateInstance( this, templSpec ); + templateClass->addMembersToTemplateInstance( this, templateArguments(), templSpec ); templateClass->setTemplateMaster(this); m_impl->variableInstances->insert(templSpec,templateClass); } @@ -4162,17 +4112,17 @@ QDict<int> *ClassDefImpl::getTemplateBaseClassNames() const return m_impl->templBaseClassNames; } -void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) +void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const ArgumentList &templateArguments,const char *templSpec) { //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec); - for (auto &mni : cd->memberNameInfoLinkedMap()) + for (const auto &mni : cd->memberNameInfoLinkedMap()) { - for (auto &mi : *mni) + for (const auto &mi : *mni) { auto actualArguments_p = stringToArgumentList(getLanguage(),templSpec); MemberDef *md = mi->memberDef(); - std::unique_ptr<MemberDef> imd { md->createTemplateInstanceMember( - cd->templateArguments(),actualArguments_p) }; + std::unique_ptr<MemberDefMutable> imd { md->createTemplateInstanceMember( + templateArguments,actualArguments_p) }; //printf("%s->setMemberClass(%p)\n",imd->name().data(),this); imd->setMemberClass(this); imd->setTemplateMaster(md); @@ -4191,6 +4141,15 @@ void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *t mn->push_back(std::move(imd)); } } + // also instantatie members for nested classes + for (const auto &innerCd : cd->getClasses()) + { + ClassDefMutable *ncd = toClassDefMutable(m_impl->innerClasses.find(innerCd->localName())); + if (ncd) + { + ncd->addMembersToTemplateInstance(innerCd,cd->templateArguments(),templSpec); + } + } } QCString ClassDefImpl::getReference() const @@ -4201,7 +4160,7 @@ QCString ClassDefImpl::getReference() const } else { - return DefinitionImpl::getReference(); + return DefinitionMixin::getReference(); } } @@ -4213,7 +4172,7 @@ bool ClassDefImpl::isReference() const } else { - return DefinitionImpl::isReference(); + return DefinitionMixin::isReference(); } } @@ -4223,7 +4182,7 @@ ArgumentLists ClassDefImpl::getTemplateParameterLists() const Definition *d=getOuterScope(); while (d && d->definitionType()==Definition::TypeClass) { - result.insert(result.begin(),dynamic_cast<ClassDef*>(d)->templateArguments()); + result.insert(result.begin(),toClassDef(d)->templateArguments()); d = d->getOuterScope(); } if (!templateArguments().empty()) @@ -4236,59 +4195,7 @@ ArgumentLists ClassDefImpl::getTemplateParameterLists() const QCString ClassDefImpl::qualifiedNameWithTemplateParameters( const ArgumentLists *actualParams,uint *actualParamIndex) const { - //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); - static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES); - //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); - QCString scName; - Definition *d=getOuterScope(); - if (d) - { - if (d->definitionType()==Definition::TypeClass) - { - ClassDef *cd=dynamic_cast<ClassDef *>(d); - scName = cd->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); - } - else if (!hideScopeNames) - { - scName = d->qualifiedName(); - } - } - - SrcLangExt lang = getLanguage(); - QCString scopeSeparator = getLanguageSpecificSeparator(lang); - if (!scName.isEmpty()) scName+=scopeSeparator; - - bool isSpecialization = localName().find('<')!=-1; - - QCString clName = className(); - //bool isGeneric = getLanguage()==SrcLangExt_CSharp; - //if (isGeneric && clName.right(2)=="-g") - //{ - // clName = clName.left(clName.length()-2); - //} - //printf("m_impl->lang=%d clName=%s isSpecialization=%d\n",getLanguage(),clName.data(),isSpecialization); - scName+=clName; - if (!templateArguments().empty()) - { - if (actualParams && *actualParamIndex<actualParams->size()) - { - const ArgumentList &al = actualParams->at(*actualParamIndex); - if (!isSpecialization) - { - scName+=tempArgListToString(al,lang); - } - (*actualParamIndex)++; - } - else - { - if (!isSpecialization) - { - scName+=tempArgListToString(templateArguments(),lang); - } - } - } - //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data()); - return scName; + return makeQualifiedNameWithTemplateParameters(this,actualParams,actualParamIndex); } QCString ClassDefImpl::className() const @@ -4416,7 +4323,14 @@ 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(this,ml); + if ((ml->listType()&MemberListType_detailedLists)==0) + { + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setSectionList(this,ml); + } + } } void ClassDefImpl::sortMemberLists() @@ -4427,10 +4341,14 @@ void ClassDefImpl::sortMemberLists() { if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); } } - if (m_impl->innerClasses) - { - m_impl->innerClasses->sort(); - } + std::sort(m_impl->innerClasses.begin(), + m_impl->innerClasses.end(), + [](const auto &c1,const auto &c2) + { + return Config_getBool(SORT_BY_SCOPE_NAME) ? + qstricmp(c1->name(), c2->name() )<0 : + qstricmp(c1->className(), c2->className())<0 ; + }); } int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, @@ -4536,26 +4454,21 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt, // name().data(),lt,process,count,invert); if ((process^invert) || showAlways) { - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDefMutable *icd=toClassDefMutable(ibcd.classDef); + int lt1,lt2; + if (icd && icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - int lt1,lt2; - if (icd->isLinkable()) + convertProtectionLevel(lt,ibcd.prot,<1,<2); + //printf("%s: convert %d->(%d,%d) prot=%d\n", + // icd->name().data(),lt,lt1,lt2,ibcd->prot); + if (visitedClasses->find(icd)==0) { - convertProtectionLevel(lt,ibcd->prot,<1,<2); - //printf("%s: convert %d->(%d,%d) prot=%d\n", - // icd->name().data(),lt,lt1,lt2,ibcd->prot); - if (visitedClasses->find(icd)==0) + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); - } + inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); } } } @@ -4677,36 +4590,31 @@ void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol, // name().data(),lt,process,invert,showAlways); if ((process^invert) || showAlways) { - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDefMutable *icd=toClassDefMutable(ibcd.classDef); + if (icd && icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - if (icd->isLinkable()) + int lt1,lt3; + convertProtectionLevel(lt,ibcd.prot,<1,<3); + if (lt2==-1 && lt3!=-1) { - int lt1,lt3; - convertProtectionLevel(lt,ibcd->prot,<1,<3); - if (lt2==-1 && lt3!=-1) - { - lt2=lt3; - } - //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot); - if (visitedClasses->find(icd)==0) - { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - icd->writeMemberDeclarations(ol,(MemberListType)lt1, - title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); - } - } - else + lt2=lt3; + } + //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot); + if (visitedClasses->find(icd)==0) + { + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - //printf("%s: class already visited!\n",icd->name().data()); + icd->writeMemberDeclarations(ol,(MemberListType)lt1, + title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); } } + else + { + //printf("%s: class already visited!\n",icd->name().data()); + } } } } @@ -4811,7 +4719,7 @@ bool ClassDefImpl::isLocal() const return m_impl->isLocal; } -ClassSDict *ClassDefImpl::getClassSDict() const +ClassLinkedRefMap ClassDefImpl::getClasses() const { return m_impl->innerClasses; } @@ -4821,16 +4729,26 @@ ClassDefImpl::CompoundType ClassDefImpl::compoundType() const return m_impl->compType; } -BaseClassList *ClassDefImpl::baseClasses() const +BaseClassList ClassDefImpl::baseClasses() const { return m_impl->inherits; } -BaseClassList *ClassDefImpl::subClasses() const +void ClassDefImpl::updateBaseClasses(const BaseClassList &bcd) +{ + m_impl->inherits = bcd; +} + +BaseClassList ClassDefImpl::subClasses() const { return m_impl->inheritedBy; } +void ClassDefImpl::updateSubClasses(const BaseClassList &bcd) +{ + m_impl->inheritedBy = bcd; +} + const MemberNameInfoLinkedMap &ClassDefImpl::memberNameInfoLinkedMap() const { return m_impl->allMemberNameInfoLinkedMap; @@ -5036,7 +4954,7 @@ MemberDef *ClassDefImpl::isSmartPointer() const return m_impl->arrowOperator; } -void ClassDefImpl::reclassifyMember(MemberDef *md,MemberType t) +void ClassDefImpl::reclassifyMember(MemberDefMutable *md,MemberType t) { md->setMemberType(t); QListIterator<MemberList> mli(m_impl->memberLists); @@ -5096,26 +5014,12 @@ bool ClassDefImpl::isEmbeddedInOuterScope() const return b1 || b2; // either reason will do } -const ClassList *ClassDefImpl::taggedInnerClasses() const -{ - return m_impl->taggedInnerClasses; -} - -void ClassDefImpl::addTaggedInnerClass(ClassDef *cd) -{ - if (m_impl->taggedInnerClasses==0) - { - m_impl->taggedInnerClasses = new ClassList; - } - m_impl->taggedInnerClasses->append(cd); -} - -ClassDef *ClassDefImpl::tagLessReference() const +const ClassDef *ClassDefImpl::tagLessReference() const { return m_impl->tagLessRef; } -void ClassDefImpl::setTagLessReference(ClassDef *cd) +void ClassDefImpl::setTagLessReference(const ClassDef *cd) { m_impl->tagLessRef = cd; } @@ -5135,11 +5039,6 @@ bool ClassDefImpl::isJavaEnum() const return m_impl->isJavaEnum; } -bool ClassDefImpl::isGeneric() const -{ - return m_impl->isGeneric; -} - void ClassDefImpl::setClassSpecifier(uint64 spec) { m_impl->spec = spec; @@ -5154,11 +5053,6 @@ bool ClassDefImpl::isExtension() const return b; } -const ClassSDict *ClassDefImpl::innerClasses() const -{ - return m_impl->innerClasses; -} - const FileList &ClassDefImpl::usedFiles() const { return m_impl->files; @@ -5186,7 +5080,7 @@ bool ClassDefImpl::isSliceLocal() const void ClassDefImpl::setName(const char *name) { - DefinitionImpl::setName(name); + DefinitionMixin::setName(name); } void ClassDefImpl::setMetaData(const char *md) @@ -5204,3 +5098,67 @@ QCString ClassDefImpl::inheritanceGraphFileName() const return m_impl->inheritFileName; } +// --- Cast functions +// +ClassDef *toClassDef(Definition *d) +{ + if (d && (typeid(*d)==typeid(ClassDefImpl) || typeid(*d)==typeid(ClassDefAliasImpl))) + { + return static_cast<ClassDef*>(d); + } + else + { + return 0; + } +} + +ClassDef *toClassDef(DefinitionMutable *md) +{ + Definition *d = toDefinition(md); + if (d && typeid(*d)==typeid(ClassDefImpl)) + { + return static_cast<ClassDef*>(d); + } + else + { + return 0; + } +} + +const ClassDef *toClassDef(const Definition *d) +{ + if (d && (typeid(*d)==typeid(ClassDefImpl) || typeid(*d)==typeid(ClassDefAliasImpl))) + { + return static_cast<const ClassDef*>(d); + } + else + { + return 0; + } +} + +ClassDefMutable *toClassDefMutable(Definition *d) +{ + if (d && typeid(*d)==typeid(ClassDefImpl)) + { + return static_cast<ClassDefMutable*>(d); + } + else + { + return 0; + } +} + +ClassDefMutable *toClassDefMutable(const Definition *d) +{ + if (d && typeid(*d)==typeid(ClassDefImpl)) + { + return const_cast<ClassDefMutable*>(static_cast<const ClassDefMutable*>(d)); + } + else + { + return 0; + } +} + + diff --git a/src/classdef.h b/src/classdef.h index d413794..217002d 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -19,6 +19,7 @@ #define CLASSDEF_H #include <vector> +#include <set> #include <qlist.h> #include <qdict.h> @@ -30,14 +31,14 @@ struct Argument; class MemberDef; +class MemberDefMutable; class MemberList; class MemberDict; class ClassList; -class ClassSDict; +class ClassLinkedRefMap; class OutputList; class FileDef; class FileList; -class BaseClassList; class NamespaceDef; class MemberDef; class ExampleSDict; @@ -52,13 +53,46 @@ class StringDict; struct IncludeInfo; class ClassDefImpl; class FTextStream; +class ClassDef; +class ClassDefMutable; + +/** Class that contains information about an inheritance relation. + */ +struct BaseClassDef +{ + 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 + * (may be a typedef name instead of the class name) + */ + QCString usedName; + + /** Protection level of the inheritance relation: + * Public, Protected, or Private + */ + Protection prot; + + /** Virtualness of the inheritance relation: + * Normal, or Virtual + */ + Specifier virt; + + /** Template arguments used for the base class */ + QCString templSpecifiers; +}; + +using BaseClassList = std::vector<BaseClassDef>; /** A abstract class representing of a compound symbol. * * A compound can be a class, struct, union, interface, service, singleton, * or exception. */ -class ClassDef : virtual public Definition +class ClassDef : public Definition { public: /** The various compound types */ @@ -75,7 +109,6 @@ class ClassDef : virtual public Definition virtual ~ClassDef() {} - //----------------------------------------------------------------------------------- // --- getters //----------------------------------------------------------------------------------- @@ -100,7 +133,7 @@ class ClassDef : virtual public Definition virtual bool isLocal() const = 0; /** returns the classes nested into this class */ - virtual ClassSDict *getClassSDict() const = 0; + virtual ClassLinkedRefMap getClasses() const = 0; /** returns TRUE if this class has documentation */ virtual bool hasDocumentation() const = 0; @@ -126,11 +159,17 @@ class ClassDef : virtual public Definition /** Returns the list of base classes from which this class directly * inherits. */ - virtual BaseClassList *baseClasses() const = 0; + virtual BaseClassList baseClasses() const = 0; + + /** Update the list of base classes to the one passed */ + virtual void updateBaseClasses(const BaseClassList &bcd) = 0; /** Returns the list of sub classes that directly derive from this class */ - virtual BaseClassList *subClasses() const = 0; + virtual BaseClassList subClasses() const = 0; + + /** Update the list of sub classes to the one passed */ + virtual void updateSubClasses(const BaseClassList &bcd) = 0; /** Returns a dictionary of all members. This includes any inherited * members. Members are sorted alphabetically. @@ -221,7 +260,7 @@ class ClassDef : virtual public Definition * available, or 0 otherwise. * @param name The name of the nested compound */ - virtual Definition *findInnerCompound(const char *name) const = 0; + virtual const Definition *findInnerCompound(const char *name) const = 0; /** Returns the template parameter lists that form the template * declaration of this class. @@ -295,15 +334,12 @@ class ClassDef : virtual public Definition virtual bool isSimple() const = 0; - virtual const ClassList *taggedInnerClasses() const = 0; - virtual ClassDef *tagLessReference() const = 0; + virtual const ClassDef *tagLessReference() const = 0; virtual MemberDef *isSmartPointer() const = 0; virtual bool isJavaEnum() const = 0; - virtual bool isGeneric() const = 0; - virtual const ClassSDict *innerClasses() const = 0; virtual QCString title() const = 0; virtual QCString generatedFromFiles() const = 0; @@ -319,6 +355,30 @@ class ClassDef : virtual public Definition virtual bool hasNonReferenceSuperClass() const = 0; //----------------------------------------------------------------------------------- + // --- count members ---- + //----------------------------------------------------------------------------------- + + virtual int countMembersIncludingGrouped(MemberListType lt, + const ClassDef *inheritedFrom,bool additional) const = 0; + virtual int countInheritanceNodes() const = 0; + virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, + int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const = 0; + + //----------------------------------------------------------------------------------- + // --- helpers ---- + //----------------------------------------------------------------------------------- + + virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, + const QCString &templSpec,bool &freshInstance) const = 0; + virtual void writeDeclarationLink(OutputList &ol,bool &found, + const char *header,bool localNames) const = 0; + +}; + +class ClassDefMutable : public DefinitionMutable, public ClassDef +{ + public: + //----------------------------------------------------------------------------------- // --- setters ---- //----------------------------------------------------------------------------------- @@ -338,7 +398,7 @@ class ClassDef : virtual public Definition virtual void setTypeConstraints(const ArgumentList &al) = 0; virtual void setCategoryOf(ClassDef *cd) = 0; virtual void setUsedOnly(bool b) = 0; - virtual void setTagLessReference(ClassDef *cd) = 0; + virtual void setTagLessReference(const ClassDef *cd) = 0; virtual void setName(const char *name) = 0; virtual void setMetaData(const char *md) = 0; @@ -350,12 +410,9 @@ class ClassDef : virtual public Definition virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) = 0; virtual void insertMember(MemberDef *) = 0; virtual void insertUsedFile(FileDef *) = 0; - virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) = 0; - virtual void addTaggedInnerClass(ClassDef *cd) = 0; + virtual void addMembersToTemplateInstance(const ClassDef *cd,const ArgumentList &templateArguments,const char *templSpec) = 0; virtual void addInnerCompound(const Definition *d) = 0; virtual bool addExample(const char *anchor,const char *name, const char *file) = 0; - virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, - const QCString &templSpec,bool &freshInstance) const = 0; virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) = 0; virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) = 0; virtual void makeTemplateArgument(bool b=TRUE) = 0; @@ -368,7 +425,7 @@ class ClassDef : virtual public Definition virtual void mergeMembers() = 0; virtual void sortMemberLists() = 0; virtual void distributeMemberGroupDocumentation() = 0; - virtual void reclassifyMember(MemberDef *md,MemberType t) = 0; + virtual void reclassifyMember(MemberDefMutable *md,MemberType t) = 0; virtual void removeMemberFromLists(MemberDef *md) = 0; virtual void setAnonymousEnumType() = 0; virtual void countMembers() = 0; @@ -387,8 +444,6 @@ class ClassDef : virtual public Definition virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const = 0; virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeInlineDocumentation(OutputList &ol) const = 0; - virtual void writeDeclarationLink(OutputList &ol,bool &found, - const char *header,bool localNames) const = 0; virtual void writeTagFile(FTextStream &) = 0; virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title, const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0, @@ -397,27 +452,11 @@ class ClassDef : virtual public Definition virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, const ClassDef *inheritedFrom,const QCString &inheritId) const = 0; - //----------------------------------------------------------------------------------- - // --- count members ---- - //----------------------------------------------------------------------------------- - - virtual int countMembersIncludingGrouped(MemberListType lt, - const ClassDef *inheritedFrom,bool additional) const = 0; - virtual int countInheritanceNodes() const = 0; - virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, - int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const = 0; - - //----------------------------------------------------------------------------------- - // --- visiting administration ---- - //----------------------------------------------------------------------------------- - - virtual void setVisited(bool visited) const = 0; - virtual bool isVisited() const = 0; }; /** Factory method to create a new ClassDef object */ -ClassDef *createClassDef( +ClassDefMutable *createClassDef( const char *fileName,int startLine,int startColumn, const char *name,ClassDef::CompoundType ct, const char *ref=0,const char *fName=0, @@ -425,6 +464,17 @@ ClassDef *createClassDef( ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd); +// --- Set of classes + +using ClassDefSet = std::set<const ClassDef*>; + +// --- Cast functions + +ClassDef *toClassDef(Definition *d); +ClassDef *toClassDef(DefinitionMutable *d); +const ClassDef *toClassDef(const Definition *d); +ClassDefMutable *toClassDefMutable(Definition *d); +ClassDefMutable *toClassDefMutable(const Definition *d); //------------------------------------------------------------------------ @@ -480,65 +530,6 @@ class UsesClassDictIterator : public QDictIterator<UsesClassDef> //------------------------------------------------------------------------ -/** Class that contains information about an inheritance relation. - */ -struct BaseClassDef -{ - 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 - * (may be a typedef name instead of the class name) - */ - QCString usedName; - - /** Protection level of the inheritance relation: - * Public, Protected, or Private - */ - Protection prot; - - /** Virtualness of the inheritance relation: - * Normal, or Virtual - */ - Specifier virt; - - /** Template arguments used for the base class */ - QCString templSpecifiers; -}; - -/** List of base classes. - * - * The classes are alphabetically sorted on name if inSort() is used. - */ -class BaseClassList : public QList<BaseClassDef> -{ - public: - ~BaseClassList() {} - int compareValues(const BaseClassDef *item1,const BaseClassDef *item2) const - { - const ClassDef *c1=item1->classDef; - const ClassDef *c2=item2->classDef; - if (c1==0 || c2==0) - return FALSE; - else - return qstricmp(c1->name(),c2->name()); - } -}; - -/** Iterator for a list of base classes. - */ -class BaseClassListIterator : public QListIterator<BaseClassDef> -{ - public: - BaseClassListIterator(const BaseClassList &bcl) : - QListIterator<BaseClassDef>(bcl) {} -}; - -//------------------------------------------------------------------------ - /** Class that contains information about a type constraint relations. */ diff --git a/src/classlist.cpp b/src/classlist.cpp index ee4ffa4..2998ac4 100644 --- a/src/classlist.cpp +++ b/src/classlist.cpp @@ -52,72 +52,59 @@ int ClassList::compareValues(const ClassDef *item1, const ClassDef *item2) const return compItems(item1,item2); } -int ClassSDict::compareValues(const ClassDef *item1, const ClassDef *item2) const -{ - return compItems(item1,item2); -} - ClassListIterator::ClassListIterator(const ClassList &cllist) : QListIterator<ClassDef>(cllist) { } -bool ClassSDict::declVisible(const ClassDef::CompoundType *filter) const +//------------------------------------------- + +bool ClassLinkedRefMap::declVisible(const ClassDef::CompoundType *filter) const { - static bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES); - static bool extractLocalClasses = Config_getBool(EXTRACT_LOCAL_CLASSES); - if (count()>0) + bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES); + bool extractLocalClasses = Config_getBool(EXTRACT_LOCAL_CLASSES); + for (const auto &cd : *this) { - ClassSDict::Iterator sdi(*this); - ClassDef *cd=0; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (!cd->isAnonymous() && + (filter==0 || *filter==cd->compoundType()) + ) { - if (!cd->isAnonymous() && - (filter==0 || *filter==cd->compoundType()) + bool isLink = cd->isLinkable(); + if (isLink || + (!hideUndocClasses && + (!cd->isLocal() || extractLocalClasses) + ) ) { - bool isLink = cd->isLinkable(); - if (isLink || - (!hideUndocClasses && - (!cd->isLocal() || extractLocalClasses) - ) - ) - { - return TRUE; - } + return true; } } } - return FALSE; + return false; } -void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter, - const char *header,bool localNames) const +void ClassLinkedRefMap::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter, + const char *header,bool localNames) const { static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); - if (count()>0) + bool found=FALSE; + for (const auto &cd : *this) { - ClassSDict::Iterator sdi(*this); - ClassDef *cd=0; - bool found=FALSE; - for (sdi.toFirst();(cd=sdi.current());++sdi) + //printf(" ClassLinkedRefMap::writeDeclaration for %s\n",cd->name().data()); + if (!cd->isAnonymous() && + !cd->isExtension() && + (cd->protection()!=Private || extractPrivate) && + (filter==0 || *filter==cd->compoundType()) + ) { - //printf(" ClassSDict::writeDeclaration for %s\n",cd->name().data()); - if (!cd->isAnonymous() && - !cd->isExtension() && - (cd->protection()!=Private || extractPrivate) && - (filter==0 || *filter==cd->compoundType()) - ) - { - //printf("writeDeclarationLink()\n"); - cd->writeDeclarationLink(ol,found,header,localNames); - } + //printf("writeDeclarationLink()\n"); + cd->writeDeclarationLink(ol,found,header,localNames); } - if (found) ol.endMemberList(); } + if (found) ol.endMemberList(); } -void ClassSDict::writeDocumentation(OutputList &ol,const Definition * container) const +void ClassLinkedRefMap::writeDocumentation(OutputList &ol,const Definition * container) const { static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); @@ -125,36 +112,35 @@ void ClassSDict::writeDocumentation(OutputList &ol,const Definition * container) static bool inlineSimpleClasses = Config_getBool(INLINE_SIMPLE_STRUCTS); if (!inlineGroupedClasses && !inlineSimpleClasses) return; - if (count()>0) - { - bool found=FALSE; + bool found=FALSE; - ClassSDict::Iterator sdi(*this); - ClassDef *cd=0; - for (sdi.toFirst();(cd=sdi.current());++sdi) + for (const auto &cd : *this) + { + //printf("%s:writeDocumentation() %p linkable=%d embedded=%d container=%p partOfGroups=%d\n", + // cd->name().data(),cd->getOuterScope(),cd->isLinkableInProject(),cd->isEmbeddedInOuterScope(), + // container,cd->partOfGroups() ? cd->partOfGroups()->count() : 0); + + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + !cd->isAlias() && + (container==0 || cd->partOfGroups()==0) // if container==0 -> show as part of the group docs, otherwise only show if not part of a group + ) { - //printf("%s:writeDocumentation() %p linkable=%d embedded=%d container=%p partOfGroups=%d\n", - // cd->name().data(),cd->getOuterScope(),cd->isLinkableInProject(),cd->isEmbeddedInOuterScope(), - // container,cd->partOfGroups() ? cd->partOfGroups()->count() : 0); - - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - !cd->isAlias() && - (container==0 || cd->partOfGroups()==0) // if container==0 -> show as part of the group docs, otherwise only show if not part of a group - ) + //printf(" showing class %s\n",cd->name().data()); + if (!found) + { + ol.writeRuler(); + ol.startGroupHeader(); + ol.parseText(fortranOpt?theTranslator->trTypeDocumentation(): + theTranslator->trClassDocumentation()); + ol.endGroupHeader(); + found=TRUE; + } + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) { - //printf(" showing class %s\n",cd->name().data()); - if (!found) - { - ol.writeRuler(); - ol.startGroupHeader(); - ol.parseText(fortranOpt?theTranslator->trTypeDocumentation(): - theTranslator->trClassDocumentation()); - ol.endGroupHeader(); - found=TRUE; - } - cd->writeInlineDocumentation(ol); + cdm->writeInlineDocumentation(ol); } } } diff --git a/src/classlist.h b/src/classlist.h index 6e4281f..9ff53db 100644 --- a/src/classlist.h +++ b/src/classlist.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,6 +21,7 @@ #include <qlist.h> #include <qdict.h> +#include "linkedmap.h" #include "classdef.h" #include "sortdict.h" @@ -44,28 +45,6 @@ class ClassListIterator : public QListIterator<ClassDef> ClassListIterator(const ClassList &list); }; -/** An unsorted dictionary of ClassDef objects. */ -class ClassDict : public QDict<ClassDef> -{ - public: - ClassDict(uint size) : QDict<ClassDef>(size) {} - ~ClassDict() {} -}; - -/** A sorted dictionary of ClassDef objects. */ -class ClassSDict : public SDict<ClassDef> -{ - public: - 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; - void writeDocumentation(OutputList &ol,const Definition *container=0) const; - bool declVisible(const ClassDef::CompoundType *filter=0) const; - private: - int compareValues(const ClassDef *item1,const ClassDef *item2) const; -}; - class GenericsCollection : public QIntDict<ClassDef> { public: @@ -73,7 +52,7 @@ class GenericsCollection : public QIntDict<ClassDef> ~GenericsCollection() {} }; -class GenericsSDict +class GenericsSDict { public: GenericsSDict() : m_dict(17) { m_dict.setAutoDelete(TRUE); } @@ -84,4 +63,18 @@ class GenericsSDict SDict<GenericsCollection> m_dict; }; +class ClassLinkedMap : public LinkedMap<ClassDef> +{ +}; + +class ClassLinkedRefMap : public LinkedRefMap<const ClassDef> +{ + public: + bool declVisible(const ClassDef::CompoundType *filter=0) const; + void writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter,const char *header,bool localNames) const; + void writeDocumentation(OutputList &ol,const Definition * container=0) const; +}; + + + #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. * @@ -25,11 +23,17 @@ %{ /* - * includes + * includes */ +#include <utility> #include <memory> #include <algorithm> +#include <unordered_map> +#include <stack> +#include <vector> +#include <string> +#include <mutex> #include <stdio.h> #include <assert.h> @@ -53,6 +57,8 @@ #include "filename.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" +#include "symbolresolver.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -60,16 +66,12 @@ #define YY_NO_UNISTD_H 1 -#define CLASSBLOCK (int *)4 -#define SCOPEBLOCK (int *)8 -#define INNERBLOCK (int *)12 +#define CLASSBLOCK 1 +#define SCOPEBLOCK 2 +#define INNERBLOCK 3 #define USE_STATE2STRING 0 -/* ----------------------------------------------------------------- - * statics - */ - // context for an Objective-C method call struct ObjCCallCtx { @@ -85,144 +87,11 @@ struct ObjCCallCtx int braceCount; }; -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class VariableContext -{ - public: - static const ClassDef *dummyContext; - - class Scope : public SDict<ClassDef> - { - public: - Scope() : SDict<ClassDef>(17) {} - }; - - VariableContext() - { - m_scopes.setAutoDelete(TRUE); - } - virtual ~VariableContext() - { - } - - void pushScope() - { - m_scopes.append(new Scope); - DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count())); - } - - void popScope() - { - if (m_scopes.count()>0) - { - DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count())); - m_scopes.remove(m_scopes.count()-1); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop var context\n")); - } - } - - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } - - void clearExceptGlobal() - { - DBG_CTX((stderr,"** Clear var context\n")); - m_scopes.clear(); - } - - void addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name); - ClassDef *findVariable(const QCString &name); - - uint count() const { return m_scopes.count(); } - - private: - Scope m_globalScope; - QList<Scope> m_scopes; -}; - -//------------------------------------------------------------------- - -class CallContext -{ - public: - struct Ctx - { - Ctx(QCString _name, QCString _type) : name(_name), type(_type), d(0) {} - QCString name; - QCString type; - const Definition *d; - }; - - CallContext() - { - m_defList.append(new Ctx("","")); - m_defList.setAutoDelete(TRUE); - } - virtual ~CallContext() {} - void setScope(const Definition *d) - { - Ctx *ctx = m_defList.getLast(); - if (ctx) - { - DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d)); - ctx->d=d; - } - } - void pushScope(QCString _name, QCString _type) - { - m_defList.append(new Ctx(_name,_type)); - DBG_CTX((stderr,"** Push call context %d\n",m_defList.count())); - } - void popScope(QCString &_name, QCString &_type) - { - if (m_defList.count()>1) - { - DBG_CTX((stderr,"** Pop call context %d\n",m_defList.count())); - Ctx *ctx = m_defList.getLast(); - if (ctx) - { - _name = ctx->name; - _type = ctx->type; - } - m_defList.removeLast(); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop call context\n")); - } - } - void clear() - { - DBG_CTX((stderr,"** Clear call context\n")); - m_defList.clear(); - m_defList.append(new Ctx("","")); - } - const Definition *getScope() const - { - Ctx *ctx = m_defList.getLast(); - if (ctx) return ctx->d; else return 0; - } - - private: - QList<Ctx> m_defList; -}; - - struct codeYY_state { CodeOutputInterface * code = 0; - ClassSDict *codeClassSDict = 0; + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; QCString curClassName; QStrList curClassBases; @@ -230,10 +99,10 @@ struct codeYY_state QCString parmName; const char * inputString = 0; //!< the code fragment as text - yy_size_t 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 + int yyLineNr = 0; //!< current line number + yy_size_t yyColNr = 0; //!< current column number bool needsTermination = FALSE; bool exampleBlock = FALSE; @@ -246,12 +115,12 @@ struct codeYY_state QCString args; QCString classScope; QCString realScope; - QStack<int> scopeStack; //!< 1 if bracket starts a scope, - // 2 for internal blocks + std::stack<int> scopeStack; //!< 1 if bracket starts a scope, + // 2 for internal blocks int anchorCount = 0; FileDef * sourceFileDef = 0; bool lineNumbers = FALSE; - Definition * currentDefinition = 0; + const Definition * currentDefinition = 0; MemberDef * currentMemberDef = 0; bool includeCodeFragment = FALSE; const char * currentFontClass = 0; @@ -262,20 +131,20 @@ struct codeYY_state QCString saveType; QCString delimiter; - int bracketCount = 0; - int curlyCount = 0; - int sharpCount = 0; + int bracketCount = 0; + int curlyCount = 0; + int sharpCount = 0; bool inFunctionTryBlock = FALSE; bool inForEachExpression = FALSE; int lastTemplCastContext = 0; - int lastSpecialCContext = 0; + int lastSpecialCContext = 0; int lastStringContext = 0; int lastSkipCppContext = 0; int lastVerbStringContext = 0; int lastObjCCallContext = 0; int memCallContext = 0; - int lastCContext = 0; + int lastCContext = 0; int skipInlineInitContext = 0; SrcLangExt lang = SrcLangExt_Unknown; @@ -284,9 +153,9 @@ struct codeYY_state bool lexInit = FALSE; - QStack<int> classScopeLengthStack; + std::stack<int> classScopeLengthStack; - int prefixed_with_this_keyword = FALSE; + int isPrefixedWithThis = FALSE; const Definition *searchCtx = 0; bool collectXRefs = FALSE; @@ -296,17 +165,17 @@ struct codeYY_state int currentObjId=0; int currentWordId=0; int currentCommentId=0; - QStack<ObjCCallCtx> contextStack; - QIntDict<ObjCCallCtx> contextDict; - QIntDict<QCString> nameDict; - QIntDict<QCString> objectDict; - QIntDict<QCString> wordDict; - QIntDict<QCString> commentDict; + std::stack<ObjCCallCtx*> contextStack; + std::unordered_map< int,std::unique_ptr<ObjCCallCtx> > contextMap; + std::unordered_map< int, QCString> nameMap; + std::unordered_map< int, QCString> objectMap; + std::unordered_map< int, QCString> wordMap; + std::unordered_map< int, QCString> commentMap; int braceCount=0; - QCString forceTagReference; VariableContext theVarContext; CallContext theCallContext; + SymbolResolver symbolResolver; }; static bool isCastKeyword(const QCString &s); @@ -330,6 +199,7 @@ static void nextCodeLine(yyscan_t yyscanner); static void startFontClass(yyscan_t yyscanner,const char *s); static void endFontClass(yyscan_t yyscanner); static void codifyLines(yyscan_t yyscanner,const char *text); +static void incrementFlowKeyWordCount(yyscan_t yyscanner); static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const Definition *d, const char *text); @@ -337,21 +207,21 @@ static void addType(yyscan_t yyscanner); static void addParmType(yyscan_t yyscanner); static void addUsingDirective(yyscan_t yyscanner,const char *name); static void setParameterList(yyscan_t yyscanner,const MemberDef *md); -static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d); -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Definition *d); +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); static void updateCallContextForSmartPointer(yyscan_t yyscanner); static bool getLinkInScope(yyscan_t yyscanner,const QCString &c, // scope const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text, - bool varOnly=FALSE - ); + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text, + bool varOnly=FALSE + ); static bool getLink(yyscan_t yyscanner,const char *className, const char *memberName, - CodeOutputInterface &ol, - const char *text=0, - bool varOnly=FALSE); + CodeOutputInterface &ol, + const char *text=0, + bool varOnly=FALSE); static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE,bool varOnly=FALSE); static bool generateClassMemberLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef *xmd,const char *memName); @@ -368,19 +238,26 @@ 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 yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void addVariable(yyscan_t yyscanner,QCString type,QCString name); +//------------------------------------------------------------------- + +static std::mutex g_searchIndexMutex; +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_addExampleMutex; +static std::mutex g_countFlowKeywordsMutex; /* ----------------------------------------------------------------- */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} B [ \t] BN [ \t\n\r] -ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* +ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* SEP ("::"|"\\") SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID} TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">" @@ -402,17 +279,45 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} RAWBEGIN (u|U|L|u8)?R\"[^ \t\(\)\\]{0,16}"(" RAWEND ")"[^ \t\(\)\\]{0,16}\" + //- start: NUMBER ------------------------------------------------------------------------- + // Note same defines in commentcnv.l: keep in sync +DECIMAL_INTEGER [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]? +HEXADECIMAL_INTEGER "0"[xX][0-9a-zA-Z']+[0-9a-zA-Z]? +OCTAL_INTEGER "0"[0-7][0-7']+[0-7]? +BINARY_INTEGER "0"[bB][01][01']*[01]? +INTEGER_NUMBER {DECIMAL_INTEGER}|{HEXADECIMAL_INTEGER}|{OCTAL_INTEGER}|{BINARY_INTEGER} + +FP_SUF [fFlL] + +DIGIT_SEQ [0-9][0-9']*[0-9]? +FRAC_CONST {DIGIT_SEQ}"."|{DIGIT_SEQ}?"."{DIGIT_SEQ} +FP_EXP [eE][+-]?{DIGIT_SEQ} +DEC_FP1 {FRAC_CONST}{FP_EXP}?{FP_SUF}? +DEC_FP2 {DIGIT_SEQ}{FP_EXP}{FP_SUF} + +HEX_DIGIT_SEQ [0-9a-fA-F][0-9a-fA-F']*[0-9a-fA-F]? +HEX_FRAC_CONST {HEX_DIGIT_SEQ}"."|{HEX_DIGIT_SEQ}?"."{HEX_DIGIT_SEQ} +BIN_EXP [pP][+-]?{DIGIT_SEQ} +HEX_FP1 "0"[xX]{HEX_FRAC_CONST}{BIN_EXP}{FP_SUF}? +HEX_FP2 "0"[xX]{HEX_DIGIT_SEQ}{BIN_EXP}{FP_SUF}? + +FLOAT_DECIMAL {DEC_FP1}|{DEC_FP2} +FLOAT_HEXADECIMAL {HEX_FP1}|{HEX_FP2} +FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL} +NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} + //- end: NUMBER --------------------------------------------------------------------------- + %option noyywrap %x SkipString %x SkipStringS %x SkipVerbString -%x SkipCPP -%x SkipComment -%x SkipCxxComment -%x RemoveSpecialCComment -%x StripSpecialCComment -%x Body +%x SkipCPP +%x SkipComment +%x SkipCxxComment +%x RemoveSpecialCComment +%x StripSpecialCComment +%x Body %x FuncCall %x MemberCall %x MemberCall2 @@ -422,22 +327,22 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" %x AlignAsEnd %x PackageName %x ClassVar -%x CppCliTypeModifierFollowup +%x CppCliTypeModifierFollowup %x Bases %x SkipSharp %x ReadInclude %x TemplDecl %x TemplCast -%x CallEnd +%x CallEnd %x ObjCMethod -%x ObjCParams -%x ObjCParamType +%x ObjCParams +%x ObjCParamType %x ObjCCall %x ObjCMName %x ObjCSkipStr %x ObjCCallComment %x OldStyleArgs -%x UsingName +%x UsingName %x RawString %x InlineInit @@ -445,480 +350,493 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <*>\x0d <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") { - startFontClass(yyscanner,"preprocessor"); - yyextra->code->codify(yytext); - BEGIN( ReadInclude ); - } -<Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ { + startFontClass(yyscanner,"preprocessor"); + yyextra->code->codify(yytext); + BEGIN( ReadInclude ); + } +<Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ { yyextra->insideObjC=TRUE; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - if (!yyextra->insideTemplate) - BEGIN( ClassName ); - } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (!yyextra->insideTemplate) + BEGIN( ClassName ); + } <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") { - if (yyextra->insideTemplate) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( ClassName ); - } -<Body>"property"|"event"/{BN}* { - if (yyextra->insideTemplate) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - if (!yyextra->insideTemplate) - BEGIN( ClassName ); - } -<Body>("package")[ \t\n]+ { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( PackageName ); - } -<ClassVar>\n { - if (!yyextra->insideObjC) REJECT; - codifyLines(yyscanner,yytext); - BEGIN(Body); - } -<Body,ClassVar,Bases>"-"|"+" { - if (!yyextra->insideObjC || yyextra->insideBody) - { - yyextra->code->codify(yytext); - } - else // Start of Objective-C method - { - //printf("Method!\n"); - yyextra->code->codify(yytext); - BEGIN(ObjCMethod); - } - } -<ObjCMethod>":" { - yyextra->code->codify(yytext); - BEGIN(ObjCParams); - } -<ObjCParams>"(" { - yyextra->code->codify(yytext); - BEGIN(ObjCParamType); - } -<ObjCParams,ObjCMethod>";"|"{" { - yyextra->code->codify(yytext); - if (*yytext=='{') - { - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - if (!yyextra->curClassName.isEmpty()) // valid class name - { - pushScope(yyscanner,yyextra->curClassName); + if (yyextra->insideTemplate) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( ClassName ); + } +<Body>"property"|"event"/{BN}* { + if (yyextra->insideTemplate) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (!yyextra->insideTemplate) + BEGIN( ClassName ); + } +<Body>("package")[ \t\n]+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( PackageName ); + } +<ClassVar>\n { + if (!yyextra->insideObjC) REJECT; + codifyLines(yyscanner,yytext); + BEGIN(Body); + } +<Body,ClassVar,Bases>"-"|"+" { + if (!yyextra->insideObjC || yyextra->insideBody) + { + yyextra->code->codify(yytext); + } + else // Start of Objective-C method + { + //printf("Method!\n"); + yyextra->code->codify(yytext); + BEGIN(ObjCMethod); + } + } +<ObjCMethod>":" { + yyextra->code->codify(yytext); + BEGIN(ObjCParams); + } +<ObjCParams>"(" { + yyextra->code->codify(yytext); + BEGIN(ObjCParamType); + } +<ObjCParams,ObjCMethod>";"|"{" { + yyextra->code->codify(yytext); + if (*yytext=='{') + { + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (!yyextra->curClassName.isEmpty()) // valid class name + { + pushScope(yyscanner,yyextra->curClassName); DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - yyextra->scopeStack.push(SCOPEBLOCK); - } - } + yyextra->scopeStack.push(SCOPEBLOCK); + } + } yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN(Body); - } -<ObjCParams>{ID}{B}*":" { - yyextra->code->codify(yytext); - } -<ObjCParamType>{TYPEKW} { - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->parmType=yytext; - } -<ObjCParamType>{ID} { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->parmType=yytext; - } -<ObjCParamType>")" { - yyextra->code->codify(yytext); - BEGIN(ObjCParams); - } -<ObjCParams>{ID} { - yyextra->code->codify(yytext); - yyextra->parmName=yytext; - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - } + BEGIN(Body); + } +<ObjCParams>{ID}{B}*":" { + yyextra->code->codify(yytext); + } +<ObjCParamType>{TYPEKW} { + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->parmType=yytext; + } +<ObjCParamType>{ID} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->parmType=yytext; + } +<ObjCParamType>")" { + yyextra->code->codify(yytext); + BEGIN(ObjCParams); + } +<ObjCParams>{ID} { + yyextra->code->codify(yytext); + yyextra->parmName=yytext; + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } <ObjCMethod,ObjCParams,ObjCParamType>{ID} { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<ObjCMethod,ObjCParams,ObjCParamType>. { - yyextra->code->codify(yytext); - } -<ObjCMethod,ObjCParams,ObjCParamType>\n { - codifyLines(yyscanner,yytext); - } -<ReadInclude>[^\n\"\>]+/(">"|"\"") { - //FileInfo *f; - bool ambig; - bool found=FALSE; - //QCString absPath = yytext; - //if (yyextra->sourceFileDef && QDir::isRelativePath(absPath)) - //{ - // absPath = QDir::cleanDirPath(yyextra->sourceFileDef->getPath()+"/"+absPath); - //} + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<ObjCMethod,ObjCParams,ObjCParamType>. { + yyextra->code->codify(yytext); + } +<ObjCMethod,ObjCParams,ObjCParamType>\n { + codifyLines(yyscanner,yytext); + } +<ReadInclude>[^\n\"\>]+/(">"|"\"") { + //FileInfo *f; + bool ambig; + bool found=FALSE; 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()) - { - if (ambig) // multiple input files match the name - { - //printf("===== yes %s is ambiguous\n",yytext); - QCString name = QDir::cleanDirPath(yytext).utf8(); - if (!name.isEmpty() && yyextra->sourceFileDef) - { - FileName *fn = Doxygen::inputNameLinkedMap->find(name); - if (fn) - { - // see if this source file actually includes the file + //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd); + if (fd && fd->isLinkable()) + { + if (ambig) // multiple input files match the name + { + //printf("===== yes %s is ambiguous\n",yytext); + QCString name = QDir::cleanDirPath(yytext).utf8(); + if (!name.isEmpty() && yyextra->sourceFileDef) + { + const FileName *fn = Doxygen::inputNameLinkedMap->find(name); + if (fn) + { + // 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(); - } - } - } - else // not ambiguous - { - found = TRUE; - } - } - //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found); - if (found) - { - writeMultiLineCodeLink(yyscanner,*yyextra->code,fd,yytext); - } - else - { - yyextra->code->codify(yytext); - } - char c=(char)yyinput(yyscanner); - QCString text; - text+=c; - yyextra->code->codify(text); - endFontClass(yyscanner); - BEGIN( Body ); - } -<Body,Bases>^[ \t]*"#" { - startFontClass(yyscanner,"preprocessor"); - yyextra->lastSkipCppContext = YY_START; - yyextra->code->codify(yytext); - BEGIN( SkipCPP ) ; - } -<SkipCPP>. { - yyextra->code->codify(yytext); - } -<SkipCPP>[^\n\/\\]+ { - yyextra->code->codify(yytext); - } -<SkipCPP>\\[\r]?\n { - codifyLines(yyscanner,yytext); - } -<SkipCPP>"//" { - yyextra->code->codify(yytext); - } -<Body,FuncCall>"{" { + } + } + } + else // not ambiguous + { + found = TRUE; + } + } + //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found); + if (found) + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,fd,yytext); + } + else + { + yyextra->code->codify(yytext); + } + char c=(char)yyinput(yyscanner); + QCString text; + text+=c; + yyextra->code->codify(text); + endFontClass(yyscanner); + BEGIN( Body ); + } +<Body,Bases>^[ \t]*"#" { + startFontClass(yyscanner,"preprocessor"); + yyextra->lastSkipCppContext = YY_START; + yyextra->code->codify(yytext); + BEGIN( SkipCPP ) ; + } +<SkipCPP>\" { + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + BEGIN( SkipString ) ; + } +<SkipCPP>. { + yyextra->code->codify(yytext); + } +<SkipCPP>[^\n\/\\\"]+ { + yyextra->code->codify(yytext); + } +<SkipCPP>\\[\r]?\n { + codifyLines(yyscanner,yytext); + } +<SkipCPP>"//"/[^/!] { + REJECT; + yyextra->code->codify(yytext); + } +<Body,FuncCall>"{" { yyextra->theVarContext.pushScope(); DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - yyextra->code->codify(yytext); - if (yyextra->insideBody) - { - yyextra->bodyCurlyCount++; - } - yyextra->type.resize(0); - yyextra->name.resize(0); - BEGIN( Body ); - } -<Body,FuncCall,MemberCall,MemberCall2>"}" { + yyextra->scopeStack.push(INNERBLOCK); + + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + yyextra->code->codify(yytext); + if (yyextra->insideBody) + { + yyextra->bodyCurlyCount++; + } + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN( Body ); + } +<Body,FuncCall,MemberCall,MemberCall2>"}" { yyextra->theVarContext.popScope(); - yyextra->type.resize(0); - yyextra->name.resize(0); - - int *scope = yyextra->scopeStack.pop(); - DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); - if (scope==SCOPEBLOCK || scope==CLASSBLOCK) - { - popScope(yyscanner); - } - - yyextra->code->codify(yytext); - - DBG_CTX((stderr,"yyextra->bodyCurlyCount=%d\n",yyextra->bodyCurlyCount)); - if (--yyextra->bodyCurlyCount<=0) - { - yyextra->insideBody=FALSE; - yyextra->currentMemberDef=0; - if (yyextra->currentDefinition) - yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); - } - BEGIN(Body); - } -<Body,ClassVar>"@end" { - //printf("End of objc scope fd=%s\n",yyextra->sourceFileDef->name().data()); + yyextra->type.resize(0); + yyextra->name.resize(0); + + if (!yyextra->scopeStack.empty()) + { + int scope = yyextra->scopeStack.top(); + yyextra->scopeStack.pop(); + DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); + if (scope==SCOPEBLOCK || scope==CLASSBLOCK) + { + popScope(yyscanner); + } + } + + yyextra->code->codify(yytext); + + DBG_CTX((stderr,"yyextra->bodyCurlyCount=%d\n",yyextra->bodyCurlyCount)); + if (--yyextra->bodyCurlyCount<=0) + { + yyextra->insideBody=FALSE; + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); + } + BEGIN(Body); + } +<Body,ClassVar>"@end" { + //printf("End of objc scope fd=%s\n",yyextra->sourceFileDef->name().data()); if (yyextra->sourceFileDef) - { - FileDef *fd=yyextra->sourceFileDef; - yyextra->insideObjC = fd->name().lower().right(2)==".m" || - fd->name().lower().right(3)==".mm"; - //printf("insideObjC=%d\n",yyextra->insideObjC); - } - else - { - yyextra->insideObjC = FALSE; - } - if (yyextra->insideBody) - { + { + const FileDef *fd=yyextra->sourceFileDef; + yyextra->insideObjC = fd->name().lower().right(2)==".m" || + fd->name().lower().right(3)==".mm"; + //printf("insideObjC=%d\n",yyextra->insideObjC); + } + else + { + yyextra->insideObjC = FALSE; + } + if (yyextra->insideBody) + { yyextra->theVarContext.popScope(); - int *scope = yyextra->scopeStack.pop(); - DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); - if (scope==SCOPEBLOCK || scope==CLASSBLOCK) - { - popScope(yyscanner); - } - yyextra->insideBody=FALSE; - } - - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - - yyextra->currentMemberDef=0; - if (yyextra->currentDefinition) - yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); - BEGIN(Body); - } -<ClassName,ClassVar>";" { - yyextra->code->codify(yytext); - yyextra->searchingForBody=FALSE; - BEGIN( Body ); - } -<ClassName,ClassVar>[*&^%]+ { - yyextra->type=yyextra->curClassName.copy(); - yyextra->name.resize(0); - yyextra->code->codify(yytext); - BEGIN( Body ); // variable of type struct * - } -<ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } -<ClassName>{ID}("."{ID})* | -<ClassName>{ID}("::"{ID})* { + if (!yyextra->scopeStack.empty()) + { + int scope = yyextra->scopeStack.top(); + yyextra->scopeStack.pop(); + DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); + if (scope==SCOPEBLOCK || scope==CLASSBLOCK) + { + popScope(yyscanner); + } + } + yyextra->insideBody=FALSE; + } + + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); + BEGIN(Body); + } +<ClassName,ClassVar>";" { + yyextra->code->codify(yytext); + yyextra->searchingForBody=FALSE; + BEGIN( Body ); + } +<ClassName,ClassVar>[*&^%]+ { + yyextra->type=yyextra->curClassName.copy(); + yyextra->name.resize(0); + yyextra->code->codify(yytext); + BEGIN( Body ); // variable of type struct * + } +<ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<ClassName>{ID}("."{ID})* | +<ClassName>{ID}("::"{ID})* { if (yyextra->lang==SrcLangExt_CSharp) yyextra->curClassName=substitute(yytext,".","::"); else yyextra->curClassName=yytext; - addType(yyscanner); + addType(yyscanner); if (yyextra->curClassName=="alignas") { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); endFontClass(yyscanner); BEGIN( AlignAs ); } else { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( ClassVar ); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); } - } -<AlignAs>"(" { + } +<AlignAs>"(" { yyextra->bracketCount=1; - yyextra->code->codify(yytext); + yyextra->code->codify(yytext); BEGIN( AlignAsEnd ); } -<AlignAs>\n { yyextra->yyLineNr++; +<AlignAs>\n { yyextra->yyLineNr++; codifyLines(yyscanner,yytext); } <AlignAs>. { yyextra->code->codify(yytext); } <AlignAsEnd>"(" { yyextra->code->codify(yytext); - yyextra->bracketCount++; + yyextra->bracketCount++; } -<AlignAsEnd>")" { +<AlignAsEnd>")" { yyextra->code->codify(yytext); if (--yyextra->bracketCount<=0) { BEGIN(ClassName); } } -<AlignAsEnd>\n { yyextra->yyLineNr++; - codifyLines(yyscanner,yytext); +<AlignAsEnd>\n { yyextra->yyLineNr++; + codifyLines(yyscanner,yytext); } <AlignAsEnd>. { yyextra->code->codify(yytext); } -<ClassName>{ID}("\\"{ID})* { // PHP namespace +<ClassName>{ID}("\\"{ID})* { // PHP namespace yyextra->curClassName=substitute(yytext,"\\","::"); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yyextra->curClassName); - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( ClassVar ); - } + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } <ClassName>{ID}{B}*"("{ID}")" { // Obj-C category yyextra->curClassName=removeRedundantWhiteSpace(yytext); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yyextra->curClassName); - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( ClassVar ); - } -<PackageName>{ID}("."{ID})* { - yyextra->curClassName=substitute(yytext,".","::"); - //printf("found package: %s\n",yyextra->curClassName.data()); - addType(yyscanner); - codifyLines(yyscanner,yytext); - } -<ClassVar>"=" { - unput(*yytext); - BEGIN( Body ); - } -<ClassVar>("extends"|"implements") { // Java, Slice - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->curClassBases.clear(); - BEGIN( Bases ); - } + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } +<PackageName>{ID}("."{ID})* { + yyextra->curClassName=substitute(yytext,".","::"); + //printf("found package: %s\n",yyextra->curClassName.data()); + addType(yyscanner); + codifyLines(yyscanner,yytext); + } +<ClassVar>"=" { + unput(*yytext); + BEGIN( Body ); + } +<ClassVar>("extends"|"implements") { // Java, Slice + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->curClassBases.clear(); + BEGIN( Bases ); + } <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") { - DBG_CTX((stderr,"***** C++/CLI modifier %s on yyextra->curClassName=%s\n",yytext,yyextra->curClassName.data())); - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( CppCliTypeModifierFollowup ); - } -<ClassVar>{ID} { - yyextra->type = yyextra->curClassName.copy(); - yyextra->name = yytext; - if (yyextra->insideBody) - { - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); - } - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* { - codifyLines(yyscanner,yytext); - yyextra->curClassBases.clear(); - BEGIN( Bases ); - } -<PackageName>[ \t]*";" | + DBG_CTX((stderr,"***** C++/CLI modifier %s on yyextra->curClassName=%s\n",yytext,yyextra->curClassName.data())); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( CppCliTypeModifierFollowup ); + } +<ClassVar>{ID} { + yyextra->type = yyextra->curClassName.copy(); + yyextra->name = yytext; + if (yyextra->insideBody) + { + addVariable(yyscanner,yyextra->type,yyextra->name); + } + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* { + codifyLines(yyscanner,yytext); + yyextra->curClassBases.clear(); + BEGIN( Bases ); + } +<PackageName>[ \t]*";" | <Bases>^{B}*/"@"{ID} | // Objective-C interface <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* { yyextra->theVarContext.pushScope(); - yyextra->code->codify(yytext); - if (YY_START==ClassVar && yyextra->curClassName.isEmpty()) - { - yyextra->curClassName = yyextra->name.copy(); - } - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - if (!yyextra->curClassName.isEmpty()) // valid class name - { + yyextra->code->codify(yytext); + if (YY_START==ClassVar && yyextra->curClassName.isEmpty()) + { + yyextra->curClassName = yyextra->name.copy(); + } + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (!yyextra->curClassName.isEmpty()) // valid class name + { DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n")); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yyextra->curClassName); - DBG_CTX((stderr,"***** yyextra->curClassName=%s\n",yyextra->curClassName.data())); - if (getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->curClassName)==0) - { - DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); - ClassDef *ncd=createClassDef("<code>",1,1, - yyextra->curClassName,ClassDef::Class,0,0,FALSE); - yyextra->codeClassSDict->append(yyextra->curClassName,ncd); - // insert base classes. - char *s=yyextra->curClassBases.first(); - while (s) - { - const ClassDef *bcd=yyextra->codeClassSDict->find(s); - if (bcd==0) bcd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s); - if (bcd && bcd!=ncd) - { - ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal); - } - s=yyextra->curClassBases.next(); - } - } - //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); - } - else // not a class name -> assume inner block - { + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + DBG_CTX((stderr,"***** yyextra->curClassName=%s\n",yyextra->curClassName.data())); + if (yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,yyextra->curClassName)==0) + { + DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); + ScopedTypeVariant var(yyextra->curClassName); + // insert base classes. + char *s=yyextra->curClassBases.first(); + while (s) + { + const ClassDef *bcd=0; + auto it = yyextra->codeClassMap.find(s); + if (it!=yyextra->codeClassMap.end()) + { + bcd = toClassDef(it->second.globalDef()); + } + if (bcd==0) bcd=yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,s); + if (bcd && bcd->name()!=yyextra->curClassName) + { + var.localDef()->insertBaseClass(bcd->name()); + } + s=yyextra->curClassBases.next(); + } + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); + } + //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); + } + else // not a class name -> assume inner block + { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - } - yyextra->curClassName.resize(0); - yyextra->curClassBases.clear(); - BEGIN( Body ); - } -<Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } -<Bases>{SEP}?({ID}{SEP})*{ID} { - DBG_CTX((stderr,"%s:addBase(%s)\n",yyextra->curClassName.data(),yytext)); - yyextra->curClassBases.inSort(yytext); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<Bases>"<" { - yyextra->code->codify(yytext); - if (!yyextra->insideObjC) - { - yyextra->sharpCount=1; - BEGIN ( SkipSharp ); - } - else - { - yyextra->insideProtocolList=TRUE; - } - } -<Bases>">" { - yyextra->code->codify(yytext); - yyextra->insideProtocolList=FALSE; - } + yyextra->scopeStack.push(INNERBLOCK); + } + yyextra->curClassName.resize(0); + yyextra->curClassBases.clear(); + BEGIN( Body ); + } +<Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Bases>{SEP}?({ID}{SEP})*{ID} { + DBG_CTX((stderr,"%s:addBase(%s)\n",yyextra->curClassName.data(),yytext)); + yyextra->curClassBases.inSort(yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<Bases>"<" { + yyextra->code->codify(yytext); + if (!yyextra->insideObjC) + { + yyextra->sharpCount=1; + BEGIN ( SkipSharp ); + } + else + { + yyextra->insideProtocolList=TRUE; + } + } +<Bases>">" { + yyextra->code->codify(yytext); + yyextra->insideProtocolList=FALSE; + } <SkipSharp>"<" { - yyextra->code->codify(yytext); - ++yyextra->sharpCount; - } -<SkipSharp>">" { - yyextra->code->codify(yytext); - if (--yyextra->sharpCount<=0) - BEGIN ( Bases ); - } + yyextra->code->codify(yytext); + ++yyextra->sharpCount; + } +<SkipSharp>">" { + yyextra->code->codify(yytext); + if (--yyextra->sharpCount<=0) + BEGIN ( Bases ); + } <SkipSharp>"\"" { - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; BEGIN(SkipString); } <SkipSharp>"\'" { - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; BEGIN(SkipStringS); } <Bases>"(" { @@ -935,111 +853,108 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" if (--yyextra->sharpCount<=0) BEGIN ( Bases ); } - - -<Bases>"," { - yyextra->code->codify(yytext); - } - + + +<Bases>"," { + yyextra->code->codify(yytext); + } + <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" { - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); - } + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); + } <Body>{SCOPEPREFIX}?"operator"/"(" { - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); } <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" { - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); - } -<Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->insideTemplate=TRUE; - yyextra->sharpCount=0; - } -<Body>"using"{BN}+"namespace"{BN}+ { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN(UsingName); - } -<UsingName>{ID}("::"{ID})* { addUsingDirective(yyscanner,yytext); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); + } +<Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->insideTemplate=TRUE; + yyextra->sharpCount=0; + } +<Body>"using"{BN}+"namespace"{BN}+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(UsingName); + } +<UsingName>{ID}("::"{ID})* { addUsingDirective(yyscanner,yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n")); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yytext); - BEGIN(Body); + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yytext); + BEGIN(Body); } -<UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); } -<UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); } -<Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# - yyextra->prefixed_with_this_keyword = TRUE; +<UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); } +<UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); } +<Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# + yyextra->isPrefixedWithThis = TRUE; } -<Body>{KEYWORD}/([^a-z_A-Z0-9]) { +<Body>{KEYWORD}/([^a-z_A-Z0-9]) { if (yyextra->lang==SrcLangExt_Java && qstrcmp("internal",yytext) ==0) REJECT; if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - if (QCString(yytext)=="typedef") - { - addType(yyscanner); - yyextra->name+=yytext; - } - endFontClass(yyscanner); - } -<Body>{KEYWORD}/{B}* { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + if (QCString(yytext)=="typedef") + { + addType(yyscanner); + yyextra->name+=yytext; + } + endFontClass(yyscanner); + } +<Body>{KEYWORD}/{B}* { if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<Body>{KEYWORD}/{BN}*"(" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Body>{KEYWORD}/{BN}*"(" { if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->name.resize(0);yyextra->type.resize(0); - } -<FuncCall>"in"/{BN}* { - if (!yyextra->inForEachExpression) REJECT; - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - // insert the variable in the parent scope, see bug 546158 - yyextra->theVarContext.popScope(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - yyextra->theVarContext.pushScope(); - yyextra->name.resize(0);yyextra->type.resize(0); - } -<Body>{FLOWKW}/{BN}*"(" { - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->name.resize(0);yyextra->type.resize(0); - yyextra->inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0); - BEGIN(FuncCall); - } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); + } +<FuncCall>"in"/{BN}* { + if (!yyextra->inForEachExpression) REJECT; + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + // insert the variable in the parent scope, see bug 546158 + yyextra->theVarContext.popScope(); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->theVarContext.pushScope(); + yyextra->name.resize(0);yyextra->type.resize(0); + } +<Body>{FLOWKW}/{BN}*"(" { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); + yyextra->inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0); + BEGIN(FuncCall); + } <Body>{FLOWCONDITION}/{BN}*"(" { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); - } + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -1047,20 +962,17 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" yyextra->inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0); BEGIN(FuncCall); } -<Body>{FLOWKW}/([^a-z_A-Z0-9]) { - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - if (yyextra->inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0)) - { - yyextra->inFunctionTryBlock=FALSE; - } - } -<Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) +<Body>{FLOWKW}/([^a-z_A-Z0-9]) { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (yyextra->inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0)) { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); + yyextra->inFunctionTryBlock=FALSE; } + } +<Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) { + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -1069,47 +981,44 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" yyextra->inFunctionTryBlock=FALSE; } } -<Body>{FLOWKW}/{B}* { - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } +<Body>{FLOWKW}/{B}* { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } <Body>{FLOWCONDITION}/{B}* { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); - } + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); } <Body>"*"{B}*")" { // end of cast? - yyextra->code->codify(yytext); - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->bracketCount--; + yyextra->code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->bracketCount--; yyextra->parmType = yyextra->name; - BEGIN(FuncCall); + BEGIN(FuncCall); } <Body>"\\)"|"\\(" { yyextra->code->codify(yytext); } -<Body>[\\|\)\+\-\/\%\~\!] { - yyextra->code->codify(yytext); - yyextra->name.resize(0);yyextra->type.resize(0); - if (*yytext==')') - { - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->bracketCount--; - BEGIN(FuncCall); - } - } +<Body>[\\|\)\+\-\/\%\~\!] { + yyextra->code->codify(yytext); + yyextra->name.resize(0);yyextra->type.resize(0); + if (*yytext==')') + { + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->bracketCount--; + BEGIN(FuncCall); + } + } <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* { - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - addType(yyscanner); - yyextra->name+=yytext; - } + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + addType(yyscanner); + yyextra->name+=yytext; + } <Body,TemplDecl,ObjCMethod>{TYPEKWSL}/{B}* { if (yyextra->lang!=SrcLangExt_Slice) { @@ -1117,390 +1026,395 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } else { - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - addType(yyscanner); - yyextra->name+=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + addType(yyscanner); + yyextra->name+=yytext; } - } + } <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->sharpCount=0; - BEGIN(TemplDecl); - } + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->sharpCount=0; + BEGIN(TemplDecl); + } <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...> - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->sharpCount=0; - BEGIN(TemplDecl); - } -<TemplDecl>"class"|"typename" { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<TemplDecl>"<" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->sharpCount=0; + BEGIN(TemplDecl); + } +<TemplDecl>"class"|"typename" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<TemplDecl>"<" { yyextra->code->codify(yytext); yyextra->sharpCount++; - } -<TemplDecl>">" { + } +<TemplDecl>">" { yyextra->code->codify(yytext); yyextra->sharpCount--; - if (yyextra->sharpCount<=0) - { - BEGIN(Body); - } - } -<TemplCast>">" { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastTemplCastContext ); - } -<TemplCast>{ID}("::"{ID})* { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<TemplCast>("const"|"volatile"){B}* { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<TemplCast>[*^]* { - codifyLines(yyscanner,yytext); - } + if (yyextra->sharpCount<=0) + { + BEGIN(Body); + } + } +<TemplCast>">" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastTemplCastContext ); + } +<TemplCast>{ID}("::"{ID})* { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<TemplCast>("const"|"volatile"){B}* { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<TemplCast>[*^]* { + codifyLines(yyscanner,yytext); + } <Body,MemberCall2,FuncCall>{CASTKW}{B}*"<" { // static_cast<T>( - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); yyextra->lastTemplCastContext = YY_START; - BEGIN(TemplCast); - } + BEGIN(TemplCast); + } <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable - addType(yyscanner); - generatePHPVariableLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext+7; + addType(yyscanner); + generatePHPVariableLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext+7; } <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"("::"{ID})*/{B}* { // A<T> *pt; - if (isCastKeyword(yytext) && YY_START==Body) - { - REJECT; - } - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext; - } -<Body>{SCOPENAME}/{BN}*[:;,)\]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5; - addType(yyscanner); - // changed this to generateFunctionLink, see bug 624514 - //generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,FALSE,TRUE); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext; - } -<Body>{SCOPENAME}/{B}* { // p->func() - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext; - } -<Body>"("{B}*("*"{B}*)+{SCOPENAME}+{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." - yyextra->code->codify(yytext); - uint s=0;while (s<(uint)yyleng && !isId(yytext[s])) s++; + if (isCastKeyword(yytext) && YY_START==Body) + { + REJECT; + } + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } +<Body>{SCOPENAME}/{BN}*[:;,)\]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5; + addType(yyscanner); + // changed this to generateFunctionLink, see bug 624514 + //generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,FALSE,TRUE); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } +<Body>{SCOPENAME}/{B}* { // p->func() + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } +<Body>"("{B}*("*"{B}*)+{SCOPENAME}+{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." + yyextra->code->codify(yytext); + 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; - } + QCString varname = ((QCString)yytext).mid(s,e-s+1); + addType(yyscanner); + yyextra->name=varname; + } <Body>{SCOPETNAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{BN}*"(" | -<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo() - if (isCastKeyword(yytext)) - { - REJECT; - } - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); - } -<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} { +<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo() + if (isCastKeyword(yytext)) + { + REJECT; + } + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} { QCString text=yytext; uint i=(uint)text.find('R'); yyextra->code->codify(text.left(i+1)); - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext+i+1); - yyextra->lastStringContext=YY_START; - yyextra->inForEachExpression = FALSE; + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext+i+1); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; yyextra->delimiter = yytext+i+2; yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); - BEGIN( RawString ); - } -<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\" { - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; - yyextra->inForEachExpression = FALSE; - BEGIN( SkipString ); - } -<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' { - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; - yyextra->inForEachExpression = FALSE; - BEGIN( SkipStringS ); - } -<SkipString>[^\"\\\r\n]* { - yyextra->code->codify(yytext); - } -<SkipStringS>[^\'\\\r\n]* { - yyextra->code->codify(yytext); - } -<SkipString,SkipStringS>"//"|"/*" { - yyextra->code->codify(yytext); - } -<SkipString>@?\" { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastStringContext ); - } -<SkipStringS>\' { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastStringContext ); - } -<SkipString,SkipStringS>\\. { - yyextra->code->codify(yytext); - } -<RawString>{RAWEND} { + BEGIN( RawString ); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\" { + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; + BEGIN( SkipString ); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{NUMBER} { //Note similar code in commentcnv.l + if (yyextra->lang!=SrcLangExt_Cpp) REJECT; + yyextra->code->codify(yytext); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' { + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; + BEGIN( SkipStringS ); + } +<SkipString>[^\"\\\r\n]* { + yyextra->code->codify(yytext); + } +<SkipStringS>[^\'\\\r\n]* { + yyextra->code->codify(yytext); + } +<SkipString,SkipStringS>"//"|"/*" { + yyextra->code->codify(yytext); + } +<SkipString>@?\" { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastStringContext ); + } +<SkipStringS>\' { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastStringContext ); + } +<SkipString,SkipStringS>\\. { + yyextra->code->codify(yytext); + } +<RawString>{RAWEND} { yyextra->code->codify(yytext); QCString delimiter = yytext+1; delimiter=delimiter.left(delimiter.length()-1); if (delimiter==yyextra->delimiter) { - BEGIN( yyextra->lastStringContext ); + BEGIN( yyextra->lastStringContext ); } } <RawString>[^)\n]+ { yyextra->code->codify(yytext); } <RawString>. { yyextra->code->codify(yytext); } <RawString>\n { codifyLines(yyscanner,yytext); } -<SkipVerbString>[^"\n]+ { - yyextra->code->codify(yytext); - } -<SkipVerbString>\"\" { // escaped quote - yyextra->code->codify(yytext); - } -<SkipVerbString>\" { // end of string - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastVerbStringContext ); - } -<SkipVerbString>. { - yyextra->code->codify(yytext); - } -<SkipVerbString>\n { - codifyLines(yyscanner,yytext); - } -<Body>":" { - yyextra->code->codify(yytext); - yyextra->name.resize(0);yyextra->type.resize(0); - } -<Body>"<" { - if (yyextra->insideTemplate) - { - yyextra->sharpCount++; - } - yyextra->code->codify(yytext); - } -<Body>">" { - if (yyextra->insideTemplate) - { - if (--yyextra->sharpCount<=0) - { - yyextra->insideTemplate=FALSE; - } - } - yyextra->code->codify(yytext); - } -<Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" { - startFontClass(yyscanner,"charliteral"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } -<Body>"."|"->" { - if (yytext[0]=='-') // -> could be overloaded - { - updateCallContextForSmartPointer(yyscanner); - } - yyextra->code->codify(yytext); - yyextra->memCallContext = YY_START; - BEGIN( MemberCall ); - } -<MemberCall>{SCOPETNAME}/{BN}*"(" { - if (yyextra->theCallContext.getScope()) - { - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - } - yyextra->name.resize(0); - } - else - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - yyextra->name.resize(0); - } - yyextra->type.resize(0); - if (yyextra->memCallContext==Body) - { - BEGIN(FuncCall); - } - else - { - BEGIN(yyextra->memCallContext); - } - } -<MemberCall>{SCOPENAME}/{B}* { - if (yyextra->theCallContext.getScope()) - { - DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope())); - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - } - yyextra->name.resize(0); - } - else - { - DBG_CTX((stderr,"no class context!\n")); - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - yyextra->name.resize(0); - } - yyextra->type.resize(0); - BEGIN(yyextra->memCallContext); - } -<Body>[,=;\[] { - if (yyextra->insideObjC && *yytext=='[') - { - //printf("Found start of ObjC call!\n"); - // start of a method call - yyextra->contextDict.setAutoDelete(TRUE); - yyextra->nameDict.setAutoDelete(TRUE); - yyextra->objectDict.setAutoDelete(TRUE); - yyextra->wordDict.setAutoDelete(TRUE); - yyextra->commentDict.setAutoDelete(TRUE); - yyextra->contextDict.clear(); - yyextra->nameDict.clear(); - yyextra->objectDict.clear(); - yyextra->wordDict.clear(); - yyextra->commentDict.clear(); - yyextra->currentCtxId = 0; - yyextra->currentNameId = 0; - yyextra->currentObjId = 0; - yyextra->currentCtx = 0; - yyextra->braceCount = 0; - unput('['); - BEGIN(ObjCCall); - } - else - { - yyextra->code->codify(yytext); - yyextra->saveName = yyextra->name.copy(); - yyextra->saveType = yyextra->type.copy(); - if (*yytext!='[' && !yyextra->type.isEmpty()) - { - //printf("yyextra->scopeStack.bottom()=%p\n",yyextra->scopeStack.bottom()); - //if (yyextra->scopeStack.top()!=CLASSBLOCK) // commented out for bug731363 - { - //printf("AddVariable: '%s' '%s' context=%d\n", - // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); - } - yyextra->name.resize(0); - } - if (*yytext==';' || *yytext=='=') - { - yyextra->type.resize(0); - yyextra->name.resize(0); - } - else if (*yytext=='[') - { - yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); - } - yyextra->args.resize(0); +<SkipVerbString>[^"\n]+ { + yyextra->code->codify(yytext); + } +<SkipVerbString>\"\" { // escaped quote + yyextra->code->codify(yytext); + } +<SkipVerbString>\" { // end of string + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastVerbStringContext ); + } +<SkipVerbString>. { + yyextra->code->codify(yytext); + } +<SkipVerbString>\n { + codifyLines(yyscanner,yytext); + } +<Body>":" { + yyextra->code->codify(yytext); + yyextra->name.resize(0);yyextra->type.resize(0); + } +<Body>"<" { + if (yyextra->insideTemplate) + { + yyextra->sharpCount++; + } + yyextra->code->codify(yytext); + } +<Body>">" { + if (yyextra->insideTemplate) + { + if (--yyextra->sharpCount<=0) + { + yyextra->insideTemplate=FALSE; + } + } + yyextra->code->codify(yytext); + } +<Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" { + startFontClass(yyscanner,"charliteral"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Body>"."|"->" { + if (yytext[0]=='-') // -> could be overloaded + { + updateCallContextForSmartPointer(yyscanner); + } + yyextra->code->codify(yytext); + yyextra->memCallContext = YY_START; + BEGIN( MemberCall ); + } +<MemberCall>{SCOPETNAME}/{BN}*"(" { + if (yyextra->theCallContext.getScope().globalDef()) + { + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + } + yyextra->name.resize(0); + } + else + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + yyextra->name.resize(0); + } + yyextra->type.resize(0); + if (yyextra->memCallContext==Body) + { + BEGIN(FuncCall); + } + else + { + BEGIN(yyextra->memCallContext); + } + } +<MemberCall>{SCOPENAME}/{B}* { + if (yyextra->theCallContext.getScope().globalDef()) + { + DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope().globalDef())); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + } + yyextra->name.resize(0); + } + else + { + DBG_CTX((stderr,"no class context!\n")); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + yyextra->name.resize(0); + } + yyextra->type.resize(0); + BEGIN(yyextra->memCallContext); + } +<Body>[,=;\[] { + if (yyextra->insideObjC && *yytext=='[') + { + //printf("Found start of ObjC call!\n"); + // start of a method call + yyextra->contextMap.clear(); + yyextra->nameMap.clear(); + yyextra->objectMap.clear(); + yyextra->wordMap.clear(); + yyextra->commentMap.clear(); + yyextra->currentCtxId = 0; + yyextra->currentNameId = 0; + yyextra->currentObjId = 0; + yyextra->currentCtx = 0; + yyextra->braceCount = 0; + unput('['); + BEGIN(ObjCCall); + } + else + { + yyextra->code->codify(yytext); + yyextra->saveName = yyextra->name.copy(); + yyextra->saveType = yyextra->type.copy(); + if (*yytext!='[' && !yyextra->type.isEmpty()) + { + //printf("yyextra->scopeStack.bottom()=%p\n",yyextra->scopeStack.bottom()); + //if (yyextra->scopeStack.top()!=CLASSBLOCK) // commented out for bug731363 + { + //printf("AddVariable: '%s' '%s' context=%d\n", + // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); + addVariable(yyscanner,yyextra->type,yyextra->name); + } + yyextra->name.resize(0); + } + if (*yytext==';' || *yytext=='=') + { + yyextra->type.resize(0); + yyextra->name.resize(0); + } + else if (*yytext=='[') + { + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + } + yyextra->args.resize(0); yyextra->parmType.resize(0); yyextra->parmName.resize(0); - } - } + } + } /* -<ObjCMemberCall>{ID} { - if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0) - { - // TODO: get proper base class for "super" - yyextra->theCallContext.setClass(getClass(yyextra->curClassName)); - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } - else - { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } - yyextra->name.resize(0); - BEGIN(ObjCMemberCall2); - } -<ObjCMemberCall>"[" { - yyextra->code->codify(yytext); - yyextra->theCallContext.pushScope(yyscanner,yyextra->name, yyextra->type); - } -<ObjCMemberCall2>{ID}":"? { - yyextra->name+=yytext; - if (yyextra->theCallContext.getClass()) - { - //printf("Calling method %s\n",yyextra->name.data()); - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getClass(),yyextra->name)) - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yyextra->name); - } - } - else - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yyextra->name); - } - yyextra->name.resize(0); - BEGIN(ObjCMemberCall3); - } -<ObjCMemberCall2,ObjCMemberCall3>"]" { - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->code->codify(yytext); - BEGIN(Body); - } +<ObjCMemberCall>{ID} { + if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0) + { + // TODO: get proper base class for "super" + yyextra->theCallContext.setClass(getClass(yyextra->curClassName)); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + else + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } + yyextra->name.resize(0); + BEGIN(ObjCMemberCall2); + } +<ObjCMemberCall>"[" { + yyextra->code->codify(yytext); + yyextra->theCallContext.pushScope(yyscanner,yyextra->name, yyextra->type); + } +<ObjCMemberCall2>{ID}":"? { + yyextra->name+=yytext; + if (yyextra->theCallContext.getClass()) + { + //printf("Calling method %s\n",yyextra->name.data()); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getClass(),yyextra->name)) + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yyextra->name); + } + } + else + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yyextra->name); + } + yyextra->name.resize(0); + BEGIN(ObjCMemberCall3); + } +<ObjCMemberCall2,ObjCMemberCall3>"]" { + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->code->codify(yytext); + BEGIN(Body); + } */ <ObjCCall,ObjCMName>"["|"{" { saveObjCContext(yyscanner); - yyextra->currentCtx->format+=*yytext; - BEGIN(ObjCCall); - //printf("open\n"); + yyextra->currentCtx->format+=*yytext; + BEGIN(ObjCCall); + //printf("open\n"); } <ObjCCall,ObjCMName>"]"|"}" { - yyextra->currentCtx->format+=*yytext; + yyextra->currentCtx->format+=*yytext; restoreObjCContext(yyscanner); - BEGIN(ObjCMName); - if (yyextra->currentCtx==0) - { - // end of call - writeObjCMethodCall(yyscanner,yyextra->contextDict.find(0)); - BEGIN(Body); - } - //printf("close\n"); + BEGIN(ObjCMName); + if (yyextra->currentCtx==0) + { + // end of call + ObjCCallCtx *ctx = 0; + auto it = yyextra->contextMap.find(0); + if (it!=yyextra->contextMap.end()) + { + ctx = it->second.get(); + } + writeObjCMethodCall(yyscanner,ctx); + BEGIN(Body); + } + //printf("close\n"); } <ObjCCall,ObjCMName>"//".* { yyextra->currentCtx->format+=escapeComment(yyscanner,yytext); @@ -1510,92 +1424,92 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" yyextra->currentCtx->comment=yytext; BEGIN(ObjCCallComment); } -<ObjCCallComment>"*/" { +<ObjCCallComment>"*/" { yyextra->currentCtx->comment+=yytext; yyextra->currentCtx->format+=escapeComment(yyscanner,yyextra->currentCtx->comment); - BEGIN(yyextra->lastObjCCallContext); - } + BEGIN(yyextra->lastObjCCallContext); + } <ObjCCallComment>[^*\n]+ { yyextra->currentCtx->comment+=yytext; } <ObjCCallComment>"//"|"/*" { yyextra->currentCtx->comment+=yytext; } <ObjCCallComment>\n { yyextra->currentCtx->comment+=*yytext; } <ObjCCallComment>. { yyextra->currentCtx->comment+=*yytext; } -<ObjCCall>{ID} { +<ObjCCall>{ID} { yyextra->currentCtx->format+=escapeObject(yyscanner,yytext); - if (yyextra->braceCount==0) - { - yyextra->currentCtx->objectTypeOrName=yytext; + if (yyextra->braceCount==0) + { + yyextra->currentCtx->objectTypeOrName=yytext; //printf("new type=%s\n",yyextra->currentCtx->objectTypeOrName.data()); - BEGIN(ObjCMName); - } - } -<ObjCMName>{ID}/{BN}*"]" { - if (yyextra->braceCount==0 && - yyextra->currentCtx->methodName.isEmpty()) + BEGIN(ObjCMName); + } + } +<ObjCMName>{ID}/{BN}*"]" { + if (yyextra->braceCount==0 && + yyextra->currentCtx->methodName.isEmpty()) { - yyextra->currentCtx->methodName=yytext; + yyextra->currentCtx->methodName=yytext; yyextra->currentCtx->format+=escapeName(yyscanner,yytext); - } - else - { + } + else + { yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); - } + } } -<ObjCMName>{ID}/{BN}*":" { +<ObjCMName>{ID}/{BN}*":" { if (yyextra->braceCount==0) { - yyextra->currentCtx->methodName+=yytext; + yyextra->currentCtx->methodName+=yytext; yyextra->currentCtx->methodName+=":"; - } + } yyextra->currentCtx->format+=escapeName(yyscanner,yytext); } <ObjCSkipStr>[^\n\"$\\]* { yyextra->currentCtx->format+=yytext; } -<ObjCSkipStr>\\. { yyextra->currentCtx->format+=yytext; } -<ObjCSkipStr>"\"" { yyextra->currentCtx->format+=yytext; - BEGIN(yyextra->lastStringContext); +<ObjCSkipStr>\\. { yyextra->currentCtx->format+=yytext; } +<ObjCSkipStr>"\"" { yyextra->currentCtx->format+=yytext; + BEGIN(yyextra->lastStringContext); } <ObjCCall,ObjCMName>{CHARLIT} { yyextra->currentCtx->format+=yytext; } -<ObjCCall,ObjCMName>"@"?"\"" { yyextra->currentCtx->format+=yytext; +<ObjCCall,ObjCMName>"@"?"\"" { yyextra->currentCtx->format+=yytext; yyextra->lastStringContext=YY_START; - BEGIN(ObjCSkipStr); + BEGIN(ObjCSkipStr); } <ObjCCall,ObjCMName,ObjCSkipStr>"$" { yyextra->currentCtx->format+="$$"; } <ObjCCall,ObjCMName>"(" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount++; } <ObjCCall,ObjCMName>")" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount--; } -<ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#) +<ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#) yyextra->currentCtx->format+=yytext; } <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); } <ObjCCall,ObjCMName,ObjCSkipStr>. { yyextra->currentCtx->format+=*yytext; } <ObjCCall,ObjCMName,ObjCSkipStr>\n { yyextra->currentCtx->format+=*yytext; } -<Body>"]" { - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->code->codify(yytext); - // TODO: nested arrays like: a[b[0]->func()]->func() - yyextra->name = yyextra->saveName.copy(); - yyextra->type = yyextra->saveType.copy(); - } -<Body>[0-9]+ { - yyextra->code->codify(yytext); - } -<Body>[0-9]+[xX][0-9A-Fa-f]+ { - yyextra->code->codify(yytext); - } +<Body>"]" { + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->code->codify(yytext); + // TODO: nested arrays like: a[b[0]->func()]->func() + yyextra->name = yyextra->saveName.copy(); + yyextra->type = yyextra->saveType.copy(); + } +<Body>[0-9]+ { + yyextra->code->codify(yytext); + } +<Body>[0-9]+[xX][0-9A-Fa-f]+ { + yyextra->code->codify(yytext); + } <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) { - //addParmType(yyscanner); - //yyextra->parmName=yytext; + //addParmType(yyscanner); + //yyextra->parmName=yytext; if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) { - addParmType(yyscanner); - yyextra->parmName=yytext; - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKWSL}/([^a-z_A-Z0-9]) { if (yyextra->lang!=SrcLangExt_Slice) { @@ -1603,25 +1517,22 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } else { - addParmType(yyscanner); - yyextra->parmName=yytext; - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } - } + } <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) { - addParmType(yyscanner); - yyextra->parmName=yytext; - startFontClass(yyscanner,"keywordflow"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordflow"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } <MemberCall2,FuncCall>{FLOWCONDITION}/([^a-z_A-Z0-9]) { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); - } + incrementFlowKeyWordCount(yyscanner); addParmType(yyscanner); yyextra->parmName=yytext; startFontClass(yyscanner,"keywordflow"); @@ -1629,25 +1540,25 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" endFontClass(yyscanner); } <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* { - if (isCastKeyword(yytext)) - { - REJECT; - } - addParmType(yyscanner); - yyextra->parmName=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); - } -<FuncCall>";" { // probably a cast, not a function call - yyextra->code->codify(yytext); - yyextra->inForEachExpression = FALSE; - BEGIN( Body ); - } -<MemberCall2,FuncCall>, { - yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - } -<MemberCall2,FuncCall>"{" { + if (isCastKeyword(yytext)) + { + REJECT; + } + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); + } +<FuncCall>";" { // probably a cast, not a function call + yyextra->code->codify(yytext); + yyextra->inForEachExpression = FALSE; + BEGIN( Body ); + } +<MemberCall2,FuncCall>, { + yyextra->code->codify(yytext); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } +<MemberCall2,FuncCall>"{" { if (yyextra->bracketCount>0) { yyextra->code->codify(yytext); @@ -1676,28 +1587,28 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <InlineInit>. { yyextra->code->codify(yytext); } -<MemberCall2,FuncCall>"(" { - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - yyextra->code->codify(yytext); - yyextra->bracketCount++; - yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); - if (YY_START==FuncCall && !yyextra->insideBody) - { - yyextra->theVarContext.pushScope(); - } - } +<MemberCall2,FuncCall>"(" { + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + yyextra->code->codify(yytext); + yyextra->bracketCount++; + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + if (YY_START==FuncCall && !yyextra->insideBody) + { + yyextra->theVarContext.pushScope(); + } + } <MemberCall2,FuncCall>{OPERATOR} { // operator - if (qstrcmp(yytext,"*") && - qstrcmp(yytext,"&") && - qstrcmp(yytext,"^") && - qstrcmp(yytext,"%")) // typically a pointer or reference - { - // not a * or &, or C++/CLI's ^ or % - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - } - yyextra->code->codify(yytext); - } -<MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" { + if (qstrcmp(yytext,"*") && + qstrcmp(yytext,"&") && + qstrcmp(yytext,"^") && + qstrcmp(yytext,"%")) // typically a pointer or reference + { + // not a * or &, or C++/CLI's ^ or % + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } + yyextra->code->codify(yytext); + } +<MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" { if (yytext[0]==')') // no a pointer cast { //printf("addVariable(%s,%s)\n",yyextra->parmType.data(),yyextra->parmName.data()); @@ -1706,553 +1617,564 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" yyextra->parmType=yyextra->parmName; yyextra->parmName.resize(0); } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } else { yyextra->parmType = yyextra->parmName; yyextra->parmName.resize(0); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - } - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->inForEachExpression = FALSE; - //yyextra->theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). - yyextra->code->codify(yytext); - if (--yyextra->bracketCount<=0) - { - if (yyextra->name.isEmpty()) - { - BEGIN( Body ); - } - else - { - BEGIN( CallEnd ); - } - } - } -<CallEnd>[ \t\n]* { codifyLines(yyscanner,yytext); } + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + } + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->inForEachExpression = FALSE; + //yyextra->theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). + yyextra->code->codify(yytext); + if (--yyextra->bracketCount<=0) + { + if (yyextra->name.isEmpty()) + { + BEGIN( Body ); + } + else + { + BEGIN( CallEnd ); + } + } + } +<CallEnd>[ \t\n]* { codifyLines(yyscanner,yytext); } /* -<MemberCall2,FuncCall>")"[ \t\n]*[;:] { +<MemberCall2,FuncCall>")"[ \t\n]*[;:] { */ -<CallEnd>[;:] { - codifyLines(yyscanner,yytext); - yyextra->bracketCount=0; - if (*yytext==';') yyextra->searchingForBody=FALSE; - if (!yyextra->type.isEmpty()) - { - DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); - } - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - yyextra->theCallContext.setScope(0); - if (*yytext==';' || yyextra->insideBody) - { - if (!yyextra->insideBody) - { +<CallEnd>[;:] { + codifyLines(yyscanner,yytext); + yyextra->bracketCount=0; + if (*yytext==';') yyextra->searchingForBody=FALSE; + if (!yyextra->type.isEmpty()) + { + DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); + addVariable(yyscanner,yyextra->type,yyextra->name); + } + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + yyextra->theCallContext.setScope(ScopedTypeVariant()); + if (*yytext==';' || yyextra->insideBody) + { + if (!yyextra->insideBody) + { yyextra->theVarContext.popScope(); - } - yyextra->name.resize(0);yyextra->type.resize(0); - BEGIN( Body ); - } - else - { - yyextra->bracketCount=0; - BEGIN( SkipInits ); - } - } + } + yyextra->name.resize(0);yyextra->type.resize(0); + BEGIN( Body ); + } + else + { + yyextra->bracketCount=0; + BEGIN( SkipInits ); + } + } <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" { if (yyextra->insideBody) - { - yyextra->theVarContext.pushScope(); - } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - int index = yyextra->name.findRev("::"); - DBG_CTX((stderr,"yyextra->name=%s\n",yyextra->name.data())); - if (index!=-1) - { - 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) - { - setClassScope(yyscanner,cd->name()); - yyextra->scopeStack.push(SCOPEBLOCK); + { + yyextra->theVarContext.pushScope(); + } + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + int index = yyextra->name.findRev("::"); + DBG_CTX((stderr,"yyextra->name=%s\n",yyextra->name.data())); + if (index!=-1) + { + QCString scope = yyextra->name.left((uint)index); + if (!yyextra->classScope.isEmpty()) scope.prepend(yyextra->classScope+"::"); + const ClassDef *cd=yyextra->symbolResolver.resolveClass(Doxygen::globalScope,scope); + if (cd) + { + setClassScope(yyscanner,cd->name()); + yyextra->scopeStack.push(SCOPEBLOCK); DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - } - else - { - //setClassScope(yyscanner,yyextra->realScope); - yyextra->scopeStack.push(INNERBLOCK); + } + else + { + //setClassScope(yyscanner,yyextra->realScope); + yyextra->scopeStack.push(INNERBLOCK); DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - } - } - else - { + } + } + else + { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - } - yytext[yyleng-1]='\0'; - QCString cv(yytext); - if (!cv.stripWhiteSpace().isEmpty()) - { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - else // just whitespace - { - codifyLines(yyscanner,yytext); - } - yyextra->code->codify("{"); - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN( Body ); - } -<CallEnd>"try" { // function-try-block - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->inFunctionTryBlock=TRUE; - } -<CallEnd>{ID} { - if (yyextra->insideBody || !yyextra->parmType.isEmpty()) - { - REJECT; - } - // could be K&R style definition - addParmType(yyscanner); - yyextra->parmName=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); - BEGIN(OldStyleArgs); - } -<OldStyleArgs>{ID} { - addParmType(yyscanner); - yyextra->parmName=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); - } -<OldStyleArgs>[,;] { - yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - if (*yytext==';') yyextra->parmType.resize(0); - yyextra->parmName.resize(0); - } -<CallEnd,OldStyleArgs>"#" { - startFontClass(yyscanner,"preprocessor"); - yyextra->lastSkipCppContext = Body; - yyextra->code->codify(yytext); - BEGIN( SkipCPP ); - } -<CallEnd>. { - unput(*yytext); - if (!yyextra->insideBody) - { - yyextra->theVarContext.popScope(); - } - yyextra->name.resize(0);yyextra->args.resize(0); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - BEGIN( Body ); - } -<SkipInits>";" { - yyextra->code->codify(yytext); - yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN( Body ); - } -<SkipInits>"{" { - yyextra->code->codify(yytext); - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - if (yyextra->name.find("::")!=-1) - { + yyextra->scopeStack.push(INNERBLOCK); + } + yytext[yyleng-1]='\0'; + QCString cv(yytext); + if (!cv.stripWhiteSpace().isEmpty()) + { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + else // just whitespace + { + codifyLines(yyscanner,yytext); + } + yyextra->code->codify("{"); + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + yyextra->type.resize(0); yyextra->name.resize(0); + BEGIN( Body ); + } +<CallEnd>"try" { // function-try-block + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->inFunctionTryBlock=TRUE; + } +<CallEnd>{ID} { + if (yyextra->insideBody || !yyextra->parmType.isEmpty()) + { + REJECT; + } + // could be K&R style definition + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); + BEGIN(OldStyleArgs); + } +<OldStyleArgs>{ID} { + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); + } +<OldStyleArgs>[,;] { + yyextra->code->codify(yytext); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + if (*yytext==';') yyextra->parmType.resize(0); + yyextra->parmName.resize(0); + } +<CallEnd,OldStyleArgs>"#" { + startFontClass(yyscanner,"preprocessor"); + yyextra->lastSkipCppContext = Body; + yyextra->code->codify(yytext); + BEGIN( SkipCPP ); + } +<CallEnd>. { + unput(*yytext); + if (!yyextra->insideBody) + { + yyextra->theVarContext.popScope(); + } + yyextra->name.resize(0);yyextra->args.resize(0); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + BEGIN( Body ); + } +<SkipInits>";" { + yyextra->code->codify(yytext); + yyextra->type.resize(0); yyextra->name.resize(0); + BEGIN( Body ); + } +<SkipInits>"{" { + yyextra->code->codify(yytext); + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (yyextra->name.find("::")!=-1) + { DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - yyextra->scopeStack.push(SCOPEBLOCK); - setClassScope(yyscanner,yyextra->realScope); - } - else - { + yyextra->scopeStack.push(SCOPEBLOCK); + setClassScope(yyscanner,yyextra->realScope); + } + else + { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - } - yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN( Body ); - } -<SkipInits>{ID} { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<FuncCall>{ID}/"(" { - generateFunctionLink(yyscanner,*yyextra->code,yytext); - } -<FuncCall>{ID}/("."|"->") { - yyextra->name=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( MemberCall2 ); - } -<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}+{B}*")"{B}*)/("."|"->") { - yyextra->code->codify(yytext); - uint s=0;while (!isId(yytext[s])) s++; + yyextra->scopeStack.push(INNERBLOCK); + } + yyextra->type.resize(0); yyextra->name.resize(0); + BEGIN( Body ); + } +<SkipInits>{ID}{B}*"{" { + QCString text = yytext; + int bracketPos = text.find('{'); + int spacePos = text.find(' '); + int len = spacePos==-1 ? bracketPos : spacePos; + generateClassOrGlobalLink(yyscanner,*yyextra->code,text.left(len)); + yyextra->code->codify(yytext+len); + } +<SkipInits>{ID} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<FuncCall>{ID}/"(" { + generateFunctionLink(yyscanner,*yyextra->code,yytext); + } +<FuncCall>{ID}/("."|"->") { + yyextra->name=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( MemberCall2 ); + } +<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}+{B}*")"{B}*)/("."|"->") { + yyextra->code->codify(yytext); + 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 ); - } -<MemberCall2>{ID}/([ \t\n]*"(") { - if (!yyextra->args.isEmpty()) - generateMemberLink(yyscanner,*yyextra->code,yyextra->args,yytext); - else - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->args.resize(0); - BEGIN( FuncCall ); - } + yyextra->name=((QCString)yytext).mid(s,e-s+1); + BEGIN( MemberCall2 ); + } +<MemberCall2>{ID}/([ \t\n]*"(") { + if (!yyextra->args.isEmpty()) + generateMemberLink(yyscanner,*yyextra->code,yyextra->args,yytext); + else + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->args.resize(0); + BEGIN( FuncCall ); + } <MemberCall2>{ID}/([ \t\n]*("."|"->")) { - //yyextra->code->codify(yytext); - yyextra->name=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( MemberCall2 ); - } -<MemberCall2>"->"|"." { - if (yytext[0]=='-') // -> could be overloaded - { - updateCallContextForSmartPointer(yyscanner); - } - yyextra->code->codify(yytext); - yyextra->memCallContext = YY_START; - BEGIN( MemberCall ); - } -<SkipComment>"/*"("!"?)"*/" { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } -<SkipComment>"//"|"/*" { - yyextra->code->codify(yytext); - } -<SkipComment>[^*/\n]+ { - yyextra->code->codify(yytext); - } -<SkipComment>[ \t]*"*/" { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - if (yyextra->lastCContext==SkipCPP) + //yyextra->code->codify(yytext); + yyextra->name=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( MemberCall2 ); + } +<MemberCall2>"->"|"." { + if (yytext[0]=='-') // -> could be overloaded + { + updateCallContextForSmartPointer(yyscanner); + } + yyextra->code->codify(yytext); + yyextra->memCallContext = YY_START; + BEGIN( MemberCall ); + } +<SkipComment>"/*"("!"?)"*/" { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } +<SkipComment>"//"|"/*" { + yyextra->code->codify(yytext); + } +<SkipComment>[^*/\n]+ { + yyextra->code->codify(yytext); + } +<SkipComment>[ \t]*"*/" { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + if (yyextra->lastCContext==SkipCPP) { startFontClass(yyscanner,"preprocessor"); } - BEGIN( yyextra->lastCContext ) ; - } -<SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation - codifyLines(yyscanner,yytext); - } -<SkipCxxComment>[^\r\n]+ { - yyextra->code->codify(yytext); - } -<SkipCxxComment>\r -<SkipCxxComment>\n { - unput('\n'); - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } -<SkipCxxComment>. { - yyextra->code->codify(yytext); - } + BEGIN( yyextra->lastCContext ) ; + } +<SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation + codifyLines(yyscanner,yytext); + } +<SkipCxxComment>[^\r\n]+ { + yyextra->code->codify(yytext); + } +<SkipCxxComment>\r +<SkipCxxComment>\n { + unput('\n'); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } +<SkipCxxComment>. { + yyextra->code->codify(yytext); + } <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] { - yyextra->yyLineNr+=QCString(yytext).contains('\n'); - } + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + } <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? { - yyextra->yyLineNr+=QCString(yytext).contains('\n'); - nextCodeLine(yyscanner); - if (yyextra->lastSpecialCContext==SkipCxxComment) - { // force end of C++ comment here - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } - else - { - BEGIN(yyextra->lastSpecialCContext); - } - } -<RemoveSpecialCComment>"*/" { - BEGIN(yyextra->lastSpecialCContext); - } + if (yyextra->lastSpecialCContext==SkipCxxComment) + { // force end of C++ comment here + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + nextCodeLine(yyscanner); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } + else + { + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + if (yytext[yyleng-1]=='\n') + { + yyextra->yyLineNr--; + unput('\n'); + } + else + { + nextCodeLine(yyscanner); + } + BEGIN(yyextra->lastSpecialCContext); + } + } +<RemoveSpecialCComment>"*/" { + BEGIN(yyextra->lastSpecialCContext); + } <RemoveSpecialCComment>[^*\n]+ <RemoveSpecialCComment>"//"|"/*" <RemoveSpecialCComment>\n { yyextra->yyLineNr++; } <RemoveSpecialCComment>. -<MemberCall>[^a-z_A-Z0-9(\n] { - yyextra->code->codify(yytext); - yyextra->type.resize(0); - yyextra->name.resize(0); - BEGIN(yyextra->memCallContext); - } -<*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment - if (YY_START==SkipCPP) REJECT; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr+=((QCString)yytext).contains('\n'); - nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - if (YY_START==SkipCxxComment) - { - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } - } -<SkipCPP>\n/.*\n { - endFontClass(yyscanner); - codifyLines(yyscanner,yytext); - BEGIN( yyextra->lastSkipCppContext ) ; - } -<*>\n{B}*"//@"[{}].*\n { // remove one-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr+=2; - nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - if (YY_START==SkipCxxComment) - { - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } - } -<*>\n{B}*"/*@"[{}] { // remove one-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - yyextra->yyLineNr++; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"//@"[{}].*\n { // remove one-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr++; - nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - } -<*>^{B}*"/*@"[{}] { // remove multi-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr++; - //nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - } -<*>"//"[!/][^\n]*\n { // strip special one-line comment +<MemberCall>[^a-z_A-Z0-9(\n] { + yyextra->code->codify(yytext); + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN(yyextra->memCallContext); + } +<*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment + if (YY_START==SkipCPP) REJECT; + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + if (YY_START==SkipCxxComment) + { + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } + } +<SkipCPP>\n/.*\n { + endFontClass(yyscanner); + BEGIN( yyextra->lastSkipCppContext ) ; + unput('\n'); + } +<*>\n{B}*"//@"[{}].*\n { // remove one-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=2; + nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + if (YY_START==SkipCxxComment) + { + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } + } +<*>\n{B}*"/*@"[{}] { // remove one-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + yyextra->yyLineNr++; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"//@"[{}].*\n { // remove one-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr++; + nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + } +<*>^{B}*"/*@"[{}] { // remove multi-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr++; + //nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + } +<*>"//"[!/][^\n]*/\n { // strip special one-line comment if (YY_START==SkipComment || YY_START==SkipString) REJECT; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - char c[2]; c[0]='\n'; c[1]=0; - codifyLines(yyscanner,c); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - } -<*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file - yyextra->forceTagReference=yytext; - uint s=(uint)yyextra->forceTagReference.find(':'); - uint e=(uint)yyextra->forceTagReference.findRev(']'); - yyextra->forceTagReference = yyextra->forceTagReference.mid(s+1,e-s-1); - } -<*>\n{B}*"/*"[!*]/[^/*] { - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - yyextra->yyLineNr++; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line - if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>"/*"[!*]/[^/*] { // special C comment block half way a line + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + } +<*>\n{B}*"/*"[!*]/[^/*] { + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + yyextra->yyLineNr++; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line + if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>"/*"[!*]/[^/*] { // special C comment block half way a line if (YY_START==SkipString) REJECT; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>"/*"("!"?)"*/" { + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>"/*"("!"?)"*/" { if (YY_START==SkipString) REJECT; if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } - } + { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + } <SkipComment>[^\*\n]+ { yyextra->code->codify(yytext); } -<*>"/*" { - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - BEGIN( SkipComment ) ; - } -<*>@\" { // C# verbatim string - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext); - yyextra->lastVerbStringContext=YY_START; - BEGIN(SkipVerbString); - } -<*>"//" { - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - yyextra->lastCContext = YY_START ; - BEGIN( SkipCxxComment ) ; - } -<*>"("|"[" { - yyextra->code->codify(yytext); - yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); - } -<*>")"|"]" { - yyextra->code->codify(yytext); - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - } -<*>\n { - yyextra->yyColNr++; - codifyLines(yyscanner,yytext); - } -<*>. { - yyextra->yyColNr++; - yyextra->code->codify(yytext); - } +<*>"/*" { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + BEGIN( SkipComment ) ; + } +<*>@\" { // C# verbatim string + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastVerbStringContext=YY_START; + BEGIN(SkipVerbString); + } +<*>"//" { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } +<*>"("|"[" { + yyextra->code->codify(yytext); + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + } +<*>")"|"]" { + yyextra->code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + } +<*>\n { + yyextra->yyColNr++; + codifyLines(yyscanner,yytext); + } +<*>[\x80-\xFF]* { // keep utf8 characters together... + yyextra->yyColNr+=yyleng; + yyextra->code->codify(yytext); + } +<*>. { + yyextra->yyColNr++; + yyextra->code->codify(yytext); + } /* -<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines - //QCString sepLine=yytext; - //yyextra->code->codify("\n\n"); - //yyextra->yyLineNr+=sepLine.contains('\n'); - //char sepLine[3]="\n\n"; - codifyLines(yyscanner,yytext); - } +<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines + //QCString sepLine=yytext; + //yyextra->code->codify("\n\n"); + //yyextra->yyLineNr+=sepLine.contains('\n'); + //char sepLine[3]="\n\n"; + codifyLines(yyscanner,yytext); + } */ %% @@ -2260,13 +2182,13 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" /*@ ---------------------------------------------------------------------------- */ -void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name) +static void addVariable(yyscan_t yyscanner,QCString type,QCString name) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data()); QCString ltype = type.simplifyWhiteSpace(); QCString lname = name.simplifyWhiteSpace(); - if (ltype.left(7)=="struct ") + if (ltype.left(7)=="struct ") { ltype = ltype.right(ltype.length()-7); } @@ -2275,94 +2197,53 @@ void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const ltype = ltype.right(ltype.length()-6); } if (ltype.isEmpty() || lname.isEmpty()) return; - DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n", - ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>")); - Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - const ClassDef *varType; - int i=0; - if ( - (varType=yyextra->codeClassSDict->find(ltype)) || // look for class definitions inside the code block - (varType=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype)) // look for global class definitions - ) + DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' currentDefinition=%s\n", + ltype.data(),lname.data(),yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>")); + auto it = yyextra->codeClassMap.find(ltype.str()); + if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block { DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); - scope->append(lname,varType); // add it to a list - } - else if ((i=ltype.find('<'))!=-1) - { - // probably a template class - QCString typeName(ltype.left(i)); - ClassDef* newDef = 0; - QCString templateArgs(ltype.right(ltype.length() - i)); - if ( !typeName.isEmpty() && - ( // look for class definitions inside the code block - (varType=yyextra->codeClassSDict->find(typeName)) || - // otherwise look for global class definitions - (varType=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,typeName,0,0,TRUE,TRUE)) - ) && // and it must be a template - !varType->templateArguments().empty()) - { - newDef = varType->getVariableInstance( templateArgs ); - } - if (newDef) - { - DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data())); - scope->append(lname, newDef); - } - else - { - // Doesn't seem to be a template. Try just the base name. - addVariable(yyscanner,typeName,name); - } + yyextra->theVarContext.addVariable(lname,std::move(it->second)); // add it to a list } - else + else { - if (m_scopes.count()>0) // for local variables add a dummy entry so the name - // is hidden to avoid false links to global variables with the same name - // TODO: make this work for namespaces as well! + const ClassDef *varDef = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ltype); + int i=0; + if (varDef) { - DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); - scope->append(lname,dummyContext); + DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list } - else + else if ((i=ltype.find('<'))!=-1) { - DBG_CTX((stderr,"** addVariable: not adding variable!\n")); + // probably a template class + QCString typeName(ltype.left(i)); + addVariable(yyscanner,typeName,name); } - } -} - -ClassDef *VariableContext::findVariable(const QCString &name) -{ - if (name.isEmpty()) return 0; - ClassDef *result = 0; - QListIterator<Scope> sli(m_scopes); - Scope *scope; - QCString key = name; - // search from inner to outer scope - for (sli.toLast();(scope=sli.current());--sli) - { - result = scope->find(key); - if (result) + else { - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; + if (!yyextra->theVarContext.atGlobalScope()) // for local variables add a dummy entry so the name + // is hidden to avoid false links to global variables with the same name + // TODO: make this work for namespaces as well! + { + DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant()); + } + else + { + DBG_CTX((stderr,"** addVariable: not adding variable!\n")); + } } } - // nothing found -> also try the global scope - result=m_globalScope.find(name); - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; } -const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8; - //------------------------------------------------------------------- /*! add class/namespace name s to the scope */ static void pushScope(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->classScopeLengthStack.push(new int(yyextra->classScope.length())); + yyextra->classScopeLengthStack.push(int(yyextra->classScope.length())); if (yyextra->classScope.isEmpty() || leftScopeMatch(s,yyextra->classScope)) { yyextra->classScope = s; @@ -2380,11 +2261,11 @@ static void pushScope(yyscan_t yyscanner,const char *s) static void popScope(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (!yyextra->classScopeLengthStack.isEmpty()) + if (!yyextra->classScopeLengthStack.empty()) { - int *pLength = yyextra->classScopeLengthStack.pop(); - yyextra->classScope.truncate(*pLength); - delete pLength; + int length = yyextra->classScopeLengthStack.top(); + yyextra->classScopeLengthStack.pop(); + yyextra->classScope.truncate(length); } else { @@ -2398,6 +2279,7 @@ static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { + std::lock_guard<std::mutex> lock(g_searchIndexMutex); if (yyextra->searchCtx) { yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); @@ -2414,6 +2296,7 @@ static void addToSearchIndex(yyscan_t yyscanner,const char *text) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { + std::lock_guard<std::mutex> lock(g_searchIndexMutex); yyextra->code->addWord(text,FALSE); } } @@ -2432,7 +2315,7 @@ static void setClassScope(yyscan_t yyscanner,const QCString &name) // remove template from scope n=n.left(ts)+n.right(n.length()-te-1); } - while (!yyextra->classScopeLengthStack.isEmpty()) + while (!yyextra->classScopeLengthStack.empty()) { popScope(yyscanner); } @@ -2460,7 +2343,7 @@ static void startCodeLine(yyscan_t yyscanner) //QCString lineNumber,lineAnchor; //lineNumber.sprintf("%05d",yyextra->yyLineNr); //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); - + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); //printf("%s:startCodeLine(%d)=%p\n",yyextra->sourceFileDef->name().data(),yyextra->yyLineNr,d); if (!yyextra->includeCodeFragment && d) @@ -2483,15 +2366,15 @@ static void startCodeLine(yyscan_t yyscanner) if (yyextra->currentMemberDef) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), - yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { yyextra->code->writeLineNumber(d->getReference(), - d->getOutputFileBase(), - 0,yyextra->yyLineNr); + d->getOutputFileBase(), + 0,yyextra->yyLineNr); setCurrentDoc(yyscanner,lineAnchor); } } @@ -2501,7 +2384,7 @@ static void startCodeLine(yyscan_t yyscanner) } } DBG_CTX((stderr,"startCodeLine(%d)\n",yyextra->yyLineNr)); - yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -2523,7 +2406,7 @@ static void nextCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char * fc = yyextra->currentFontClass; endCodeLine(yyscanner); - if (yyextra->yyLineNr<yyextra->inputLines) + if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; startCodeLine(yyscanner); @@ -2548,7 +2431,6 @@ static void codifyLines(yyscan_t yyscanner,const char *text) { yyextra->yyLineNr++; yyextra->yyColNr=1; - //*(p-1)='\0'; int l = (int)(p-sp-1); char *tmp = (char*)malloc(l+1); memcpy(tmp,sp,l); @@ -2565,8 +2447,22 @@ static void codifyLines(yyscan_t yyscanner,const char *text) } } +static void incrementFlowKeyWordCount(yyscan_t yyscanner) +{ + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + MemberDefMutable *md = toMemberDefMutable(yyextra->currentMemberDef); + if (md) + { + md->incrementFlowKeyWordCount(); + } + } +} + /*! 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(yyscan_t yyscanner,CodeOutputInterface &ol, @@ -2574,12 +2470,12 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + TooltipManager::instance().addTooltip(ol,d); 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(); @@ -2634,7 +2530,7 @@ static void addUsingDirective(yyscan_t yyscanner,const char *name) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->sourceFileDef && name) { - NamespaceDef *nd = Doxygen::namespaceSDict->find(name); + const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(name); if (nd) { yyextra->sourceFileDef->addUsingDirective(nd); @@ -2656,11 +2552,11 @@ static void setParameterList(yyscan_t yyscanner,const MemberDef *md) if (i!=-1) yyextra->parmType = yyextra->parmType.left(i); yyextra->parmType.stripPrefix("const "); yyextra->parmType=yyextra->parmType.stripWhiteSpace(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } } -static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d) +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Definition *d) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int pos=0; @@ -2673,11 +2569,11 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definitio const ClassDef *cd=0; if (!yyextra->classScope.isEmpty()) { - cd=getResolvedClass(d,yyextra->sourceFileDef,yyextra->classScope+"::"+clName); + cd=yyextra->symbolResolver.resolveClass(d,yyextra->classScope+"::"+clName); } if (cd==0) { - cd=getResolvedClass(d,yyextra->sourceFileDef,clName); + cd=yyextra->symbolResolver.resolveClass(d,clName); } //printf("stripClass trying '%s' = %p\n",clName.data(),cd); if (cd) @@ -2689,7 +2585,7 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definitio return 0; } -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { if (name.isEmpty()) return 0; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -2701,14 +2597,14 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) QCString scope = name.left(scopeEnd); QCString locName = name.right(name.length()-scopeEnd-2); //printf("explicit scope: name=%s scope=%s\n",locName.data(),scope.data()); - ClassDef *mcd = getClass(scope); + const ClassDef *mcd = getClass(scope); if (mcd && !locName.isEmpty()) { MemberDef *md=mcd->getMemberByName(locName); if (md) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md; } } @@ -2717,46 +2613,46 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd && !locName.isEmpty()) { - MemberDef *md=mnd->getMemberByName(locName); - if (md) - { - //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); - return md; - } + MemberDef *md=mnd->getMemberByName(locName); + if (md) + { + //printf("name=%s scope=%s\n",locName.data(),scope.data()); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + return md; + } } } } - - MemberName *mn; - ClassDef *mcd = yyextra->theVarContext.findVariable(name); - if (mcd) // local variable + + const MemberName *mn; + const ScopedTypeVariant *mcv = yyextra->theVarContext.findVariable(name); + if (mcv) { DBG_CTX((stderr,"local variable?\n")); - if (mcd!=VariableContext::dummyContext) + if (mcv->type()!=ScopedTypeVariant::Dummy) // locally found variable { - DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(mcd); + DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcv->name().data())); + yyextra->theCallContext.setScope(*mcv); } } else { DBG_CTX((stderr,"class member? scope=%s\n",yyextra->classScope.data())); - // look for a class member - mcd = getClass(yyextra->classScope); + // look for a class member + const ClassDef *mcd = getClass(yyextra->classScope); if (mcd) { DBG_CTX((stderr,"Inside class %s\n",mcd->name().data())); - MemberDef *md=mcd->getMemberByName(name); - if (md) + const MemberDef *md=mcd->getMemberByName(name); + if (md) { DBG_CTX((stderr,"Found member %s\n",md->name().data())); - if (yyextra->scopeStack.top()!=CLASSBLOCK) - { + if (yyextra->scopeStack.empty() || yyextra->scopeStack.top()!=CLASSBLOCK) + { DBG_CTX((stderr,"class member '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); - } - return md; + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + } + return md; } } } @@ -2770,7 +2666,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) const std::unique_ptr<MemberDef> &md=mn->front(); if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md.get(); } return 0; @@ -2779,19 +2675,17 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { for (const auto &md : *mn) { - //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n", - // mn,md, - // md->getBodyDef(),yyextra->sourceFileDef); - - // in case there are multiple members we could link to, we - // only link to members if defined in the same file or - // defined as external. - if ((!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) && - (yyextra->forceTagReference.isEmpty() || yyextra->forceTagReference==md->getReference()) - ) + //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n", + // mn,md, + // md->getBodyDef(),yyextra->sourceFileDef); + + // in case there are multiple members we could link to, we + // only link to members if defined in the same file or + // defined as external. + if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { - 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()); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); return md.get(); } } @@ -2804,15 +2698,15 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) static void updateCallContextForSmartPointer(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - const Definition *d = yyextra->theCallContext.getScope(); + const Definition *d = yyextra->theCallContext.getScope().globalDef(); //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>"); - MemberDef *md; - if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer())) + const MemberDef *md; + if (d && d->definitionType()==Definition::TypeClass && (md=(toClassDef(d))->isSmartPointer())) { const ClassDef *ncd = stripClassName(yyscanner,md->typeString(),md->getOuterScope()); if (ncd) { - yyextra->theCallContext.setScope(ncd); + yyextra->theCallContext.setScope(ScopedTypeVariant(ncd)); //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data()); } } @@ -2821,11 +2715,11 @@ static void updateCallContextForSmartPointer(yyscan_t yyscanner) static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, // scope const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text, - bool varOnly - ) + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text, + bool varOnly + ) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const MemberDef *md = 0; @@ -2834,7 +2728,7 @@ static bool getLinkInScope(yyscan_t yyscanner, const NamespaceDef *nd = 0; const GroupDef *gd = 0; DBG_CTX((stderr,"getLinkInScope: trying '%s'::'%s' varOnly=%d\n",c.data(),m.data(),varOnly)); - if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef,FALSE,yyextra->forceTagReference) && + if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef,FALSE) && (!varOnly || md->isVariable())) { if (md->isLinkable()) @@ -2842,11 +2736,13 @@ static bool getLinkInScope(yyscan_t yyscanner, //printf("found it %s!\n",md->qualifiedName().data()); if (yyextra->exampleBlock) { + std::lock_guard<std::mutex> lock(g_addExampleMutex); QCString anchor; anchor.sprintf("a%d",yyextra->anchorCount); //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), // yyextra->exampleFile.data()); - if (const_cast<MemberDef*>(md)->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) { ol.writeCodeAnchor(anchor); yyextra->anchorCount++; @@ -2858,14 +2754,15 @@ static bool getLinkInScope(yyscan_t yyscanner, if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); if (d && d->isLinkable()) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n", // yyextra->currentDefinition,yyextra->currentMemberDef,yyextra->insideBody); if (yyextra->currentDefinition && yyextra->currentMemberDef && md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } //printf("d->getReference()='%s' d->getOutputBase()='%s' name='%s' member name='%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data()); @@ -2887,9 +2784,9 @@ static bool getLinkInScope(yyscan_t yyscanner, static bool getLink(yyscan_t yyscanner, const char *className, const char *memberName, - CodeOutputInterface &ol, - const char *text, - bool varOnly) + CodeOutputInterface &ol, + const char *text, + bool varOnly) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("getLink(%s,%s) yyextra->curClassName=%s\n",className,memberName,yyextra->curClassName.data()); @@ -2935,18 +2832,20 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { className = substitute(className,".","::"); // for PHP namespaces } - const ClassDef *cd=0,*lcd=0; + const ScopedTypeVariant *lcd=0; + const ClassDef *cd=0; const MemberDef *md=0; bool isLocal=FALSE; //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); - if (!yyextra->prefixed_with_this_keyword || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable + if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { - Definition *d = yyextra->currentDefinition; + const Definition *d = yyextra->currentDefinition; //printf("d=%s yyextra->sourceFileDef=%s\n",d?d->name().data():"<none>",yyextra->sourceFileDef?yyextra->sourceFileDef->name().data():"<none>"); - cd = getResolvedClass(d,yyextra->sourceFileDef,className,&md); - DBG_CTX((stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n", - className.data(),yyextra->theVarContext.count(),cd?cd->name().data():"<none>", + cd = yyextra->symbolResolver.resolveClass(d,className); + md = yyextra->symbolResolver.getTypedef(); + DBG_CTX((stderr,"non-local variable name=%s cd=%s md=%s!\n", + className.data(),cd?cd->name().data():"<none>", md?md->name().data():"<none>")); if (cd==0 && md==0 && (i=className.find('<'))!=-1) { @@ -2954,13 +2853,14 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, DBG_CTX((stderr,"bareName=%s\n",bareName.data())); if (bareName!=className) { - cd=getResolvedClass(d,yyextra->sourceFileDef,bareName,&md); // try unspecialized version + cd = yyextra->symbolResolver.resolveClass(d,bareName); // try unspecialized version + md = yyextra->symbolResolver.getTypedef(); } } const NamespaceDef *nd = getResolvedNamespace(className); if (nd && nd->isLinkable()) { - yyextra->theCallContext.setScope(nd); + yyextra->theCallContext.setScope(ScopedTypeVariant(nd)); addToSearchIndex(yyscanner,className); writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,clName); return; @@ -2973,58 +2873,61 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { if (getLink(yyscanner,yyextra->classScope,clName,ol,clName,varOnly)) { - return; + return; } } } else { //printf("local variable!\n"); - if (lcd!=VariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { //printf("non-dummy context lcd=%s!\n",lcd->name().data()); - yyextra->theCallContext.setScope(lcd); + yyextra->theCallContext.setScope(*lcd); // to following is needed for links to a global variable, but is // no good for a link to a local variable that is also a global symbol. - + //if (getLink(yyscanner,yyextra->classScope,clName,ol,clName)) //{ - //return; + //return; //} } isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); } - yyextra->prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls + yyextra->isPrefixedWithThis = FALSE; // discard the "this" prefix for the next calls if (cd && cd->isLinkable()) // is it a linkable class { DBG_CTX((stderr,"is linkable class %s\n",clName)); if (yyextra->exampleBlock) { + std::lock_guard<std::mutex> lock(g_addExampleMutex); QCString anchor; anchor.sprintf("_a%d",yyextra->anchorCount); //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), // yyextra->exampleFile.data()); - if (const_cast<ClassDef*>(cd)->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + ClassDefMutable *cdm = toClassDefMutable(const_cast<ClassDef*>(cd)); + if (cdm && cdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) { - ol.writeCodeAnchor(anchor); - yyextra->anchorCount++; + ol.writeCodeAnchor(anchor); + yyextra->anchorCount++; } } writeMultiLineCodeLink(yyscanner,ol,cd,clName); addToSearchIndex(yyscanner,className); - yyextra->theCallContext.setScope(cd); + yyextra->theCallContext.setScope(ScopedTypeVariant(cd)); if (md) { const Definition *d = md->getOuterScope()==Doxygen::globalScope ? md->getFileDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); - if (d && d->isLinkable() && md->isLinkable() && + if (d && d->isLinkable() && md->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } } } @@ -3035,55 +2938,40 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { if (md==0) // not found as a typedef { - md = setCallContextForVar(yyscanner,clName); - //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); - if (md && yyextra->currentDefinition) - { - DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", - md->name().data(),yyextra->currentDefinition->name().data(), - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md), - md->getOuterScope()->name().data())); - } - - if (md && yyextra->currentDefinition && - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) - { - md=0; // variable not accessible - } + md = setCallContextForVar(yyscanner,clName); + //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); + if (md && yyextra->currentDefinition) + { + DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", + md->name().data(),yyextra->currentDefinition->name().data(), + yyextra->symbolResolver.isAccessibleFrom(yyextra->currentDefinition,md), + md->getOuterScope()->name().data())); + } + + if (md && yyextra->currentDefinition && + yyextra->symbolResolver.isAccessibleFrom(yyextra->currentDefinition,md)==-1) + { + md=0; // variable not accessible + } } if (md && (!varOnly || md->isVariable())) { DBG_CTX((stderr,"is a global md=%p yyextra->currentDefinition=%s linkable=%d\n",md,yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>",md->isLinkable())); - if (md->isLinkable()) - { - QCString text; - if (!yyextra->forceTagReference.isEmpty()) // explicit reference to symbol in tag file - { - text=yyextra->forceTagReference; - if (text.right(4)==".tag") // strip .tag if present - { - text=text.left(text.length()-4); - } - text+=getLanguageSpecificSeparator(md->getLanguage()); - text+=clName; - const_cast<MemberDef*>(md)->setName(text); - const_cast<MemberDef*>(md)->setLocalName(text); - } - else // normal reference - { - text=clName; - } - writeMultiLineCodeLink(yyscanner,ol,md,text); + if (md->isLinkable()) + { + QCString text=clName; + writeMultiLineCodeLink(yyscanner,ol,md,text); addToSearchIndex(yyscanner,clName); - if (yyextra->currentMemberDef && yyextra->collectXRefs) - { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); - } - return; - } + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); + } + return; + } } } - + // nothing found, just write out the word DBG_CTX((stderr,"not found!\n")); codifyLines(yyscanner,clName); @@ -3106,11 +2994,13 @@ static bool generateClassMemberLink(yyscan_t yyscanner, if (yyextra->exampleBlock) { + std::lock_guard<std::mutex> lock(g_addExampleMutex); QCString anchor; anchor.sprintf("a%d",yyextra->anchorCount); //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), // yyextra->exampleFile.data()); - if (xmd->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + MemberDefMutable *mdm = toMemberDefMutable(xmd); + if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) { ol.writeCodeAnchor(anchor); yyextra->anchorCount++; @@ -3119,7 +3009,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); - yyextra->theCallContext.setScope(typeClass); + yyextra->theCallContext.setScope(ScopedTypeVariant(typeClass)); const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? xmd->getFileDef() : xmd->getOuterScope(); @@ -3135,9 +3025,10 @@ static bool generateClassMemberLink(yyscan_t yyscanner, { // add usage reference if (yyextra->currentDefinition && yyextra->currentMemberDef && - /*xmd!=yyextra->currentMemberDef &&*/ yyextra->insideBody && yyextra->collectXRefs) + /*xmd!=yyextra->currentMemberDef &&*/ yyextra->insideBody && yyextra->collectXRefs) { - addDocCrossReference(yyextra->currentMemberDef,xmd); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(xmd)); } // write the actual link @@ -3158,7 +3049,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (def && def->definitionType()==Definition::TypeClass) { - const ClassDef *cd = dynamic_cast<const ClassDef*>(def); + const ClassDef *cd = toClassDef(def); MemberDef *xmd = cd->getMemberByName(memName); //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd); if (xmd) @@ -3167,10 +3058,10 @@ static bool generateClassMemberLink(yyscan_t yyscanner, } else { - Definition *innerDef = cd->findInnerCompound(memName); + const Definition *innerDef = cd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3179,12 +3070,12 @@ static bool generateClassMemberLink(yyscan_t yyscanner, } else if (def && def->definitionType()==Definition::TypeNamespace) { - const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(def); + const NamespaceDef *nd = toNamespaceDef(def); //printf("Looking for %s inside namespace %s\n",memName,nd->name().data()); - Definition *innerDef = nd->findInnerCompound(memName); + const Definition *innerDef = nd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3205,80 +3096,79 @@ static void generateMemberLink(yyscan_t yyscanner, if (varName.isEmpty()) return; // look for the variable in the current context - const ClassDef *vcd = yyextra->theVarContext.findVariable(varName); - if (vcd) + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(varName); + if (stv) { - if (vcd!=VariableContext::dummyContext) + if (stv->type()!=ScopedTypeVariant::Dummy) { //printf("Class found!\n"); - if (getLink(yyscanner,vcd->name(),memName,ol)) + if (getLink(yyscanner,stv->name(),memName,ol)) { - //printf("Found result!\n"); - return; + //printf("Found result!\n"); + return; } - if (vcd->baseClasses()) + if (stv->localDef() && !stv->localDef()->baseClasses().empty()) { - BaseClassListIterator bcli(*vcd->baseClasses()); - for ( ; bcli.current() ; ++bcli) - { - if (getLink(yyscanner,bcli.current()->classDef->name(),memName,ol)) - { - //printf("Found result!\n"); - return; - } - } + for (const auto &bcName : stv->localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,memName,ol)) + { + //printf("Found result!\n"); + return; + } + } } } } else // variable not in current context, maybe it is in a parent context { - vcd = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); + const ClassDef *vcd = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,yyextra->classScope); if (vcd && vcd->isLinkable()) { //printf("Found class %s for variable '%s'\n",yyextra->classScope.data(),varName.data()); MemberName *vmn=Doxygen::memberNameLinkedMap->find(varName); if (vmn==0) { - int vi; - QCString vn=varName; - if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member - { - ClassDef *jcd = getClass(vn.left(vi)); - vn=vn.right(vn.length()-vi-2); - vmn=Doxygen::memberNameLinkedMap->find(vn); - //printf("Trying name '%s' scope=%s\n",vn.data(),scope.data()); - if (vmn) - { + int vi; + QCString vn=varName; + if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member + { + const ClassDef *jcd = getClass(vn.left(vi)); + vn=vn.right(vn.length()-vi-2); + vmn=Doxygen::memberNameLinkedMap->find(vn); + //printf("Trying name '%s' scope=%s\n",vn.data(),scope.data()); + if (vmn) + { for (const auto &vmd : *vmn) - { - if (vmd->getClassDef()==jcd) - { - //printf("Found variable type=%s\n",vmd->typeString()); - const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); - if (mcd && mcd->isLinkable()) - { - if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; - } - } - } - } - } + { + if (vmd->getClassDef()==jcd) + { + //printf("Found variable type=%s\n",vmd->typeString()); + const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); + if (mcd && mcd->isLinkable()) + { + if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; + } + } + } + } + } } if (vmn) { - //printf("There is a variable with name '%s'\n",varName); + //printf("There is a variable with name '%s'\n",varName); for (const auto &vmd : *vmn) - { - if (vmd->getClassDef()==vcd) - { - //printf("Found variable type=%s\n",vmd->typeString()); - const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); - if (mcd && mcd->isLinkable()) - { - if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; - } - } - } + { + if (vmd->getClassDef()==vcd) + { + //printf("Found variable type=%s\n",vmd->typeString()); + const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); + if (mcd && mcd->isLinkable()) + { + if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; + } + } + } } } } @@ -3304,7 +3194,6 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //CodeClassDef *ccd=0; - ClassDef *ccd=0; QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); if (yyextra->lang==SrcLangExt_PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4); @@ -3316,13 +3205,13 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons int len=2; int i=locFunc.findRev("::"); if (yyextra->currentMemberDef && yyextra->currentMemberDef->resolveAlias()->getClassDef() && - funcName==yyextra->currentMemberDef->localName() && + funcName==yyextra->currentMemberDef->localName() && yyextra->currentMemberDef->getDefLine()==yyextra->yyLineNr && generateClassMemberLink(yyscanner,ol,yyextra->currentMemberDef,funcName) ) { // special case where funcName is the name of a method that is also - // defined on this line. In this case we can directly link to + // defined on this line. In this case we can directly link to // yyextra->currentMemberDef, which is not only faster, but // in case of overloaded methods, this will make sure that we link to // the correct method, and thereby get the correct reimplemented relations. @@ -3364,33 +3253,41 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons funcWithFullScope = locScope+"::"+funcWithScope; } } - if (!fullScope.isEmpty() && (ccd=yyextra->codeClassSDict->find(fullScope))) + + if (!fullScope.isEmpty()) { - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd->baseClasses()) + auto it = yyextra->codeClassMap.find(fullScope.str()); + if (it!=yyextra->codeClassMap.end()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName)) - { - goto exit; - } + for (const auto &bcName : ccd.localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + goto exit; + } + } } } } - if (!locScope.isEmpty() && fullScope!=locScope && (ccd=yyextra->codeClassSDict->find(locScope))) + + if (!locScope.isEmpty() && fullScope!=locScope) { - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd->baseClasses()) + auto it = yyextra->codeClassMap.find(locScope.str()); + if (it!=yyextra->codeClassMap.end()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),funcWithScope,ol,funcName)) - { - goto exit; - } + for (const auto &bcName : ccd.localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,funcWithScope,ol,funcName)) + { + goto exit; + } + } } } } @@ -3398,8 +3295,7 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons { generateClassOrGlobalLink(yyscanner,ol,funcName); } -exit: - yyextra->forceTagReference.resize(0); +exit: return; } @@ -3410,17 +3306,17 @@ static int countLines(yyscan_t yyscanner) const char *p=yyextra->inputString; char c; int count=1; - while ((c=*p)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; } - if (p>yyextra->inputString && *(p-1)!='\n') + if (p>yyextra->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++, - yyextra->needsTermination=TRUE; - } + count++, + yyextra->needsTermination=TRUE; + } return count; } @@ -3458,62 +3354,63 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$') { //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(), - // ctx->methodName.data()); - ClassDef *cd = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); - if (cd==0) // not a local variable + // ctx->methodName.data()); + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); + if (stv==0) // not a local variable { - if (ctx->objectTypeOrName=="self") - { - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ctx->objectType = dynamic_cast<ClassDef *>(yyextra->currentDefinition); - } - } - else - { - ctx->objectType = getResolvedClass( - yyextra->currentDefinition, - yyextra->sourceFileDef, - ctx->objectTypeOrName, - &ctx->method); - } - //printf(" object is class? %p\n",ctx->objectType); - if (ctx->objectType) // found class - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>"); - } - else if (ctx->method==0) // search for class variable with the same name - { - //printf(" no\n"); - //printf("yyextra->currentDefinition=%p\n",yyextra->currentDefinition); - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ctx->objectVar = (dynamic_cast<ClassDef *>(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName); - //printf(" ctx->objectVar=%p\n",ctx->objectVar); - if (ctx->objectVar) - { - ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition); - //printf(" ctx->objectType=%p\n",ctx->objectType); - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - //printf(" ctx->method=%p\n",ctx->method); - } - } - } - } + if (ctx->objectTypeOrName=="self") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectType = toClassDef(yyextra->currentDefinition); + } + } + else + { + ctx->objectType = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ctx->objectTypeOrName); + ctx->method = yyextra->symbolResolver.getTypedef(); + } + //printf(" object is class? %p\n",ctx->objectType); + if (ctx->objectType) // found class + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>"); + } + else if (ctx->method==0) // search for class variable with the same name + { + //printf(" no\n"); + //printf("yyextra->currentDefinition=%p\n",yyextra->currentDefinition); + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectVar = (toClassDef(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName); + //printf(" ctx->objectVar=%p\n",ctx->objectVar); + if (ctx->objectVar) + { + ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition); + //printf(" ctx->objectType=%p\n",ctx->objectType); + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + //printf(" ctx->method=%p\n",ctx->method); + } + } + } + } } else // local variable { - //printf(" object is local variable\n"); - if (cd!=VariableContext::dummyContext && !ctx->methodName.isEmpty()) - { - ctx->method = cd->getMemberByName(ctx->methodName); - //printf(" class=%p method=%p\n",cd,ctx->method); - } + //printf(" object is local variable\n"); + if (stv->globalDef() && !ctx->methodName.isEmpty()) + { + const ClassDef *cd = toClassDef(stv->globalDef()); + if (cd) + { + ctx->method = cd->getMemberByName(ctx->methodName); + } + //printf(" class=%p method=%p\n",cd,ctx->method); + } } } } @@ -3526,210 +3423,209 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) char nc=*p++; if (nc=='$') // escaped $ { - yyextra->code->codify("$"); + yyextra->code->codify("$"); } - else // name fragment or reference to a nested call + else // name fragment or reference to a nested call { - if (nc=='n') // name fragment - { + if (nc=='n') // name fragment + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pName = yyextra->nameDict.find(refId); - if (pName) - { - if (ctx->method && ctx->method->isLinkable()) - { - writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,pName->data()); - if (yyextra->currentMemberDef && yyextra->collectXRefs) - { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(ctx->method)); - } - } - else - { - codifyLines(yyscanner,pName->data()); - } - } - else - { - //printf("Invalid name: id=%d\n",refId); - } - } - else if (nc=='o') // reference to potential object name - { + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->nameMap.find(refId); + if (it!=yyextra->nameMap.end()) + { + QCString name = it->second; + if (ctx->method && ctx->method->isLinkable()) + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,name); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(ctx->method)); + } + } + else + { + codifyLines(yyscanner,name); + } + } + else + { + //printf("Invalid name: id=%d\n",refId); + } + } + else if (nc=='o') // reference to potential object name + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pObject = yyextra->objectDict.find(refId); - if (pObject) - { - if (*pObject=="self") - { - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ctx->objectType = dynamic_cast<ClassDef *>(yyextra->currentDefinition); - if (ctx->objectType->categoryOf()) - { - ctx->objectType = ctx->objectType->categoryOf(); - } - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,pObject->data()); - endFontClass(yyscanner); - } - else if (*pObject=="super") - { - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ClassDef *cd = dynamic_cast<ClassDef *>(yyextra->currentDefinition); - if (cd->categoryOf()) - { - cd = cd->categoryOf(); - } - BaseClassList *bcd = cd->baseClasses(); - if (bcd) // get direct base class (there should be only one) - { - BaseClassListIterator bli(*bcd); - BaseClassDef *bclass; - for (bli.toFirst();(bclass=bli.current());++bli) - { - if (bclass->classDef->compoundType()!=ClassDef::Protocol) - { - ctx->objectType = bclass->classDef; - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - } - } - } - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,pObject->data()); - endFontClass(yyscanner); - } - else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable - { - writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,pObject->data()); - if (yyextra->currentMemberDef && yyextra->collectXRefs) - { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(ctx->objectVar)); - } - } - else if (ctx->objectType && - ctx->objectType!=VariableContext::dummyContext && - ctx->objectType->isLinkable() - ) // object is class name - { - const ClassDef *cd = ctx->objectType; - writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,pObject->data()); - } - else // object still needs to be resolved - { - const ClassDef *cd = getResolvedClass(yyextra->currentDefinition, - yyextra->sourceFileDef, *pObject); - if (cd && cd->isLinkable()) - { - if (ctx->objectType==0) ctx->objectType=cd; - writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,pObject->data()); - } - else - { - codifyLines(yyscanner,pObject->data()); - } - } - } - else - { - //printf("Invalid object: id=%d\n",refId); - } - } - else if (nc=='c') // reference to nested call - { + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->objectMap.find(refId); + if (it!=yyextra->objectMap.end()) + { + QCString object = it->second; + if (object=="self") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectType = toClassDef(yyextra->currentDefinition); + if (ctx->objectType->categoryOf()) + { + ctx->objectType = ctx->objectType->categoryOf(); + } + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,object); + endFontClass(yyscanner); + } + else if (object=="super") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + const ClassDef *cd = toClassDef(yyextra->currentDefinition); + if (cd->categoryOf()) + { + cd = cd->categoryOf(); + } + for (const auto &bclass : cd->baseClasses()) + { + if (bclass.classDef->compoundType()!=ClassDef::Protocol) + { + ctx->objectType = bclass.classDef; + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + } + } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,object); + endFontClass(yyscanner); + } + else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,object); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(ctx->objectVar)); + } + } + else if (ctx->objectType && + ctx->objectType->isLinkable() + ) // object is class name + { + const ClassDef *cd = ctx->objectType; + writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,object); + } + else // object still needs to be resolved + { + const ClassDef *cd = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition, object); + if (cd && cd->isLinkable()) + { + if (ctx->objectType==0) ctx->objectType=cd; + writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,object); + } + else + { + codifyLines(yyscanner,object); + } + } + } + else + { + //printf("Invalid object: id=%d\n",refId); + } + } + else if (nc=='c') // reference to nested call + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - ObjCCallCtx *ictx = yyextra->contextDict.find(refId); - if (ictx) // recurse into nested call - { - writeObjCMethodCall(yyscanner,ictx); - if (ictx->method) // link to nested call successfully - { - // get the ClassDef representing the method's return type - if (QCString(ictx->method->typeString())=="id") - { - // see if the method name is unique, if so we link to it - 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->size()==1) // member name unique - { - ctx->method = mn->front().get(); - } - } - else - { - ctx->objectType = stripClassName(yyscanner,ictx->method->typeString(),yyextra->currentDefinition); - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType); - } - } - else - { - //printf("Invalid context: id=%d\n",refId); - } - } - else if (nc=='w') // some word - { + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->contextMap.find(refId); + if (it!=yyextra->contextMap.end()) // recurse into nested call + { + ObjCCallCtx *ictx = it->second.get(); + writeObjCMethodCall(yyscanner,ictx); + if (ictx->method) // link to nested call successfully + { + // get the ClassDef representing the method's return type + if (QCString(ictx->method->typeString())=="id") + { + // see if the method name is unique, if so we link to it + 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->size()==1) // member name unique + { + ctx->method = mn->front().get(); + } + } + else + { + ctx->objectType = stripClassName(yyscanner,ictx->method->typeString(),yyextra->currentDefinition); + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType); + } + } + else + { + //printf("Invalid context: id=%d\n",refId); + } + } + else if (nc=='w') // some word + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pWord = yyextra->wordDict.find(refId); - if (pWord) - { - codifyLines(yyscanner,pWord->data()); - } - } + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->wordMap.find(refId); + if (it!=yyextra->wordMap.end()) + { + QCString word = it->second; + codifyLines(yyscanner,word); + } + } else if (nc=='d') // comment block { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pComment = yyextra->commentDict.find(refId); - if (pComment) + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->commentMap.find(refId); + if (it!=yyextra->commentMap.end()) { + QCString comment = it->second; startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,pComment->data()); - endFontClass(yyscanner); + codifyLines(yyscanner,comment); + endFontClass(yyscanner); } } - else // illegal marker - { - ASSERT("invalid escape sequence"==0); - } + else // illegal marker + { + ASSERT("invalid escape sequence"==0); + } } } else // normal non-marker character @@ -3746,14 +3642,14 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) } // Replaces an Objective-C method name fragment s by a marker of the form -// $n12, the number (12) can later be used as a key for obtaining the name -// fragment, from yyextra->nameDict +// $n12, the number (12) can later be used as a key for obtaining the name +// fragment, from yyextra->nameMap static QCString escapeName(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$n%d",yyextra->currentNameId); - yyextra->nameDict.insert(yyextra->currentNameId,new QCString(s)); + yyextra->nameMap.emplace(std::make_pair(yyextra->currentNameId,s)); yyextra->currentNameId++; return result; } @@ -3763,7 +3659,7 @@ static QCString escapeObject(yyscan_t yyscanner,const char *s) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$o%d",yyextra->currentObjId); - yyextra->objectDict.insert(yyextra->currentObjId,new QCString(s)); + yyextra->objectMap.emplace(std::make_pair(yyextra->currentObjId,s)); yyextra->currentObjId++; return result; } @@ -3773,7 +3669,7 @@ static QCString escapeWord(yyscan_t yyscanner,const char *s) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$w%d",yyextra->currentWordId); - yyextra->wordDict.insert(yyextra->currentWordId,new QCString(s)); + yyextra->wordMap.emplace(std::make_pair(yyextra->currentWordId,s)); yyextra->currentWordId++; return result; } @@ -3783,7 +3679,7 @@ static QCString escapeComment(yyscan_t yyscanner,const char *s) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$d%d",yyextra->currentCommentId); - yyextra->commentDict.insert(yyextra->currentCommentId,new QCString(s)); + yyextra->commentMap.emplace(std::make_pair(yyextra->currentCommentId,s)); yyextra->currentCommentId++; return result; } @@ -3835,7 +3731,7 @@ static void saveObjCContext(yyscan_t yyscanner) { //printf("Trying to save NULL context!\n"); } - ObjCCallCtx *newCtx = new ObjCCallCtx; + auto newCtx = std::make_unique<ObjCCallCtx>(); newCtx->id = yyextra->currentCtxId; newCtx->lexState = YY_START; newCtx->braceCount = yyextra->braceCount; @@ -3843,8 +3739,8 @@ static void saveObjCContext(yyscan_t yyscanner) newCtx->objectVar = 0; newCtx->method = 0; //printf("save state=%d\n",YY_START); - yyextra->contextDict.insert(yyextra->currentCtxId,newCtx); - yyextra->currentCtx = newCtx; + yyextra->currentCtx = newCtx.get(); + yyextra->contextMap.emplace(std::make_pair(yyextra->currentCtxId,std::move(newCtx))); yyextra->braceCount = 0; yyextra->currentCtxId++; } @@ -3855,9 +3751,10 @@ static void restoreObjCContext(yyscan_t yyscanner) //printf("restore state=%d->%d\n",YY_START,yyextra->currentCtx->lexState); BEGIN(yyextra->currentCtx->lexState); yyextra->braceCount = yyextra->currentCtx->braceCount; - if (!yyextra->contextStack.isEmpty()) + if (!yyextra->contextStack.empty()) { - yyextra->currentCtx = yyextra->contextStack.pop(); + yyextra->currentCtx = yyextra->contextStack.top(); + yyextra->contextStack.pop(); } else { @@ -3878,14 +3775,11 @@ CCodeParser::CCodeParser() : p(std::make_unique<CCodeParser::Private>()) #ifdef FLEX_DEBUG codeYYset_debug(1,p->yyscanner); #endif + resetCodeParserState(); } CCodeParser::~CCodeParser() { - struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; - yyextra->classScopeLengthStack.clear(); - delete yyextra->codeClassSDict; - yyextra->codeClassSDict=0; codeYYlex_destroy(p->yyscanner); } @@ -3893,22 +3787,17 @@ void CCodeParser::resetCodeParserState() { struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; //printf("***CodeParser::reset()\n"); - yyextra->forceTagReference.resize(0); yyextra->theVarContext.clear(); - yyextra->classScopeLengthStack.setAutoDelete(TRUE); - yyextra->classScopeLengthStack.clear(); - delete yyextra->codeClassSDict; - yyextra->codeClassSDict = new ClassSDict(17); - yyextra->codeClassSDict->setAutoDelete(TRUE); - yyextra->codeClassSDict->clear(); + while (!yyextra->classScopeLengthStack.empty()) yyextra->classScopeLengthStack.pop(); + yyextra->codeClassMap.clear(); yyextra->curClassBases.clear(); yyextra->anchorCount = 0; } -void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const QCString &s, +void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const QCString &s, SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd, - int startLine,int endLine,bool inlineFragment, - const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, + int startLine,int endLine,bool inlineFragment, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs) { yyscan_t yyscanner = p->yyscanner; @@ -3920,10 +3809,6 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - if (yyextra->codeClassSDict==0) - { - resetCodeParserState(); - } yyextra->code = &od; yyextra->inputString = s; yyextra->inputPosition = 0; @@ -3933,6 +3818,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const yyextra->searchCtx = searchCtx; yyextra->collectXRefs = collectXRefs; yyextra->inFunctionTryBlock = FALSE; + yyextra->symbolResolver.setFileScope(fd); if (startLine!=-1) yyextra->yyLineNr = startLine; @@ -3950,10 +3836,10 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const yyextra->sharpCount = 0; yyextra->insideTemplate = FALSE; yyextra->theCallContext.clear(); - yyextra->scopeStack.clear(); + while (!yyextra->scopeStack.empty()) yyextra->scopeStack.pop(); yyextra->classScope = className; //printf("parseCCode %s\n",className); - yyextra->exampleBlock = exBlock; + yyextra->exampleBlock = exBlock; yyextra->exampleName = exName; yyextra->sourceFileDef = fd; yyextra->lineNumbers = fd!=0 && showLineNumbers; @@ -3966,7 +3852,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const } yyextra->lang = lang; yyextra->insideObjC = lang==SrcLangExt_ObjC; - if (yyextra->sourceFileDef) + if (yyextra->sourceFileDef) { setCurrentDoc(yyscanner,"l00001"); } @@ -4004,6 +3890,8 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } + // write the tooltips + TooltipManager::instance().writeTooltips(od); printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); return; diff --git a/src/commentcnv.l b/src/commentcnv.l index a7d74ef..036f830 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -142,12 +142,44 @@ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z %x CondLine %x ReadAliasArgs + //- start: NUMBER ------------------------------------------------------------------------- + // Note same defines in code.l: keep in sync +DECIMAL_INTEGER [1-9][0-9']*[0-9]?[uU]?[lL]?[lL]? +HEXADECIMAL_INTEGER "0"[xX][0-9a-zA-Z']+[0-9a-zA-Z]? +OCTAL_INTEGER "0"[0-7][0-7']+[0-7]? +BINARY_INTEGER "0"[bB][01][01']*[01]? +INTEGER_NUMBER {DECIMAL_INTEGER}|{HEXADECIMAL_INTEGER}|{OCTAL_INTEGER}|{BINARY_INTEGER} + +FP_SUF [fFlL] + +DIGIT_SEQ [0-9][0-9']*[0-9]? +FRAC_CONST {DIGIT_SEQ}"."|{DIGIT_SEQ}?"."{DIGIT_SEQ} +FP_EXP [eE][+-]?{DIGIT_SEQ} +DEC_FP1 {FRAC_CONST}{FP_EXP}?{FP_SUF}? +DEC_FP2 {DIGIT_SEQ}{FP_EXP}{FP_SUF} + +HEX_DIGIT_SEQ [0-9a-fA-F][0-9a-fA-F']*[0-9a-fA-F]? +HEX_FRAC_CONST {HEX_DIGIT_SEQ}"."|{HEX_DIGIT_SEQ}?"."{HEX_DIGIT_SEQ} +BIN_EXP [pP][+-]?{DIGIT_SEQ} +HEX_FP1 "0"[xX]{HEX_FRAC_CONST}{BIN_EXP}{FP_SUF}? +HEX_FP2 "0"[xX]{HEX_DIGIT_SEQ}{BIN_EXP}{FP_SUF}? + +FLOAT_DECIMAL {DEC_FP1}|{DEC_FP2} +FLOAT_HEXADECIMAL {HEX_FP1}|{HEX_FP2} +FLOAT_NUMBER {FLOAT_DECIMAL}|{FLOAT_HEXADECIMAL} +NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} + //- end: NUMBER --------------------------------------------------------------------------- + %% -<Scan>[^"'!\/\n\\#,\-]* { /* eat anything that is not " / , or \n */ +<Scan>{NUMBER} { //Note similar code in code.l + if (yyextra->lang!=SrcLangExt_Cpp) REJECT; + copyToOutput(yyscanner,yytext,(int)yyleng); + } +<Scan>[^"'!\/\n\\#,\-=; \t]* { /* eat anything that is not " / , or \n */ copyToOutput(yyscanner,yytext,(int)yyleng); } -<Scan>[,] { /* eat , so we have a nice separator in long initialization lines */ +<Scan>[,= ;\t] { /* eat , so we have a nice separator in long initialization lines */ copyToOutput(yyscanner,yytext,(int)yyleng); } <Scan>"\"\"\""! { /* start of python long comment */ @@ -1076,45 +1108,6 @@ static void replaceComment(yyscan_t yyscanner,int offset) } } -// simplified way to know if this is fixed form -// duplicate in fortrancode.l -static bool recognizeFixedForm(const char* contents) -{ - int column=0; - bool skipLine=FALSE; - - for(int i=0;;i++) { - column++; - - switch(contents[i]) { - case '\n': - column=0; - skipLine=FALSE; - break; - case ' ': - break; - case '\000': - return FALSE; - case 'C': - case 'c': - case '*': - if(column==1) return TRUE; - if(skipLine) break; - return FALSE; - case '!': - if(column>1 && column<7) return FALSE; - skipLine=TRUE; - break; - default: - if(skipLine) break; - if(column==7) return TRUE; - return FALSE; - } - } - return FALSE; -} - - /*! This function does three things: * -# It converts multi-line C++ style comment blocks (that are aligned) * to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO). @@ -1151,7 +1144,8 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) yyextra->isFixedForm = FALSE; if (yyextra->lang==SrcLangExt_Fortran) { - yyextra->isFixedForm = recognizeFixedForm(inBuf->data()); + FortranFormat fmt = convertFileNameFortranParserCode(fileName); + yyextra->isFixedForm = recognizeFixedForm(inBuf->data(),fmt); } if (yyextra->lang==SrcLangExt_Markdown) @@ -1173,7 +1167,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) warn(yyextra->fileName,ctx->lineNr,"Conditional section%sdoes not have " "a corresponding \\endcond command within this file.",sectionInfo.data()); } - if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown) + if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown && yyextra->lang!=SrcLangExt_Fortran) { QCString tmp= "(probable line reference: "; bool first = TRUE; diff --git a/src/commentscan.l b/src/commentscan.l index 5a71b14..767b964 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -148,7 +148,8 @@ 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. + Block, // command starts a new paragraphs / ends a brief description. + XRef // command is a cross reference (todo, bug, test, xrefitem). }; struct DocCmdMap @@ -170,7 +171,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "author", { 0, CommandSpacing::Block }}, { "authors", { 0, CommandSpacing::Block }}, { "brief", { &handleBrief, CommandSpacing::Invisible }}, - { "bug", { &handleBug, CommandSpacing::Block }}, + { "bug", { &handleBug, CommandSpacing::XRef }}, { "callergraph", { &handleCallergraph, CommandSpacing::Invisible }}, { "callgraph", { &handleCallgraph, CommandSpacing::Invisible }}, { "category", { &handleCategory, CommandSpacing::Invisible }}, @@ -184,7 +185,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "date", { 0, CommandSpacing::Block }}, { "def", { &handleDef, CommandSpacing::Invisible }}, { "defgroup", { &handleDefGroup, CommandSpacing::Invisible }}, - { "deprecated", { &handleDeprecated, CommandSpacing::Block }}, + { "deprecated", { &handleDeprecated, CommandSpacing::XRef }}, { "details", { &handleDetails, CommandSpacing::Block }}, { "dir", { &handleDir, CommandSpacing::Invisible }}, { "docbookinclude", { 0, CommandSpacing::Inline }}, @@ -283,10 +284,10 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "subsection", { &handleSection, CommandSpacing::Block }}, { "subsubsection", { &handleSection, CommandSpacing::Block }}, { "tableofcontents", { &handleToc, CommandSpacing::Invisible }}, - { "test", { &handleTest, CommandSpacing::Block }}, + { "test", { &handleTest, CommandSpacing::XRef }}, { "throw", { 0, CommandSpacing::Block }}, { "throws", { 0, CommandSpacing::Block }}, - { "todo", { &handleTodo, CommandSpacing::Block }}, + { "todo", { &handleTodo, CommandSpacing::XRef }}, { "tparam", { 0, CommandSpacing::Block }}, { "typedef", { &handleFn, CommandSpacing::Invisible }}, { "union", { &handleUnion, CommandSpacing::Invisible }}, @@ -299,7 +300,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "weakgroup", { &handleWeakGroup, CommandSpacing::Invisible }}, { "xmlinclude", { 0, CommandSpacing::Inline }}, { "xmlonly", { &handleFormatBlock, CommandSpacing::Invisible }}, - { "xrefitem", { &handleXRefItem, CommandSpacing::Block }} + { "xrefitem", { &handleXRefItem, CommandSpacing::XRef }} }; #define YY_NO_INPUT 1 @@ -438,6 +439,8 @@ 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); +#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0) + //----------------------------------------------------------------------------- #undef YY_INPUT @@ -666,6 +669,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" optList = QCStringList::split(',',optStr); } auto it = docCmdMap.find(cmdName.data()); + //printf("lookup command '%s' found=%d\n",cmdName.data(),it!=docCmdMap.end()); if (it!=docCmdMap.end()) // special action is required { int i=0; @@ -871,9 +875,9 @@ RCSTAG "$"{ID}":"[^\n$]+"$" yyextra->briefEndsAtDot=FALSE; } } -<Comment>\n { // newline - addOutput(yyscanner,*yytext); - yyextra->lineNr++; +<Comment>{DOCNL} { // newline + addOutput(yyscanner,yytext); + if (*yytext == '\n') yyextra->lineNr++; } <Comment>. { // catch-all for anything else addOutput(yyscanner,*yytext); @@ -884,7 +888,11 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } <HtmlComment>{DOCNL} { - if (*yytext=='\n') yyextra->lineNr++; + if (*yytext=='\n') + { + addOutput(yyscanner,*yytext); + yyextra->lineNr++; + } } <HtmlComment>[^\\\n\-]+ { // ignore unimportant characters } @@ -953,7 +961,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" warn(yyextra->fileName,yyextra->lineNr, "missing argument after \\enum." ); - unput('\n'); + unput_string(yytext,yyleng); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; BEGIN( Comment ); @@ -976,7 +984,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "missing argument after " "\\namespace." ); - unput('\n'); + unput_string(yytext,yyleng); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; BEGIN( Comment ); @@ -999,7 +1007,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "missing argument after " "\\package." ); - unput('\n'); + unput_string(yytext,yyleng); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; BEGIN( Comment ); @@ -1037,12 +1045,18 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <ClassDocArg1,CategoryDocArg1>. { // ignore other stuff } +<ClassDocArg2>{DOCNL} { + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + unput_string(yytext,yyleng); + BEGIN( Comment ); + } <ClassDocArg2>{FILE}|"<>" { // second argument; include file yyextra->current->includeFile = yytext; BEGIN( ClassDocArg3 ); @@ -1051,12 +1065,6 @@ RCSTAG "$"{ID}":"[^\n$]+"$" yyextra->lineNr++; addOutput(yyscanner,'\n'); } -<ClassDocArg2>{DOCNL} { - //addOutput(yyscanner,'\n'); - //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); - BEGIN( Comment ); - } <ClassDocArg2>. { // ignore other stuff } @@ -1070,7 +1078,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } <ClassDocArg3>{DOCNL} { //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <ClassDocArg3>. { // ignore other stuff @@ -1101,7 +1109,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <GroupDocArg1>. { // ignore other stuff @@ -1124,7 +1132,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "\\defgroup %s", yyextra->current->name.data() ); } - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1149,7 +1157,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "missing argument after " "\\page." ); - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1157,7 +1165,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <PageDocArg1>. { // ignore other stuff } <PageDocArg2>{DOCNL} { // second argument; page title - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1191,7 +1199,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" /* --------- handle arguments of the file/dir/example command ------------ */ <FileDocArg1>{DOCNL} { // no file name specified - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1289,7 +1297,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" warn(yyextra->fileName,yyextra->lineNr, "Missing argument of '\\%s' command",yyextra->currentCmd.data() ); - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1303,7 +1311,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <LineParam>{DOCNL} { // end of argument //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <LineParam>{LC} { // line continuation @@ -1667,7 +1675,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <NameParam>{DOCNL} { // end of argument //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <NameParam>{LC} { // line continuation @@ -1705,7 +1713,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <InGroupParam>{LC} { // line continuation @@ -1723,7 +1731,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" { //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); yyextra->langParser->parsePrototype(yyextra->functionProto); BEGIN( Comment ); } @@ -1810,7 +1818,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <ExtendsParam>. { // ignore other stuff @@ -1847,7 +1855,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <CiteLabel>. { // invalid character for cite label @@ -2782,6 +2790,7 @@ static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s) yyextra->current->section = s; yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->lineNr; + yyextra->current->docLine = yyextra->lineNr; return FALSE; } } @@ -2823,28 +2832,29 @@ static void addXRefItem(yyscan_t yyscanner, RefList *refList = RefListManager::instance().add(listName,listTitle,itemTitle); RefItem *item = 0; - for (RefItem *i : yyextra->current->sli) + for (auto it = yyextra->current->sli.rbegin(); it != yyextra->current->sli.rend(); ++it) { + RefItem *i = *it; if (i && qstrcmp(i->list()->listName(),listName)==0) { - //printf("found %s lii->type=%s\n",listName,lii->type); + //printf("found %s lii->type=%s\n",listName,i->list()->listName().data()); 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); + //printf("listName=%s item id = %d existing\n",listName,item->id()); 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(); + //printf("listName=%s item id = %d new yyextra->current=%p\n",listName,item->id(),yyextra->current); QCString anchorLabel; anchorLabel.sprintf("_%s%06d",listName,item->id()); item->setText(yyextra->outputXRef); @@ -3234,7 +3244,7 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars yyextra->guards = std::stack<GuardedSection>(); yyextra->langParser = parser; yyextra->current = curEntry; - yyextra->current->docLine = (lineNr > 1 ? lineNr-1: 1); + yyextra->current->docLine = (lineNr > 1 ? lineNr : 1); if (comment.isEmpty()) return FALSE; // avoid empty strings yyextra->inputString = comment; yyextra->inputString.append(" "); diff --git a/src/config.xml b/src/config.xml index b3718be..3f0d406 100644 --- a/src/config.xml +++ b/src/config.xml @@ -174,7 +174,6 @@ FILE_PATTERNS = *.cpp *.h q*.doc RECURSIVE = YES EXCLUDE_PATTERNS = *codec.cpp moc_* */compat/* */3rdparty/* ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 IGNORE_PREFIX = Q ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES @@ -660,7 +659,9 @@ Go to the <a href="commands.html">next</a> section or return to the <br>Note: For files without extension you can use `no_extension` as a placeholder. <br>Note that for custom extensions you also need to set \ref cfg_file_patterns "FILE_PATTERNS" otherwise the - files are not read by doxygen. + files are not read by doxygen. When specifying `no_extension` you should add `*` + to the \ref cfg_file_patterns "FILE_PATTERNS". + <br>Note see also the list of \ref default_file_extension_mapping "default file extension mappings". ]]> </docs> </option> @@ -916,6 +917,15 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> + <option type='bool' id='RESOLVE_UNNAMED_PARAMS' defval='1'> + <docs> +<![CDATA[ + If this flag is set to \c YES, the name of an unnamed parameter in a declaration will be + determined by the corresponding definition. By default unnamed parameters remain unnamed + in the output. +]]> + </docs> + </option> <option type='bool' id='HIDE_UNDOC_MEMBERS' defval='0'> <docs> <![CDATA[ @@ -971,12 +981,20 @@ Go to the <a href="commands.html">next</a> section or return to the <option type='bool' id='CASE_SENSE_NAMES' defval='0' altdefval='Portable::fileSystemIsCaseSensitive()'> <docs> <![CDATA[ - If the \c CASE_SENSE_NAMES tag is set to \c NO then doxygen - 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) and - Mac users are advised to set this option to \c NO. + With the correct setting of option \c CASE_SENSE_NAMES doxygen will better be able to match the + capabilities of the underlying filesystem. + + In case the filesystem is case sensitive (i.e. it supports files in the same directory + whose names only differ in casing), the option must be set to \c YES to properly deal with such files + in case they appear in the input. + + For filesystems that are not case sensitive the option should be be set to \c NO to properly + deal with output files written for symbols that only differ in casing, such as for two classes, + one named \c CLASS and the other named \c Class, and to also support references to files without + having to specify the exact matching casing. + + On Windows (including Cygwin) and MacOS, users should typically set this option to \c NO, + whereas on Linux or other Unix flavors it should typically be set to \c YES. ]]> </docs> </option> @@ -1317,13 +1335,19 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" ]]> </docs> </option> - <option type='bool' id='WARN_AS_ERROR' defval='0'> + <option type='enum' id='WARN_AS_ERROR' defval='NO'> <docs> <![CDATA[ If the \c WARN_AS_ERROR tag is set to \c YES then doxygen will immediately stop when a warning is encountered. + If the \c WARN_AS_ERROR tag is set to \c FAIL_ON_WARNINGS then doxygen will continue + running as if \c WARN_AS_ERROR tag is set to \c NO, but at the end of the doxygen + process doxygen will return with a non-zero status. ]]> </docs> + <value name="NO"/> + <value name="YES" /> + <value name="FAIL_ON_WARNINGS" /> </option> <option type='string' id='WARN_FORMAT' format='string' defval='$file:$line: $text'> <docs> @@ -1386,6 +1410,8 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" Note that for custom extensions or not directly supported extensions you also need to set \ref cfg_extension_mapping "EXTENSION_MAPPING" for the extension otherwise the files are not read by doxygen.<br> + Note the list of default checked file patterns might differ from the list of + \ref default_file_extension_mapping "default file extension mappings".<br> If left blank the following patterns are tested: ]]> </docs> @@ -1420,8 +1446,6 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" <value name='*.md'/> <value name='*.mm'/> <value name='*.dox' desc='(to be provided as doxygen C comment)'/> - <value name='*.doc' desc='(to be provided as doxygen C comment)'/> - <value name='*.txt' desc='(to be provided as doxygen C comment)'/> <value name='*.py'/> <value name='*.pyw'/> <value name='*.f90'/> @@ -1730,10 +1754,10 @@ to disable this feature. <docs> <![CDATA[ If clang assisted parsing is enabled you can provide the clang parser with the - path to the directory containing a file called compile_commands.json. + 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. + 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. @@ -1753,14 +1777,6 @@ to disable this feature. ]]> </docs> </option> - <option type='int' id='COLS_IN_ALPHA_INDEX' minval='1' maxval='20' defval='5' depends='ALPHABETICAL_INDEX'> - <docs> -<![CDATA[ - The \c COLS_IN_ALPHA_INDEX tag can be - used to specify the number of columns in which the alphabetical index list will be split. -]]> - </docs> - </option> <option type='list' id='IGNORE_PREFIX' format='string' depends='ALPHABETICAL_INDEX'> <docs> <![CDATA[ @@ -2279,7 +2295,9 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <option type='string' id='QHG_LOCATION' format='file' defval='' depends='GENERATE_QHP'> <docs> <![CDATA[ - The \c QHG_LOCATION tag can be used to specify the location of Qt's qhelpgenerator. + The \c QHG_LOCATION tag can + be used to specify the location (absolute path including file name) of + Qt's qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the generated `.qhp` file. ]]> </docs> @@ -2436,7 +2454,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <![CDATA[ When MathJax is enabled you can set the default output format to be used for the MathJax output. - See <a href="http://docs.mathjax.org/en/latest/output.html">the MathJax site</a> + See <a href="http://docs.mathjax.org/en/v2.7-latest/output.html">the MathJax site</a> for more details. ]]> </docs> @@ -2475,7 +2493,7 @@ MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols The \c MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces of code that will be used on startup of the MathJax code. See -<a href="http://docs.mathjax.org/en/latest/output.html">the MathJax site</a> +<a href="http://docs.mathjax.org/en/v2.7-latest/output.html">the MathJax site</a> for more details. ]]> </docs> @@ -3409,7 +3427,7 @@ to be found in the default search path. ]]> </docs> </option> - <option type='int' id='UML_LIMIT_NUM_FIELDS' defval='10' minval='0' maxval='100' depends='HAVE_DOT'> + <option type='int' id='UML_LIMIT_NUM_FIELDS' defval='10' minval='0' maxval='100' depends='UML_LOOK'> <docs> <![CDATA[ If the \ref cfg_uml_look "UML_LOOK" tag is enabled, the fields and methods are shown inside @@ -3423,6 +3441,32 @@ to be found in the default search path. ]]> </docs> </option> + <option type='enum' id='DOT_UML_DETAILS' defval='NO' depends='UML_LOOK'> + <docs> +<![CDATA[ +If the \c DOT_UML_DETAILS tag is set to \c NO, doxygen will +show attributes and methods without types and arguments in the UML graphs. +If the \c DOT_UML_DETAILS tag is set to \c YES, doxygen will +add type and arguments for attributes and methods in the UML graphs. +If the \c DOT_UML_DETAILS tag is set to \c NONE, doxygen will not generate +fields with class member information in the UML graphs. +The class diagrams will look similar to the default class diagrams but using +UML notation for the relationships. +]]> + </docs> + <value name="NO" /> + <value name="YES" /> + <value name="NONE" /> + </option> + <option type='int' id='DOT_WRAP_THRESHOLD' defval='17' minval='0' maxval='1000' depends='HAVE_DOT'> + <docs> +<![CDATA[ + The \c DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters to display on + a single line. If the actual line length exceeds this threshold significantly it will wrapped + across multiple lines. Some heuristics are apply to avoid ugly line breaks. +]]> + </docs> + </option> <option type='bool' id='TEMPLATE_RELATIONS' defval='0' depends='HAVE_DOT'> <docs> <![CDATA[ @@ -3653,11 +3697,14 @@ to be found in the default search path. ]]> </docs> </option> - <option type='bool' id='DOT_CLEANUP' defval='1' depends='HAVE_DOT'> + <option type='bool' id='DOT_CLEANUP' defval='1'> <docs> <![CDATA[ If the \c DOT_CLEANUP tag is set to \c YES, doxygen will -remove the intermediate dot files that are used to generate the various graphs. +remove the intermediate files that are used to generate the various graphs. + <br>Note: +This setting is not only used for dot files but also for msc and plantuml +temporary files. ]]> </docs> </option> @@ -3683,5 +3730,6 @@ remove the intermediate dot files that are used to generate the various graphs. <option type='obsolete' id='PERL_PATH'/> <option type='obsolete' id='MSCGEN_PATH'/> <option type='obsolete' id='TCL_SUBST'/> + <option type='obsolete' id='COLS_IN_ALPHA_INDEX'/> </group> </doxygenconfig> diff --git a/src/configgen.py b/src/configgen.py index 4ffa8f8..063c1f4 100755 --- a/src/configgen.py +++ b/src/configgen.py @@ -62,7 +62,7 @@ def transformDocs(doc): # fallback for not handled doc = re.sub('\\\\ref', '', doc) #<a href="address">description</a> -> description (see: address) - doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \\1)', doc) + doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \n\\1)', doc) # LaTeX name as formula -> LaTeX doc = doc.replace("\\f$\\mbox{\\LaTeX}\\f$", "LaTeX") # Other formula's (now just 2) so explicitly mentioned. diff --git a/src/configimpl.l b/src/configimpl.l index ed23a12..e2ef8eb 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -18,7 +18,7 @@ %{ /* - * includes + * includes */ #include <stdio.h> #include <stdlib.h> @@ -160,9 +160,9 @@ void ConfigOption::writeStringValue(FTextStream &t,const QCString &s) p=se.data(); while (*p) { - if (*p==' ' && *(p+1)=='\0') break; // skip inserted space at the end - if (*p=='"') t << "\\"; // escape quotes - t << *p++; + if (*p==' ' && *(p+1)=='\0') break; // skip inserted space at the end + if (*p=='"') t << "\\"; // escape quotes + t << *p++; } t << "\""; } @@ -495,7 +495,7 @@ void ConfigDisabled::writeTemplate(FTextStream &,bool,bool) {} /* ----------------------------------------------------------------- * - * static variables + * static variables */ struct ConfigFileState @@ -508,15 +508,13 @@ struct ConfigFileState }; static const char *g_inputString; -static int g_inputPosition; +static int g_inputPosition; static int g_yyLineNr; static QCString g_yyFileName; -static QCString g_tmpString; +static QCString g_cmd; static QCString *g_string=0; -static bool *g_bool=0; static StringVector *g_list=0; -static int g_lastState; -static QCString g_elemStr; +static QCString g_listStr; static StringVector g_includePathList; static QStack<ConfigFileState> g_includeStack; static int g_includeDepth; @@ -526,8 +524,8 @@ static ConfigImpl *g_config; /* ----------------------------------------------------------------- */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); static yy_size_t yyread(char *buf,yy_size_t max_size) { @@ -594,6 +592,183 @@ static void checkEncoding() g_encoding = *option->valueRef(); } +static QCString stripComment(const QCString &s) +{ + // check if there is a comment at the end of the string + bool insideQuote=false; + int l = s.length(); + for (int i=0;i<l;i++) + { + char c = s.at(i); + if (c=='\\') // skip over escaped characters + { + i++; + } + else if (c=='"') // toggle inside/outside quotation + { + insideQuote=!insideQuote; + } + else if (!insideQuote && c=='#') // found start of a comment + { + if (i<l-1 && s.at(i+1)=='#') // ## -> user comment + { + g_config->appendUserComment(s.mid(i)+"\n"); + } + return s.left(i).stripWhiteSpace(); + } + } + return s; +} + +static void processString() +{ + // strip leading and trailing whitespace + QCString s = stripComment(g_string->stripWhiteSpace()); + int l = s.length(); + + // remove surrounding quotes if present (and not escaped) + if (l>=2 && s.at(0)=='"' && s.at(l-1)=='"' && // remove quotes + (s.at(l-2)!='\\' || (s.at(l-2)=='\\' && s.at(l-3)=='\\'))) + { + s=s.mid(1,s.length()-2); + l=s.length(); + } + + // check for invalid and/or escaped quotes + bool warned=false; + QCString result; + for (int i=0;i<l;i++) + { + char c = s.at(i); + if (c=='\\') // escaped character + { + if (i<l-1 && s.at(i+1)=='"') // unescape the quote character + { + result+='"'; + } + else // keep other escaped characters in escaped form + { + result+=c; + if (i<l-1) + { + result+=s.at(i+1); + } + } + i++; // skip over the escaped character + } + else if (c=='"') // unescaped quote + { + if (!warned) + { + config_warn("Invalid value for '%s' tag at line %d, file %s: Value '%s' is not properly quoted\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data(),g_string->stripWhiteSpace().data()); + } + warned=true; + } + else // normal character + { + result+=c; + } + } + + // recode the string + *g_string=configStringRecode(result,g_encoding,"UTF-8"); + + // update encoding + checkEncoding(); + + //printf("Processed string '%s'\n",g_string->data()); +} + +static void processList() +{ + bool allowCommaAsSeparator = g_cmd!="PREDEFINED"; + + const QCString s = stripComment(g_listStr.stripWhiteSpace()); + int l = s.length(); + + QCString elemStr; + + // helper to push elemStr to the list and clear it + auto addElem = [&elemStr]() + { + if (!elemStr.isEmpty()) + { + QCString e = configStringRecode(elemStr,g_encoding,"UTF-8"); + //printf("Processed list element '%s'\n",e.data()); + g_list->push_back(e.str()); + elemStr=""; + } + }; + + bool needsSeparator=false; + int insideQuote=false; + bool warned=false; + for (int i=0;i<l;i++) + { + char c = s.at(i); + if (!needsSeparator && c=='\\') // escaped character + { + if (i<l-1 && s.at(i+1)=='"') // unescape the quote character + { + elemStr+='"'; + } + else // keep other escaped characters in escaped form + { + elemStr+=c; + if (i<l-1) + { + elemStr+=s.at(i+1); + } + } + i++; // skip over the escaped character + } + else if (!needsSeparator && c=='"') // quote character + { + if (!insideQuote) + { + insideQuote=true; + } + else // this quote ends an element + { + insideQuote=false; + needsSeparator=true; + } + } + else if (!insideQuote && ((c==',' && allowCommaAsSeparator) || isspace(c))) // separator + { + needsSeparator=false; + addElem(); + } + else // normal content character + { + if (needsSeparator) + { + if (!warned) + { + config_warn("Invalid value for '%s' tag at line %d, file %s: Values in list '%s' are not properly space %sseparated\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data(),g_listStr.stripWhiteSpace().data(),allowCommaAsSeparator?"or comma ":""); + warned=true; + } + needsSeparator=false; + i--; // try the character again as part of a new element + addElem(); + } + else + { + elemStr+=c; + } + } + } + // add last part + addElem(); + if (insideQuote) + { + config_warn("Invalid value for '%s' tag at line %d, file %s: Values in list '%s' are not properly quoted\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data(),g_listStr.stripWhiteSpace().data()); + } +} + static FILE *tryPath(const char *path,const char *fileName) { QCString absName=(path ? (QCString)path+"/"+fileName : (QCString)fileName); @@ -634,7 +809,7 @@ static void readIncludeFile(const char *incName) { if (g_includeDepth==MAX_INCLUDE_DEPTH) { config_term("maximum include depth (%d) reached, %s is not included. Aborting...\n", - MAX_INCLUDE_DEPTH,incName); + MAX_INCLUDE_DEPTH,incName); } QCString inc = incName; @@ -680,278 +855,235 @@ static void readIncludeFile(const char *incName) %} %option noyywrap +%option nounput -%x PreStart %x Start -%x SkipComment %x SkipInvalid %x GetString -%x GetBool %x GetStrList -%x GetStrList1 -%x GetQuotedString -%x GetEnvVar %x Include %% <*>\0x0d -<PreStart>"##".*"\n" { g_config->appendStartComment(yytext);g_yyLineNr++;} -<PreStart>. { - BEGIN(Start); - unput(*yytext); - } -<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 = g_config->get(cmd); - if (option==0) // oops not known - { - config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - cmd.data(),g_yyLineNr,g_yyFileName.data()); - BEGIN(SkipInvalid); - } - else // known tag - { + + /*-------------- Comments ---------------*/ + +<Start>"##".*"\n" { + g_config->appendUserComment(yytext); + g_yyLineNr++; + } +<Start>"#"[^#].*"\n" { /* normal comment */ + g_yyLineNr++; + } + + /*-------------- TAG start ---------------*/ + +<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { g_cmd=yytext; + g_cmd=g_cmd.left(g_cmd.length()-1).stripWhiteSpace(); + ConfigOption *option = g_config->get(g_cmd); + if (option==0) // oops not known + { + config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data()); + BEGIN(SkipInvalid); + } + else // known tag + { option->setUserComment(g_config->takeUserComment()); - option->setEncoding(g_encoding); - switch(option->kind()) - { - case ConfigOption::O_Info: - // shouldn't get here! - BEGIN(SkipInvalid); - break; - case ConfigOption::O_List: - g_list = ((ConfigList *)option)->valueRef(); - g_list->clear(); - g_elemStr=""; - if (cmd == "PREDEFINED") - { - BEGIN(GetStrList1); - } - else - { - BEGIN(GetStrList); - } - break; - case ConfigOption::O_Enum: - g_string = ((ConfigEnum *)option)->valueRef(); - g_string->resize(0); - BEGIN(GetString); - break; - case ConfigOption::O_String: - g_string = ((ConfigString *)option)->valueRef(); - g_string->resize(0); - BEGIN(GetString); - break; - case ConfigOption::O_Int: - g_string = ((ConfigInt *)option)->valueStringRef(); - g_string->resize(0); - BEGIN(GetString); - break; - case ConfigOption::O_Bool: - g_string = ((ConfigBool *)option)->valueStringRef(); - g_string->resize(0); - BEGIN(GetString); - break; - case ConfigOption::O_Obsolete: + option->setEncoding(g_encoding); + switch(option->kind()) + { + case ConfigOption::O_Info: + // shouldn't get here! + BEGIN(SkipInvalid); + break; + case ConfigOption::O_List: + g_list = ((ConfigList *)option)->valueRef(); + g_list->clear(); + g_listStr=""; + BEGIN(GetStrList); + break; + case ConfigOption::O_Enum: + g_string = ((ConfigEnum *)option)->valueRef(); + g_string->resize(0); + BEGIN(GetString); + break; + case ConfigOption::O_String: + g_string = ((ConfigString *)option)->valueRef(); + g_string->resize(0); + BEGIN(GetString); + break; + case ConfigOption::O_Int: + g_string = ((ConfigInt *)option)->valueStringRef(); + g_string->resize(0); + BEGIN(GetString); + break; + case ConfigOption::O_Bool: + g_string = ((ConfigBool *)option)->valueStringRef(); + g_string->resize(0); + BEGIN(GetString); + break; + case ConfigOption::O_Obsolete: 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(),g_yyLineNr,g_yyFileName.data()); + config_warn("Tag '%s' at line %d of file '%s' has become obsolete.\n" + " This tag has been removed.\n", g_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(),g_yyLineNr,g_yyFileName.data()); + 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", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); } - BEGIN(SkipInvalid); - break; - case ConfigOption::O_Disabled: + BEGIN(SkipInvalid); + break; + case ConfigOption::O_Disabled: 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(),g_yyLineNr,g_yyFileName.data()); + 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", g_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(),g_yyLineNr,g_yyFileName.data()); + 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", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); } - BEGIN(SkipInvalid); - break; - } - } - } -<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { QCString cmd=yytext; - 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(),g_yyLineNr,g_yyFileName.data()); - BEGIN(SkipInvalid); - } - else // known tag - { + BEGIN(SkipInvalid); + break; + } + } + } +<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { g_cmd=yytext; + g_cmd=g_cmd.left(g_cmd.length()-2).stripWhiteSpace(); + ConfigOption *option = g_config->get(g_cmd); + if (option==0) // oops not known + { + config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data()); + BEGIN(SkipInvalid); + } + else // known tag + { option->setUserComment(g_config->takeUserComment()); - switch(option->kind()) - { - case ConfigOption::O_Info: - // shouldn't get here! - BEGIN(SkipInvalid); - break; - case ConfigOption::O_List: - 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,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(),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(),g_yyLineNr,g_yyFileName.data()); - BEGIN(SkipInvalid); - break; - } - } - } -<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_list=&g_includePathList; g_list->clear(); g_elemStr=""; } + switch(option->kind()) + { + case ConfigOption::O_Info: + // shouldn't get here! + BEGIN(SkipInvalid); + break; + case ConfigOption::O_List: + g_list = ((ConfigList *)option)->valueRef(); + g_listStr=""; + 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,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", g_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", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); + BEGIN(SkipInvalid); + break; + } + } + } + + /*-------------- INCLUDE* ---------------*/ + +<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_list=&g_includePathList; g_list->clear(); g_listStr=""; } /* include a g_config file */ -<Start>"@INCLUDE"[ \t]*"=" { BEGIN(Include);} +<Start>"@INCLUDE"[ \t]*"=" { BEGIN(Include);} <Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { - readIncludeFile(configStringRecode(yytext,g_encoding,"UTF-8")); - BEGIN(Start); - } -<<EOF>> { + 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()); + //printf("Include stack depth=%d\n",g_includeStack.count()); if (g_includeStack.isEmpty()) - { - //printf("Terminating scanner!\n"); - yyterminate(); - } - else - { - 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 ); - g_yyLineNr=fs->lineNr; - g_yyFileName=fs->fileName; - delete fs; fs=0; + { + //printf("Terminating scanner!\n"); + yyterminate(); + } + else + { + 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 ); + g_yyLineNr=fs->lineNr; + g_yyFileName=fs->fileName; + delete fs; fs=0; g_includeDepth--; - } - } - -<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",g_elemStr.data()); - g_list->push_back(g_elemStr.data()); - } - 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 (!g_elemStr.isEmpty()) - { - //printf("elemStr2='%s'\n",g_elemStr.data()); - g_list->push_back(g_elemStr.data()); - } - g_elemStr.resize(0); - } -<GetString>[^ \"\t\r\n]+ { (*g_string)+=configStringRecode(yytext,g_encoding,"UTF-8"); - checkEncoding(); + } + } + +<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 ---------------*/ + +<GetString>\n { processString(); + g_yyLineNr++; // end of string + BEGIN(Start); + } +<GetString>\\[ \r\t]*\n { g_yyLineNr++; // line continuation + *g_string+=' '; + } +<GetString>"\\" { // escape character + *g_string+=yytext; + } +<GetString>[^\n\\]+ { // string part without escape characters + *g_string+=yytext; + } + + /*-------------- GetStrList --------------*/ + +<GetStrList>\n { processList(); + g_yyLineNr++; // end of list + BEGIN(Start); + } +<GetStrList>\\[ \r\t]*\n { g_yyLineNr++; // line continuation + g_listStr+=' '; + } +<GetStrList>"\\" { // escape character + g_listStr+=yytext; + } +<GetStrList>[^\n\\]+ { // string part without escape characters + g_listStr+=yytext; + } + + /*-------------- SkipInvalid --------------*/ + +<SkipInvalid>\n { g_yyLineNr++; // end of list + BEGIN(Start); + } +<SkipInvalid>\\[ \r\t]*\n { g_yyLineNr++; // line continuation + } +<SkipInvalid>"\\" { // escape character } -<GetString,GetStrList,GetStrList1,SkipInvalid>"\"" { g_lastState=YY_START; - BEGIN(GetQuotedString); - g_tmpString.resize(0); - } -<GetQuotedString>"\""|"\n" { - // we add a bogus space to signal that the string was quoted. This space will be stripped later on. - g_tmpString+=" "; - //printf("Quoted String = '%s'\n",g_tmpString.data()); - if (g_lastState==GetString) - { - (*g_string)+=configStringRecode(g_tmpString,g_encoding,"UTF-8"); - checkEncoding(); - } - else - { - g_elemStr+=configStringRecode(g_tmpString,g_encoding,"UTF-8"); - } - if (*yytext=='\n') - { - config_warn("Missing end quote (\") on line %d, file %s\n",g_yyLineNr,g_yyFileName.data()); - g_yyLineNr++; - } - BEGIN(g_lastState); - } -<GetQuotedString>"\\\"" { - g_tmpString+='"'; - } -<GetQuotedString>. { g_tmpString+=*yytext; } -<GetBool>[a-zA-Z]+ { - QCString bs=yytext; - bs=bs.upper(); - if (bs=="YES" || bs=="1") - *g_bool=TRUE; - else if (bs=="NO" || bs=="0") - *g_bool=FALSE; - else - { - *g_bool=FALSE; - config_warn("Invalid value '%s' for " - "boolean tag in line %d, file %s; use YES or NO\n", - bs.data(),g_yyLineNr,g_yyFileName.data()); - } - } -<GetStrList1>[^ \#\"\t\r\n]+ { - g_elemStr+=configStringRecode(yytext,g_encoding,"UTF-8"); - } -<GetStrList>[^ \#\"\t\r\n,]+ { - g_elemStr+=configStringRecode(yytext,g_encoding,"UTF-8"); - } -<SkipComment>\n { g_yyLineNr++; BEGIN(Start); } -<SkipComment>\\[ \r\t]*\n { g_yyLineNr++; BEGIN(Start); } -<*>\\[ \r\t]*\n { g_yyLineNr++; } -<*>. -<*>\n { g_yyLineNr++ ; } +<SkipInvalid>[^\n\\]+ { // string part without escape characters + } + + /*-------------- fall through -------------*/ + +<*>\\[ \r\t]*\n { g_yyLineNr++; } +<*>[ \t\r] +<*>\n { g_yyLineNr++ ; } +<*>. { config_warn("ignoring unknown character '%c' at line %d, file %s\n",yytext[0],g_yyLineNr,g_yyFileName.data()); } %% @@ -1051,10 +1183,10 @@ static void substEnvVarsInStrList(StringVector &sl) //printf("Result %s was quoted=%d\n",result.data(),wasQuoted); 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 - splitting is done to allow quoted items with spaces! */ + may have expanded into a list, which we'll + 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(); int i,p=0; @@ -1062,38 +1194,38 @@ static void substEnvVarsInStrList(StringVector &sl) // search for a "word" for (i=0;i<l;i++) { - char c=0; - // skip until start of new word - 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++; - if (i<l) // not at the end of the string - { - if (c=='"') // word within quotes - { - p=i+1; - for (i++;i<l;i++) - { - c=result.at(i); - if (c=='"') // end quote - { + char c=0; + // skip until start of new word + 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++; + if (i<l) // not at the end of the string + { + if (c=='"') // word within quotes + { + p=i+1; + for (i++;i<l;i++) + { + c=result.at(i); + if (c=='"') // end quote + { results.push_back(result.mid(p,i-p).data()); - p=i+1; - break; - } - else if (c=='\\') // skip escaped stuff - { - i++; - } - } - } - else if (c==' ' || c=='\t') // separator - { + p=i+1; + break; + } + else if (c=='\\') // skip escaped stuff + { + i++; + } + } + } + else if (c==' ' || c=='\t') // separator + { if (i>p) results.push_back(result.mid(p,i-p).data()); - p=i+1; - } - } + p=i+1; + } + } } if (p!=l) // add the leftover as a string { @@ -1221,9 +1353,9 @@ static QCString configFileToString(const char *name) f.readBlock(contents.rawData(),fsize); f.close(); if (fsize==0 || contents[fsize-1]=='\n') - contents[fsize]='\0'; + contents[fsize]='\0'; else - contents[fsize]='\n'; // to help the scanner + contents[fsize]='\n'; // to help the scanner contents[fsize+1]='\0'; return contents; } @@ -1246,7 +1378,7 @@ bool ConfigImpl::parseString(const char *fn,const char *str,bool update) g_includeStack.clear(); g_includeDepth = 0; configimplYYrestart( configimplYYin ); - BEGIN( PreStart ); + BEGIN( Start ); g_configUpdate = update; configimplYYlex(); g_configUpdate = FALSE; @@ -1436,7 +1568,7 @@ void Config::checkAndCorrect() if (!fi.exists()) { config_term("tag HTML_HEADER: header file '%s' " - "does not exist\n",headerFile.data()); + "does not exist\n",headerFile.data()); } } @@ -1449,7 +1581,7 @@ void Config::checkAndCorrect() if (!fi.exists()) { config_term("tag HTML_FOOTER: footer file '%s' " - "does not exist\n",footerFile.data()); + "does not exist\n",footerFile.data()); } } @@ -1464,7 +1596,7 @@ void Config::checkAndCorrect() 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); @@ -1484,7 +1616,7 @@ void Config::checkAndCorrect() if (!fi.exists()) { config_term("tag LATEX_HEADER: header file '%s' " - "does not exist\n",latexHeaderFile.data()); + "does not exist\n",latexHeaderFile.data()); } } @@ -1497,7 +1629,7 @@ void Config::checkAndCorrect() if (!fi.exists()) { config_term("tag LATEX_FOOTER: footer file '%s' " - "does not exist\n",latexFooterFile.data()); + "does not exist\n",latexFooterFile.data()); } } @@ -1508,7 +1640,7 @@ void Config::checkAndCorrect() { QFileInfo fi(s.c_str()); if (!fi.exists()) warn_uncond("tag INCLUDE_PATH: include path '%s' " - "does not exist\n",s.c_str()); + "does not exist\n",s.c_str()); } //------------------------ @@ -1541,7 +1673,7 @@ void Config::checkAndCorrect() 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()); + alias.data()); } } @@ -1666,12 +1798,12 @@ void Config::checkAndCorrect() QFileInfo dp(dotPath+"/dot"+Portable::commandExtension()); if (!dp.exists() || !dp.isFile()) { - warn_uncond("the dot tool could not be found at %s\n",dotPath.data()); - dotPath=""; + warn_uncond("the dot tool could not be found at %s\n",dotPath.data()); + dotPath=""; } else { - dotPath=dp.dirPath(TRUE).utf8()+"/"; + dotPath=dp.dirPath(TRUE).utf8()+"/"; } } #if defined(_WIN32) // convert slashes @@ -1759,7 +1891,7 @@ void Config::checkAndCorrect() QFileInfo fi(s.c_str()); if (!fi.exists()) { - warn_uncond("tag INPUT: input source '%s' does not exist\n",s.c_str()); + warn_uncond("tag INPUT: input source '%s' does not exist\n",s.c_str()); } } } @@ -1929,8 +2061,8 @@ void Config::checkAndCorrect() warn_uncond("enabling OPTIMIZE_OUTPUT_VHDL assumes the following settings:\n" - "%s%s%s%s%s%s",s1,s2,s3,s4,s5,s6 - ); + "%s%s%s%s%s%s",s1,s2,s3,s4,s5,s6 + ); Config_updateBool(INLINE_INHERITED_MEMB, FALSE); Config_updateBool(INHERIT_DOCS, FALSE); diff --git a/src/context.cpp b/src/context.cpp index 29a704a..b7a547f 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1301,8 +1301,8 @@ static TemplateVariant parseDoc(const Definition *def,const QCString &file,int l static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const QCString &relPath, const QCString &code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE) { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(md->getDefFileExtension()); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(md->getDefFileExtension()); + intf->resetCodeParserState(); QGString s; FTextStream t(&s); switch (g_globals.outputFormat) @@ -1310,14 +1310,14 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q case ContextOutputFormat_Html: { HtmlCodeGenerator codeGen(t,relPath); - intf.parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + intf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), startLine,endLine,TRUE,md,showLineNumbers,md); } break; case ContextOutputFormat_Latex: { LatexCodeGenerator codeGen(t,relPath,md->docFile()); - intf.parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + intf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), startLine,endLine,TRUE,md,showLineNumbers,md); } break; @@ -1332,8 +1332,8 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) { static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + intf->resetCodeParserState(); QGString s; FTextStream t(&s); switch (g_globals.outputFormat) @@ -1341,7 +1341,7 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) case ContextOutputFormat_Html: { HtmlCodeGenerator codeGen(t,relPath); - intf.parseCode(codeGen,0, + intf->parseCode(codeGen,0, fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources fd->getLanguage(), // lang FALSE, // isExampleBlock @@ -1360,7 +1360,7 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) case ContextOutputFormat_Latex: { LatexCodeGenerator codeGen(t,relPath,fd->docFile()); - intf.parseCode(codeGen,0, + intf->parseCode(codeGen,0, fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources fd->getLanguage(), // lang FALSE, // isExampleBlock @@ -1554,16 +1554,14 @@ class DefinitionContext QCString result = "unspecified"; switch (m_def->definitionType()) { - case DefinitionIntf::TypeClass: result="class"; break; - case DefinitionIntf::TypeFile: result="file"; break; - case DefinitionIntf::TypeNamespace: result="namespace"; break; - case DefinitionIntf::TypeGroup: result="module"; break; - case DefinitionIntf::TypePackage: result="package"; break; - case DefinitionIntf::TypePage: result="page"; break; - case DefinitionIntf::TypeDir: result="dir"; break; - case DefinitionIntf::TypeMember: // fall through - case DefinitionIntf::TypeSymbolList: - break; + case Definition::TypeClass: result="class"; break; + case Definition::TypeFile: result="file"; break; + case Definition::TypeNamespace: result="namespace"; break; + case Definition::TypeGroup: result="module"; break; + case Definition::TypePackage: result="package"; break; + case Definition::TypePage: result="page"; break; + case Definition::TypeDir: result="dir"; break; + case Definition::TypeMember: break; } return result; } @@ -1587,9 +1585,9 @@ class DefinitionContext { fillPath(outerScope,list); } - else if (type==Definition::TypeFile && (dynamic_cast<const FileDef*>(def))->getDirDef()) + else if (type==Definition::TypeFile && (toFileDef(def))->getDirDef()) { - fillPath((dynamic_cast<const FileDef*>(def))->getDirDef(),list); + fillPath((toFileDef(def))->getDirDef(),list); } list->append(NavPathElemContext::alloc(def)); } @@ -1603,9 +1601,9 @@ class DefinitionContext { fillPath(m_def->getOuterScope(),list); } - else if (m_def->definitionType()==Definition::TypeFile && (dynamic_cast<const FileDef *>(m_def))->getDirDef()) + else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef()) { - fillPath((dynamic_cast<const FileDef *>(m_def))->getDirDef(),list); + fillPath((toFileDef(m_def))->getDirDef(),list); } cache.navPath.reset(list); } @@ -1672,7 +1670,6 @@ class DefinitionContext SharedPtr<TemplateStruct> lineLink; }; - private: Cachable &getCache() const { @@ -1680,7 +1677,7 @@ class DefinitionContext assert(c!=0); return *c; } - const Definition *m_def; + const Definition *m_def; }; //%% } @@ -2320,16 +2317,11 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> if (!cache.classes) { TemplateList *classList = TemplateList::alloc(); - if (m_classDef->getClassSDict()) + for (const auto &cd : m_classDef->getClasses()) { - ClassSDict::Iterator sdi(*m_classDef->getClassSDict()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (cd->visibleInParentsDeclList()) { - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.classes.reset(classList); @@ -2342,20 +2334,15 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> if (!cache.innerClasses) { TemplateList *classList = TemplateList::alloc(); - if (m_classDef->getClassSDict()) + for (const auto &cd : m_classDef->getClasses()) { - ClassSDict::Iterator sdi(*m_classDef->getClassSDict()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups()==0 + ) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups()==0 - ) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.innerClasses.reset(classList); @@ -2375,7 +2362,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> { addTemplateDecls(parent,tl); } - const ClassDef *cd=dynamic_cast<const ClassDef *>(d); + const ClassDef *cd=toClassDef(d); if (!cd->templateArguments().empty()) { ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString()); @@ -2755,22 +2742,17 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); TemplateList *classList = TemplateList::alloc(); - if (m_namespaceDef->getClassSDict()) + for (const auto &cd : m_namespaceDef->getClasses()) { - ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (sliceOpt && (cd->compoundType()==ClassDef::Struct || + cd->compoundType()==ClassDef::Interface || + cd->compoundType()==ClassDef::Exception)) { - if (sliceOpt && (cd->compoundType()==ClassDef::Struct || - cd->compoundType()==ClassDef::Interface || - cd->compoundType()==ClassDef::Exception)) - { - continue; // These types appear in their own sections. - } - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + continue; // These types appear in their own sections. + } + if (cd->visibleInParentsDeclList()) + { + classList->append(ClassContext::alloc(cd)); } } cache.classes.reset(classList); @@ -2783,16 +2765,11 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (!cache.namespaces) { TemplateList *namespaceList = TemplateList::alloc(); - if (m_namespaceDef->getNamespaceSDict()) + for (const auto &nd : m_namespaceDef->getNamespaces()) { - NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict()); - const NamespaceDef *nd; - for (sdi.toFirst();(nd=sdi.current());++sdi) + if (nd->isLinkable() && !nd->isConstantGroup()) { - if (nd->isLinkable() && !nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + namespaceList->append(NamespaceContext::alloc(nd)); } } cache.namespaces.reset(namespaceList); @@ -2805,16 +2782,11 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (!cache.constantgroups) { TemplateList *namespaceList = TemplateList::alloc(); - if (m_namespaceDef->getNamespaceSDict()) + for (const auto &nd : m_namespaceDef->getNamespaces()) { - NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict()); - const NamespaceDef *nd; - for (sdi.toFirst();(nd=sdi.current());++sdi) + if (nd->isLinkable() && nd->isConstantGroup()) { - if (nd->isLinkable() && nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + namespaceList->append(NamespaceContext::alloc(nd)); } } cache.constantgroups.reset(namespaceList); @@ -2923,19 +2895,14 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (!cache.inlineClasses) { TemplateList *classList = TemplateList::alloc(); - if (m_namespaceDef->getClassSDict()) + for (const auto &cd : m_namespaceDef->getClasses()) { - ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups()==0) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups()==0) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.inlineClasses.reset(classList); @@ -3220,16 +3187,11 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (!cache.classes) { TemplateList *classList = TemplateList::alloc(); - if (m_fileDef->getClassSDict()) + for (const auto &cd : m_fileDef->getClasses()) { - ClassSDict::Iterator sdi(*m_fileDef->getClassSDict()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (cd->visibleInParentsDeclList()) { - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.classes.reset(classList); @@ -3242,16 +3204,11 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (!cache.namespaces) { TemplateList *namespaceList = TemplateList::alloc(); - if (m_fileDef->getNamespaceSDict()) + for (const auto &nd : m_fileDef->getNamespaces()) { - NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict()); - const NamespaceDef *nd; - for (sdi.toFirst();(nd=sdi.current());++sdi) + if (nd->isLinkable() && !nd->isConstantGroup()) { - if (nd->isLinkable() && !nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + namespaceList->append(NamespaceContext::alloc(nd)); } } cache.namespaces.reset(namespaceList); @@ -3264,16 +3221,11 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (!cache.constantgroups) { TemplateList *namespaceList = TemplateList::alloc(); - if (m_fileDef->getNamespaceSDict()) + for (const auto &nd : m_fileDef->getNamespaces()) { - NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict()); - NamespaceDef *nd; - for (sdi.toFirst();(nd=sdi.current());++sdi) + if (nd->isLinkable() && nd->isConstantGroup()) { - if (nd->isLinkable() && nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + namespaceList->append(NamespaceContext::alloc(nd)); } } cache.constantgroups.reset(namespaceList); @@ -3387,19 +3339,14 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (!cache.inlineClasses) { TemplateList *classList = TemplateList::alloc(); - if (m_fileDef->getClassSDict()) + for (const auto &cd : m_fileDef->getClasses()) { - ClassSDict::Iterator sdi(*m_fileDef->getClassSDict()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups()==0) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups()==0) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.inlineClasses.reset(classList); @@ -3805,6 +3752,7 @@ class TextGeneratorHtml : public TextGeneratorIntf : m_ts(ts), m_relPath(relPath) {} void writeString(const char *s,bool keepSpaces) const { + static const char *hex="0123456789ABCDEF"; if (s==0) return; if (keepSpaces) { @@ -3820,6 +3768,19 @@ class TextGeneratorHtml : public TextGeneratorIntf case '"': m_ts << """; break; case '&': m_ts << "&"; break; case ' ': m_ts << " "; break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) // non-printable control characters + { + m_ts << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_ts << c; + } + } + break; } } } @@ -3896,13 +3857,25 @@ class TextGeneratorLatex : public TextGeneratorIntf if (f && anchor) m_ts << "_"; if (anchor) m_ts << anchor; m_ts << "}{"; - filterLatexString(m_ts,text); + filterLatexString(m_ts,text, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); m_ts << "}}"; } else { m_ts << "\\textbf{ "; - filterLatexString(m_ts,text); + filterLatexString(m_ts,text, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); m_ts << "}"; } } @@ -4931,7 +4904,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.sourceRefs) { - cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers(),TRUE)); + cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers())); } return cache.sourceRefs.get(); } @@ -4940,7 +4913,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.sourceRefBys) { - cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers(),TRUE)); + cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers())); } return cache.sourceRefBys.get(); } @@ -5486,16 +5459,11 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (!cache.classes) { TemplateList *classList = TemplateList::alloc(); - if (m_groupDef->getClasses()) + for (const auto &cd : m_groupDef->getClasses()) { - ClassSDict::Iterator sdi(*m_groupDef->getClasses()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (cd->visibleInParentsDeclList()) { - if (cd->visibleInParentsDeclList()) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.classes.reset(classList); @@ -5508,16 +5476,11 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (!cache.namespaces) { TemplateList *namespaceList = TemplateList::alloc(); - if (m_groupDef->getNamespaces()) + for (const auto &nd : m_groupDef->getNamespaces()) { - NamespaceSDict::Iterator sdi(*m_groupDef->getNamespaces()); - const NamespaceDef *nd; - for (sdi.toFirst();(nd=sdi.current());++sdi) + if (nd->isLinkable() && !nd->isConstantGroup()) { - if (nd->isLinkable() && !nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + namespaceList->append(NamespaceContext::alloc(nd)); } } cache.namespaces.reset(namespaceList); @@ -5530,16 +5493,11 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (!cache.constantgroups) { TemplateList *namespaceList = TemplateList::alloc(); - if (m_groupDef->getNamespaces()) + for (const auto &nd : m_groupDef->getNamespaces()) { - NamespaceSDict::Iterator sdi(*m_groupDef->getNamespaces()); - NamespaceDef *nd; - for (sdi.toFirst();(nd=sdi.current());++sdi) + if (nd->isLinkable() && nd->isConstantGroup()) { - if (nd->isLinkable() && nd->isConstantGroup()) - { - namespaceList->append(NamespaceContext::alloc(nd)); - } + namespaceList->append(NamespaceContext::alloc(nd)); } } cache.constantgroups.reset(namespaceList); @@ -5702,19 +5660,14 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (!cache.inlineClasses) { TemplateList *classList = TemplateList::alloc(); - if (m_groupDef->getClasses()) + for (const auto &cd : m_groupDef->getClasses()) { - ClassSDict::Iterator sdi(*m_groupDef->getClasses()); - const ClassDef *cd; - for (sdi.toFirst();(cd=sdi.current());++sdi) + if (!cd->isAnonymous() && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + cd->partOfGroups()==0) { - if (!cd->isAnonymous() && - cd->isLinkableInProject() && - cd->isEmbeddedInOuterScope() && - cd->partOfGroups()==0) - { - classList->append(ClassContext::alloc(cd)); - } + classList->append(ClassContext::alloc(cd)); } } cache.inlineClasses.reset(classList); @@ -5801,11 +5754,9 @@ TemplateVariant ModuleContext::get(const char *n) const class ClassListContext::Private : public GenericNodeListContext { public: - void addClasses(const ClassSDict &classSDict) + void addClasses(const ClassLinkedMap &classLinkedMap) { - ClassSDict::Iterator cli(classSDict); - const ClassDef *cd; - for (cli.toFirst() ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : classLinkedMap) { if (cd->getLanguage()==SrcLangExt_VHDL && ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || @@ -5817,7 +5768,7 @@ class ClassListContext::Private : public GenericNodeListContext if (cd->isLinkableInProject() && cd->templateMaster()==0 && !cd->isHidden() && !cd->isEmbeddedInOuterScope()) { - append(ClassContext::alloc(cd)); + append(ClassContext::alloc(cd.get())); } } } @@ -5826,8 +5777,8 @@ class ClassListContext::Private : public GenericNodeListContext ClassListContext::ClassListContext() : RefCountedContext("ClassListContext") { p = new Private; - p->addClasses(*Doxygen::classSDict); - p->addClasses(*Doxygen::hiddenClasses); + p->addClasses(*Doxygen::classLinkedMap); + p->addClasses(*Doxygen::hiddenClassLinkedMap); } ClassListContext::~ClassListContext() @@ -5880,11 +5831,9 @@ class ClassIndexContext::Private if (!m_cache.classes) { TemplateList *classList = TemplateList::alloc(); - if (Doxygen::classSDict) + if (Doxygen::classLinkedMap) { - ClassSDict::Iterator cli(*Doxygen::classSDict); - const ClassDef *cd; - for (cli.toFirst() ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->getLanguage()==SrcLangExt_VHDL && ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || @@ -5895,7 +5844,7 @@ class ClassIndexContext::Private } if (cd->isLinkableInProject() && cd->templateMaster()==0) { - classList->append(ClassContext::alloc(cd)); + classList->append(ClassContext::alloc(cd.get())); } } } @@ -6046,10 +5995,9 @@ class ClassHierarchyContext::Private Private() { m_classTree.reset(NestingContext::alloc(0,0)); - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); - m_classTree->addClassHierarchy(*Doxygen::classSDict,TRUE); - m_classTree->addClassHierarchy(*Doxygen::hiddenClasses,TRUE); + ClassDefSet visitedClasses; + m_classTree->addClassHierarchy(*Doxygen::classLinkedMap,visitedClasses); + m_classTree->addClassHierarchy(*Doxygen::hiddenClassLinkedMap,visitedClasses); //%% ClassInheritance tree static bool init=FALSE; if (!init) @@ -6104,15 +6052,10 @@ class ClassHierarchyContext::Private { TemplateList *diagrams = TemplateList::alloc(); DotGfxHierarchyTable *hierarchy = getHierarchy(); - if (hierarchy->subGraphs()) + int id=0; + for (auto n : hierarchy->subGraphs()) { - int id=0; - QListIterator<DotNode> li(*hierarchy->subGraphs()); - DotNode *n; - for (li.toFirst();(n=li.current());++li) - { - diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++)); - } + diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++)); } m_cache.diagrams.reset(diagrams); } @@ -6191,7 +6134,8 @@ class NestingNodeContext::Private { public: Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode, - const Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper) + const Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper, + ClassDefSet &visitedClasses) : m_parent(parent), m_def(d), m_level(level), m_index(index) { m_children.reset(NestingContext::alloc(thisNode,level+1)); @@ -6231,11 +6175,11 @@ class NestingNodeContext::Private init=TRUE; } - addNamespaces(addCls); - addClasses(inherit,hideSuper); - addDirFiles(); - addPages(); - addModules(); + addNamespaces(addCls,visitedClasses); + addClasses(inherit,hideSuper,visitedClasses); + addDirFiles(visitedClasses); + addPages(visitedClasses); + addModules(visitedClasses); } TemplateVariant get(const char *n) const { @@ -6253,7 +6197,7 @@ class NestingNodeContext::Private { if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass) { - m_cache.classContext.reset(ClassContext::alloc(dynamic_cast<const ClassDef*>(m_def))); + m_cache.classContext.reset(ClassContext::alloc(toClassDef(m_def))); } if (m_cache.classContext) { @@ -6268,7 +6212,7 @@ class NestingNodeContext::Private { if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace) { - m_cache.namespaceContext.reset(NamespaceContext::alloc(dynamic_cast<const NamespaceDef*>(m_def))); + m_cache.namespaceContext.reset(NamespaceContext::alloc(toNamespaceDef(m_def))); } if (m_cache.namespaceContext) { @@ -6283,7 +6227,7 @@ class NestingNodeContext::Private { if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir) { - m_cache.dirContext.reset(DirContext::alloc(dynamic_cast<const DirDef*>(m_def))); + m_cache.dirContext.reset(DirContext::alloc(toDirDef(m_def))); } if (m_cache.dirContext) { @@ -6298,7 +6242,7 @@ class NestingNodeContext::Private { if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile) { - m_cache.fileContext.reset(FileContext::alloc(dynamic_cast<const FileDef*>(m_def))); + m_cache.fileContext.reset(FileContext::alloc(toFileDef(m_def))); } if (m_cache.fileContext) { @@ -6313,7 +6257,7 @@ class NestingNodeContext::Private { if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage) { - m_cache.pageContext.reset(PageContext::alloc(dynamic_cast<const PageDef*>(m_def),FALSE,FALSE)); + m_cache.pageContext.reset(PageContext::alloc(toPageDef(m_def),FALSE,FALSE)); } if (m_cache.pageContext) { @@ -6328,7 +6272,7 @@ class NestingNodeContext::Private { if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup) { - m_cache.moduleContext.reset(ModuleContext::alloc(dynamic_cast<const GroupDef*>(m_def))); + m_cache.moduleContext.reset(ModuleContext::alloc(toGroupDef(m_def))); } if (m_cache.moduleContext) { @@ -6398,72 +6342,72 @@ class NestingNodeContext::Private //------------------------------------------------------------------ - void addClasses(bool inherit, bool hideSuper) + void addClasses(bool inherit, bool hideSuper,ClassDefSet &visitedClasses) { - const ClassDef *cd = dynamic_cast<const ClassDef*>(m_def); + const ClassDef *cd = toClassDef(m_def); if (cd && inherit) { - bool hasChildren = !cd->isVisited() && !hideSuper && classHasVisibleChildren(cd); + bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() && + !hideSuper && classHasVisibleChildren(cd); if (hasChildren) { - bool wasVisited=cd->isVisited(); - cd->setVisited(TRUE); + visitedClasses.insert(cd); if (cd->getLanguage()==SrcLangExt_VHDL) { - m_children->addDerivedClasses(cd->baseClasses(),wasVisited); + m_children->addDerivedClasses(cd->baseClasses(),false,visitedClasses); } else { - m_children->addDerivedClasses(cd->subClasses(),wasVisited); + m_children->addDerivedClasses(cd->subClasses(),false,visitedClasses); } } } else { - if (cd && cd->getClassSDict()) + if (cd) { - m_children->addClasses(*cd->getClassSDict(),FALSE); + m_children->addClasses(cd->getClasses(),FALSE,visitedClasses); } } } - void addNamespaces(bool addClasses) + void addNamespaces(bool addClasses,ClassDefSet &visitedClasses) { - const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(m_def); - if (nd && nd->getNamespaceSDict()) + const NamespaceDef *nd = toNamespaceDef(m_def); + if (nd && !nd->getNamespaces().empty()) { - m_children->addNamespaces(*nd->getNamespaceSDict(),FALSE,addClasses); + m_children->addNamespaces(nd->getNamespaces(),FALSE,addClasses,visitedClasses); } - if (addClasses && nd && nd->getClassSDict()) + if (addClasses && nd) { - m_children->addClasses(*nd->getClassSDict(),FALSE); + m_children->addClasses(nd->getClasses(),FALSE,visitedClasses); } } - void addDirFiles() + void addDirFiles(ClassDefSet &visitedClasses) { - const DirDef *dd = dynamic_cast<const DirDef*>(m_def); + const DirDef *dd = toDirDef(m_def); if (dd) { - m_children->addDirs(dd->subDirs()); + m_children->addDirs(dd->subDirs(),visitedClasses); if (dd && dd->getFiles()) { - m_children->addFiles(*dd->getFiles()); + m_children->addFiles(*dd->getFiles(),visitedClasses); } } } - void addPages() + void addPages(ClassDefSet &visitedClasses) { - const PageDef *pd = dynamic_cast<const PageDef*>(m_def); + const PageDef *pd = toPageDef(m_def); if (pd && pd->getSubPages()) { - m_children->addPages(*pd->getSubPages(),FALSE); + m_children->addPages(*pd->getSubPages(),FALSE,visitedClasses); } } - void addModules() + void addModules(ClassDefSet &visitedClasses) { - const GroupDef *gd = dynamic_cast<const GroupDef*>(m_def); + const GroupDef *gd = toGroupDef(m_def); if (gd && gd->getSubGroups()) { - m_children->addModules(*gd->getSubGroups()); + m_children->addModules(*gd->getSubGroups(),visitedClasses); } } private: @@ -6490,10 +6434,11 @@ class NestingNodeContext::Private PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst; NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent, - const Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper) + const Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper, + ClassDefSet &visitedClasses) : RefCountedContext("NestingNodeContext") { - p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper); + p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper,visitedClasses); } NestingNodeContext::~NestingNodeContext() @@ -6520,56 +6465,74 @@ class NestingContext::Private : public GenericNodeListContext Private(const NestingNodeContext *parent,int level) : m_parent(parent), m_level(level), m_index(0) {} - void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses) + void addNamespace(const NamespaceDef *nd,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) { - NamespaceSDict::Iterator nli(nsDict); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + if (!nd->isAnonymous() && + (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) { - if (!nd->isAnonymous() && - (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) + bool hasChildren = namespaceHasNestedNamespace(nd); + bool isLinkable = nd->isLinkableInProject(); + if (isLinkable || hasChildren) { - bool hasChildren = namespaceHasVisibleChild(nd,addClasses,false,ClassDef::Class); - bool isLinkable = nd->isLinkableInProject(); - if (isLinkable || hasChildren) - { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses,FALSE,FALSE); - append(nnc); - m_index++; - } + NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses,FALSE,FALSE,visitedClasses); + append(nnc); + m_index++; } } } - void addClasses(const ClassSDict &clDict,bool rootOnly) + void addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) { - ClassSDict::Iterator cli(clDict); - const ClassDef *cd; - for (;(cd=cli.current());++cli) + for (const auto &nd : nsLinkedMap) { - if (cd->getLanguage()==SrcLangExt_VHDL) + addNamespace(nd.get(),rootOnly,addClasses,visitedClasses); + } + } + void addNamespaces(const NamespaceLinkedRefMap &nsLinkedMap,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) + { + for (const auto &nd : nsLinkedMap) + { + addNamespace(nd,rootOnly,addClasses,visitedClasses); + } + } + void addClass(const ClassDef *cd,bool rootOnly,ClassDefSet &visitedClasses) + { + if (cd->getLanguage()==SrcLangExt_VHDL) + { + if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || + (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS + )// no architecture { - if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || - (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS - )// no architecture - { - continue; - } + return; } - if (!rootOnly || - cd->getOuterScope()==0 || - cd->getOuterScope()==Doxygen::globalScope - ) + } + if (!rootOnly || + cd->getOuterScope()==0 || + cd->getOuterScope()==Doxygen::globalScope + ) + { + if (classVisibleInIndex(cd) && cd->templateMaster()==0) { - if (classVisibleInIndex(cd) && cd->templateMaster()==0) - { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,FALSE,FALSE); - append(nnc); - m_index++; - } + NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,FALSE,FALSE,visitedClasses); + append(nnc); + m_index++; } } } - void addDirs(const DirSDict &dirDict) + void addClasses(const ClassLinkedRefMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses) + { + for (const auto &cd : clLinkedMap) + { + addClass(cd,rootOnly,visitedClasses); + } + } + void addClasses(const ClassLinkedMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses) + { + for (const auto &cd : clLinkedMap) + { + addClass(cd.get(),rootOnly,visitedClasses); + } + } + void addDirs(const DirSDict &dirDict,ClassDefSet &visitedClasses) { SDict<DirDef>::Iterator dli(dirDict); const DirDef *dd; @@ -6577,20 +6540,20 @@ class NestingContext::Private : public GenericNodeListContext { if (dd->getOuterScope()==Doxygen::globalScope) { - append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addDirs(const DirList &dirList) + void addDirs(const DirList &dirList,ClassDefSet &visitedClasses) { for(const auto dd : dirList) { - append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } - void addFiles(const FileNameLinkedMap &fnList) + void addFiles(const FileNameLinkedMap &fnList,ClassDefSet &visitedClasses) { for (const FileNameLinkedMap::Ptr &fn : fnList) { @@ -6598,23 +6561,23 @@ class NestingContext::Private : public GenericNodeListContext { if (fd->getDirDef()==0) // top level file { - append(NestingNodeContext::alloc(m_parent,fd.get(),m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,fd.get(),m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } } - void addFiles(const FileList &fList) + void addFiles(const FileList &fList,ClassDefSet &visitedClasses) { QListIterator<FileDef> li(fList); const FileDef *fd; for (li.toFirst();(fd=li.current());++li) { - append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } - void addPages(const PageSDict &pages,bool rootOnly) + void addPages(const PageSDict &pages,bool rootOnly,ClassDefSet &visitedClasses) { SDict<PageDef>::Iterator pli(pages); const PageDef *pd; @@ -6624,12 +6587,12 @@ class NestingContext::Private : public GenericNodeListContext pd->getOuterScope()==0 || pd->getOuterScope()->definitionType()!=Definition::TypePage) { - append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addModules(const GroupSDict &groups) + void addModules(const GroupSDict &groups,ClassDefSet &visitedClasses) { GroupSDict::Iterator gli(groups); const GroupDef *gd; @@ -6640,12 +6603,12 @@ class NestingContext::Private : public GenericNodeListContext (!gd->isReference() || externalGroups) ) { - append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addModules(const GroupList &list) + void addModules(const GroupList &list,ClassDefSet &visitedClasses) { GroupListIterator gli(list); const GroupDef *gd; @@ -6653,19 +6616,16 @@ class NestingContext::Private : public GenericNodeListContext { if (gd->isVisible()) { - append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addDerivedClasses(const BaseClassList *bcl,bool hideSuper) + void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli) + for (const auto &bcd : bcl) { - const ClassDef *cd=bcd->classDef; + const ClassDef *cd=bcd.classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -6683,17 +6643,15 @@ class NestingContext::Private : public GenericNodeListContext if (cd->isVisibleInHierarchy() && b) { - NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,hideSuper); + NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,hideSuper,visitedClasses); append(tnc); m_index++; } } } - void addClassHierarchy(const ClassSDict &classSDict,bool) + void addClassHierarchy(const ClassLinkedMap &classLinkedMap,ClassDefSet &visitedClasses) { - ClassSDict::Iterator cli(classSDict); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : classLinkedMap) { bool b; if (cd->getLanguage()==SrcLangExt_VHDL) @@ -6713,7 +6671,7 @@ class NestingContext::Private : public GenericNodeListContext if (cd->isVisibleInHierarchy()) // should it be visible { // new root level class - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,cd->isVisited()); + NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd.get(),m_index,m_level,TRUE,TRUE,FALSE,visitedClasses); append(nnc); m_index++; } @@ -6753,59 +6711,69 @@ TemplateListIntf::ConstIterator *NestingContext::createIterator() const return p->createIterator(); } -void NestingContext::addClasses(const ClassSDict &clDict,bool rootOnly) +void NestingContext::addClasses(const ClassLinkedRefMap &clLinkedRefMap,bool rootOnly,ClassDefSet &visitedClasses) +{ + p->addClasses(clLinkedRefMap,rootOnly,visitedClasses); +} + +void NestingContext::addClasses(const ClassLinkedMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses) +{ + p->addClasses(clLinkedMap,rootOnly,visitedClasses); +} + +void NestingContext::addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) { - p->addClasses(clDict,rootOnly); + p->addNamespaces(nsLinkedMap,rootOnly,addClasses,visitedClasses); } -void NestingContext::addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses) +void NestingContext::addNamespaces(const NamespaceLinkedRefMap &nsLinkedRefMap,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) { - p->addNamespaces(nsDict,rootOnly,addClasses); + p->addNamespaces(nsLinkedRefMap,rootOnly,addClasses,visitedClasses); } -void NestingContext::addDirs(const DirSDict &dirs) +void NestingContext::addDirs(const DirSDict &dirs,ClassDefSet &visitedClasses) { - p->addDirs(dirs); + p->addDirs(dirs,visitedClasses); } -void NestingContext::addDirs(const DirList &dirs) +void NestingContext::addDirs(const DirList &dirs,ClassDefSet &visitedClasses) { - p->addDirs(dirs); + p->addDirs(dirs,visitedClasses); } -void NestingContext::addFiles(const FileNameLinkedMap &files) +void NestingContext::addFiles(const FileNameLinkedMap &files,ClassDefSet &visitedClasses) { - p->addFiles(files); + p->addFiles(files,visitedClasses); } -void NestingContext::addFiles(const FileList &files) +void NestingContext::addFiles(const FileList &files,ClassDefSet &visitedClasses) { - p->addFiles(files); + p->addFiles(files,visitedClasses); } -void NestingContext::addPages(const PageSDict &pages,bool rootOnly) +void NestingContext::addPages(const PageSDict &pages,bool rootOnly,ClassDefSet &visitedClasses) { - p->addPages(pages,rootOnly); + p->addPages(pages,rootOnly,visitedClasses); } -void NestingContext::addModules(const GroupSDict &modules) +void NestingContext::addModules(const GroupSDict &modules,ClassDefSet &visitedClasses) { - p->addModules(modules); + p->addModules(modules,visitedClasses); } -void NestingContext::addModules(const GroupList &modules) +void NestingContext::addModules(const GroupList &modules,ClassDefSet &visitedClasses) { - p->addModules(modules); + p->addModules(modules,visitedClasses); } -void NestingContext::addClassHierarchy(const ClassSDict &classSDict,bool rootOnly) +void NestingContext::addClassHierarchy(const ClassLinkedMap &classLinkedMap,ClassDefSet &visitedClasses) { - p->addClassHierarchy(classSDict,rootOnly); + p->addClassHierarchy(classLinkedMap,visitedClasses); } -void NestingContext::addDerivedClasses(const BaseClassList *bcl,bool hideSuper) +void NestingContext::addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses) { - p->addDerivedClasses(bcl,hideSuper); + p->addDerivedClasses(bcl,hideSuper,visitedClasses); } //------------------------------------------------------------------------ @@ -6818,14 +6786,9 @@ class ClassTreeContext::Private Private() { m_classTree.reset(NestingContext::alloc(0,0)); - if (Doxygen::namespaceSDict) - { - m_classTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,TRUE); - } - if (Doxygen::classSDict) - { - m_classTree->addClasses(*Doxygen::classSDict,TRUE); - } + ClassDefSet visitedClasses; + m_classTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,TRUE,visitedClasses); + m_classTree->addClasses(*Doxygen::classLinkedMap,TRUE,visitedClasses); //%% Nesting tree static bool init=FALSE; if (!init) @@ -6939,15 +6902,13 @@ TemplateVariant ClassTreeContext::get(const char *name) const class NamespaceListContext::Private : public GenericNodeListContext { public: - void addNamespaces(const NamespaceSDict &nsDict) + void addNamespaces(const NamespaceLinkedMap &nsLinkedMap) { - NamespaceSDict::Iterator nli(nsDict); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : nsLinkedMap) { if (nd->isLinkableInProject()) { - append(NamespaceContext::alloc(nd)); + append(NamespaceContext::alloc(nd.get())); } } } @@ -6956,7 +6917,7 @@ class NamespaceListContext::Private : public GenericNodeListContext NamespaceListContext::NamespaceListContext() : RefCountedContext("NamespaceListContext") { p = new Private; - p->addNamespaces(*Doxygen::namespaceSDict); + p->addNamespaces(*Doxygen::namespaceLinkedMap); } NamespaceListContext::~NamespaceListContext() @@ -6990,10 +6951,8 @@ class NamespaceTreeContext::Private Private() { m_namespaceTree.reset(NestingContext::alloc(0,0)); - if (Doxygen::namespaceSDict) - { - m_namespaceTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,FALSE); - } + ClassDefSet visitedClasses; + m_namespaceTree->addNamespaces(*Doxygen::namespaceLinkedMap,TRUE,FALSE,visitedClasses); //%% Nesting tree static bool init=FALSE; if (!init) @@ -7262,13 +7221,14 @@ class FileTreeContext::Private { // Add dirs tree m_dirFileTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; if (Doxygen::directories) { - m_dirFileTree->addDirs(*Doxygen::directories); + m_dirFileTree->addDirs(*Doxygen::directories,visitedClasses); } if (Doxygen::inputNameLinkedMap) { - m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap); + m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses); } //%% DirFile tree: static bool init=FALSE; @@ -7374,10 +7334,11 @@ class PageTreeContext::Private Private(const PageSDict *pages) { m_pageTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; // Add pages if (pages) { - m_pageTree->addPages(*pages,TRUE); + m_pageTree->addPages(*pages,TRUE,visitedClasses); } //%% PageNodeList tree: @@ -7627,10 +7588,11 @@ class ModuleTreeContext::Private Private() { m_moduleTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; // Add modules if (Doxygen::groupSDict) { - m_moduleTree->addModules(*Doxygen::groupSDict); + m_moduleTree->addModules(*Doxygen::groupSDict,visitedClasses); } //%% ModuleList tree: @@ -7770,11 +7732,11 @@ class NavPathElemContext::Private QCString text = m_def->localName(); if (type==Definition::TypeGroup) { - text = (dynamic_cast<const GroupDef*>(m_def))->groupTitle(); + text = (toGroupDef(m_def))->groupTitle(); } - else if (type==Definition::TypePage && ((dynamic_cast<const PageDef*>(m_def))->hasTitle())) + else if (type==Definition::TypePage && ((toPageDef(m_def))->hasTitle())) { - text = (dynamic_cast<const PageDef*>(m_def))->title(); + text = (toPageDef(m_def))->title(); } else if (type==Definition::TypeClass) { @@ -7832,10 +7794,11 @@ class ExampleTreeContext::Private Private() { m_exampleTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; // Add pages if (Doxygen::exampleSDict) { - m_exampleTree->addPages(*Doxygen::exampleSDict,TRUE); + m_exampleTree->addPages(*Doxygen::exampleSDict,TRUE,visitedClasses); } static bool init=FALSE; @@ -8524,29 +8487,24 @@ class InheritanceListContext::Private : public GenericNodeListContext } }; -InheritanceListContext::InheritanceListContext(const BaseClassList *list, bool baseClasses) : RefCountedContext("InheritanceListContext") +InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : RefCountedContext("InheritanceListContext") { p = new Private; - if (list) + for (const auto &bcd : list) { - BaseClassListIterator li(*list); - BaseClassDef *bcd; - for (li.toFirst();(bcd=li.current());++li) + const ClassDef *cd=bcd.classDef; + QCString name; + if (baseClasses) { - const ClassDef *cd=bcd->classDef; - QCString name; - if (baseClasses) - { - name = insertTemplateSpecifierInScope( - cd->displayName(),bcd->templSpecifiers); - } - else - { - name = cd->displayName(); - } - //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses); - p->addClass(cd,name); + name = insertTemplateSpecifierInScope( + cd->displayName(),bcd.templSpecifiers); + } + else + { + name = cd->displayName(); } + //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses); + p->addClass(cd,name); } } @@ -8577,7 +8535,7 @@ TemplateListIntf::ConstIterator *InheritanceListContext::createIterator() const class MemberListContext::Private : public GenericNodeListContext { public: - void addMember(MemberDef *md) + void addMember(const MemberDef *md) { append(MemberContext::alloc(md)); } @@ -8626,6 +8584,16 @@ MemberListContext::MemberListContext(MemberSDict *list,bool doSort) : RefCounted } } +MemberListContext::MemberListContext(std::vector<const MemberDef *> &&ml) : RefCountedContext("MemberListContext") +{ + p = new Private; + for (const auto &md : ml) + { + p->addMember(md); + } + ml.clear(); +} + MemberListContext::~MemberListContext() { delete p; @@ -9044,7 +9012,7 @@ class MemberListInfoContext::Private m_def->definitionType()==Definition::TypeClass) { InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc(); - ctx->addMemberList(dynamic_cast<const ClassDef*>(m_def),m_memberList->listType(),m_title,FALSE); + ctx->addMemberList(toClassDef(m_def),m_memberList->listType(),m_title,FALSE); m_cache.inherited.reset(ctx); } if (m_cache.inherited) @@ -9270,31 +9238,26 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext int lt2, const QCString &title,bool additionalList, QPtrDict<void> *visitedClasses) { - if (cd->baseClasses()) + for (const auto &ibcd : cd->baseClasses()) { - BaseClassListIterator it(*cd->baseClasses()); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *icd=ibcd.classDef; + if (icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - if (icd->isLinkable()) + int lt1,lt3; + convertProtectionLevel(lt,ibcd.prot,<1,<3); + if (lt2==-1 && lt3!=-1) { - int lt1,lt3; - convertProtectionLevel(lt,ibcd->prot,<1,<3); - if (lt2==-1 && lt3!=-1) - { - lt2=lt3; - } - if (visitedClasses->find(icd)==0) + lt2=lt3; + } + if (visitedClasses->find(icd)==0) + { + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - // add member info for members of cd with list type lt - addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList); - // recurse down the inheritance tree - findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses); - } + // add member info for members of cd with list type lt + addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList); + // recurse down the inheritance tree + findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses); } } } @@ -9551,7 +9514,7 @@ class SymbolContext::Private const Definition *prev = m_prevDef; const Definition *nextScope = next ? next->getOuterScope() : 0; const Definition *prevScope = prev ? prev->getOuterScope() : 0; - const MemberDef *md = dynamic_cast<const MemberDef*>(m_def); + const MemberDef *md = toMemberDef(m_def); bool isFunctionLike = md && (md->isFunction() || md->isSlot() || md->isSignal()); bool overloadedFunction = isFunctionLike && ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope)); @@ -10300,25 +10263,9 @@ void generateOutputViaTemplate() } // clear all cached data in Definition objects. - QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap); - const DefinitionIntf *intf; - for (;(intf=di.current());++di) + for (const auto &kv : Doxygen::symbolMap) { - if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols - { - DefinitionListIterator dli(*dynamic_cast<const DefinitionList*>(intf)); - const Definition *d; - // for each symbol - for (dli.toFirst();(d=dli.current());++dli) - { - d->setCookie(0); - } - } - else // single symbol - { - const Definition *d = dynamic_cast<const Definition *>(intf); - d->setCookie(0); - } + kv.second->setCookie(0); } e.destroyContext(ctx); diff --git a/src/context.h b/src/context.h index 7256dc6..1a2df8c 100644 --- a/src/context.h +++ b/src/context.h @@ -21,19 +21,18 @@ #include <qlist.h> #include <stdio.h> #include "dirdef.h" +#include "classdef.h" class Definition; -class ClassDef; -class ClassSDict; -class BaseClassList; class PageDef; class GroupDef; class NamespaceDef; -class BaseClassList; -class NamespaceSDict; +class NamespaceLinkedMap; +class NamespaceLinkedRefMap; class FileDef; class FileList; class FileNameLinkedMap; +class ClassLinkedMap; class DirSDict; class DirDef; class PageSDict; @@ -455,7 +454,7 @@ class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStr virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } - void addChildren(const BaseClassList *bcl,bool hideSuper); + void addChildren(const BaseClassList &bcl,bool hideSuper); private: ClassInheritanceNodeContext(const ClassDef *); @@ -510,8 +509,9 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf { public: static NestingNodeContext *alloc(const NestingNodeContext *parent,const Definition *def, - int index,int level,bool addClasses,bool inherit,bool hideSuper) - { return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper); } + int index,int level,bool addClasses,bool inherit,bool hideSuper, + ClassDefSet &visitedClasses) + { return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper,visitedClasses); } QCString id() const; @@ -522,7 +522,8 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf private: NestingNodeContext(const NestingNodeContext *parent, - const Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper); + const Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper, + ClassDefSet &visitedClasses); ~NestingNodeContext(); class Private; Private *p; @@ -533,6 +534,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf class NestingContext : public RefCountedContext, public TemplateListIntf { public: + static NestingContext *alloc(const NestingNodeContext *parent,int level) { return new NestingContext(parent,level); } @@ -543,17 +545,19 @@ class NestingContext : public RefCountedContext, public TemplateListIntf virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } - void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses); - void addClasses(const ClassSDict &clDict,bool rootOnly); - void addDirs(const DirSDict &); - void addDirs(const DirList &); - void addFiles(const FileNameLinkedMap &); - void addFiles(const FileList &); - void addPages(const PageSDict &pages,bool rootOnly); - void addModules(const GroupSDict &modules); - void addModules(const GroupList &modules); - void addClassHierarchy(const ClassSDict &clDict,bool rootOnly); - void addDerivedClasses(const BaseClassList *bcl,bool hideSuper); + void addNamespaces(const NamespaceLinkedMap &nsLinkedMap,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses); + void addNamespaces(const NamespaceLinkedRefMap &nsLinkedMap,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses); + void addClasses(const ClassLinkedRefMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses); + void addClasses(const ClassLinkedMap &clLinkedMap,bool rootOnly,ClassDefSet &visitedClasses); + void addDirs(const DirSDict &,ClassDefSet &visitedClasses); + void addDirs(const DirList &,ClassDefSet &visitedClasses); + void addFiles(const FileNameLinkedMap &,ClassDefSet &visitedClasses); + void addFiles(const FileList &,ClassDefSet &visitedClasses); + void addPages(const PageSDict &pages,bool rootOnly,ClassDefSet &visitedClasses); + void addModules(const GroupSDict &modules,ClassDefSet &visitedClasses); + void addModules(const GroupList &modules,ClassDefSet &visitedClasses); + void addClassHierarchy(const ClassLinkedMap &clLinkedMap,ClassDefSet &visitedClasses); + void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses); private: NestingContext(const NestingNodeContext *parent,int level); @@ -929,7 +933,7 @@ class InheritanceNodeContext : public RefCountedContext, public TemplateStructIn class InheritanceListContext : public RefCountedContext, public TemplateListIntf { public: - static InheritanceListContext *alloc(const BaseClassList *list,bool baseClasses) + static InheritanceListContext *alloc(const BaseClassList &list,bool baseClasses) { return new InheritanceListContext(list,baseClasses); } // TemplateListIntf @@ -940,7 +944,7 @@ class InheritanceListContext : public RefCountedContext, public TemplateListIntf virtual int release() { return RefCountedContext::release(); } private: - InheritanceListContext(const BaseClassList *list,bool baseClasses); + InheritanceListContext(const BaseClassList &list,bool baseClasses); ~InheritanceListContext(); class Private; Private *p; @@ -957,6 +961,8 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf { return new MemberListContext(ml); } static MemberListContext *alloc(MemberSDict *ml,bool doSort) { return new MemberListContext(ml,doSort); } + static MemberListContext *alloc(std::vector<const MemberDef *> &&ml) + { return new MemberListContext(std::move(ml)); } // TemplateListIntf virtual uint count() const; @@ -969,6 +975,7 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf MemberListContext(); MemberListContext(const MemberList *ml); MemberListContext(MemberSDict *ml,bool doSort); + MemberListContext(std::vector<const MemberDef *> &&ml); ~MemberListContext(); class Private; Private *p; diff --git a/src/declinfo.l b/src/declinfo.l index 2f497f9..014ef75 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -149,6 +149,7 @@ ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) addType(yyscanner); } <Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? { + if (yyextra->insidePHP) REJECT; addType(yyscanner); QCString text=yytext; yyextra->type+=text.stripWhiteSpace(); diff --git a/src/defargs.l b/src/defargs.l index 6ecc7ff..e25c1fe 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -511,6 +511,8 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <FuncQual>"volatile" { yyextra->argList->setVolatileSpecifier(TRUE); } +<FuncQual>"override" { + } <FuncQual>"&" { yyextra->argList->setRefQualifier(RefQualifierLValue); } @@ -790,7 +792,7 @@ std::unique_ptr<ArgumentList> stringToArgumentList(SrcLangExt lang, const char * yyextra->argList->setNoParameters(TRUE); } if (extraTypeChars) *extraTypeChars=yyextra->extraTypeChars; - //printf("stringToArgumentList(%s) result=%s\n",argsString,argListToString(al).data()); + //printf("stringToArgumentList(%s) result=%s\n",argsString,argListToString(*al).data()); printlex(yy_flex_debug, FALSE, __FILE__, NULL); defargsYYlex_destroy(yyscanner); return al; diff --git a/src/defgen.cpp b/src/defgen.cpp index 02f51c5..a1cd28d 100644 --- a/src/defgen.cpp +++ b/src/defgen.cpp @@ -243,71 +243,58 @@ void generateDEFForMember(MemberDef *md, //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict) + QCString refPrefix = " " + memPrefix + "ref-"; + auto refList = md->getReferencesMembers(); + for (const auto &rmd : refList) { - MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; - QCString refPrefix = " " + memPrefix + "ref-"; - - for (mdi.toFirst();(rmd=mdi.current());++mdi) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + t << memPrefix << "referenceto = {" << endl; + t << refPrefix << "id = '" + << rmd->getBodyDef()->getOutputFileBase() + << "_1" // encoded ':' character (see util.cpp:convertNameToFile) + << rmd->anchor() << "';" << endl; + + t << refPrefix << "line = '" + << rmd->getStartBodyLine() << "';" << endl; + + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) { - t << memPrefix << "referenceto = {" << endl; - t << refPrefix << "id = '" - << rmd->getBodyDef()->getOutputFileBase() - << "_1" // encoded ':' character (see util.cpp:convertNameToFile) - << rmd->anchor() << "';" << endl; - - t << refPrefix << "line = '" - << rmd->getStartBodyLine() << "';" << endl; - - QCString scope = rmd->getScopeString(); - QCString name = rmd->name(); - if (!scope.isEmpty() && scope!=def->name()) - { - name.prepend(scope+"::"); - } - - t << refPrefix << "name = "; - writeDEFString(t,name); - t << ';' << endl << " };" << endl; + name.prepend(scope+"::"); } - } /* for (mdi.toFirst...) */ + + t << refPrefix << "name = "; + writeDEFString(t,name); + t << ';' << endl << " };" << endl; + } } - mdict = md->getReferencedByMembers(); - if (mdict) + auto refByList = md->getReferencedByMembers(); + for (const auto &rmd : refByList) { - MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; - QCString refPrefix = " " + memPrefix + "ref-"; - - for (mdi.toFirst();(rmd=mdi.current());++mdi) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + t << memPrefix << "referencedby = {" << endl; + t << refPrefix << "id = '" + << rmd->getBodyDef()->getOutputFileBase() + << "_1" // encoded ':' character (see util.cpp:convertNameToFile) + << rmd->anchor() << "';" << endl; + + t << refPrefix << "line = '" + << rmd->getStartBodyLine() << "';" << endl; + + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) { - t << memPrefix << "referencedby = {" << endl; - t << refPrefix << "id = '" - << rmd->getBodyDef()->getOutputFileBase() - << "_1" // encoded ':' character (see util.cpp:convertNameToFile) - << rmd->anchor() << "';" << endl; - - t << refPrefix << "line = '" - << rmd->getStartBodyLine() << "';" << endl; - - QCString scope = rmd->getScopeString(); - QCString name = rmd->name(); - if (!scope.isEmpty() && scope!=def->name()) - { - name.prepend(scope+"::"); - } - - t << refPrefix << "name = "; - writeDEFString(t,name); - t << ';' << endl << " };" << endl; + name.prepend(scope+"::"); } - } /* for (mdi.toFirst...) */ + + t << refPrefix << "name = "; + writeDEFString(t,name); + t << ';' << endl << " };" << endl; + } } t << " }; /* " << Prefix << "-member */" << endl; @@ -358,60 +345,50 @@ void generateDEFForClass(ClassDef *cd,FTextStream &t) t << " cp-id = '" << cd->getOutputFileBase() << "';" << endl; t << " cp-name = '" << cd->name() << "';" << endl; - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " cp-ref = {" << endl << " ref-type = base;" << endl; + t << " ref-id = '" + << bcd.classDef->getOutputFileBase() << "';" << endl; + t << " ref-prot = "; + switch (bcd.prot) { - t << " cp-ref = {" << endl << " ref-type = base;" << endl; - t << " ref-id = '" - << bcd->classDef->getOutputFileBase() << "';" << endl; - t << " ref-prot = "; - switch (bcd->prot) - { - case Public: t << "public;" << endl; break; - case Package: // package scope is not possible - case Protected: t << "protected;" << endl; break; - case Private: t << "private;" << endl; break; - } - t << " ref-virt = "; - switch(bcd->virt) - { - case Normal: t << "non-virtual;"; break; - case Virtual: t << "virtual;"; break; - case Pure: t << "pure-virtual;"; break; - } - t << endl << " };" << endl; + case Public: t << "public;" << endl; break; + case Package: // package scope is not possible + case Protected: t << "protected;" << endl; break; + case Private: t << "private;" << endl; break; + } + t << " ref-virt = "; + switch(bcd.virt) + { + case Normal: t << "non-virtual;"; break; + case Virtual: t << "virtual;"; break; + case Pure: t << "pure-virtual;"; break; } + t << endl << " };" << endl; } - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " cp-ref = {" << endl << " ref-type = derived;" << endl; + t << " ref-id = '" + << bcd.classDef->getOutputFileBase() << "';" << endl; + t << " ref-prot = "; + switch (bcd.prot) { - t << " cp-ref = {" << endl << " ref-type = derived;" << endl; - t << " ref-id = '" - << bcd->classDef->getOutputFileBase() << "';" << endl; - t << " ref-prot = "; - switch (bcd->prot) - { - case Public: t << "public;" << endl; break; - case Package: // packet scope is not possible! - case Protected: t << "protected;" << endl; break; - case Private: t << "private;" << endl; break; - } - t << " ref-virt = "; - switch(bcd->virt) - { - case Normal: t << "non-virtual;"; break; - case Virtual: t << "virtual;"; break; - case Pure: t << "pure-virtual;"; break; - } - t << endl << " };" << endl; + case Public: t << "public;" << endl; break; + case Package: // packet scope is not possible! + case Protected: t << "protected;" << endl; break; + case Private: t << "private;" << endl; break; + } + t << " ref-virt = "; + switch (bcd.virt) + { + case Normal: t << "non-virtual;"; break; + case Virtual: t << "virtual;"; break; + case Pure: t << "pure-virtual;"; break; } + t << endl << " };" << endl; } int numMembers = 0; @@ -611,13 +588,11 @@ void generateDEF() FTextStream t(&f); t << "AutoGen Definitions dummy;" << endl; - if (Doxygen::classSDict->count()+Doxygen::inputNameLinkedMap->size()>0) + if (Doxygen::classLinkedMap->size()+Doxygen::inputNameLinkedMap->size()>0) { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - generateDEFForClass(cd,t); + generateDEFForClass(cd.get(),t); } for (const auto &fn : *Doxygen::inputNameLinkedMap) { diff --git a/src/definition.cpp b/src/definition.cpp index 3ed331c..b719388 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -16,6 +16,10 @@ */ #include <algorithm> +#include <iterator> +#include <unordered_map> +#include <string> + #include <ctype.h> #include <qregexp.h> #include "md5.h" @@ -46,6 +50,7 @@ #include "bufstr.h" #include "reflist.h" + //----------------------------------------------------------------------------------------- /** Private data associated with a Symbol DefinitionImpl object. */ @@ -56,10 +61,12 @@ class DefinitionImpl::IMPL void init(const char *df, const char *n); void setDefFileName(const QCString &df); + Definition *def = 0; + SectionRefs sectionRefs; - MemberSDict *sourceRefByDict = 0; - MemberSDict *sourceRefsDict = 0; + std::unordered_map<std::string,const MemberDef *> sourceRefByDict; + std::unordered_map<std::string,const MemberDef *> sourceRefsDict; RefItemVector xrefListItems; GroupList *partOfGroups = 0; @@ -94,14 +101,12 @@ class DefinitionImpl::IMPL QCString symbolName; int defLine; int defColumn; - Cookie *cookie; + Definition::Cookie *cookie; }; DefinitionImpl::IMPL::~IMPL() { - delete sourceRefByDict; - delete sourceRefsDict; delete partOfGroups; delete brief; delete details; @@ -138,8 +143,8 @@ void DefinitionImpl::IMPL::init(const char *df, const char *n) details = 0; body = 0; inbodyDocs = 0; - sourceRefByDict = 0; - sourceRefsDict = 0; + sourceRefByDict.clear(); + sourceRefsDict.clear(); outerScope = Doxygen::globalScope; partOfGroups = 0; hidden = FALSE; @@ -176,14 +181,14 @@ static bool matchExcludedSymbols(const char *name) QRegExp re(substitute(pattern,"*",".*"),TRUE); int pl; int i = re.match(symName,0,&pl); - //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data()); + //printf(" %d = re.match(%s) pattern=%s pl=%d len=%d\n",i,symName.data(),pattern.data(),pl,symName.length()); if (i!=-1) // wildcard match { uint ui=(uint)i; uint sl=symName.length(); // check if it is a whole word match - 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)) + if ((ui==0 || pattern.at(0)=='*' || (!isId(symName.at(ui-1)) && !forceStart)) && + (ui+pl==sl || pattern.at(pattern.length()-1)=='*' || (!isId(symName.at(ui+pl)) && !forceEnd)) ) { //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); @@ -222,86 +227,30 @@ static void addToMap(const char *name,Definition *d) if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2); if (!symbolName.isEmpty()) { - //printf("******* adding symbol '%s' (%p)\n",symbolName.data(),d); - DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); - //printf(" addToMap(%p): looking for symbol %s: %p\n",d,symbolName.data(),di); - if (di==0) // new Symbol - { - //printf(" new symbol!\n"); - Doxygen::symbolMap->insert(symbolName,d); - } - else // existing symbol - { - //printf(" existing symbol: "); - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // already multiple symbols - { - //printf("adding to exiting list\n"); - DefinitionList *dl = (DefinitionList*)di; - dl->append(d); - } - else // going from one to two symbols - { - Doxygen::symbolMap->take(symbolName); - DefinitionList *dl = new DefinitionList; - //printf("replacing symbol by list %p with elements %p and %p\n",dl,di,d); - dl->append((Definition*)di); - dl->append(d); - Doxygen::symbolMap->insert(symbolName,dl); - } - } - - // auto resize if needed - static int sizeIndex=9; - if (Doxygen::symbolMap->size()>SDict_primes[sizeIndex]) - { - Doxygen::symbolMap->resize(SDict_primes[++sizeIndex]); - } + Doxygen::symbolMap.add(symbolName,d); d->_setSymbolName(symbolName); } } -static void removeFromMap(Definition *d) +static void removeFromMap(const char *name,Definition *d) { - QCString symbolName = d->_symbolName(); - if (!symbolName.isEmpty()) - { - //printf("******* removing symbol '%s' (%p)\n",symbolName.data(),d); - DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); - if (di) - { - if (di!=d) // symbolName not unique - { - //printf(" removing from list: %p!\n",di); - DefinitionList *dl = (DefinitionList*)di; - bool b = dl->removeRef(d); - ASSERT(b==TRUE); - if (dl->isEmpty()) - { - Doxygen::symbolMap->take(symbolName); - delete dl; - } - } - else // symbolName unique - { - //printf(" removing symbol %p\n",di); - Doxygen::symbolMap->take(symbolName); - } - } - } + Doxygen::symbolMap.remove(name,d); } -DefinitionImpl::DefinitionImpl(const char *df,int dl,int dc, +DefinitionImpl::DefinitionImpl(Definition *def, + const char *df,int dl,int dc, const char *name,const char *b, const char *d,bool isSymbol) { m_impl = new DefinitionImpl::IMPL; setName(name); + m_impl->def = def; m_impl->defLine = dl; m_impl->defColumn = dc; m_impl->init(df,name); m_impl->isSymbol = isSymbol; - if (isSymbol) addToMap(name,this); + if (isSymbol) addToMap(name,def); _setBriefDescription(b,df,dl); _setDocumentation(d,df,dl,TRUE,FALSE); if (matchExcludedSymbols(name)) @@ -314,33 +263,11 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) { m_impl = new DefinitionImpl::IMPL; *m_impl = *d.m_impl; - m_impl->sourceRefByDict = 0; - m_impl->sourceRefsDict = 0; m_impl->partOfGroups = 0; m_impl->brief = 0; m_impl->details = 0; m_impl->body = 0; m_impl->inbodyDocs = 0; - if (d.m_impl->sourceRefByDict) - { - m_impl->sourceRefByDict = new MemberSDict; - MemberSDict::IteratorDict it(*d.m_impl->sourceRefByDict); - MemberDef *md; - for (it.toFirst();(md=it.current());++it) - { - m_impl->sourceRefByDict->append(it.currentKey(),md); - } - } - if (d.m_impl->sourceRefsDict) - { - m_impl->sourceRefsDict = new MemberSDict; - MemberSDict::IteratorDict it(*d.m_impl->sourceRefsDict); - MemberDef *md; - for (it.toFirst();(md=it.current());++it) - { - m_impl->sourceRefsDict->append(it.currentKey(),md); - } - } if (d.m_impl->partOfGroups) { GroupListIterator it(*d.m_impl->partOfGroups); @@ -367,14 +294,14 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) m_impl->inbodyDocs = new DocInfo(*d.m_impl->inbodyDocs); } - if (m_impl->isSymbol) addToMap(m_impl->name,this); + if (m_impl->isSymbol) addToMap(m_impl->name,m_impl->def); } DefinitionImpl::~DefinitionImpl() { if (m_impl->isSymbol) { - removeFromMap(this); + removeFromMap(m_impl->symbolName,m_impl->def); } if (m_impl) { @@ -399,7 +326,7 @@ void DefinitionImpl::setId(const char *id) if (Doxygen::clangUsrMap) { //printf("DefinitionImpl::setId '%s'->'%s'\n",id,m_impl->name.data()); - Doxygen::clangUsrMap->insert(id,this); + Doxygen::clangUsrMap->insert(id,m_impl->def); } } @@ -425,7 +352,7 @@ void DefinitionImpl::addSectionsToDefinition(const std::vector<const SectionInfo if (m_impl->sectionRefs.find(gsi->label())==0) { m_impl->sectionRefs.add(gsi); - gsi->setDefinition(this); + gsi->setDefinition(m_impl->def); } } } @@ -481,7 +408,7 @@ void DefinitionImpl::addSectionsToIndex() ((int)((*it_next)->type()) > nextLevel) : FALSE; Doxygen::indexList->addContentsItem(isDir,title, getReference(), - getOutputFileBase(), + m_impl->def->getOutputFileBase(), si->label(), FALSE, TRUE); @@ -505,7 +432,7 @@ void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile) const if (!si->generated() && si->ref().isEmpty() && !si->label().startsWith("autotoc_md")) { //printf("write an entry!\n"); - if (definitionType()==TypeMember) tagFile << " "; + if (m_impl->def->definitionType()==Definition::TypeMember) tagFile << " "; tagFile << " <docanchor file=\"" << addHtmlExtensionIfMissing(si->fileName()) << "\""; if (!si->title().isEmpty()) { @@ -613,6 +540,8 @@ void DefinitionImpl::_setBriefDescription(const char *b,const char *briefFile,in outputLanguage!="Korean"; QCString brief = b; brief = brief.stripWhiteSpace(); + brief = stripLeadingAndTrailingEmptyLines(brief,briefLine); + brief = brief.stripWhiteSpace(); if (brief.isEmpty()) return; uint bl = brief.length(); if (bl>0 && needsDot) // add punctuation if needed @@ -976,7 +905,7 @@ bool readCodeFragment(const char *fileName, QCString DefinitionImpl::getSourceFileBase() const { - ASSERT(definitionType()!=Definition::TypeFile); // file overloads this method + ASSERT(m_impl->def->definitionType()!=Definition::TypeFile); // file overloads this method QCString fn; static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); if (sourceBrowser && @@ -1234,37 +1163,56 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const { //printf("Adding code fragment '%s' ext='%s'\n", // codeFragment.data(),m_impl->defFileExt.data()); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(m_impl->defFileExt); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(m_impl->defFileExt); + intf->resetCodeParserState(); //printf("Read:\n'%s'\n\n",codeFragment.data()); const MemberDef *thisMd = 0; - if (definitionType()==TypeMember) thisMd = dynamic_cast <const MemberDef*>(this); - - ol.startCodeFragment(); - intf.parseCode(ol, // codeOutIntf - scopeName, // scope - codeFragment, // input - m_impl->lang, // lang - FALSE, // isExample - 0, // exampleName - m_impl->body->fileDef, // fileDef - actualStart, // startLine - actualEnd, // endLine - TRUE, // inlineFragment - thisMd, // memberDef - TRUE // show line numbers - ); - ol.endCodeFragment(); + if (m_impl->def->definitionType()==Definition::TypeMember) + { + thisMd = toMemberDef(m_impl->def); + } + + ol.startCodeFragment("DoxyCode"); + intf->parseCode(ol, // codeOutIntf + scopeName, // scope + codeFragment, // input + m_impl->lang, // lang + FALSE, // isExample + 0, // exampleName + m_impl->body->fileDef, // fileDef + actualStart, // startLine + actualEnd, // endLine + TRUE, // inlineFragment + thisMd, // memberDef + TRUE // show line numbers + ); + ol.endCodeFragment("DoxyCode"); } } ol.popGeneratorState(); } +static inline std::vector<const MemberDef*> refMapToVector(const std::unordered_map<std::string,const MemberDef *> &map) +{ + // convert map to a vector of values + std::vector<const MemberDef *> result; + std::transform(map.begin(),map.end(), // iterate over map + std::back_inserter(result), // add results to vector + [](const auto &item) + { return item.second; } // extract value to add from map Key,Value pair + ); + // and sort it + std::sort(result.begin(),result.end(), + [](const auto &m1,const auto &m2) { return genericCompareMembers(m1,m2)<0; }); + return result; +} + /*! 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 + const QCString &text,const std::unordered_map<std::string,const MemberDef *> &membersMap, + bool /*funcOnly*/) const { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); @@ -1272,15 +1220,15 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE); ol.pushGeneratorState(); - if (members) + if (!membersMap.empty()) { - members->sort(); + auto members = refMapToVector(membersMap); ol.startParagraph("reference"); ol.parseText(text); ol.docify(" "); - QCString ldefLine=theTranslator->trWriteList((int)members->count()); + QCString ldefLine=theTranslator->trWriteList((int)members.size()); QRegExp marker("@[0-9]+"); uint index=0; @@ -1292,7 +1240,7 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, bool ok; ol.parseText(ldefLine.mid(index,(uint)newIndex-index)); uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - MemberDef *md=members->at(entryIndex); + const MemberDef *md=members.at(entryIndex); if (ok && md) { QCString scope=md->getScopeString(); @@ -1464,14 +1412,7 @@ void DefinitionImpl::addSourceReferencedBy(const MemberDef *md) name.prepend(scope+"::"); } - if (m_impl->sourceRefByDict==0) - { - m_impl->sourceRefByDict = new MemberSDict; - } - if (m_impl->sourceRefByDict->find(name)==0) - { - m_impl->sourceRefByDict->append(name,md); - } + m_impl->sourceRefByDict.insert({name.str(),md}); } } @@ -1487,18 +1428,11 @@ void DefinitionImpl::addSourceReferences(const MemberDef *md) name.prepend(scope+"::"); } - if (m_impl->sourceRefsDict==0) - { - m_impl->sourceRefsDict = new MemberSDict; - } - if (m_impl->sourceRefsDict->find(name)==0) - { - m_impl->sourceRefsDict->append(name,md); - } + m_impl->sourceRefsDict.insert({name.str(),md}); } } -Definition *DefinitionImpl::findInnerCompound(const char *) const +const Definition *DefinitionImpl::findInnerCompound(const char *) const { return 0; } @@ -1633,16 +1567,18 @@ QCString DefinitionImpl::pathFragment() const { result = m_impl->outerScope->pathFragment(); } - if (isLinkable()) + if (m_impl->def->isLinkable()) { if (!result.isEmpty()) result+="/"; - if (definitionType()==Definition::TypeGroup && (dynamic_cast <const GroupDef*>(this))->groupTitle()) + if (m_impl->def->definitionType()==Definition::TypeGroup && + (toGroupDef(m_impl->def))->groupTitle()) { - result+=(dynamic_cast <const GroupDef*>(this))->groupTitle(); + result+=(toGroupDef(m_impl->def))->groupTitle(); } - else if (definitionType()==Definition::TypePage && (dynamic_cast <const PageDef*>(this))->hasTitle()) + else if (m_impl->def->definitionType()==Definition::TypePage && + (toPageDef(m_impl->def))->hasTitle()) { - result+=(dynamic_cast <const PageDef*>(this))->title(); + result+=(toPageDef(m_impl->def))->title(); } else { @@ -1671,37 +1607,37 @@ QCString DefinitionImpl::navigationPathAsString() const { result+=outerScope->navigationPathAsString(); } - else if (definitionType()==Definition::TypeFile && (dynamic_cast<const FileDef*>(this))->getDirDef()) + else if (m_impl->def->definitionType()==Definition::TypeFile && (toFileDef(m_impl->def))->getDirDef()) { - result+=(dynamic_cast<const FileDef*>(this))->getDirDef()->navigationPathAsString(); + result+=(toFileDef(m_impl->def))->getDirDef()->navigationPathAsString(); } result+="<li class=\"navelem\">"; - if (isLinkable()) + if (m_impl->def->isLinkable()) { - if (definitionType()==Definition::TypeGroup && (dynamic_cast<const GroupDef*>(this))->groupTitle()) + if (m_impl->def->definitionType()==Definition::TypeGroup && (toGroupDef(m_impl->def))->groupTitle()) { - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ - convertToHtml((dynamic_cast<const GroupDef*>(this))->groupTitle())+"</a>"; + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + convertToHtml((toGroupDef(m_impl->def))->groupTitle())+"</a>"; } - else if (definitionType()==Definition::TypePage && (dynamic_cast<const PageDef*>(this))->hasTitle()) + else if (m_impl->def->definitionType()==Definition::TypePage && (toPageDef(m_impl->def))->hasTitle()) { - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ - convertToHtml((dynamic_cast<const PageDef*>(this))->title())+"</a>"; + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + convertToHtml((toPageDef(m_impl->def))->title())+"</a>"; } - else if (definitionType()==Definition::TypeClass) + else if (m_impl->def->definitionType()==Definition::TypeClass) { QCString name = locName; if (name.right(2)=="-p" /*|| name.right(2)=="-g"*/) { name = name.left(name.length()-2); } - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension; - if (!anchor().isEmpty()) result+="#"+anchor(); + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension; + if (!m_impl->def->anchor().isEmpty()) result+="#"+m_impl->def->anchor(); result+="\">"+convertToHtml(name)+"</a>"; } else { - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ convertToHtml(locName)+"</a>"; } } @@ -1954,33 +1890,24 @@ 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 ? - (abbr ? abbreviate(m_impl->brief->doc,displayName()) : m_impl->brief->doc) : + (abbr ? abbreviate(m_impl->brief->doc,m_impl->def->displayName()) : m_impl->brief->doc) : QCString(""); } -QCString DefinitionImpl::briefDescriptionAsTooltip() const +void DefinitionImpl::computeTooltip() { - if (m_impl->brief) + if (m_impl->brief && m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) { - if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) - { - static bool reentering=FALSE; - if (!reentering) - { - const MemberDef *md = definitionType()==TypeMember ? dynamic_cast<const MemberDef*>(this) : 0; - const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this; - reentering=TRUE; // prevent requests for tooltips while parsing a tooltip - m_impl->brief->tooltip = parseCommentAsText( - scope,md, - m_impl->brief->doc, - m_impl->brief->file, - m_impl->brief->line); - reentering=FALSE; - } - } - return m_impl->brief->tooltip; + const MemberDef *md = m_impl->def->definitionType()==Definition::TypeMember ? toMemberDef(m_impl->def) : 0; + const Definition *scope = m_impl->def->definitionType()==Definition::TypeMember ? m_impl->def->getOuterScope() : m_impl->def; + m_impl->brief->tooltip = parseCommentAsText(scope,md, + m_impl->brief->doc, m_impl->brief->file, m_impl->brief->line); } - return QCString(""); +} + +QCString DefinitionImpl::briefDescriptionAsTooltip() const +{ + return m_impl->brief ? m_impl->brief->tooltip : QCString(); } int DefinitionImpl::briefLine() const @@ -2030,12 +1957,12 @@ bool DefinitionImpl::isHidden() const bool DefinitionImpl::isVisibleInProject() const { - return isLinkableInProject() && !m_impl->hidden; + return m_impl->def->isLinkableInProject() && !m_impl->hidden; } bool DefinitionImpl::isVisible() const { - return isLinkable() && !m_impl->hidden; + return m_impl->def->isLinkable() && !m_impl->hidden; } bool DefinitionImpl::isArtificial() const @@ -2098,16 +2025,49 @@ Definition *DefinitionImpl::getOuterScope() const return m_impl->outerScope; } -MemberSDict *DefinitionImpl::getReferencesMembers() const +std::vector<const MemberDef*> DefinitionImpl::getReferencesMembers() const +{ + return refMapToVector(m_impl->sourceRefsDict); +} + +std::vector<const MemberDef*> DefinitionImpl::getReferencedByMembers() const { - return m_impl->sourceRefsDict; + return refMapToVector(m_impl->sourceRefByDict); } -MemberSDict *DefinitionImpl::getReferencedByMembers() const +void DefinitionImpl::mergeReferences(const Definition *other) { - return m_impl->sourceRefByDict; + const DefinitionImpl *defImpl = other->toDefinitionImpl_(); + if (defImpl) + { + for (const auto &kv : defImpl->m_impl->sourceRefsDict) + { + auto it = m_impl->sourceRefsDict.find(kv.first); + if (it != m_impl->sourceRefsDict.end()) + { + m_impl->sourceRefsDict.insert(kv); + } + } + } } +void DefinitionImpl::mergeReferencedBy(const Definition *other) +{ + const DefinitionImpl *defImpl = other->toDefinitionImpl_(); + if (defImpl) + { + for (const auto &kv : defImpl->m_impl->sourceRefByDict) + { + auto it = m_impl->sourceRefByDict.find(kv.first); + if (it != m_impl->sourceRefByDict.end()) + { + m_impl->sourceRefByDict.insert({kv.first,kv.second}); + } + } + } +} + + void DefinitionImpl::setReference(const char *r) { m_impl->ref=r; @@ -2177,7 +2137,7 @@ QCString DefinitionImpl::externalReference(const QCString &relPath) const return relPath; } -const QCString &DefinitionImpl::name() const +QCString DefinitionImpl::name() const { return m_impl->name; } @@ -2197,7 +2157,7 @@ int DefinitionImpl::getDefColumn() const return m_impl->defColumn; } -void DefinitionImpl::setCookie(Cookie *cookie) const +void DefinitionImpl::setCookie(Definition::Cookie *cookie) const { delete m_impl->cookie; m_impl->cookie = cookie; @@ -2218,16 +2178,62 @@ void DefinitionImpl::writeSummaryLinks(OutputList &) const //--------------------------------------------------------------------------------- -DefinitionAliasImpl::DefinitionAliasImpl(const Definition *scope,const Definition *alias) - : m_scope(scope), m_def(alias), m_cookie(0) +DefinitionAliasImpl::DefinitionAliasImpl(Definition *def,const Definition *scope, const Definition *alias) + : m_def(def), m_scope(scope), m_symbolName(alias->_symbolName()) { - //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name())); - addToMap(alias->name(),this); } DefinitionAliasImpl::~DefinitionAliasImpl() { - //printf("~DefinitionAliasImpl()\n"); - removeFromMap(this); +} + +void DefinitionAliasImpl::init() +{ + //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name())); + addToMap(m_symbolName,m_def); +} + +void DefinitionAliasImpl::deinit() +{ + removeFromMap(m_symbolName,m_def); +} + +QCString DefinitionAliasImpl::qualifiedName() const +{ + //printf("start %s::qualifiedName() localName=%s\n",name().data(),m_impl->localName.data()); + if (m_scope==0) + { + return m_def->localName(); + } + else + { + return m_scope->qualifiedName()+ + getLanguageSpecificSeparator(m_scope->getLanguage())+ + m_def->localName(); + } +} + +QCString DefinitionAliasImpl::name() const +{ + return qualifiedName(); +} + +//--------------------------------------------------------------------------------- + +Definition *toDefinition(DefinitionMutable *dm) +{ + if (dm==0) return 0; + return dm->toDefinition_(); +} + +DefinitionMutable *toDefinitionMutable(Definition *d) +{ + if (d==0) return 0; + return d->toDefinitionMutable_(); +} + +DefinitionMutable *toDefinitionMutable(const Definition *d) +{ + return toDefinitionMutable(const_cast<Definition*>(d)); } diff --git a/src/definition.h b/src/definition.h index 8ad15b2..204e6f6 100644 --- a/src/definition.h +++ b/src/definition.h @@ -40,6 +40,8 @@ class GroupDef; class GroupList; class SectionInfo; class Definition; +class DefinitionMutable; +class DefinitionImpl; class FTextStream; /** Data associated with a detailed description. */ @@ -68,12 +70,19 @@ struct BodyInfo FileDef *fileDef; //!< file definition containing the function body }; -/** Abstract interface for a Definition or DefinitionList */ -class DefinitionIntf +/** 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. + */ +class Definition { public: - DefinitionIntf() {} - virtual ~DefinitionIntf() {} + struct Cookie + { + virtual ~Cookie() {} + }; + /*! Types of derived classes */ enum DefType { @@ -84,34 +93,22 @@ class DefinitionIntf TypeGroup = 4, TypePackage = 5, TypePage = 6, - TypeDir = 7, - TypeSymbolList = 8 + TypeDir = 7 }; - /*! 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. - * - * 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. - */ -class Definition : public DefinitionIntf -{ - public: - struct Cookie - { - virtual ~Cookie() {} - }; //----------------------------------------------------------------------------------- // ---- getters ----- //----------------------------------------------------------------------------------- + + /*! Use this for dynamic inspection of the type of the derived class */ + virtual DefType definitionType() const = 0; + /*! Returns TRUE if this is an alias of another definition */ virtual bool isAlias() const = 0; /*! Returns the name of the definition */ - virtual const QCString &name() const = 0; + virtual QCString name() const = 0; /*! Returns TRUE iff this definition has an artificially generated name * (typically starting with a @) that is used for nameless definitions @@ -269,11 +266,11 @@ class Definition : public DefinitionIntf virtual const RefItemVector &xrefListItems() const = 0; - virtual Definition *findInnerCompound(const char *name) const = 0; + virtual const Definition *findInnerCompound(const char *name) const = 0; virtual Definition *getOuterScope() const = 0; - virtual MemberSDict *getReferencesMembers() const = 0; - virtual MemberSDict *getReferencedByMembers() const = 0; + virtual std::vector<const MemberDef *> getReferencesMembers() const = 0; + virtual std::vector<const MemberDef *> getReferencedByMembers() const = 0; virtual bool hasSections() const = 0; virtual bool hasSources() const = 0; @@ -290,6 +287,34 @@ class Definition : public DefinitionIntf virtual QCString pathFragment() const = 0; //----------------------------------------------------------------------------------- + // --- cookie storage ---- + //----------------------------------------------------------------------------------- + virtual void setCookie(Cookie *cookie) const = 0; + virtual Cookie *cookie() const = 0; + + //----------------------------------------------------------------------------------- + // --- symbol name ---- + //----------------------------------------------------------------------------------- + virtual void _setSymbolName(const QCString &name) = 0; + virtual QCString _symbolName() const = 0; + + // --------------------------------- + virtual ~Definition() = default; + + private: + friend class DefinitionImpl; + friend DefinitionMutable* toDefinitionMutable(Definition *); + friend DefinitionMutable* toDefinitionMutable(const Definition *); + virtual DefinitionMutable *toDefinitionMutable_() = 0; + virtual const DefinitionImpl *toDefinitionImpl_() const = 0; +}; + +class DefinitionMutable +{ + public: + + + //----------------------------------------------------------------------------------- // ---- setters ----- //----------------------------------------------------------------------------------- @@ -347,6 +372,9 @@ class Definition : public DefinitionIntf virtual void mergeRefItems(Definition *d) = 0; virtual void addInnerCompound(const Definition *d) = 0; virtual void addSectionsToIndex() = 0; + virtual void mergeReferences(const Definition *other) = 0; + virtual void mergeReferencedBy(const Definition *other) = 0; + virtual void computeTooltip() = 0; //----------------------------------------------------------------------------------- // --- writing output ---- @@ -361,40 +389,17 @@ class Definition : public DefinitionIntf virtual void writeDocAnchorsToTagFile(FTextStream &) const = 0; virtual void writeToc(OutputList &ol, const LocalToc <) const = 0; - //----------------------------------------------------------------------------------- - // --- cookie storage ---- - //----------------------------------------------------------------------------------- - virtual void setCookie(Cookie *cookie) const = 0; - virtual Cookie *cookie() const = 0; - - //----------------------------------------------------------------------------------- - // --- symbol name ---- - //----------------------------------------------------------------------------------- - virtual void _setSymbolName(const QCString &name) = 0; - virtual QCString _symbolName() const = 0; -}; - -/** A list of Definition objects. */ -class DefinitionList : public QList<Definition>, public DefinitionIntf -{ - public: - ~DefinitionList() {} - DefType definitionType() const { return TypeSymbolList; } - int compareValues(const Definition *item1,const Definition *item2) const - { - return qstricmp(item1->name(),item2->name()); - } + // --------------------------------- + virtual ~DefinitionMutable() = default; + private: + friend Definition* toDefinition(DefinitionMutable *); + virtual Definition *toDefinition_() = 0; }; -/** An iterator for Definition objects in a DefinitionList. */ -class DefinitionListIterator : public QListIterator<Definition> -{ - public: - DefinitionListIterator(const DefinitionList &l) : - QListIterator<Definition>(l) {} - ~DefinitionListIterator() {} -}; +Definition *toDefinition(DefinitionMutable *dm); +DefinitionMutable *toDefinitionMutable(Definition *d); +DefinitionMutable *toDefinitionMutable(const Definition *d); /** 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 diff --git a/src/definitionimpl.h b/src/definitionimpl.h index e91d989..e455dc4 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -18,113 +18,116 @@ #ifndef DEFINITIONIMPL_H #define DEFINITIONIMPL_H +#include <unordered_map> +#include <string> + #include "definition.h" -class DefinitionImpl : virtual public Definition +class DefinitionImpl { public: - /*! Create a new definition */ DefinitionImpl( + Definition *def, const char *defFileName,int defLine,int defColumn, const char *name,const char *b=0,const char *d=0, bool isSymbol=TRUE); virtual ~DefinitionImpl(); - virtual bool isAlias() const { return FALSE; } - virtual const QCString &name() const; - virtual bool isAnonymous() const; - virtual QCString localName() const; - virtual QCString qualifiedName() const; - virtual QCString symbolName() const; - virtual QCString getSourceFileBase() const; - virtual QCString getSourceAnchor() const; - virtual QCString documentation() const; - virtual int docLine() const; - virtual QCString docFile() const; - virtual QCString briefDescription(bool abbreviate=FALSE) const; - virtual QCString briefDescriptionAsTooltip() const; - virtual int briefLine() const; - virtual QCString inbodyDocumentation() const; - virtual QCString inbodyFile() const; - virtual int inbodyLine() const; - virtual QCString briefFile() const; - virtual QCString getDefFileName() const; - virtual QCString getDefFileExtension() const; - virtual int getDefLine() const; - virtual int getDefColumn() const; - virtual bool hasDocumentation() const; - virtual bool hasUserDocumentation() const; - virtual bool isVisibleInProject() const; - virtual bool isVisible() const; - virtual bool isHidden() const; - virtual bool isArtificial() const; - 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 RefItemVector &xrefListItems() const; - virtual Definition *findInnerCompound(const char *name) const; - virtual Definition *getOuterScope() const; - virtual MemberSDict *getReferencesMembers() const; - virtual MemberSDict *getReferencedByMembers() const; - virtual bool hasSections() const; - virtual bool hasSources() const; - virtual bool hasBriefDescription() const; - virtual QCString id() 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); - 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 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 RefItemVector &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 QCString navigationPathAsString() const; - virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const; - virtual void writeSummaryLinks(OutputList &) const; - virtual QCString pathFragment() const; - virtual void writeDocAnchorsToTagFile(FTextStream &) const; - virtual void setLocalName(const QCString name); - virtual void addSectionsToIndex(); - virtual void writeToc(OutputList &ol, const LocalToc <) const; - virtual void setCookie(Cookie *cookie) const; - virtual Cookie *cookie() const; - - protected: + QCString name() const; + bool isAnonymous() const; + QCString localName() const; + QCString qualifiedName() const; + QCString symbolName() const; + QCString getSourceFileBase() const; + QCString getSourceAnchor() const; + QCString documentation() const; + int docLine() const; + QCString docFile() const; + QCString briefDescription(bool abbreviate=FALSE) const; + QCString briefDescriptionAsTooltip() const; + int briefLine() const; + QCString inbodyDocumentation() const; + QCString inbodyFile() const; + int inbodyLine() const; + QCString briefFile() const; + QCString getDefFileName() const; + QCString getDefFileExtension() const; + int getDefLine() const; + int getDefColumn() const; + bool hasDocumentation() const; + bool hasUserDocumentation() const; + bool isVisibleInProject() const; + bool isVisible() const; + bool isHidden() const; + bool isArtificial() const; + QCString getReference() const; + bool isReference() const; + QCString externalReference(const QCString &relPath) const; + int getStartDefLine() const; + int getStartBodyLine() const; + int getEndBodyLine() const; + FileDef *getBodyDef() const; + SrcLangExt getLanguage() const; + GroupList *partOfGroups() const; + bool isLinkableViaGroup() const; + const RefItemVector &xrefListItems() const; + const Definition *findInnerCompound(const char *name) const; + Definition *getOuterScope() const; + std::vector<const MemberDef *> getReferencesMembers() const; + std::vector<const MemberDef *> getReferencedByMembers() const; + bool hasSections() const; + bool hasSources() const; + bool hasBriefDescription() const; + QCString id() const; + const SectionRefs &getSectionRefs() const; + void setName(const char *name); + void setId(const char *name); + void setDefFile(const QCString& df,int defLine,int defColumn); + void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE); + void setBriefDescription(const char *b,const char *briefFile,int briefLine); + void setInbodyDocumentation(const char *d,const char *docFile,int docLine); + void setReference(const char *r); + void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList); + void setBodySegment(int defLine,int bls,int ble); + void setBodyDef(FileDef *fd); + void addSourceReferencedBy(const MemberDef *d); + void addSourceReferences(const MemberDef *d); + void setRefItems(const RefItemVector &sli); + void mergeRefItems(Definition *d); + void mergeReferences(const Definition *other); + void mergeReferencedBy(const Definition *other); + void addInnerCompound(const Definition *d); + void setOuterScope(Definition *d); + void setHidden(bool b); + void setArtificial(bool b); + void setLanguage(SrcLangExt lang); + void writeSourceDef(OutputList &ol,const char *scopeName) const; + void writeInlineCode(OutputList &ol,const char *scopeName) const; + void writeSourceRefs(OutputList &ol,const char *scopeName) const; + void writeSourceReffedBy(OutputList &ol,const char *scopeName) const; + void makePartOfGroup(GroupDef *gd); + void writeNavigationPath(OutputList &ol) const; + QCString navigationPathAsString() const; + void writeQuickMemberLinks(OutputList &,const MemberDef *) const; + void writeSummaryLinks(OutputList &) const; + QCString pathFragment() const; + void writeDocAnchorsToTagFile(FTextStream &) const; + void setLocalName(const QCString name); + void addSectionsToIndex(); + void writeToc(OutputList &ol, const LocalToc <) const; + void setCookie(Definition::Cookie *cookie) const; + Definition::Cookie *cookie() const; + void computeTooltip(); + void _setSymbolName(const QCString &name); + QCString _symbolName() const; DefinitionImpl(const DefinitionImpl &d); private: - virtual void _setSymbolName(const QCString &name); - virtual QCString _symbolName() const ; int _getXRefListId(const char *listName) const; - void _writeSourceRefList(OutputList &ol,const char *scopeName, - const QCString &text,MemberSDict *members,bool) const; + void _writeSourceRefList(OutputList &ol,const char *scopeName,const QCString &text, + const std::unordered_map<std::string,const MemberDef *> &members,bool) const; void _setBriefDescription(const char *b,const char *briefFile,int briefLine); void _setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace,bool atTop); void _setInbodyDocumentation(const char *d,const char *docFile,int docLine); @@ -135,156 +138,308 @@ class DefinitionImpl : virtual public Definition IMPL *m_impl; // internal structure holding all private data }; -class DefinitionAliasImpl : virtual public Definition +template<class Base> +class DefinitionMixin : public Base { public: - DefinitionAliasImpl(const Definition *scope,const Definition *alias); + /*! Create a new definition */ + DefinitionMixin( + const char *defFileName,int defLine,int defColumn, + const char *name,const char *b=0,const char *d=0, + bool isSymbol=TRUE) : m_impl(this,defFileName,defLine,defColumn,name,b,d,isSymbol) {} + virtual ~DefinitionMixin() {} + + virtual bool isAlias() const { return FALSE; } + + //======== Definition + virtual QCString name() const { return m_impl.name(); } + virtual bool isAnonymous() const { return m_impl.isAnonymous(); } + virtual QCString localName() const { return m_impl.localName(); } + virtual QCString qualifiedName() const { return m_impl.qualifiedName(); } + virtual QCString symbolName() const { return m_impl.symbolName(); } + virtual QCString getSourceFileBase() const { return m_impl.getSourceFileBase(); } + virtual QCString getSourceAnchor() const { return m_impl.getSourceAnchor(); } + virtual QCString documentation() const { return m_impl.documentation(); } + virtual int docLine() const { return m_impl.docLine(); } + virtual QCString docFile() const { return m_impl.docFile(); } + virtual QCString briefDescription(bool abbreviate=FALSE) const { return m_impl.briefDescription(abbreviate); } + virtual QCString briefDescriptionAsTooltip() const { return m_impl.briefDescriptionAsTooltip(); } + virtual int briefLine() const { return m_impl.briefLine(); } + virtual QCString inbodyDocumentation() const { return m_impl.inbodyDocumentation(); } + virtual QCString inbodyFile() const { return m_impl.inbodyFile(); } + virtual int inbodyLine() const { return m_impl.inbodyLine(); } + virtual QCString briefFile() const { return m_impl.briefFile(); } + virtual QCString getDefFileName() const { return m_impl.getDefFileName(); } + virtual QCString getDefFileExtension() const { return m_impl.getDefFileExtension(); } + virtual int getDefLine() const { return m_impl.getDefLine(); } + virtual int getDefColumn() const { return m_impl.getDefColumn(); } + virtual bool hasDocumentation() const { return m_impl.hasDocumentation(); } + virtual bool hasUserDocumentation() const { return m_impl.hasUserDocumentation(); } + virtual bool isVisibleInProject() const { return m_impl.isVisibleInProject(); } + virtual bool isVisible() const { return m_impl.isVisible(); } + virtual bool isHidden() const { return m_impl.isHidden(); } + virtual bool isArtificial() const { return m_impl.isArtificial(); } + virtual QCString getReference() const { return m_impl.getReference(); } + virtual bool isReference() const { return m_impl.isReference(); } + virtual QCString externalReference(const QCString &relPath) const { return m_impl.externalReference(relPath); } + virtual int getStartDefLine() const { return m_impl.getStartDefLine(); } + virtual int getStartBodyLine() const { return m_impl.getStartBodyLine(); } + virtual int getEndBodyLine() const { return m_impl.getEndBodyLine(); } + virtual FileDef *getBodyDef() const { return m_impl.getBodyDef(); } + virtual SrcLangExt getLanguage() const { return m_impl.getLanguage(); } + virtual GroupList *partOfGroups() const { return m_impl.partOfGroups(); } + virtual bool isLinkableViaGroup() const { return m_impl.isLinkableViaGroup(); } + virtual const RefItemVector &xrefListItems() const { return m_impl.xrefListItems(); } + virtual const Definition *findInnerCompound(const char *name) const { return m_impl.findInnerCompound(name); } + virtual Definition *getOuterScope() const { return m_impl.getOuterScope(); } + virtual std::vector<const MemberDef *> getReferencesMembers() const { return m_impl.getReferencesMembers(); } + virtual std::vector<const MemberDef *> getReferencedByMembers() const { return m_impl.getReferencedByMembers(); } + virtual bool hasSections() const { return m_impl.hasSections(); } + virtual bool hasSources() const { return m_impl.hasSources(); } + virtual bool hasBriefDescription() const { return m_impl.hasBriefDescription(); } + virtual QCString id() const { return m_impl.id(); } + virtual const SectionRefs &getSectionRefs() const { return m_impl.getSectionRefs(); } + + //======== DefinitionMutable + virtual void setName(const char *name) { m_impl.setName(name); } + virtual void setId(const char *name) { m_impl.setId(name); } + virtual void setDefFile(const QCString& df,int defLine,int defColumn) + { m_impl.setDefFile(df,defLine,defColumn); } + virtual void setDocumentation(const char *doc,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) + { m_impl.setDocumentation(doc,docFile,docLine,stripWhiteSpace); } + virtual void setBriefDescription(const char *brief,const char *briefFile,int briefLine) + { m_impl.setBriefDescription(brief,briefFile,briefLine); } + virtual void setInbodyDocumentation(const char *doc,const char *docFile,int docLine) + { m_impl.setInbodyDocumentation(doc,docFile,docLine); } + virtual void setReference(const char *r) + { m_impl.setReference(r); } + virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList) + { m_impl.addSectionsToDefinition(anchorList); } + virtual void setBodySegment(int defLine,int bls,int ble) + { m_impl.setBodySegment(defLine,bls,ble); } + virtual void setBodyDef(FileDef *fd) + { m_impl.setBodyDef(fd); } + virtual void addSourceReferencedBy(const MemberDef *md) + { m_impl.addSourceReferencedBy(md); } + virtual void addSourceReferences(const MemberDef *md) + { m_impl.addSourceReferences(md); } + virtual void setRefItems(const RefItemVector &sli) + { m_impl.setRefItems(sli); } + virtual void mergeRefItems(Definition *def) + { m_impl.mergeRefItems(def); } + virtual void mergeReferences(const Definition *other) + { m_impl.mergeReferences(other); } + virtual void mergeReferencedBy(const Definition *other) + { m_impl.mergeReferencedBy(other); } + virtual void addInnerCompound(const Definition *def) + { m_impl.addInnerCompound(def); } + virtual void setOuterScope(Definition *def) + { m_impl.setOuterScope(def); } + virtual void setHidden(bool b) + { m_impl.setHidden(b); } + virtual void setArtificial(bool b) + { m_impl.setArtificial(b); } + virtual void setLanguage(SrcLangExt lang) + { m_impl.setLanguage(lang); } + virtual void writeSourceDef(OutputList &ol,const char *scopeName) const + { m_impl.writeSourceDef(ol,scopeName); } + virtual void writeInlineCode(OutputList &ol,const char *scopeName) const + { m_impl.writeInlineCode(ol,scopeName); } + virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const + { m_impl.writeSourceRefs(ol,scopeName); } + virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const + { m_impl.writeSourceReffedBy(ol,scopeName); } + virtual void makePartOfGroup(GroupDef *gd) + { m_impl.makePartOfGroup(gd); } + virtual void writeNavigationPath(OutputList &ol) const + { m_impl.writeNavigationPath(ol); } + virtual QCString navigationPathAsString() const + { return m_impl.navigationPathAsString(); } + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const + { m_impl.writeQuickMemberLinks(ol,md); } + virtual void writeSummaryLinks(OutputList &ol) const + { m_impl.writeSummaryLinks(ol); } + virtual QCString pathFragment() const + { return m_impl.pathFragment(); } + virtual void writeDocAnchorsToTagFile(FTextStream &fs) const + { m_impl.writeDocAnchorsToTagFile(fs); } + virtual void setLocalName(const QCString name) + { m_impl.setLocalName(name); } + virtual void addSectionsToIndex() + { m_impl.addSectionsToIndex(); } + virtual void writeToc(OutputList &ol, const LocalToc <) const + { m_impl.writeToc(ol,lt); } + virtual void setCookie(Definition::Cookie *cookie) const + { m_impl.setCookie(cookie); } + virtual Definition::Cookie *cookie() const + { return m_impl.cookie(); } + virtual void computeTooltip() + { m_impl.computeTooltip(); } + virtual void _setSymbolName(const QCString &name) + { m_impl._setSymbolName(name); } + virtual QCString _symbolName() const + { return m_impl._symbolName(); } + + protected: + + DefinitionMixin(const DefinitionMixin &def) = default; + + private: + virtual Definition *toDefinition_() { return this; } + virtual DefinitionMutable *toDefinitionMutable_() { return this; } + virtual const DefinitionImpl *toDefinitionImpl_() const { return &m_impl; } + + DefinitionImpl m_impl; +}; + +class DefinitionAliasImpl +{ + public: + DefinitionAliasImpl(Definition *def,const Definition *scope,const Definition *alias); virtual ~DefinitionAliasImpl(); + void init(); + void deinit(); + QCString name() const; + QCString qualifiedName() const; + private: + Definition *m_def; + const Definition *m_scope; + QCString m_symbolName; + QCString m_qualifiedName; +}; + +template<class Base> +class DefinitionAliasMixin : public Base +{ + public: + DefinitionAliasMixin(const Definition *scope,const Definition *alias) + : m_impl(this,scope,alias), m_scope(scope), m_alias(alias), m_cookie(0) {} + + void init() { m_impl.init(); } + void deinit() { m_impl.deinit(); } + + virtual ~DefinitionAliasMixin() = default; virtual bool isAlias() const { return TRUE; } - virtual const QCString &name() const - { return m_def->name(); } + + //======== Definition + virtual QCString name() const + { return m_impl.name(); } virtual bool isAnonymous() const - { return m_def->isAnonymous(); } + { return m_alias->isAnonymous(); } virtual QCString localName() const - { return m_def->localName(); } + { return m_alias->localName(); } virtual QCString qualifiedName() const - { return m_def->qualifiedName(); } + { return m_impl.qualifiedName(); } virtual QCString symbolName() const - { return m_def->symbolName(); } + { return m_alias->symbolName(); } virtual QCString getSourceFileBase() const - { return m_def->getSourceFileBase(); } + { return m_alias->getSourceFileBase(); } virtual QCString getSourceAnchor() const - { return m_def->getSourceAnchor(); } + { return m_alias->getSourceAnchor(); } virtual QCString documentation() const - { return m_def->documentation(); } + { return m_alias->documentation(); } virtual int docLine() const - { return m_def->docLine(); } + { return m_alias->docLine(); } virtual QCString docFile() const - { return m_def->docFile(); } + { return m_alias->docFile(); } virtual QCString briefDescription(bool abbreviate=FALSE) const - { return m_def->briefDescription(abbreviate); } + { return m_alias->briefDescription(abbreviate); } virtual QCString briefDescriptionAsTooltip() const - { return m_def->briefDescriptionAsTooltip(); } + { return m_alias->briefDescriptionAsTooltip(); } virtual int briefLine() const - { return m_def->briefLine(); } + { return m_alias->briefLine(); } virtual QCString inbodyDocumentation() const - { return m_def->inbodyDocumentation(); } + { return m_alias->inbodyDocumentation(); } virtual QCString inbodyFile() const - { return m_def->inbodyFile(); } + { return m_alias->inbodyFile(); } virtual int inbodyLine() const - { return m_def->inbodyLine(); } + { return m_alias->inbodyLine(); } virtual QCString briefFile() const - { return m_def->briefFile(); } + { return m_alias->briefFile(); } virtual QCString getDefFileName() const - { return m_def->getDefFileName(); } + { return m_alias->getDefFileName(); } virtual QCString getDefFileExtension() const - { return m_def->getDefFileExtension(); } + { return m_alias->getDefFileExtension(); } virtual int getDefLine() const - { return m_def->getDefLine(); } + { return m_alias->getDefLine(); } virtual int getDefColumn() const - { return m_def->getDefColumn(); } + { return m_alias->getDefColumn(); } virtual bool hasDocumentation() const - { return m_def->hasDocumentation(); } + { return m_alias->hasDocumentation(); } virtual bool hasUserDocumentation() const - { return m_def->hasUserDocumentation(); } + { return m_alias->hasUserDocumentation(); } virtual bool isVisibleInProject() const - { return m_def->isVisibleInProject(); } + { return m_alias->isVisibleInProject(); } virtual bool isVisible() const - { return m_def->isVisible(); } + { return m_alias->isVisible(); } virtual bool isHidden() const - { return m_def->isHidden(); } + { return m_alias->isHidden(); } virtual bool isArtificial() const - { return m_def->isArtificial(); } + { return m_alias->isArtificial(); } virtual QCString getReference() const - { return m_def->getReference(); } + { return m_alias->getReference(); } virtual bool isReference() const - { return m_def->isReference(); } + { return m_alias->isReference(); } virtual QCString externalReference(const QCString &relPath) const - { return m_def->externalReference(relPath); } + { return m_alias->externalReference(relPath); } virtual int getStartDefLine() const - { return m_def->getStartDefLine(); } + { return m_alias->getStartDefLine(); } virtual int getStartBodyLine() const - { return m_def->getStartBodyLine(); } + { return m_alias->getStartBodyLine(); } virtual int getEndBodyLine() const - { return m_def->getEndBodyLine(); } + { return m_alias->getEndBodyLine(); } virtual FileDef *getBodyDef() const - { return m_def->getBodyDef(); } + { return m_alias->getBodyDef(); } virtual SrcLangExt getLanguage() const - { return m_def->getLanguage(); } + { return m_alias->getLanguage(); } virtual GroupList *partOfGroups() const - { return m_def->partOfGroups(); } + { return m_alias->partOfGroups(); } virtual bool isLinkableViaGroup() const - { return m_def->isLinkableViaGroup(); } + { return m_alias->isLinkableViaGroup(); } virtual const RefItemVector &xrefListItems() const - { return m_def->xrefListItems(); } - virtual Definition *findInnerCompound(const char *name) const - { return m_def->findInnerCompound(name); } + { return m_alias->xrefListItems(); } + virtual const Definition *findInnerCompound(const char *name) const + { return m_alias->findInnerCompound(name); } virtual Definition *getOuterScope() const { return const_cast<Definition*>(m_scope); } - virtual MemberSDict *getReferencesMembers() const - { return m_def->getReferencesMembers(); } - virtual MemberSDict *getReferencedByMembers() const - { return m_def->getReferencedByMembers(); } + virtual std::vector<const MemberDef *> getReferencesMembers() const + { return m_alias->getReferencesMembers(); } + virtual std::vector<const MemberDef *> getReferencedByMembers() const + { return m_alias->getReferencedByMembers(); } virtual bool hasSections() const - { return m_def->hasSections(); } + { return m_alias->hasSections(); } virtual bool hasSources() const - { return m_def->hasSources(); } + { return m_alias->hasSources(); } virtual bool hasBriefDescription() const - { return m_def->hasBriefDescription(); } + { return m_alias->hasBriefDescription(); } virtual QCString id() const - { return m_def->id(); } + { return m_alias->id(); } virtual const SectionRefs &getSectionRefs() const - { return m_def->getSectionRefs(); } + { return m_alias->getSectionRefs(); } virtual QCString navigationPathAsString() const - { return m_def->navigationPathAsString(); } + { return m_alias->navigationPathAsString(); } virtual QCString pathFragment() const - { return m_def->pathFragment(); } - 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) {} - virtual void addSectionsToIndex() {} - 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; } + { return m_alias->pathFragment(); } + protected: - const Definition *getAlias() const { return m_def; } + const Definition *getAlias() const { return m_alias; } const Definition *getScope() const { return m_scope; } private: + virtual Definition *toDefinition_() { return this; } + virtual DefinitionMutable *toDefinitionMutable_() { return 0; } + virtual const DefinitionImpl *toDefinitionImpl_() const { return 0; } + + virtual void setCookie(Definition::Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } + virtual Definition::Cookie *cookie() const { return m_cookie; } virtual void _setSymbolName(const QCString &name) { m_symbolName = name; } virtual QCString _symbolName() const { return m_symbolName; } + DefinitionAliasImpl m_impl; const Definition *m_scope; - const Definition *m_def; - mutable Cookie *m_cookie; + const Definition *m_alias; + mutable Definition::Cookie *m_cookie; QCString m_symbolName; }; - #endif diff --git a/src/diagram.cpp b/src/diagram.cpp index d0b7a08..64ea491 100644 --- a/src/diagram.cpp +++ b/src/diagram.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. * @@ -36,86 +33,80 @@ //----------------------------------------------------------------------------- -class DiagramItemList; +class TreeDiagram; +class DiagramItem; +using DiagramItemList = std::vector<DiagramItem*>; /** Class representing a single node in the built-in class diagram */ -class DiagramItem +class DiagramItem { public: 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+=(uint)dx; y+=(uint)dy; } - uint xPos() const { return x; } - uint yPos() const { return y; } + DiagramItem *parentItem() { return m_parent; } + DiagramItemList getChildren() { return m_children; } + void move(int dx,int dy) { m_x+=(uint)dx; m_y+=(uint)dy; } + uint xPos() const { return m_x; } + uint yPos() const { return m_y; } uint avgChildPos() const; uint numChildren() const; void addChild(DiagramItem *di); - uint number() const { return num; } - Protection protection() const { return prot; } - Specifier virtualness() const { return virt; } - void putInList() { inList=TRUE; } - bool isInList() const { return inList; } - const ClassDef *getClassDef() const { return classDef; } + uint number() const { return m_num; } + Protection protection() const { return m_prot; } + Specifier virtualness() const { return m_virt; } + void putInList() { m_inList=TRUE; } + bool isInList() const { return m_inList; } + const ClassDef *getClassDef() const { return m_classDef; } private: - DiagramItemList *children; - DiagramItem *parent; - uint x,y; - uint num; - Protection prot; - Specifier virt; - QCString templSpec; - bool inList; - const ClassDef *classDef; -}; - -/** Class representing a list of DiagramItem object. */ -class DiagramItemList : public QList<DiagramItem> -{ - public: - DiagramItemList() : QList<DiagramItem>() {} - ~DiagramItemList() {} + DiagramItemList m_children; + DiagramItem *m_parent; + uint m_x = 0; + uint m_y = 0; + uint m_num; + Protection m_prot; + Specifier m_virt; + QCString m_templSpec; + bool m_inList = false; + const ClassDef *m_classDef; }; /** Class representing a row in the built-in class diagram */ -class DiagramRow : public QList<DiagramItem> +class DiagramRow { public: - DiagramRow(TreeDiagram *d,uint l) : QList<DiagramItem>() - { - diagram=d; - level=l; - setAutoDelete(TRUE); - } + using Ptr = std::unique_ptr<DiagramItem>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; + using reverse_iterator = typename Vec::reverse_iterator; + DiagramRow(TreeDiagram *d,uint l) : m_diagram(d), m_level(l) {} void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts); - uint number() { return level; } + uint number() { return m_level; } + + DiagramItem *item(int index) { return m_items.at(index).get(); } + uint numItems() const { return static_cast<uint>(m_items.size()); } + iterator begin() { return m_items.begin(); } + iterator end() { return m_items.end(); } + reverse_iterator rbegin() { return m_items.rbegin(); } + reverse_iterator rend() { return m_items.rend(); } private: - TreeDiagram *diagram; - uint level; -}; - -/** Class representing iterator for the rows in the built-in class diagram. */ -class DiagramRowIterator : public QListIterator<DiagramRow> -{ - public: - DiagramRowIterator(const QList<DiagramRow> &d) - : QListIterator<DiagramRow>(d) {} + TreeDiagram *m_diagram; + uint m_level; + Vec m_items; }; /** Class representing the tree layout for the built-in class diagram. */ -class TreeDiagram : public QList<DiagramRow> +class TreeDiagram { public: + using Ptr = std::unique_ptr<DiagramRow>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; TreeDiagram(const ClassDef *root,bool doBases); - ~TreeDiagram(); void computeLayout(); uint computeRows(); - //uint computeCols(); void moveChildren(DiagramItem *root,int dx); void computeExtremes(uint *labelWidth,uint *xpos); void drawBoxes(FTextStream &t,Image *image, @@ -128,10 +119,17 @@ class TreeDiagram : public QList<DiagramRow> bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellheight); + DiagramRow *row(int index) { return m_rows.at(index).get(); } + uint numRows() const { return static_cast<uint>(m_rows.size()); } + DiagramRow *addRow(uint l) + { m_rows.push_back(std::make_unique<DiagramRow>(this,l)); return m_rows.back().get(); } + iterator begin() { return m_rows.begin(); } + iterator end() { return m_rows.end(); } private: bool layoutTree(DiagramItem *root,uint row); TreeDiagram &operator=(const TreeDiagram &); TreeDiagram(const TreeDiagram &); + Vec m_rows; }; @@ -147,18 +145,6 @@ const uint labelVertSpacing = 32; // vertical distance between labels const uint labelHorMargin = 6; // horiz. spacing between label and box const uint fontHeight = 12; // height of a character -//static QCString escapeLatex(const char *s) -//{ -// QCString result; -// char c; -// while ((c=*s++)) -// { -// if (c=='_') result+="\\_"; -// else result+=c; -// } -// return result; -//} - static uint protToMask(Protection p) { switch(p) @@ -207,18 +193,21 @@ static uint virtToMask(Specifier p) } // pre: dil is not empty -static Protection getMinProtectionLevel(DiagramItemList *dil) +static Protection getMinProtectionLevel(const DiagramItemList &dil) { - QListIterator<DiagramItem> it(*dil); - DiagramItem *di=it.current(); - Protection result=di->protection(); - for (++it;(di=it.current());++it) + auto it = dil.begin(); + Protection result = Private; + if (it!=dil.end()) { - Protection p=di->protection(); - if (p!=result) + result=(*it)->protection(); + for (++it;it!=dil.end();++it) { - if (result==Protected && p==Public) result=p; - else if (result==Private) result=p; + Protection p=(*it)->protection(); + if (p!=result) + { + if (result==Protected && p==Public) result=p; + else if (result==Private) result=p; + } } } return result; @@ -261,7 +250,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { QCString ref=cd->getReference(); t << "<area "; - if (!ref.isEmpty()) + if (!ref.isEmpty()) { t << externalLinkTarget(true); } @@ -278,7 +267,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { t << "title=\"" << convertToHtml(tooltip) << "\" "; } - t << "alt=\"" << convertToXML(cd->displayName()); + t << "alt=\"" << convertToXML(cd->displayName()); t << "\" shape=\"rect\" coords=\"" << x << "," << y << ","; t << (x+w) << "," << (y+h) << "\"/>" << endl; } @@ -286,41 +275,28 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, //----------------------------------------------------------------------------- DiagramItem::DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, - Protection pr,Specifier vi,const char *ts) -{ - parent=p; - x=y=0; - num=number; - children = new DiagramItemList; - prot=pr; - virt=vi; - inList=FALSE; - classDef=cd; - templSpec=ts; -} - -DiagramItem::~DiagramItem() + Protection pr,Specifier vi,const char *ts) + : m_parent(p), m_num(number), m_prot(pr), m_virt(vi), m_templSpec(ts), m_classDef(cd) { - delete children; } QCString DiagramItem::label() const { QCString result; - if (!templSpec.isEmpty()) + if (!m_templSpec.isEmpty()) { // we use classDef->name() here and not displayName() in order // to get the name used in the inheritance relation. - QCString n = classDef->name(); + QCString n = m_classDef->name(); if (/*n.right(2)=="-g" ||*/ n.right(2)=="-p") { n = n.left(n.length()-2); } - result=insertTemplateSpecifierInScope(n,templSpec); + result=insertTemplateSpecifierInScope(n,m_templSpec); } else { - result=classDef->displayName(); + result=m_classDef->displayName(); } if (Config_getBool(HIDE_SCOPE_NAMES)) result=stripScope(result); return result; @@ -328,104 +304,88 @@ QCString DiagramItem::label() const QCString DiagramItem::fileName() const { - return classDef->getOutputFileBase(); + return m_classDef->getOutputFileBase(); } uint DiagramItem::avgChildPos() const { DiagramItem *di; - uint c=children->count(); + size_t c=m_children.size(); if (c==0) // no children -> don't move return xPos(); - if ((di=children->getFirst())->isInList()) // children should be in a list + if ((di=m_children.front())->isInList()) // children should be in a list return di->xPos(); if (c&1) // odd number of children -> get pos of middle child - return children->at(c/2)->xPos(); + return m_children.at(c/2)->xPos(); else // even number of children -> get middle of most middle children - return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2; + return (m_children.at(c/2-1)->xPos()+m_children.at(c/2)->xPos())/2; } uint DiagramItem::numChildren() const { - return children->count(); + return static_cast<uint>(m_children.size()); } void DiagramItem::addChild(DiagramItem *di) { - children->append(di); + m_children.push_back(di); } +//--------------------------------------------------------------------------- + void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts) { - //if (cd->visited) return; // the visit check does not work in case of - // multiple inheritance of the same class! - DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(), - cd,prot,virt,ts); - //cd->visited=TRUE; - if (parent) parent->addChild(di); - di->move((int)(count()*gridWidth),(int)(level*gridHeight)); - append(di); - BaseClassList *bcl=doBases ? cd->baseClasses() : cd->subClasses(); + auto di = std::make_unique<DiagramItem>(parent, m_diagram->row(m_level)->numItems(), + cd,prot,virt,ts); + DiagramItem *di_ptr = di.get(); + if (parent) parent->addChild(di_ptr); + di->move((int)(m_items.size()*gridWidth),(int)(m_level*gridHeight)); + m_items.push_back(std::move(di)); int count=0; - if (bcl) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { /* there are base/sub classes */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) - { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++; - } + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy()) count++; } if (count>0 && (prot!=Private || !doBases)) { DiagramRow *row=0; - if (diagram->count()<=level+1) /* add new row */ + if (m_diagram->numRows()<=m_level+1) /* add new row */ { - row = new DiagramRow(diagram,level+1); - diagram->append(row); + row=m_diagram->addRow(m_level+1); } else /* get next row */ { - row=diagram->at(level+1); + row=m_diagram->row(m_level+1); } - /* insert base classes in the next row */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy()) { - row->insertClass(di,ccd,doBases,bcd->prot, - doBases?bcd->virt:Normal, - doBases?bcd->templSpecifiers.data():""); + row->insertClass(di_ptr,ccd,doBases,bcd.prot, + doBases?bcd.virt:Normal, + doBases?bcd.templSpecifiers.data():""); } } } } -TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) -{ - setAutoDelete(TRUE); - DiagramRow *row=new DiagramRow(this,0); - append(row); - row->insertClass(0,root,doBases,Public,Normal,0); -} +//--------------------------------------------------------------------------- -TreeDiagram::~TreeDiagram() +TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) { + auto row = std::make_unique<DiagramRow>(this,0); + DiagramRow *row_ptr = row.get(); + m_rows.push_back(std::move(row)); + row_ptr->insertClass(0,root,doBases,Public,Normal,0); } - void TreeDiagram::moveChildren(DiagramItem *root,int dx) { - DiagramItemList *dil=root->getChildren(); - QListIterator<DiagramItem> it(*dil); - DiagramItem *di; - for (;(di=it.current());++it) + for (const auto &di : root->getChildren()) { di->move(dx,0); moveChildren(di,dx); @@ -437,37 +397,36 @@ bool TreeDiagram::layoutTree(DiagramItem *root,uint r) bool moved=FALSE; //printf("layoutTree(%s,%d)\n",root->label().data(),r); - DiagramItemList *dil=root->getChildren(); - if (dil->count()>0) + if (root->numChildren()>0) { + auto children = root->getChildren(); uint k; uint pPos=root->xPos(); uint cPos=root->avgChildPos(); if (pPos>cPos) // move children { - DiagramRow *row=at(r+1); + const auto &row=m_rows.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((int)(pPos-cPos),0); + for (k=children.front()->number();k<row->numItems();k++) + row->item(k)->move((int)(pPos-cPos),0); moved=TRUE; } else if (pPos<cPos) // move parent { - DiagramRow *row=at(r); + const auto &row=m_rows.at(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((int)(cPos-pPos),0); + for (k=root->number();k<row->numItems();k++) + row->item(k)->move((int)(cPos-pPos),0); moved=TRUE; } // recurse to children - QListIterator<DiagramItem> it(*dil); - DiagramItem *di; - for (;(di=it.current()) && !moved && !di->isInList();++it) + auto it = children.begin(); + for (;it!=children.end() && !moved && !(*it)->isInList();++it) { - moved = layoutTree(di,r+1); + moved = layoutTree(*it,r+1); } } return moved; @@ -475,18 +434,16 @@ bool TreeDiagram::layoutTree(DiagramItem *root,uint r) void TreeDiagram::computeLayout() { - QListIterator<DiagramRow> it(*this); - DiagramRow *row; - for (;(row=it.current()) && row->count()<maxTreeWidth;++it) {} - if (row) + auto it = m_rows.begin(); + while (it!=m_rows.end() && (*it)->numItems()<maxTreeWidth) ++it; + if (it!=m_rows.end()) { + const auto &row = *it; //printf("computeLayout() list row at %d\n",row->number()); - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; DiagramItem *opi=0; int delta=0; bool first=TRUE; - for (;(di=rit.current());++rit) + for (const auto &di : *row) { DiagramItem *pi=di->parentItem(); if (pi==opi && !first) { delta-=gridWidth; } @@ -499,21 +456,24 @@ void TreeDiagram::computeLayout() } // re-organize the diagram items - DiagramItem *root=getFirst()->getFirst(); + DiagramItem *root=m_rows.front()->item(0); while (layoutTree(root,0)) { } // move first items of the lists - if (row) + if (it!=m_rows.end()) { - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; - while ((di=rit.current())) + const auto &row = *it; + auto rit = row->begin(); + while (rit!=row->end()) { - DiagramItem *pi=di->parentItem(); - if (pi->getChildren()->count()>1) + DiagramItem *pi=(*rit)->parentItem(); + if (pi->numChildren()>1) { - di->move(gridWidth,0); - while (di && di->parentItem()==pi) { ++rit; di=rit.current(); } + (*rit)->move(gridWidth,0); + while (rit!=row->end() && (*rit)->parentItem()==pi) + { + ++rit; + } } else { @@ -527,23 +487,23 @@ uint TreeDiagram::computeRows() { //printf("TreeDiagram::computeRows()=%d\n",count()); uint count=0; - QListIterator<DiagramRow> it(*this); - DiagramRow *row; - for (;(row=it.current()) && !row->getFirst()->isInList();++it) + auto it = m_rows.begin(); + while (it!=m_rows.end() && !(*it)->item(0)->isInList()) { - count++; + ++it; + ++count; } + //printf("count=%d row=%p\n",count,row); - if (row) + if (it!=m_rows.end()) { + const auto &row = *it; uint maxListLen=0; uint curListLen=0; DiagramItem *opi=0; - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; - for (;(di=rit.current());++rit) + for (const auto &di : *row) // for each item in a row { - if (di->parentItem()!=opi) curListLen=1; else curListLen++; + if (di->parentItem()!=opi) curListLen=1; else curListLen++; if (curListLen>maxListLen) maxListLen=curListLen; opi=di->parentItem(); } @@ -556,48 +516,80 @@ uint TreeDiagram::computeRows() void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos) { uint ml=0,mx=0; - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; - bool done=FALSE; - for (;(dr=it.current()) && !done;++it) + for (const auto &dr : m_rows) // for each row { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + bool done=FALSE; + for (const auto &di : *dr) // for each item in a row { if (di->isInList()) done=TRUE; if (maxXPos) mx=QMAX(mx,(uint)di->xPos()); if (maxLabelLen) ml=QMAX(ml,Image::stringLength(di->label())); } + if (done) break; } if (maxLabelLen) *maxLabelLen=ml; if (maxXPos) *maxXPos=mx; } -void TreeDiagram::drawBoxes(FTextStream &t,Image *image, +//! helper class representing an iterator that can iterate forwards or backwards +template<class C,class I> +class DualDirIterator +{ + public: + DualDirIterator(C &container,bool fwd) + : m_container(container), m_forward(fwd) + { + if (fwd) m_it = container.begin(); + else m_rit = container.rbegin(); + } + void operator++() + { + if (m_forward) ++m_it++; else ++m_rit; + } + I &operator*() + { + return m_forward ? *m_it : *m_rit; + } + + bool atEnd() + { + if (m_forward) + return m_it==m_container.end(); + else + return m_rit==m_container.rend(); + } + + private: + C &m_container; + bool m_forward; + typename C::iterator m_it; + typename C::reverse_iterator m_rit; +}; + +void TreeDiagram::drawBoxes(FTextStream &t,Image *image, bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellHeight, QCString relPath, bool generateMap) { - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; - if (!doBase) ++it; - bool done=FALSE; + auto it = m_rows.begin(); + if (it!=m_rows.end() && !doBase) ++it; bool firstRow = doBase; - for (;(dr=it.current()) && !done;++it) + bool done=FALSE; + for (;it!=m_rows.end() && !done;++it) // for each row { + const auto &dr = *it; uint x=0,y=0; float xf=0.0f,yf=0.0f; - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di = rit.current(); - if (di->isInList()) // put boxes in a list + DiagramItem *firstDi = dr->item(0); + if (firstDi->isInList()) // put boxes in a list { DiagramItem *opi=0; - if (doBase) rit.toLast(); else rit.toFirst(); - while ((di=rit.current())) + DualDirIterator<DiagramRow,const std::unique_ptr<DiagramItem>&> dit(*dr,!doBase); + while (!dit.atEnd()) { + DiagramItem *di = (*dit).get(); if (di->parentItem()==opi) { if (bitmap) @@ -643,27 +635,27 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, } } opi=di->parentItem(); - + if (bitmap) { bool hasDocs=di->getClassDef()->isLinkable(); writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow, - hasDocs,di->getChildren()->count()>0); - if (!firstRow && generateMap) + hasDocs,di->numChildren()>0); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else { - writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0); + writeVectorBox(t,di,xf,yf,di->numChildren()>0); } - - if (doBase) --rit; else ++rit; + + ++dit; } done=TRUE; } else // draw a tree of boxes { - for (rit.toFirst();(di=rit.current());++rit) + for (const auto &di : *dr) { if (bitmap) { @@ -681,8 +673,8 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; } bool hasDocs=di->getClassDef()->isLinkable(); - writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); - if (!firstRow && generateMap) + writeBitmapBox(di.get(),image,x,y,cellWidth,cellHeight,firstRow,hasDocs); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else @@ -696,7 +688,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, { yf = superRows-1-di->yPos()/(float)gridHeight; } - writeVectorBox(t,di,xf,yf); + writeVectorBox(t,di.get(),xf,yf); } } } @@ -709,22 +701,23 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, uint baseRows,uint superRows, uint cellWidth,uint cellHeight) { - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; bool done=FALSE; - for (;(dr=it.current()) && !done;++it) // for each row + auto it = m_rows.begin(); + for (;it!=m_rows.end() && !done;++it) // for each row { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di = rit.current(); - if (di->isInList()) // row consists of list connectors + const auto &dr = *it; + DiagramItem *rootDi = dr->item(0); + if (rootDi->isInList()) // row consists of list connectors { uint x=0,y=0,ys=0; float xf=0.0f,yf=0.0f,ysf=0.0f; - for (;(di=rit.current());++rit) + auto rit = dr->begin(); + while (rit!=dr->end()) { + DiagramItem *di=(*rit).get(); DiagramItem *pi=di->parentItem(); - DiagramItemList *dil=pi->getChildren(); - DiagramItem *last=dil->getLast(); + DiagramItemList dil=pi->getChildren(); + DiagramItem *last=dil.back(); if (di==last) // single child { if (bitmap) // draw pixels @@ -754,12 +747,12 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << (di->xPos()/(float)gridWidth) << " " + t << "1 " << (di->xPos()/(float)gridWidth) << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << (di->xPos()/(float)gridWidth) << " " + t << "0 " << (di->xPos()/(float)gridWidth) << " " << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } @@ -832,7 +825,8 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, yf -= 1.0f; } } - ++rit; di=rit.current(); + ++rit; + if (rit!=dr->end()) di = (*rit).get(); else di=0; } // add last horizontal line and a vertical connection line if (bitmap) @@ -878,15 +872,16 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } } } + if (rit!=dr->end()) ++rit; } done=TRUE; // the tree is drawn now } else // normal tree connector { - for (;(di=rit.current());++rit) + for (const auto &di : *dr) { uint x=0,y=0; - DiagramItemList *dil = di->getChildren(); + DiagramItemList dil = di->getChildren(); DiagramItem *parent = di->parentItem(); if (parent) // item has a parent -> connect to it { @@ -919,18 +914,18 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } } } - if (dil->count()>0) + if (!dil.empty()) { Protection p=getMinProtectionLevel(dil); uint mask=protToMask(p); @@ -959,19 +954,19 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " out\n"; } else { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << ((float)superRows-1.75f-di->yPos()/(float)gridHeight) << " out\n"; } } /* write input line */ - DiagramItem *first = dil->getFirst(); - DiagramItem *last = dil->getLast(); + DiagramItem *first = dil.front(); + DiagramItem *last = dil.back(); if (first!=last && !first->isInList()) /* connect with all base classes */ { if (bitmap) @@ -979,14 +974,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, uint xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; uint xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth - + cellWidth/2; + + cellWidth/2; if (doBase) // base classes { - image->drawHorzLine(y,xs,xe,col,mask); + image->drawHorzLine(y,xs,xe,col,mask); } else // super classes { - image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); + image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); } } else @@ -994,14 +989,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " - << (first->yPos()/(float)gridHeight+superRows-1) + << (first->yPos()/(float)gridHeight+superRows-1) << " conn\n"; } else { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " << ((float)superRows-first->yPos()/(float)gridHeight) << " conn\n"; @@ -1014,74 +1009,69 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } } +//----------------------------------------------------------------- -void clearVisitFlags() +struct ClassDiagram::Private { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) - { - cd->setVisited(FALSE); - } -} + Private(const ClassDef *root) : base(root,true), super(root,false) {} + TreeDiagram base; + TreeDiagram super; +}; + +//----------------------------------------------------------------- + -ClassDiagram::ClassDiagram(const ClassDef *root) +ClassDiagram::ClassDiagram(const ClassDef *root) : p(std::make_unique<Private>(root)) { - clearVisitFlags(); - base = new TreeDiagram(root,TRUE); - base->computeLayout(); - clearVisitFlags(); - super = new TreeDiagram(root,FALSE); - super->computeLayout(); - DiagramItem *baseItem = base->getFirst()->getFirst(); - DiagramItem *superItem = super->getFirst()->getFirst(); + p->base.computeLayout(); + p->super.computeLayout(); + DiagramItem *baseItem = p->base.row(0)->item(0); + DiagramItem *superItem = p->super.row(0)->item(0); uint xbase = baseItem->xPos(); uint xsuper = superItem->xPos(); if (xbase>xsuper) { superItem->move((int)(xbase-xsuper),0); - super->moveChildren(superItem,(int)(xbase-xsuper)); + p->super.moveChildren(superItem,(int)(xbase-xsuper)); } else if (xbase<xsuper) { baseItem->move((int)(xsuper-xbase),0); - base->moveChildren(baseItem,(int)(xsuper-xbase)); + p->base.moveChildren(baseItem,(int)(xsuper-xbase)); } } ClassDiagram::~ClassDiagram() { - delete base; - delete super; } void ClassDiagram::writeFigure(FTextStream &output,const char *path, const char *fileName) const { - uint baseRows=base->computeRows(); - uint superRows=super->computeRows(); + uint baseRows=p->base.computeRows(); + uint superRows=p->super.computeRows(); uint baseMaxX, baseMaxLabelWidth, superMaxX, superMaxLabelWidth; - base->computeExtremes(&baseMaxLabelWidth,&baseMaxX); - super->computeExtremes(&superMaxLabelWidth,&superMaxX); + p->base.computeExtremes(&baseMaxLabelWidth,&baseMaxX); + p->super.computeExtremes(&superMaxLabelWidth,&superMaxX); uint rows=baseRows+superRows-1; uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth; - + // Estimate the image aspect width and height in pixels. uint estHeight = rows*40; uint estWidth = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth)); //printf("Estimated size %d x %d\n",estWidth,estHeight); - + const float pageWidth = 14.0f; // estimated page width in cm. // Somewhat lower to deal with estimation - // errors. - + // errors. + // compute the image height in centimeters based on the estimates float realHeight = QMIN(rows,12); // real height in cm float realWidth = realHeight * estWidth/(float)estHeight; if (realWidth>pageWidth) // assume that the page width is about 15 cm { - realHeight*=pageWidth/realWidth; + realHeight*=pageWidth/realWidth; realWidth=pageWidth; } @@ -1089,11 +1079,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, output << "\\begin{figure}[H]\n" "\\begin{center}\n" "\\leavevmode\n"; - output << "\\includegraphics[height=" << realHeight << "cm]{" + output << "\\includegraphics[height=" << realHeight << "cm]{" << fileName << "}" << endl; output << "\\end{center}\n" "\\end{figure}\n"; - + //printf("writeFigure rows=%d cols=%d\n",rows,cols); QCString epsBaseName=(QCString)path+"/"+fileName; @@ -1105,11 +1095,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, term("Could not open file %s for writing\n",f1.name().data()); } FTextStream t(&f1); - + //printf("writeEPS() rows=%d cols=%d\n",rows,cols); - + // generate EPS header and postscript variables and procedures - + t << "%!PS-Adobe-2.0 EPSF-2.0\n"; t << "%%Title: ClassName\n"; t << "%%Creator: Doxygen\n"; @@ -1287,31 +1277,29 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, t << "1 boundaspect scale\n"; - bool done=FALSE; - QListIterator<DiagramRow> bit(*base); - DiagramRow *dr; - for (;(dr=bit.current()) && !done;++bit) + for (const auto &dr : p->base) { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + bool done=FALSE; + for (const auto &di : *dr) { done=di->isInList(); t << "(" << convertToPSString(di->label()) << ") cw\n"; } + if (done) break; } - QListIterator<DiagramRow> sit(*super); - ++sit; - done=FALSE; - for (;(dr=sit.current()) && !done;++sit) + + auto it = p->super.begin(); + if (it!=p->super.end()) ++it; + for (;it!=p->super.end();++it) { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + const auto &dr = *it; + bool done=FALSE; + for (const auto &di : *dr) { done=di->isInList(); t << "(" << convertToPSString(di->label()) << ") cw\n"; } + if (done) break; } t << "/boxwidth boxwidth marginwidth 2 mul add def\n" @@ -1322,14 +1310,14 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n" << " max def\n" << "boundx scalefactor div boundy scalefactor div scale\n"; - + t << "\n% ----- classes -----\n\n"; - base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); - super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); - + p->base.drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); + p->super.drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); + t << "\n% ----- relations -----\n\n"; - base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); - super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); + p->base.drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); + p->super.drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); f1.close(); if (Config_getBool(USE_PDFLATEX)) @@ -1351,17 +1339,17 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, void ClassDiagram::writeImage(FTextStream &t,const char *path, - const char *relPath,const char *fileName, + const char *relPath,const char *fileName, bool generateMap) const { - uint baseRows=base->computeRows(); - uint superRows=super->computeRows(); + uint baseRows=p->base.computeRows(); + uint superRows=p->super.computeRows(); uint rows=baseRows+superRows-1; uint lb,ls,xb,xs; - base->computeExtremes(&lb,&xb); - super->computeExtremes(&ls,&xs); - + p->base.computeExtremes(&lb,&xb); + p->super.computeExtremes(&ls,&xs); + uint cellWidth = QMAX(lb,ls)+labelHorMargin*2; uint maxXPos = QMAX(xb,xs); uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3 @@ -1372,10 +1360,10 @@ void ClassDiagram::writeImage(FTextStream &t,const char *path, Image image(imageWidth,imageHeight); - base->drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); - super->drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); - base->drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight); - super->drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight); + p->base.drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); + p->super.drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); + p->base.drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight); + p->super.drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight); #define IMAGE_EXT ".png" image.save((QCString)path+"/"+fileName+IMAGE_EXT); diff --git a/src/diagram.h b/src/diagram.h index 05af28e..d8e7612 100644 --- a/src/diagram.h +++ b/src/diagram.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. * @@ -19,10 +19,9 @@ #ifndef DIAGRAM_H #define DIAGRAM_H -#include <qglobal.h> +#include <memory> class ClassDef; -class TreeDiagram; class FTextStream; /** Class representing a built-in class diagram. */ @@ -36,8 +35,8 @@ class ClassDiagram void writeImage(FTextStream &t,const char *path,const char *relPath, const char *file,bool generateMap=TRUE) const; private: - TreeDiagram *base; - TreeDiagram *super; + struct Private; + std::unique_ptr<Private> p; }; #endif diff --git a/src/dirdef.cpp b/src/dirdef.cpp index b058f86..14d978e 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -19,7 +19,7 @@ //---------------------------------------------------------------------- -class DirDefImpl : public DefinitionImpl, public DirDef +class DirDefImpl : public DefinitionMixin<DirDef> { public: DirDefImpl(const char *path); @@ -93,7 +93,7 @@ DirDef *createDirDef(const char *path) static int g_dirCount=0; -DirDefImpl::DirDefImpl(const char *path) : DefinitionImpl(path,1,1,path) +DirDefImpl::DirDefImpl(const char *path) : DefinitionMixin(path,1,1,path) { bool fullPathNames = Config_getBool(FULL_PATH_NAMES); // get display name (stripping the paths mentioned in STRIP_FROM_PATH) @@ -1101,3 +1101,31 @@ bool compareDirDefs(const DirDef *item1, const DirDef *item2) return qstricmp(item1->shortName(),item2->shortName()) < 0; } +// --- Cast functions + +DirDef *toDirDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(DirDefImpl)) + { + return static_cast<DirDef*>(d); + } + else + { + return 0; + } +} + +const DirDef *toDirDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(DirDefImpl)) + { + return static_cast<const DirDef*>(d); + } + else + { + return 0; + } +} + diff --git a/src/dirdef.h b/src/dirdef.h index 468901d..1057049 100644 --- a/src/dirdef.h +++ b/src/dirdef.h @@ -24,7 +24,6 @@ #include <qcstring.h> class FileList; -class ClassSDict; class QStrList; class FileDef; class OutputList; @@ -39,7 +38,7 @@ typedef std::vector<DirDef*> DirList; bool compareDirDefs(const DirDef *item1, const DirDef *item2); /** A model of a directory symbol. */ -class DirDef : virtual public Definition +class DirDef : public DefinitionMutable, public Definition { public: virtual ~DirDef() {} @@ -79,6 +78,14 @@ class DirDef : virtual public Definition virtual void computeDependencies() = 0; }; +// --- Cast functions + +DirDef *toDirDef(Definition *d); +const DirDef *toDirDef(const Definition *d); + +// ------------------ + + /** Class representing a pair of FileDef objects */ class FilePair { diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index e5c9a6b..2d0521b 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -89,7 +89,7 @@ inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col) { case '\t': { - static int tabSize = Config_getInt(TAB_SIZE); + int tabSize = Config_getInt(TAB_SIZE); int spacesToNextTabStop = tabSize - (col%tabSize); col+=spacesToNextTabStop; while (spacesToNextTabStop--) t << " "; @@ -101,9 +101,21 @@ inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col) case '&': t << "&"; col++; break; case '\'': t << "'"; col++; break; case '"': t << """; col++; break; - case '\007': t << "^G"; col++; break; // bell - case '\014': t << "^L"; col++; break; // form feed - default: t << c; col++; break; + default: + { + uchar uc = static_cast<uchar>(c); + static const char *hex="0123456789ABCDEF"; + if (uc<32) + { + t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + t << c; + } + col++; + } + break; } } } @@ -140,7 +152,6 @@ DocbookCodeGenerator::DocbookCodeGenerator(FTextStream &t) DocbookCodeGenerator::DocbookCodeGenerator() { - m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); } DocbookCodeGenerator::~DocbookCodeGenerator() {} @@ -243,37 +254,41 @@ void DocbookCodeGenerator::finish() { endCodeLine(); } -void DocbookCodeGenerator::startCodeFragment() +void DocbookCodeGenerator::startCodeFragment(const char *) { - m_t << "<literallayout><computeroutput>" << endl; +DB_GEN_C + m_t << "<programlisting>"; } -void DocbookCodeGenerator::endCodeFragment() + +void DocbookCodeGenerator::endCodeFragment(const char *) { +DB_GEN_C //endCodeLine checks is there is still an open code line, if so closes it. endCodeLine(); - m_t << "</computeroutput></literallayout>" << endl; + m_t << "</programlisting>"; } -DocbookGenerator::DocbookGenerator() : OutputGenerator() +//------------------------------------------------------------------------------- + +DocbookGenerator::DocbookGenerator() : OutputGenerator(Config_getString(DOCBOOK_OUTPUT)) { DB_GEN_C - m_dir=Config_getString(DOCBOOK_OUTPUT); - //insideTabbing=FALSE; - //firstDescItem=TRUE; - //disableLinks=FALSE; - //m_indent=0; - //templateMemberItem = FALSE; - m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); - m_denseText = FALSE; - m_inGroup = FALSE; - m_inDetail = FALSE; - m_levelListItem = 0; - m_descTable = FALSE; - m_inLevel = -1; - m_firstMember = 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(const DocbookGenerator &og) : OutputGenerator(og) +{ +} + +DocbookGenerator &DocbookGenerator::operator=(const DocbookGenerator &og) +{ + OutputGenerator::operator=(og); + return *this; +} + +std::unique_ptr<OutputGenerator> DocbookGenerator::clone() const +{ + return std::make_unique<DocbookGenerator>(*this); } DocbookGenerator::~DocbookGenerator() @@ -293,7 +308,7 @@ void DocbookGenerator::init() createSubDirs(d); } -void DocbookGenerator::startFile(const char *name,const char *,const char *) +void DocbookGenerator::startFile(const char *name,const char *,const char *,int) { DB_GEN_C QCString fileName=name; @@ -428,7 +443,7 @@ DB_GEN_C2("IndexSections " << is) void DocbookGenerator::endIndexSection(IndexSections is) { DB_GEN_C2("IndexSections " << is) - static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); + bool sourceBrowser = Config_getBool(SOURCE_BROWSER); switch (is) { case isTitlePageStart: @@ -517,24 +532,12 @@ DB_GEN_C2("IndexSections " << is) case isNamespaceDocumentation: { t << "</title>" << endl; - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - bool found=FALSE; - for (nli.toFirst();(nd=nli.current()) && !found;++nli) - { - if (nd->isLinkableInProject()) - { - t << "<xi:include href=\"" << nd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; - found=TRUE; - } - } - while ((nd=nli.current())) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "<xi:include href=\"" << nd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; } - ++nli; } } t << "</chapter>\n"; @@ -542,25 +545,12 @@ DB_GEN_C2("IndexSections " << is) case isClassDocumentation: { t << "</title>" << endl; - ClassSDict::Iterator cli(*Doxygen::classSDict); - const ClassDef *cd=0; - bool found=FALSE; - for (cli.toFirst();(cd=cli.current()) && !found;++cli) - { - if (cd->isLinkableInProject() && - cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() - ) - { - t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; - found=TRUE; - } - } - for (;(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; @@ -651,7 +641,7 @@ DB_GEN_C } } -void DocbookGenerator::writeDoc(DocNode *n,const Definition *,const MemberDef *) +void DocbookGenerator::writeDoc(DocNode *n,const Definition *,const MemberDef *,int) { DB_GEN_C DocbookDocVisitor *visitor = @@ -734,12 +724,12 @@ void DocbookGenerator::endMemberItem() DB_GEN_C t << "</para>" << endl; } -void DocbookGenerator::startBold(void) +void DocbookGenerator::startBold() { DB_GEN_C t << "<emphasis role=\"strong\">"; } -void DocbookGenerator::endBold(void) +void DocbookGenerator::endBold() { DB_GEN_C t << "</emphasis>"; @@ -757,7 +747,7 @@ DB_GEN_C2("extraIndentLevel " << extraIndentLevel) t << "<section>" << endl; t << "<title>"; } -void DocbookGenerator::writeRuler(void) +void DocbookGenerator::writeRuler() { DB_GEN_C2("m_inLevel " << m_inLevel) DB_GEN_C2("m_inGroup " << m_inGroup) @@ -913,7 +903,7 @@ DB_GEN_C 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); + d.writeImage(t,dir(),relPath,fileName,FALSE); t << " </mediaobject>" << endl; t << " </informalfigure>" << endl; t << "</para>" << endl; @@ -947,12 +937,12 @@ void DocbookGenerator::endExamples() DB_GEN_C t << "</simplesect>" << endl; } -void DocbookGenerator::startSubsubsection(void) +void DocbookGenerator::startSubsubsection() { DB_GEN_C t << "<simplesect><title>"; } -void DocbookGenerator::endSubsubsection(void) +void DocbookGenerator::endSubsubsection() { DB_GEN_C t << "</title></simplesect>" << endl; @@ -997,19 +987,6 @@ DB_GEN_C if (closeBracket) t << ")"; } } -void DocbookGenerator::startCodeFragment() -{ -DB_GEN_C - t << "<programlisting>"; -} -void DocbookGenerator::endCodeFragment() -{ -DB_GEN_C - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << "</programlisting>"; -} void DocbookGenerator::startMemberTemplateParams() { DB_GEN_C @@ -1104,7 +1081,7 @@ DB_GEN_C void DocbookGenerator::endGroupCollaboration(DotGroupCollaboration &g) { DB_GEN_C - g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),m_fileName,relPath,FALSE); + g.writeGraph(t,GOF_BITMAP,EOF_DocBook,dir(),fileName(),relPath,FALSE); } void DocbookGenerator::startDotGraph() { @@ -1113,7 +1090,7 @@ DB_GEN_C void DocbookGenerator::endDotGraph(DotClassGraph &g) { DB_GEN_C - g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),m_fileName,relPath,TRUE,FALSE); + g.writeGraph(t,GOF_BITMAP,EOF_DocBook,dir(),fileName(),relPath,TRUE,FALSE); } void DocbookGenerator::startInclDepGraph() { @@ -1122,7 +1099,7 @@ DB_GEN_C void DocbookGenerator::endInclDepGraph(DotInclDepGraph &g) { DB_GEN_C - QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), m_fileName,relPath,FALSE); + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,dir(),fileName(),relPath,FALSE); } void DocbookGenerator::startCallGraph() { @@ -1131,7 +1108,7 @@ DB_GEN_C void DocbookGenerator::endCallGraph(DotCallGraph &g) { DB_GEN_C - QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), m_fileName,relPath,FALSE); + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,dir(),fileName(),relPath,FALSE); } void DocbookGenerator::startDirDepGraph() { @@ -1140,7 +1117,7 @@ DB_GEN_C void DocbookGenerator::endDirDepGraph(DotDirDeps &g) { DB_GEN_C - QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), m_fileName,relPath,FALSE); + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,dir(),fileName(),relPath,FALSE); } void DocbookGenerator::startMemberDocList() { diff --git a/src/docbookgen.h b/src/docbookgen.h index bed2f5f..214ec97 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -1,6 +1,6 @@ /****************************************************************************** * -* +* * * Copyright (C) 1997-2015 by Dimitri van Heesch. * @@ -15,6 +15,7 @@ #ifndef DOCBOOKGEN_H #define DOCBOOKGEN_H +#include "config.h" #include "outputgen.h" class DocbookCodeGenerator : public CodeOutputInterface @@ -52,21 +53,21 @@ class DocbookCodeGenerator : public CodeOutputInterface void setCurrentDoc(const Definition *,const char *,bool); void addWord(const char *,bool); void finish(); - void startCodeFragment(); - void endCodeFragment(); + void startCodeFragment(const char *style); + void endCodeFragment(const char *style); private: FTextStream m_t; - bool m_streamSet = FALSE; + bool m_streamSet = false; QCString m_refId; QCString m_external; int m_lineNumber = -1; int m_col = 0; - bool m_insideCodeLine = FALSE; - bool m_insideSpecialHL = FALSE; + bool m_insideCodeLine = false; + bool m_insideSpecialHL = false; QCString m_relPath; QCString m_sourceFileName; - bool m_prettyCode = FALSE; + bool m_prettyCode = Config_getBool(DOCBOOK_PROGRAMLISTING); }; @@ -97,20 +98,14 @@ class DocbookGenerator : public OutputGenerator { public: DocbookGenerator(); - ~DocbookGenerator(); + DocbookGenerator(const DocbookGenerator &o); + DocbookGenerator &operator=(const DocbookGenerator &o); + virtual ~DocbookGenerator(); + virtual std::unique_ptr<OutputGenerator> clone() const; + static void init(); - /////////////////////////////////////////////////////////////// - // generic generator methods - /////////////////////////////////////////////////////////////// - void enable() - { if (m_genStack->top()) m_active=*m_genStack->top(); else m_active=TRUE; } - void disable() { m_active=FALSE; } - void enableIf(OutputType o) { if (o==Docbook) enable(); } - void disableIf(OutputType o) { if (o==Docbook) disable(); } - void disableIfNot(OutputType o) { if (o!=Docbook) disable(); } - bool isEnabled(OutputType o) { return (o==Docbook && m_active); } - OutputGenerator *get(OutputType o) { return (o==Docbook) ? this : 0; } + OutputType type() const { return Docbook; } // --- CodeOutputInterface void codify(const char *text) @@ -135,15 +130,19 @@ class DocbookGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment(const char *style) + { m_codeGen.endCodeFragment(style); } // --------------------------- - void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md); + void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md,int id); /////////////////////////////////////////////////////////////// // structural output interface /////////////////////////////////////////////////////////////// void startFile(const char *name,const char *manName, - const char *title); + const char *title,int id); void writeSearchInfo(){DB_GEN_EMPTY}; void writeFooter(const char *){DB_GEN_NEW}; void endFile(); @@ -174,35 +173,33 @@ class DocbookGenerator : public OutputGenerator void writeChar(char); void writeString(const char *); void startParagraph(const char *); - void endParagraph(void); + void endParagraph(); void writeObjectLink(const char *,const char *,const char *,const char *); void startHtmlLink(const char *){DB_GEN_NEW}; - void endHtmlLink(void){DB_GEN_NEW}; - void startBold(void); - void endBold(void); - void startTypewriter(void); - void endTypewriter(void); - void startEmphasis(void){DB_GEN_NEW}; - void endEmphasis(void){DB_GEN_NEW}; - void startCodeFragment(void); - void endCodeFragment(void); - void writeRuler(void); - void startDescription(void){DB_GEN_NEW}; - void endDescription(void){DB_GEN_NEW}; - void startDescItem(void){DB_GEN_NEW}; - void startDescForItem(void){DB_GEN_EMPTY}; - void endDescForItem(void){DB_GEN_EMPTY}; - void endDescItem(void){DB_GEN_NEW}; - void startCenter(void){DB_GEN_NEW}; - void endCenter(void){DB_GEN_NEW}; - void startSmall(void){DB_GEN_NEW}; - void endSmall(void){DB_GEN_NEW}; - void startExamples(void); - void endExamples(void); + void endHtmlLink(){DB_GEN_NEW}; + void startBold(); + void endBold(); + void startTypewriter(); + void endTypewriter(); + void startEmphasis(){DB_GEN_NEW}; + void endEmphasis(){DB_GEN_NEW}; + void writeRuler(); + void startDescription(){DB_GEN_NEW}; + void endDescription(){DB_GEN_NEW}; + void startDescItem(){DB_GEN_NEW}; + void startDescForItem(){DB_GEN_EMPTY}; + void endDescForItem(){DB_GEN_EMPTY}; + void endDescItem(){DB_GEN_NEW}; + void startCenter(){DB_GEN_NEW}; + void endCenter(){DB_GEN_NEW}; + void startSmall(){DB_GEN_NEW}; + void endSmall(){DB_GEN_NEW}; + void startExamples(); + void endExamples(); void startParamList(BaseOutputDocInterface::ParamListTypes,const char *){DB_GEN_NEW}; - void endParamList(void){DB_GEN_NEW}; - void startTitle(void){DB_GEN_NEW}; - void endTitle(void){DB_GEN_NEW}; + void endParamList(){DB_GEN_NEW}; + void startTitle(){DB_GEN_NEW}; + void endTitle(){DB_GEN_NEW}; void writeAnchor(const char *,const char *){DB_GEN_EMPTY}; void startSection(const char *,const char *,SectionType); void endSection(const char *,SectionType); @@ -210,21 +207,21 @@ class DocbookGenerator : public OutputGenerator void addIndexItem(const char *,const char *); void writeNonBreakableSpace(int); void startDescTable(const char *); - void endDescTable(void); - void startDescTableRow(void); - void endDescTableRow(void); - void startDescTableTitle(void); - void endDescTableTitle(void); - void startDescTableData(void); - void endDescTableData(void); + void endDescTable(); + void startDescTableRow(); + void endDescTableRow(); + void startDescTableTitle(); + void endDescTableTitle(); + void startDescTableData(); + void endDescTableData(); void startTextLink(const char *,const char *){DB_GEN_NEW}; - void endTextLink(void){DB_GEN_NEW}; - void startPageRef(void){DB_GEN_NEW}; + void endTextLink(){DB_GEN_NEW}; + void startPageRef(){DB_GEN_NEW}; void endPageRef(const char *,const char *){DB_GEN_NEW}; - void startSubsection(void){DB_GEN_NEW}; - void endSubsection(void){DB_GEN_NEW}; - void startSubsubsection(void); - void endSubsubsection(void); + void startSubsection(){DB_GEN_NEW}; + void endSubsection(){DB_GEN_NEW}; + void startSubsubsection(); + void endSubsubsection(); void startGroupHeader(int); @@ -343,21 +340,19 @@ class DocbookGenerator : public OutputGenerator void addWord(const char *,bool) {DB_GEN_EMPTY} private: - DocbookGenerator(const DocbookGenerator &o); - DocbookGenerator &operator=(const DocbookGenerator &o); - + QCString relPath; DocbookCodeGenerator m_codeGen; - bool m_prettyCode; - bool m_denseText; - bool m_inGroup; - bool m_inDetail; - int m_levelListItem; - bool m_inListItem[20]; - bool m_inSimpleSect[20]; - bool m_descTable; - int m_inLevel; - bool m_firstMember; + bool m_prettyCode = Config_getBool(DOCBOOK_PROGRAMLISTING); + bool m_denseText = false; + bool m_inGroup = false; + bool m_inDetail = false; + int m_levelListItem = 0; + bool m_inListItem[20] = { false, }; + bool m_inSimpleSect[20] = { false, }; + bool m_descTable = false; + int m_inLevel = -1; + bool m_firstMember = false; }; #endif diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 78af6e0..d444b7b 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -316,9 +316,11 @@ DB_VIS_C { case DocVerbatim::Code: // fall though m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(m_langExt) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(m_langExt).parseCode(m_ci,s->context(), + s->text(), + langExt, + s->isExample(), + s->exampleFile()); m_t << "</computeroutput></literallayout>"; break; case DocVerbatim::Verbatim: @@ -354,12 +356,13 @@ DB_VIS_C QFile file(baseName+".dot"); if (!file.open(IO_WriteOnly)) { - err("Could not open file %s.msc for writing\n",baseName.data()); + err("Could not open file %s.dot for writing\n",baseName.data()); } file.writeBlock( stext, stext.length() ); file.close(); writeDotFile(baseName, s); m_t << "</para>" << endl; + if (Config_getBool(DOT_CLEANUP)) file.remove(); } break; case DocVerbatim::Msc: @@ -386,6 +389,7 @@ DB_VIS_C file.close(); writeMscFile(baseName,s); m_t << "</para>" << endl; + if (Config_getBool(DOT_CLEANUP)) file.remove(); } break; case DocVerbatim::PlantUML: @@ -425,24 +429,22 @@ DB_VIS_C m_t << "<literallayout><computeroutput>"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile(), fd); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile(), fd); delete fd; m_t << "</computeroutput></literallayout>"; } break; case DocInclude::Include: m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile()); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile()); m_t << "</computeroutput></literallayout>"; break; case DocInclude::DontInclude: @@ -463,14 +465,13 @@ DB_VIS_C break; case DocInclude::Snippet: m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile() - ); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile() + ); m_t << "</computeroutput></literallayout>"; break; case DocInclude::SnipWithLines: @@ -478,8 +479,7 @@ DB_VIS_C QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -531,17 +531,16 @@ DB_VIS_C fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(), - op->text(),langExt,op->isExample(), - op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(), + op->text(),langExt,op->isExample(), + op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); diff --git a/src/docparser.cpp b/src/docparser.cpp index 73131f6..af9e6a8 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -176,7 +176,7 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->initialStyleStack = g_initialStyleStack; ctx->copyStack = g_copyStack; ctx->fileName = g_fileName; - ctx->lineNo = doctokenizerYYlineno; + ctx->lineNo = getDoctokinizerLineNr(); ctx->relPath = g_relPath; if (saveParamInfo) @@ -217,7 +217,7 @@ static void docParserPopContext(bool keepParamInfo=FALSE) g_initialStyleStack = ctx->initialStyleStack; g_copyStack = ctx->copyStack; g_fileName = ctx->fileName; - doctokenizerYYlineno = ctx->lineNo; + setDoctokinizerLineNr(ctx->lineNo); g_relPath = ctx->relPath; if (!keepParamInfo) @@ -292,7 +292,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName)); text+="Possible candidates:\n"; text+=showFileDefMatches(Doxygen::imageNameLinkedMap,fileName); - warn_doc_error(g_fileName,doctokenizerYYlineno,"%s", text.data()); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"%s", text.data()); } QCString inputFile = fd->absFilePath(); @@ -331,7 +331,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool if (outfi.isSymLink()) { QFile::remove(outputFile); - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "destination of image %s is a symlink, replacing with image", qPrint(outputFile)); } @@ -349,19 +349,19 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "could not write output image %s",qPrint(outputFile)); } } //else //{ - // warn(g_fileName,doctokenizerYYlineno, + // warn(g_fileName,getDoctokinizerLineNr(), // "Prevented to copy file %s onto itself!\n",qPrint(inputFile)); //} } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "could not open image %s",qPrint(fileName)); } @@ -389,7 +389,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool result=fileName; if (result.left(5)!="http:" && result.left(6)!="https:" && dowarn) { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "image file %s is not found in IMAGE_PATH: " "assuming external image.",qPrint(fileName) ); @@ -770,7 +770,7 @@ static bool findDocsForMemberOrCompound(const char *commandName, //printf("Trying fullName='%s'\n",fullName.data()); // try class, namespace, group, page, file reference - cd = Doxygen::classSDict->find(fullName); + cd = Doxygen::classLinkedMap->find(fullName); if (cd) // class { *pDoc=cd->documentation(); @@ -778,7 +778,7 @@ static bool findDocsForMemberOrCompound(const char *commandName, *pDef=cd; return TRUE; } - nd = Doxygen::namespaceSDict->find(fullName); + nd = Doxygen::namespaceLinkedMap->find(fullName); if (nd) // namespace { *pDoc=nd->documentation(); @@ -812,16 +812,16 @@ inline void errorHandleDefaultToken(DocNode *parent,int tok, cmd_start = "@"; case TK_COMMAND_BS: children.append(new DocWord(parent,TK_COMMAND_CHAR(tok) + g_token->name)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s as part of a %s", qPrint(cmd_start + g_token->name),txt); break; case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found found as part of a %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found found as part of a %s", qPrint(g_token->name), txt); break; default: children.append(new DocWord(parent,g_token->name)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s found as part of a %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s found as part of a %s", tokToString(tok), txt); break; } @@ -841,7 +841,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return tok; } @@ -910,22 +910,22 @@ static void handleStyleLeave(DocNode *parent,QList<DocNode> &children, { if (g_styleStack.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag without matching <%s>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> tag without matching <%s>", qPrint(tagName),qPrint(tagName)); } else if (g_styleStack.top()->tagName()!=tagNameLower) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag while expecting </%s>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> tag while expecting </%s>", qPrint(tagName),qPrint(g_styleStack.top()->tagName())); } else if (g_styleStack.top()->style()!=s) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag while expecting </%s>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> tag while expecting </%s>", qPrint(tagName),qPrint(g_styleStack.top()->tagName())); } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> at different nesting level (%d) than expected (%d)", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> at different nesting level (%d) than expected (%d)", qPrint(tagName),g_nodeStack.count(),g_styleStack.top()->position()); } } @@ -988,7 +988,7 @@ static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttrib } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found <a> tag with name option but without value!"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found <a> tag with name option but without value!"); } } else if (opt->name=="href") // <a href=url>..</a> tag @@ -1042,7 +1042,7 @@ static void handleUnclosedStyleCommands() DocStyleChange *sc = g_initialStyleStack.top(); g_initialStyleStack.pop(); handleUnclosedStyleCommands(); - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "end of comment block while expecting " "command </%s>",qPrint(sc->tagName())); } @@ -1100,7 +1100,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor } else if (compound->definitionType()==Definition::TypeGroup) { - name=(dynamic_cast<const GroupDef*>(compound))->groupTitle(); + name=(toGroupDef(compound))->groupTitle(); } children.append(new DocLinkedWord(parent,name, @@ -1112,7 +1112,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor ); } else if (compound->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(compound))->generateSourceFile() + (toFileDef(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { children.append(new @@ -1165,7 +1165,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor { if (g_token->name.left(1)=="#" || g_token->name.left(2)=="::") { - warn_doc_error(g_fileName,doctokenizerYYlineno,"explicit link request to '%s' could not be resolved",qPrint(name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"explicit link request to '%s' could not be resolved",qPrint(name)); children.append(new DocWord(parent,g_token->name)); } else @@ -1205,7 +1205,7 @@ static DocInternalRef *handleInternalRef(DocNode *parent) QCString tokenName = g_token->name; if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(tokenName)); return 0; } @@ -1213,7 +1213,7 @@ static DocInternalRef *handleInternalRef(DocNode *parent) tok=doctokenizerYYlex(); // get the reference id if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(tokenName)); return 0; } @@ -1225,7 +1225,7 @@ static DocAnchor *handleAnchor(DocNode *parent) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(g_token->name)); return 0; } @@ -1233,13 +1233,13 @@ static DocAnchor *handleAnchor(DocNode *parent) tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s",qPrint(g_token->name)); return 0; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(g_token->name)); return 0; } @@ -1301,7 +1301,7 @@ static void defaultHandleTitleAndSize(const int cmd, DocNode *parent, QList<DocN } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option '%s' after \\%s command, expected 'width' or 'height'", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unknown option '%s' after \\%s command, expected 'width' or 'height'", qPrint(g_token->name), Mappers::cmdMapper->find(cmd).data()); break; } @@ -1330,7 +1330,7 @@ static void defaultHandleTitleAndSize(const int cmd, DocNode *parent, QList<DocN static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool handleWord) { - DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); + DBG(("token %s at %d",tokToString(tok),getDoctokinizerLineNr())); if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || tok==TK_COMMAND_AT || tok==TK_COMMAND_BS || tok==TK_HTMLTAG ) @@ -1445,7 +1445,7 @@ reparsetoken: doctokenizerYYsetStateHtmlOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block")); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"htmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1454,7 +1454,7 @@ reparsetoken: doctokenizerYYsetStateManOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"manonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1463,7 +1463,7 @@ reparsetoken: doctokenizerYYsetStateRtfOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"rtfonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1472,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"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"latexonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1481,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"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"xmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1490,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"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"docbookonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1543,10 +1543,10 @@ reparsetoken: switch (Mappers::htmlTagMapper->map(tokenName)) { case HTML_DIV: - warn_doc_error(g_fileName,doctokenizerYYlineno,"found <div> tag in heading\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found <div> tag in heading\n"); break; case HTML_PRE: - warn_doc_error(g_fileName,doctokenizerYYlineno,"found <pre> tag in heading\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found <pre> tag in heading\n"); break; case HTML_BOLD: if (!g_token->endTag) @@ -1758,7 +1758,7 @@ static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribL } if (!found) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"IMG tag does not have a SRC attribute!\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"IMG tag does not have a SRC attribute!\n"); } } @@ -1787,7 +1787,7 @@ DocEmoji::DocEmoji(DocNode *parent,const QCString &symName) : m_index = EmojiEntityMapper::instance()->symbol2index(m_symName); if (m_index==-1) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unsupported emoji symbol '%s'\n",qPrint(m_symName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Found unsupported emoji symbol '%s'\n",qPrint(m_symName)); } } @@ -1867,7 +1867,7 @@ static void readTextFileByName(const QCString &file,QCString &text) text = fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)); if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included file name %s is ambiguous" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included file name %s is ambiguous" "Possible candidates:\n%s",qPrint(file), qPrint(showFileDefMatches(Doxygen::exampleNameLinkedMap,file)) ); @@ -1875,7 +1875,7 @@ static void readTextFileByName(const QCString &file,QCString &text) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included file %s is not found. " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included file %s is not found. " "Check your EXAMPLE_PATH",qPrint(file)); } } @@ -1918,7 +1918,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) m_parent = parent; if (id.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Empty anchor label"); return; } @@ -1934,7 +1934,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid cite anchor id '%s'",qPrint(id)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid cite anchor id '%s'",qPrint(id)); m_anchor = "invalid"; m_file = "invalid"; } @@ -1954,7 +1954,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid anchor id '%s'",qPrint(id)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid anchor id '%s'",qPrint(id)); m_anchor = "invalid"; m_file = "invalid"; } @@ -2015,7 +2015,7 @@ void DocInclude::parse() int count; if (!m_blockId.isEmpty() && (count=m_text.contains(m_blockId.data()))!=2) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n", m_blockId.data(),m_file.data(),count); } break; @@ -2033,7 +2033,7 @@ void DocIncOperator::parse() { if (g_includeFileName.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "No previous '\\include' or '\\dontinclude' command for '\\%s' present", typeAsString()); } @@ -2225,7 +2225,7 @@ DocFormula::DocFormula(DocNode *parent,int id) : } else // wrong \_form#<n> command { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Wrong formula id %d",id); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Wrong formula id %d",id); m_id = -1; } } @@ -2287,13 +2287,13 @@ void DocSecRefItem::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to unknown section %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"reference to unknown section %s", qPrint(m_target)); } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to empty target"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"reference to empty target"); } DBG(("DocSecRefItem::parse() end\n")); @@ -2324,13 +2324,13 @@ void DocSecRefList::parse() tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\refitem command"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\refitem command"); break; } tok=doctokenizerYYlex(); if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\refitem", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of \\refitem", tokToString(tok)); break; } @@ -2343,7 +2343,7 @@ void DocSecRefList::parse() case CMD_ENDSECREFLIST: goto endsecreflist; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\secreflist", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s as part of a \\secreflist", qPrint(cmd_start + g_token->name)); goto endsecreflist; } @@ -2354,7 +2354,7 @@ void DocSecRefList::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s inside section reference list", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s inside section reference list", tokToString(tok)); goto endsecreflist; } @@ -2448,8 +2448,8 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : } m_isSubPage = pd && pd->hasParentPage(); 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); + //printf("m_text=%s,m_ref=%s,m_file=%s,type=%d\n", + // m_text.data(),m_ref.data(),m_file.data(),m_refType); return; } else if (resolveLink(context,target,TRUE,&compound,anchor)) @@ -2464,16 +2464,16 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : { if (anchor.isEmpty() && /* compound link */ compound->definitionType()==Definition::TypeGroup && /* is group */ - (dynamic_cast<const GroupDef *>(compound))->groupTitle() /* with title */ + (toGroupDef(compound))->groupTitle() /* with title */ ) { - m_text=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link + m_text=(toGroupDef(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeMember && - (dynamic_cast<const MemberDef*>(compound))->isObjCMethod()) + (toMemberDef(compound))->isObjCMethod()) { // Objective C Method - const MemberDef *member = dynamic_cast<const MemberDef*>(compound); + const MemberDef *member = toMemberDef(compound); bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; m_text = member->objCMethodName(localLink,g_inSeeBlock); } @@ -2485,7 +2485,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : return; } else if (compound && compound->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(compound))->generateSourceFile() + (toFileDef(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2494,7 +2494,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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unable to resolve reference to '%s' for \\ref command", qPrint(target)); } @@ -2589,16 +2589,16 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont m_text = target; if (numBibFiles==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"\\cite command found but no bib files specified via CITE_BIB_FILES!"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"\\cite command found but no bib files specified via CITE_BIB_FILES!"); } else if (cite==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to '%s' for \\cite command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unable to resolve reference to '%s' for \\cite command", qPrint(target)); } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"\\cite command to '%s' does not have an associated number", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"\\cite command to '%s' does not have an associated number", qPrint(target)); } } @@ -2626,7 +2626,7 @@ DocLink::DocLink(DocNode *parent,const QCString &target) m_ref = compound->getReference(); } else if (compound && compound->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(compound))->generateSourceFile() + (toFileDef(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2636,7 +2636,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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unable to resolve link to '%s' for \\link command", qPrint(target)); } @@ -2664,23 +2664,23 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) case CMD_ENDLINK: if (isJavaLink) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"{@link.. ended with @endlink command"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"{@link.. ended with @endlink command"); } goto endlink; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\link", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s as part of a \\link", qPrint(cmd_start + g_token->name)); break; } break; case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found as part of a \\link", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found as part of a \\link", qPrint(g_token->name)); break; case TK_HTMLTAG: if (g_token->name!="see" || !isXmlLink) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected xml/html command %s found as part of a \\link", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected xml/html command %s found as part of a \\link", qPrint(g_token->name)); } goto endlink; @@ -2708,7 +2708,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) m_children.append(new DocWord(this,g_token->name)); break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s", tokToString(tok)); break; } @@ -2716,7 +2716,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " link command\n"); } endlink: @@ -2759,7 +2759,7 @@ bool DocDotFile::parse() ok = true; if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file name %s is ambiguous.\n" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dot file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), qPrint(showFileDefMatches(Doxygen::dotFileNameLinkedMap,m_name)) ); @@ -2767,7 +2767,7 @@ bool DocDotFile::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dot file %s is not found " "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name)); } return ok; @@ -2796,7 +2796,7 @@ bool DocMscFile::parse() ok = true; if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file name %s is ambiguous.\n" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included msc file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), qPrint(showFileDefMatches(Doxygen::mscFileNameLinkedMap,m_name)) ); @@ -2804,7 +2804,7 @@ bool DocMscFile::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included msc file %s is not found " "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name)); } return ok; @@ -2835,7 +2835,7 @@ bool DocDiaFile::parse() ok = true; if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file name %s is ambiguous.\n" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dia file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), qPrint(showFileDefMatches(Doxygen::diaFileNameLinkedMap,m_name)) ); @@ -2843,7 +2843,7 @@ bool DocDiaFile::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dia file %s is not found " "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name)); } return ok; @@ -2930,7 +2930,7 @@ int DocHtmlHeader::parse() { if (m_level!=1) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h1>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h1>", m_level); } goto endheader; @@ -2939,7 +2939,7 @@ int DocHtmlHeader::parse() { if (m_level!=2) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h2>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h2>", m_level); } goto endheader; @@ -2948,7 +2948,7 @@ int DocHtmlHeader::parse() { if (m_level!=3) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h3>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h3>", m_level); } goto endheader; @@ -2957,7 +2957,7 @@ int DocHtmlHeader::parse() { if (m_level!=4) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h4>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h4>", m_level); } goto endheader; @@ -2966,7 +2966,7 @@ int DocHtmlHeader::parse() { if (m_level!=5) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h5>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h5>", m_level); } goto endheader; @@ -2975,7 +2975,7 @@ int DocHtmlHeader::parse() { if (m_level!=6) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h6>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h6>", m_level); } goto endheader; @@ -2994,7 +2994,7 @@ int DocHtmlHeader::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <h%d> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <h%d> context", g_token->endTag?"/":"",qPrint(g_token->name),m_level); } } @@ -3008,7 +3008,7 @@ int DocHtmlHeader::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <h%d> tag\n",m_level); } endheader: @@ -3043,7 +3043,7 @@ int DocHRef::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <a href=...> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <a href=...> context", g_token->endTag?"/":"",qPrint(g_token->name)); } } @@ -3056,7 +3056,7 @@ int DocHRef::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <a href=...> tag"); } endhref: @@ -3094,7 +3094,7 @@ int DocInternal::parse(int level) } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid list item found"); } } while (retval!=0 && retval!=RetVal_Section && @@ -3120,7 +3120,7 @@ int DocInternal::parse(int level) if (retval==RetVal_Internal) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"\\internal command found inside internal section"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"\\internal command found inside internal section"); } DBG(("DocInternal::parse() end: retval=%x\n",retval)); @@ -3139,7 +3139,7 @@ int DocIndexEntry::parse() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\addindex command"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\addindex command"); goto endindexentry; } doctokenizerYYsetStateTitle(); @@ -3177,7 +3177,7 @@ int DocIndexEntry::parse() case DocSymbol::Sym_ndash: m_entry+="--"; break; case DocSymbol::Sym_mdash: m_entry+="---"; break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected symbol found as argument of \\addindex"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected symbol found as argument of \\addindex"); break; } } @@ -3204,13 +3204,13 @@ int DocIndexEntry::parse() case CMD_MINUS: m_entry+='-'; break; case CMD_EQUAL: m_entry+='='; break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command %s found as argument of \\addindex", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected command %s found as argument of \\addindex", qPrint(g_token->name)); break; } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s", tokToString(tok)); break; } @@ -3245,7 +3245,7 @@ DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid caption id '%s'",qPrint(opt->value)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid caption id '%s'",qPrint(opt->value)); } } else // copy attribute @@ -3278,7 +3278,7 @@ int DocHtmlCaption::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <caption> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <caption> context", g_token->endTag?"/":"",qPrint(g_token->name)); } } @@ -3291,7 +3291,7 @@ int DocHtmlCaption::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <caption> tag"); } endcaption: @@ -3478,7 +3478,7 @@ int DocHtmlRow::parse() } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <td> or <th> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endrow; @@ -3486,13 +3486,13 @@ int DocHtmlRow::parse() } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html description title"); goto endrow; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <td> or <th> tag but found %s token instead!", tokToString(tok)); goto endrow; } @@ -3542,7 +3542,7 @@ int DocHtmlRow::parseXml(bool isHeading) } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <term> or <description> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <term> or <description> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endrow; @@ -3550,13 +3550,13 @@ int DocHtmlRow::parseXml(bool isHeading) } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html description title"); goto endrow; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <td> or <th> tag but found %s token instead!", tokToString(tok)); goto endrow; } @@ -3605,7 +3605,7 @@ getrow: { if (m_caption) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"table already has a caption, found another one"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"table already has a caption, found another one"); } else { @@ -3620,18 +3620,18 @@ getrow: } else // found wrong token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> or <caption> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <tr> or <caption> tag but " "found <%s%s> instead!", g_token->endTag ? "/" : "", qPrint(g_token->name)); } } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a <tr> or <caption> tag"); } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <tr> tag but found %s token instead!", tokToString(tok)); } @@ -3813,7 +3813,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(g_token->name)); } else @@ -3822,7 +3822,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); // get the reference id if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of \\%s command", tokToString(tok),qPrint(cmdName)); } else @@ -3843,7 +3843,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(cmdName)); } else @@ -3852,7 +3852,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of \\%s command", tokToString(tok),qPrint(cmdName)); } else @@ -3871,13 +3871,13 @@ int DocHtmlDescTitle::parse() break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s found as part of a <dt> tag", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s found as part of a <dt> tag", qPrint(cmd_start + g_token->name)); } } break; case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol \\%s found as part of a <dt> tag", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol \\%s found as part of a <dt> tag", qPrint(g_token->name)); break; case TK_HTMLTAG: @@ -3912,13 +3912,13 @@ int DocHtmlDescTitle::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <dt> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <dt> context", g_token->endTag?"/":"",qPrint(g_token->name)); } } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s found as part of a <dt> tag", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s found as part of a <dt> tag", tokToString(tok)); break; } @@ -3926,7 +3926,7 @@ int DocHtmlDescTitle::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <dt> tag"); } endtitle: @@ -3986,7 +3986,7 @@ int DocHtmlDescList::parse() } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <dt> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto enddesclist; @@ -3994,13 +3994,13 @@ int DocHtmlDescList::parse() } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html description title"); goto enddesclist; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <dt> tag but found %s token instead!", tokToString(tok)); goto enddesclist; } @@ -4025,7 +4025,7 @@ int DocHtmlDescList::parse() if (retval==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <dl> block"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while inside <dl> block"); } enddesclist: @@ -4125,7 +4125,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"empty list!"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"empty list!"); retval = RetVal_EndList; goto endlist; } @@ -4133,7 +4133,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <li> tag but " "found <%s%s> instead!",g_token->endTag?"/":"",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endlist; @@ -4143,7 +4143,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html list item"); goto endlist; } @@ -4151,7 +4151,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <li> tag but found %s token instead!", tokToString(tok)); goto endlist; } @@ -4165,7 +4165,7 @@ int DocHtmlList::parse() if (retval==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <%cl> block", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while inside <%cl> block", m_type==Unordered ? 'u' : 'o'); } @@ -4198,7 +4198,7 @@ int DocHtmlList::parseXml() } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <item> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endlist; @@ -4206,13 +4206,13 @@ int DocHtmlList::parseXml() } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html list item"); goto endlist; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <item> tag but found %s token instead!", tokToString(tok)); goto endlist; } @@ -4228,7 +4228,7 @@ int DocHtmlList::parseXml() if (retval==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <list type=\"%s\"> block", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while inside <list type=\"%s\"> block", m_type==Unordered ? "bullet" : "number"); } @@ -4616,7 +4616,7 @@ int DocParamList::parse(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); retval=0; goto endparamlist; @@ -4654,14 +4654,14 @@ int DocParamList::parse(const QCString &cmdName) doctokenizerYYsetStatePara(); if (tok==0) /* premature end of comment block */ { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; } if (tok!=TK_WHITESPACE) /* premature end of comment block */ { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token in comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token in comment block while parsing the " "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; @@ -4734,7 +4734,7 @@ int DocParamList::parseXml(const QCString ¶mName) if (retval==0) /* premature end of comment block */ { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unterminated param or exception tag"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unterminated param or exception tag"); } else { @@ -4853,7 +4853,7 @@ void DocPara::handleCite() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint("cite")); return; } @@ -4861,13 +4861,13 @@ void DocPara::handleCite() tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint("cite")); return; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint("cite")); return; } @@ -4885,7 +4885,7 @@ void DocPara::handleEmoji() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint("emoji")); return; } @@ -4893,13 +4893,13 @@ void DocPara::handleEmoji() tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint("emoji")); return; } else if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint("emoji")); return; } @@ -4937,7 +4937,7 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -4946,13 +4946,13 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type doctokenizerYYsetStatePara(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s", qPrint(saveCmdName)); return; } else if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5001,7 +5001,7 @@ void DocPara::handleImage(const QCString &cmdName) { if (g_token->name.lower() != "inline") { - warn_doc_error(g_fileName,doctokenizerYYlineno,"currently only 'inline' supported as option of %s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"currently only 'inline' supported as option of %s command", qPrint(saveCmdName)); } else @@ -5012,14 +5012,14 @@ void DocPara::handleImage(const QCString &cmdName) } if (!((tok==TK_WORD) && (g_token->name == "}"))) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected closing '}' at option of %s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected closing '}' at option of %s command", qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command with option", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command with option", qPrint(saveCmdName)); return; } @@ -5027,7 +5027,7 @@ void DocPara::handleImage(const QCString &cmdName) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5035,14 +5035,14 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5054,7 +5054,7 @@ void DocPara::handleImage(const QCString &cmdName) else if (imgType=="rtf") t=DocImage::Rtf; else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"output format %s specified as the first argument of " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"output format %s specified as the first argument of " "%s command is not valid", qPrint(imgType),qPrint(saveCmdName)); return; @@ -5064,7 +5064,7 @@ void DocPara::handleImage(const QCString &cmdName) doctokenizerYYsetStatePara(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5081,7 +5081,7 @@ void DocPara::handleFile(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5090,7 +5090,7 @@ void DocPara::handleFile(const QCString &cmdName) doctokenizerYYsetStatePara(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5119,7 +5119,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5127,7 +5127,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) tok=doctokenizerYYlex(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"%s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5148,7 +5148,7 @@ void DocPara::handleRef(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5157,7 +5157,7 @@ void DocPara::handleRef(const QCString &cmdName) DocRef *ref=0; if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); goto endref; } @@ -5212,7 +5212,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } else if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5221,13 +5221,13 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) doctokenizerYYsetStatePara(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s",qPrint(saveCmdName)); return; } else if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5241,7 +5241,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) doctokenizerYYsetStatePara(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected block identifier, but found token %s instead while parsing the %s command", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5262,7 +5262,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } docParserPushContext(); g_fileName = fileName; - doctokenizerYYlineno=inc_line; + setDoctokinizerLineNr(inc_line); internalValidatingParseDoc(this,m_children,inc_text); docParserPopContext(); } @@ -5281,20 +5281,20 @@ void DocPara::handleSection(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint(saveCmdName)); return; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5341,7 +5341,7 @@ int DocPara::handleStartCode() i++; } m_children.append(new DocVerbatim(this,g_context,stripIndentation(g_token->verb.mid(li)),DocVerbatim::Code,g_isExample,g_exampleName,FALSE,lang)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"code section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"code section ended without end marker"); doctokenizerYYsetStatePara(); return retval; } @@ -5384,7 +5384,7 @@ 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 '%c%s'",TK_COMMAND_CHAR(tok),qPrint(cmdName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"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)); @@ -5551,7 +5551,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateHtmlOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block")); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"htmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5560,7 +5560,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateManOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"manonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5569,7 +5569,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateRtfOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"rtfonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5578,7 +5578,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateLatexOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"latexonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5587,7 +5587,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateXmlOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"xmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5596,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"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"docbookonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5605,7 +5605,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateVerbatim(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Verbatim,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"verbatim section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"verbatim section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5621,7 +5621,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) dv->setWidth(width); dv->setHeight(height); m_children.append(dv); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"dot section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"dot section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5637,7 +5637,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) dv->setWidth(width); dv->setHeight(height); m_children.append(dv); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"msc section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"msc section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5659,14 +5659,14 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) dv->setHeight(height); if (jarPath.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"ignoring \\startuml command because PLANTUML_JAR_PATH is not set"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"ignoring \\startuml command because PLANTUML_JAR_PATH is not set"); delete dv; } else { m_children.append(dv); } - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"startuml section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"startuml section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5685,7 +5685,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) case CMD_ENDDOT: case CMD_ENDMSC: case CMD_ENDUML: - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); break; case CMD_PARAM: retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir); @@ -5838,10 +5838,10 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) } break; case CMD_SECREFITEM: - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); break; case CMD_ENDSECREFLIST: - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); break; case CMD_FORMULA: { @@ -5853,7 +5853,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) // retval = handleLanguageSwitch(); // break; case CMD_INTERNALREF: - //warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + //warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); { DocInternalRef *ref = handleInternalRef(this); if (ref) @@ -5908,7 +5908,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta 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.", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"HTML tag ('<%s/>') may not use the 'empty tag' XHTML syntax.", tagName.data()); } switch (tagId) @@ -5933,7 +5933,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta if (g_token->emptyTag) break; if (!insideUL(this) && !insideOL(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <li> tag found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"lonely <li> tag found"); } else { @@ -6014,7 +6014,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta retval = RetVal_DescTitle; break; case HTML_DD: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <dd> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag <dd> found"); break; case HTML_TABLE: if (!g_token->emptyTag) @@ -6034,7 +6034,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta retval = RetVal_TableHCell; break; case HTML_CAPTION: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <caption> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag <caption> found"); break; case HTML_BR: { @@ -6115,7 +6115,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta { if (Config_getBool(WARN_NO_PARAMDOC)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"empty 'name' attribute for <param%s> tag.",tagId==XML_PARAM?"":"type"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"empty 'name' attribute for <param%s> tag.",tagId==XML_PARAM?"":"type"); } } else @@ -6127,7 +6127,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param%s> tag.",tagId==XML_PARAM?"":"type"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'name' attribute from <param%s> tag.",tagId==XML_PARAM?"":"type"); } } break; @@ -6145,7 +6145,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type"); } } break; @@ -6160,7 +6160,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <exception> tag."); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'cref' attribute from <exception> tag."); } } break; @@ -6176,7 +6176,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <item> tag found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"lonely <item> tag found"); } break; case XML_RETURNS: @@ -6237,7 +6237,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' or 'langword' attribute from <see> tag."); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'cref' or 'langword' attribute from <see> tag."); } } break; @@ -6271,7 +6271,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <seealso> tag."); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'cref' attribute from <seealso> tag."); } } break; @@ -6305,7 +6305,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta g_xmlComment=TRUE; break; case HTML_UNKNOWN: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag <%s> found", qPrint(tagName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported xml/html tag <%s> found", qPrint(tagName)); m_children.append(new DocWord(this, "<"+tagName+g_token->attribsStr+">")); break; case XML_INHERITDOC: @@ -6329,7 +6329,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_UL: if (!insideUL(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ul> tag without matching <ul>"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </ul> tag without matching <ul>"); } else { @@ -6339,7 +6339,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_OL: if (!insideOL(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ol> tag without matching <ol>"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </ol> tag without matching <ol>"); } else { @@ -6349,7 +6349,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_LI: if (!insideLI(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </li> tag without matching <li>"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </li> tag without matching <li>"); } else { @@ -6362,7 +6362,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) //case HTML_PRE: // if (!insidePRE(this)) // { - // warn_doc_error(g_fileName,doctokenizerYYlineno,"found </pre> tag without matching <pre>"); + // warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </pre> tag without matching <pre>"); // } // else // { @@ -6441,37 +6441,37 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) // ignore </th> tag break; case HTML_CAPTION: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </caption> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </caption> found"); break; case HTML_BR: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal </br> tag found\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal </br> tag found\n"); break; case HTML_H1: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h1> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h1> found"); break; case HTML_H2: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h2> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h2> found"); break; case HTML_H3: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h3> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h3> found"); break; case HTML_H4: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h4> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h4> found"); break; case HTML_H5: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h5> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h5> found"); break; case HTML_H6: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h6> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h6> found"); break; case HTML_IMG: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </img> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </img> found"); break; case HTML_HR: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal </hr> tag found\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal </hr> tag found\n"); break; case HTML_A: - //warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </a> found"); + //warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </a> found"); // ignore </a> tag (can be part of <a name=...></a> break; @@ -6506,12 +6506,12 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) // These tags are defined in .Net but are currently unsupported break; case HTML_UNKNOWN: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag </%s> found", qPrint(tagName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported xml/html tag </%s> found", qPrint(tagName)); m_children.append(new DocWord(this,"</"+tagName+">")); break; default: // we should not get here! - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end tag %s\n",qPrint(tagName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end tag %s\n",qPrint(tagName)); ASSERT(0); break; } @@ -6529,7 +6529,7 @@ int DocPara::parse() while ((tok=doctokenizerYYlex())) // get the next token { reparsetoken: - DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); + DBG(("token %s at %d",tokToString(tok),getDoctokinizerLineNr())); if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || tok==TK_COMMAND_AT || tok == TK_COMMAND_BS || tok==TK_HTMLTAG ) @@ -6651,7 +6651,7 @@ reparsetoken: } break; case TK_ENDLIST: - DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno)); + DBG(("Found end of list inside of paragraph at line %d\n",getDoctokinizerLineNr())); if (parent()->kind()==DocNode::Kind_AutoListItem) { ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList); @@ -6664,13 +6664,13 @@ reparsetoken: } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"End of list marker found " "has invalid indent level"); } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found without any preceding " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"End of list marker found without any preceding " "list items"); } break; @@ -6783,7 +6783,7 @@ reparsetoken: } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found", qPrint(g_token->name)); } break; @@ -6818,7 +6818,7 @@ reparsetoken: } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "Found unexpected token (id=%x)\n",tok); break; } @@ -6880,7 +6880,7 @@ int DocSection::parse() } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid list item found"); } if (retval==RetVal_Internal) { @@ -6921,7 +6921,7 @@ int DocSection::parse() else if (retval==RetVal_Subsubsection && m_level<=Doxygen::subpageNestingLevel+2) { if ((m_level<=1+Doxygen::subpageNestingLevel) && !g_token->sectionId.startsWith("autotoc_md")) - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); // then parse any number of nested sections while (retval==RetVal_Subsubsection) // more sections follow { @@ -6935,7 +6935,7 @@ int DocSection::parse() else if (retval==RetVal_Paragraph && m_level<=QMIN(5,Doxygen::subpageNestingLevel+3)) { if ((m_level<=2+Doxygen::subpageNestingLevel) && !g_token->sectionId.startsWith("autotoc_md")) - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); // then parse any number of nested sections while (retval==RetVal_Paragraph) // more sections follow { @@ -6995,7 +6995,7 @@ void DocText::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found", qPrint(g_token->name)); } } @@ -7057,13 +7057,13 @@ void DocText::parse() m_children.append(new DocSymbol(this,DocSymbol::Sym_Equal)); break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command '%s' found", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected command '%s' found", qPrint(g_token->name)); break; } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s", tokToString(tok)); break; } @@ -7107,7 +7107,7 @@ void DocRoot::parse() { if (!g_token->sectionId.startsWith("autotoc_md")) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command (id: '%s') outside of subsubsection context!",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found paragraph command (id: '%s') outside of subsubsection context!",qPrint(g_token->sectionId)); } while (retval==RetVal_Paragraph) { @@ -7123,13 +7123,13 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid paragraph id '%s'; ignoring paragraph",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid paragraph id '%s'; ignoring paragraph",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for paragraph; ignoring paragraph"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for paragraph; ignoring paragraph"); retval = 0; } } @@ -7137,7 +7137,7 @@ void DocRoot::parse() if (retval==RetVal_Subsubsection) { if (!(g_token->sectionId.startsWith("autotoc_md"))) - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command (id: '%s') outside of subsection context!",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found subsubsection command (id: '%s') outside of subsection context!",qPrint(g_token->sectionId)); while (retval==RetVal_Subsubsection) { if (!g_token->sectionId.isEmpty()) @@ -7152,13 +7152,13 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsubsection id '%s'; ignoring subsubsection",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid subsubsection id '%s'; ignoring subsubsection",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for subsubsection; ignoring subsubsection"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for subsubsection; ignoring subsubsection"); retval = 0; } } @@ -7167,7 +7167,7 @@ void DocRoot::parse() { if (!g_token->sectionId.startsWith("autotoc_md")) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command (id: '%s') outside of section context!",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found subsection command (id: '%s') outside of section context!",qPrint(g_token->sectionId)); } while (retval==RetVal_Subsection) { @@ -7183,20 +7183,20 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsection id '%s'; ignoring subsection",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid subsection id '%s'; ignoring subsection",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for subsection; ignoring subsection"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for subsection; ignoring subsection"); retval = 0; } } } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid list item found"); } if (retval==RetVal_Internal) { @@ -7223,13 +7223,13 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid section id '%s'; ignoring section",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid section id '%s'; ignoring section",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for section; ignoring section"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for section; ignoring section"); retval = 0; } } @@ -7397,14 +7397,14 @@ static QCString processCopyDoc(const char *data,uint &len) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "Found recursive @copy%s or @copydoc relation for argument '%s'.\n", isBrief?"brief":"details",id.data()); } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "@copy%s or @copydoc target '%s' not found", isBrief?"brief":"details", id.data()); } @@ -7590,12 +7590,12 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } else if (ctx && ctx->definitionType()==Definition::TypePage) { - const Definition *scope = (dynamic_cast<const PageDef*>(ctx))->getPageScope(); + const Definition *scope = (toPageDef(ctx))->getPageScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else if (ctx && ctx->definitionType()==Definition::TypeGroup) { - const Definition *scope = (dynamic_cast<const GroupDef*>(ctx))->getGroupScope(); + const Definition *scope = (toGroupDef(ctx))->getGroupScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else @@ -7727,7 +7727,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, g_markdownSupport = markdownSupport; //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); - doctokenizerYYlineno=startLine; + setDoctokinizerLineNr(startLine); uint inpLen=qstrlen(input); QCString inpStr = processCopyDoc(input,inpLen); if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n') @@ -7802,7 +7802,7 @@ DocText *validatingParseText(const char *input) if (input) { - doctokenizerYYlineno=1; + setDoctokinizerLineNr(1); doctokenizerYYinit(input,g_fileName,Config_getBool(MARKDOWN_SUPPORT)); // build abstract syntax tree diff --git a/src/docsets.cpp b/src/docsets.cpp index d92e4f3..c59ca76 100644 --- a/src/docsets.cpp +++ b/src/docsets.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. * @@ -66,7 +66,7 @@ void DocSets::initialize() } FTextStream ts(&makefile); - ts << "DOCSET_NAME=" << bundleId << ".docset\n" + ts << "DOCSET_NAME=" << bundleId << ".docset\n" "DOCSET_CONTENTS=$(DOCSET_NAME)/Contents\n" "DOCSET_RESOURCES=$(DOCSET_CONTENTS)/Resources\n" "DOCSET_DOCUMENTS=$(DOCSET_RESOURCES)/Documents\n" @@ -116,25 +116,25 @@ void DocSets::initialize() } FTextStream ts(&plist); - ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" - "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" - "<plist version=\"1.0\">\n" - "<dict>\n" - " <key>CFBundleName</key>\n" - " <string>" << projectName << "</string>\n" + ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + "<plist version=\"1.0\">\n" + "<dict>\n" + " <key>CFBundleName</key>\n" + " <string>" << projectName << "</string>\n" " <key>CFBundleIdentifier</key>\n" - " <string>" << bundleId << "</string>\n" + " <string>" << bundleId << "</string>\n" " <key>CFBundleVersion</key>\n" " <string>" << projectNumber << "</string>\n" - " <key>DocSetFeedName</key>\n" + " <key>DocSetFeedName</key>\n" " <string>" << feedName << "</string>\n" " <key>DocSetPublisherIdentifier</key>\n" " <string>" << publisherId << "</string>\n" " <key>DocSetPublisherName</key>\n" " <string>" << publisherName << "</string>\n" // markers for Dash - " <key>DashDocSetFamily</key>\n" + " <key>DashDocSetFamily</key>\n" " <string>doxy</string>\n" " <key>DocSetPlatformFamily</key>\n" " <string>doxygen</string>\n" @@ -226,8 +226,8 @@ void DocSets::decContentsDepth() } void DocSets::addContentsItem(bool isDir, - const char *name, - const char *ref, + const char *name, + const char *ref, const char *file, const char *anchor, bool /* separateIndex */, @@ -247,7 +247,7 @@ void DocSets::addContentsItem(bool isDir, m_nts << indent() << " <Name>" << convertToXML(name) << "</Name>" << endl; if (file && file[0]=='^') // URL marker { - m_nts << indent() << " <URL>" << convertToXML(&file[1]) + m_nts << indent() << " <URL>" << convertToXML(&file[1]) << "</URL>" << endl; } else // relative file @@ -294,11 +294,11 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, // determine language QCString lang; SrcLangExt langExt = SrcLangExt_Cpp; - if (md) + if (md) { langExt = md->getLanguage(); } - else if (context) + else if (context) { langExt = context->getLanguage(); } @@ -309,7 +309,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, { if (md && (md->isObjCMethod() || md->isObjCProperty())) lang="occ"; // Objective C/C++ - else if (fd && fd->name().right(2).lower()==".c") + else if (fd && fd->name().right(2).lower()==".c") lang="c"; // Plain C else if (cd==0 && nd==0) lang="c"; // Plain C symbol outside any class or namespace @@ -386,9 +386,9 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, case MemberType_DCOP: type="dcop"; break; case MemberType_Property: - if (cd && cd->compoundType()==ClassDef::Protocol) + if (cd && cd->compoundType()==ClassDef::Protocol) type="intfp"; // interface property - else + else type="instp"; // instance property break; case MemberType_Event: @@ -404,7 +404,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, } cd = md->getClassDef(); nd = md->getNamespaceDef(); - if (cd) + if (cd) { scope = cd->qualifiedName(); } @@ -427,28 +427,28 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, { if (fd==0 && context->definitionType()==Definition::TypeFile) { - fd = dynamic_cast<const FileDef*>(context); + fd = toFileDef(context); } if (cd==0 && context->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<const ClassDef*>(context); + cd = toClassDef(context); } if (nd==0 && context->definitionType()==Definition::TypeNamespace) { - nd = dynamic_cast<const NamespaceDef*>(context); + nd = toNamespaceDef(context); } if (fd) { type="file"; } - else if (cd) + else if (cd) { scope = cd->qualifiedName(); if (cd->isTemplate()) { type="tmplt"; } - else if (cd->compoundType()==ClassDef::Protocol) + else if (cd->compoundType()==ClassDef::Protocol) { type="intf"; if (scope.right(2)=="-p") scope=scope.left(scope.length()-2); @@ -461,7 +461,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, { type="cat"; } - else + else { type = "cl"; } @@ -510,7 +510,7 @@ void DocSets::writeToken(FTextStream &t, t << " <Scope>" << convertToXML(scope) << "</Scope>" << endl; } t << " </TokenIdentifier>" << endl; - t << " <Path>" << d->getOutputFileBase() + t << " <Path>" << d->getOutputFileBase() << Doxygen::htmlFileExtension << "</Path>" << endl; if (anchor) { diff --git a/src/doctokenizer.h b/src/doctokenizer.h index f43cd07..235b403 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -115,12 +115,14 @@ struct TokenInfo // globals extern TokenInfo *g_token; -extern int doctokenizerYYlineno; extern FILE *doctokenizerYYin; // helper functions const char *tokToString(int token); +void setDoctokinizerLineNr(int lineno); +int getDoctokinizerLineNr(void); + // operations on the scanner void doctokenizerYYFindSections(const char *input,const Definition *d, const char *fileName); diff --git a/src/doctokenizer.l b/src/doctokenizer.l index ac5b6d2..330db00 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -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. * @@ -49,7 +49,7 @@ #define USE_STATE2STRING 0 #define TK_COMMAND_SEL() (yytext[0] == '@' ? TK_COMMAND_AT : TK_COMMAND_BS) - + //-------------------------------------------------------------------------- // context for tokenizer phase @@ -75,13 +75,18 @@ struct DocLexerContext TokenInfo *token; int rule; int autoListLevel; - int inputPos; + yy_size_t inputPos; const char *inputString; YY_BUFFER_STATE state; }; static QStack<DocLexerContext> g_lexerStack; +static int g_yyLineNr = 0; + +#define lineCount(s,len) do { for(int i=0;i<(int)len;i++) if (s[i]=='\n') g_yyLineNr++; } while(0) + + #if USE_STATE2STRING static const char *stateToString(int state); #endif @@ -124,6 +129,7 @@ QCString extractPartAfterNewLine(const QCString &text) int nl2 = text.findRev("\\ilinebr"); if (nl2!=-1) { + if (text.at(nl2+8)==' ') nl2++; // skip space after \\ilinebr return text.mid(nl2+8); } return text; @@ -187,7 +193,7 @@ static void processSection() } else { - warn(g_fileName,yylineno,"Found section/anchor %s without context\n",g_secLabel.data()); + warn(g_fileName,g_yyLineNr,"Found section/anchor %s without context\n",g_secLabel.data()); } SectionInfo *si = SectionManager::instance().find(g_secLabel); if (si) @@ -203,10 +209,10 @@ static void handleHtmlTag() g_token->attribs.clear(); g_token->endTag = FALSE; g_token->emptyTag = FALSE; - + // Check for end tag int startNamePos=1; - if (tagText.at(1)=='/') + if (tagText.at(1)=='/') { g_token->endTag = TRUE; startNamePos++; @@ -234,7 +240,7 @@ static void handleHtmlTag() // check for end of the tag if (c == '>') break; // Check for XML style "empty" tag. - if (c == '/') + if (c == '/') { g_token->emptyTag = TRUE; break; @@ -244,42 +250,42 @@ static void handleHtmlTag() while (i<(int)yyleng && !isspace((uchar)c) && c!='=' && c!= '>') { c=tagText.at(++i); } endName=i; HtmlAttrib opt; - opt.name = tagText.mid(startName,endName-startName).lower(); + opt.name = tagText.mid(startName,endName-startName).lower(); // skip spaces - while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } + while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } if (tagText.at(i)=='=') // option has value { c=tagText.at(++i); // skip spaces - while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } + while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } if (tagText.at(i)=='\'') // option '...' { c=tagText.at(++i); - startAttrib=i; - - // search for matching quote - while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); } - endAttrib=i; + startAttrib=i; + + // search for matching quote + while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); } + endAttrib=i; if (i<(int)yyleng) { c=tagText.at(++i);} } else if (tagText.at(i)=='"') // option "..." { c=tagText.at(++i); - startAttrib=i; - // search for matching quote - while (i<(int)yyleng && c!='"') { c=tagText.at(++i); } - endAttrib=i; + startAttrib=i; + // search for matching quote + while (i<(int)yyleng && c!='"') { c=tagText.at(++i); } + endAttrib=i; if (i<(int)yyleng) { c=tagText.at(++i);} } else // value without any quotes { - startAttrib=i; - // search for separator or end symbol - while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); } - endAttrib=i; + startAttrib=i; + // search for separator or end symbol + while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); } + endAttrib=i; if (i<(int)yyleng) { c=tagText.at(++i);} } - opt.value = tagText.mid(startAttrib,endAttrib-startAttrib); + opt.value = tagText.mid(startAttrib,endAttrib-startAttrib); if (opt.name == "align") opt.value = opt.value.lower(); else if (opt.name == "valign") { @@ -296,7 +302,7 @@ static void handleHtmlTag() } g_token->attribsStr = tagText.mid(startAttribList,i-startAttribList); } - + static QCString stripEmptyLines(const QCString &s) { if (s.isEmpty()) return QCString(); @@ -307,11 +313,11 @@ static QCString stripEmptyLines(const QCString &s) { int c; while ((c=s[p]) && (c==' ' || c=='\t')) p++; - if (s[p]=='\n') + if (s[p]=='\n') { - start=++p; + start=++p; } - else + else { break; } @@ -323,7 +329,7 @@ static QCString stripEmptyLines(const QCString &s) { int c; while ((c=s[p]) && (c==' ' || c=='\t')) p--; - if (s[p]=='\n') + if (s[p]=='\n') { end=p; } @@ -337,6 +343,7 @@ static QCString stripEmptyLines(const QCString &s) return s.mid(start,end-start); } +#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0) //-------------------------------------------------------------------------- #undef YY_INPUT @@ -378,21 +385,21 @@ OLISTITEM {BLANK}*[1-9][0-9]*"."{BLANK} ENDLIST {BLANK}*"."{BLANK}*\n ATTRNAME [a-z_A-Z\x80-\xFF][:a-z_A-Z0-9\x80-\xFF\-]* ATTRIB {ATTRNAME}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))? -URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=] +URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=\x80-\xFF] URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+ -URLPROTOCOL ("http:"|"https:"|"ftp:"|"file:"|"news:"|"irc") -FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+&#] -FILEECHAR [a-z_A-Z0-9\-\+&#] +URLPROTOCOL ("http:"|"https:"|"ftp:"|"ftps:"|"sftp:"|"file:"|"news:"|"irc:"|"ircs:") +FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+&#@] +FILEECHAR [a-z_A-Z0-9\-\+&#@] HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)+ FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK} -LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? +LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? VERBATIM "verbatim"{BLANK}* SPCMD1 {CMD}([a-z_A-Z][a-z_A-Z0-9]*|{VERBATIM}|"--"|"---") SPCMD2 {CMD}[\\@<>&$#%~".+=|-] SPCMD3 {CMD}_form#[0-9]+ SPCMD4 {CMD}"::" SPCMD5 {CMD}":" -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\*\&\(\)\[\]] @@ -427,7 +434,7 @@ WORD2 "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'" WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}" WORD2NQ "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'" CAPTION [cC][aA][pP][tT][iI][oO][nN] -HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">" +HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">" HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p"|"strike"|"u"|"del"|"ins"|"s" HTMLKEYU "STRONG"|"CENTER"|"TABLE"|"CAPTION"|"SMALL"|"CODE"|"DFN"|"VAR"|"IMG"|"PRE"|"SUB"|"SUP"|"TR"|"TD"|"TH"|"OL"|"UL"|"LI"|"TT"|"KBD"|"EM"|"HR"|"DL"|"DT"|"DD"|"BR"|"I"|"A"|"B"|"P"|"STRIKE"|"U"|"DEL"|"INS"|"S" HTMLKEYW {HTMLKEYL}|{HTMLKEYU} @@ -439,9 +446,9 @@ REFWORD4_NOCV (({SCOPEPRE}*"operator"{OPMASKOP2})|(("::"|"#"){SCOPEPRE}*"operat REFWORD4 {REFWORD4_NOCV}{CVSPEC}? REFWORD {FILEMASK}|{LABELID}|{REFWORD2}|{REFWORD3}|{REFWORD4} REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} +RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revision"|"Source"|"State")":"[^:\n$][^\n$]*"$" %option noyywrap -%option yylineno %x St_Para %x St_Comment @@ -493,21 +500,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} %% <St_Para>\r /* skip carriage return */ -<St_Para>^{LISTITEM} { /* list item */ +<St_Para>^{LISTITEM} { /* list item */ + lineCount(yytext,yyleng); QCString text=yytext; - int dashPos = text.findRev('-'); - g_token->isEnumList = text.at(dashPos+1)=='#'; + int dashPos = text.findRev('-'); + g_token->isEnumList = text.at(dashPos+1)=='#'; g_token->id = -1; - g_token->indent = computeIndent(yytext,dashPos); + g_token->indent = computeIndent(yytext,dashPos); return TK_LISTITEM; } -<St_Para>^{MLISTITEM} { /* list item */ +<St_Para>^{MLISTITEM} { /* list item */ if (!g_markdownSupport || g_insidePre) { REJECT; } else { + lineCount(yytext,yyleng); QCString text=yytext; static QRegExp re("[*+]"); int listPos = text.findRev(re); @@ -517,7 +526,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>^{OLISTITEM} { /* numbered list item */ +<St_Para>^{OLISTITEM} { /* numbered list item */ if (!g_markdownSupport || g_insidePre) { REJECT; @@ -534,21 +543,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */ + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); - int dashPos = text.findRev('-'); - g_token->isEnumList = text.at(dashPos+1)=='#'; + int dashPos = text.findRev('-'); + g_token->isEnumList = text.at(dashPos+1)=='#'; g_token->id = -1; - g_token->indent = computeIndent(text,dashPos); + g_token->indent = computeIndent(text,dashPos); return TK_LISTITEM; } -<St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */ if (!g_markdownSupport || g_insidePre) { REJECT; } else { + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); static QRegExp re("[*+]"); int markPos = text.findRev(re); @@ -558,13 +569,14 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */ if (!g_markdownSupport || g_insidePre) { REJECT; } else { + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); static QRegExp re("[1-9]"); int digitPos = text.find(re); @@ -575,41 +587,44 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>^{ENDLIST} { /* end list */ +<St_Para>^{ENDLIST} { /* end list */ + lineCount(yytext,yyleng); int dotPos = QCString(yytext).findRev('.'); - g_token->indent = computeIndent(yytext,dotPos); + g_token->indent = computeIndent(yytext,dotPos); return TK_ENDLIST; } -<St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */ + lineCount(yytext,yyleng); 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}+ { - g_token->name = "javalink"; - return TK_COMMAND_AT; - } + g_token->name = "javalink"; + return TK_COMMAND_AT; + } <St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" { - g_token->name = "inheritdoc"; - return TK_COMMAND_AT; - } + g_token->name = "inheritdoc"; + return TK_COMMAND_AT; + } <St_Para>"@_fakenl" { // artificial new line - yylineno++; - } + //g_yyLineNr++; + } <St_Para>{SPCMD3} { - g_token->name = "_form"; - bool ok; - g_token->id = QCString(yytext).right((int)yyleng-7).toInt(&ok); - ASSERT(ok); - return TK_COMMAND_SEL(); - } + g_token->name = "_form"; + bool ok; + g_token->id = QCString(yytext).right((int)yyleng-7).toInt(&ok); + ASSERT(ok); + return TK_COMMAND_SEL(); + } <St_Para>{CMD}"n"\n { /* \n followed by real newline */ - yylineno++; + lineCount(yytext,yyleng); + //g_yyLineNr++; g_token->name = yytext+1; - g_token->name = g_token->name.stripWhiteSpace(); - g_token->paramDir=TokenInfo::Unspecified; - return TK_COMMAND_SEL(); + g_token->name = g_token->name.stripWhiteSpace(); + g_token->paramDir=TokenInfo::Unspecified; + return TK_COMMAND_SEL(); } <St_Para>"\\ilinebr" { } @@ -618,108 +633,109 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_Para>{SPCMD5} | <St_Para>{SPCMD4} { /* special command */ g_token->name = yytext+1; - g_token->name = g_token->name.stripWhiteSpace(); - g_token->paramDir=TokenInfo::Unspecified; + g_token->name = g_token->name.stripWhiteSpace(); + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); - } + } <St_Para>{PARAMIO} { /* param [in,out] command */ - g_token->name = "param"; - QCString s(yytext); - bool isIn = s.find("in")!=-1; - bool isOut = s.find("out")!=-1; - if (isIn) - { - if (isOut) - { - g_token->paramDir=TokenInfo::InOut; - } - else - { - g_token->paramDir=TokenInfo::In; - } - } - else if (isOut) - { - g_token->paramDir=TokenInfo::Out; - } - else - { - g_token->paramDir=TokenInfo::Unspecified; - } - return TK_COMMAND_SEL(); - } + g_token->name = "param"; + QCString s(yytext); + bool isIn = s.find("in")!=-1; + bool isOut = s.find("out")!=-1; + if (isIn) + { + if (isOut) + { + g_token->paramDir=TokenInfo::InOut; + } + else + { + g_token->paramDir=TokenInfo::In; + } + } + else if (isOut) + { + g_token->paramDir=TokenInfo::Out; + } + else + { + g_token->paramDir=TokenInfo::Unspecified; + } + return TK_COMMAND_SEL(); + } <St_Para>{URLPROTOCOL}{URLMASK}/[,\.] { // URL, or URL. g_token->name=yytext; - g_token->isEMailAddr=FALSE; - return TK_URL; + g_token->isEMailAddr=FALSE; + return TK_URL; } <St_Para>{URLPROTOCOL}{URLMASK} { // URL g_token->name=yytext; - g_token->isEMailAddr=FALSE; - return TK_URL; + g_token->isEMailAddr=FALSE; + return TK_URL; } <St_Para>"<"{URLPROTOCOL}{URLMASK}">" { // URL g_token->name=yytext; g_token->name = g_token->name.mid(1,g_token->name.length()-2); - g_token->isEMailAddr=FALSE; - return TK_URL; + g_token->isEMailAddr=FALSE; + return TK_URL; } <St_Para>{MAILADDR} { // Mail address g_token->name=yytext; g_token->name.stripPrefix("mailto:"); - g_token->isEMailAddr=TRUE; - return TK_URL; + g_token->isEMailAddr=TRUE; + return TK_URL; } <St_Para>"<"{MAILADDR}">" { // Mail address g_token->name=yytext; g_token->name = g_token->name.mid(1,g_token->name.length()-2); g_token->name.stripPrefix("mailto:"); - g_token->isEMailAddr=TRUE; - return TK_URL; + g_token->isEMailAddr=TRUE; + return TK_URL; } <St_Para>"<"{MAILADDR2}">" { // anti spam mail address g_token->name=yytext; - return TK_WORD; + return TK_WORD; } -<St_Para>"$"{ID}":"[^:\n$][^\n$]*"$" { /* RCS tag */ +<St_Para>{RCSID} { /* RCS tag */ QCString tagName(yytext+1); - int index=tagName.find(':'); - g_token->name = tagName.left(index); - int text_begin = index+2; - int text_end = tagName.length()-1; - if (tagName[text_begin-1]==':') /* check for Subversion fixed-length keyword */ - { - ++text_begin; - if (tagName[text_end-1]=='#') - --text_end; - } - g_token->text = tagName.mid(text_begin,text_end-text_begin); - return TK_RCSTAG; - } + int index=tagName.find(':'); + g_token->name = tagName.left(index); + int text_begin = index+2; + int text_end = tagName.length()-1; + if (tagName[text_begin-1]==':') /* check for Subversion fixed-length keyword */ + { + ++text_begin; + if (tagName[text_end-1]=='#') + --text_end; + } + g_token->text = tagName.mid(text_begin,text_end-text_begin); + return TK_RCSTAG; + } <St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}")" | /* environment variable */ <St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}"("{ID}"))" { /* environment variable */ QCString name = &yytext[2]; - name = name.left(name.length()-1); - QCString value = Portable::getenv(name); - for (int i=value.length()-1;i>=0;i--) unput(value.at(i)); + name = name.left(name.length()-1); + QCString value = Portable::getenv(name); + for (int i=value.length()-1;i>=0;i--) unput(value.at(i)); } -<St_Para>{HTMLTAG} { /* html tag */ +<St_Para>{HTMLTAG} { /* html tag */ + lineCount(yytext,yyleng); handleHtmlTag(); return TK_HTMLTAG; } -<St_Para,St_Text>"&"{ID}";" { /* special symbol */ +<St_Para,St_Text>"&"{ID}";" { /* special symbol */ g_token->name = yytext; return TK_SYMBOL; } /********* patterns for linkable words ******************/ -<St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html - * tag to be recognized as a templated classes - */ +<St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html + * tag to be recognized as a templated classes + */ g_token->name = yytext; return TK_LNKWORD; - } + } <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments <St_Para>{LNKWORD1} | <St_Para>{LNKWORD1}{FUNCARG} | @@ -727,34 +743,35 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_Para>{LNKWORD3} { g_token->name = yytext; return TK_LNKWORD; - } + } <St_Para>{LNKWORD1}{FUNCARG}{CVSPEC}[^a-z_A-Z0-9] { g_token->name = yytext; g_token->name = g_token->name.left(g_token->name.length()-1); - unput(yytext[(int)yyleng-1]); + unput(yytext[(int)yyleng-1]); return TK_LNKWORD; } /********* patterns for normal words ******************/ <St_Para,St_Text>[\-+0-9] | <St_Para,St_Text>{WORD1} | -<St_Para,St_Text>{WORD2} { /* function call */ +<St_Para,St_Text>{WORD2} { /* function call */ + lineCount(yytext,yyleng); if (yytext[0]=='%') // strip % if present - g_token->name = &yytext[1]; - else + g_token->name = &yytext[1]; + else g_token->name = yytext; return TK_WORD; - /* the following is dummy code to please the - * compiler, removing this results in a warning - * on my machine - */ - goto find_rule; + /* the following is dummy code to please the + * compiler, removing this results in a warning + * on my machine + */ + goto find_rule; } <St_Text>({ID}".")+{ID} { g_token->name = yytext; return TK_WORD; - } + } <St_Para,St_Text>"operator"/{BLANK}*"<"[a-zA-Z_0-9]+">" { // Special case: word "operator" followed by a HTML command // avoid interpretation as "operator <" g_token->name = yytext; @@ -764,45 +781,58 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} /*******************************************************/ <St_Para,St_Text>{BLANK}+ | -<St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */ +<St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */ + lineCount(yytext,yyleng); g_token->chars=yytext; return TK_WHITESPACE; } <St_Text>[\\@<>&$#%~] { g_token->name = yytext; return TK_COMMAND_SEL(); - } + } <St_Para>({BLANK}*\n)+{BLANK}*\n/{LISTITEM} { /* skip trailing paragraph followed by new list item */ if (g_insidePre || g_autoListLevel==0) { REJECT; } + lineCount(yytext,yyleng); } <St_Para>({BLANK}*\n)+{BLANK}*\n/{MLISTITEM} { /* skip trailing paragraph followed by new list item */ if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } + lineCount(yytext,yyleng); } <St_Para>({BLANK}*\n)+{BLANK}*\n/{OLISTITEM} { /* skip trailing paragraph followed by new list item */ if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } + lineCount(yytext,yyleng); } -<St_Para>({BLANK}*\n)+{BLANK}*\n{BLANK}* { - g_token->indent=computeIndent(yytext,(int)yyleng); - int i; - // put back the indentation (needed for list items) - for (i=0;i<g_token->indent;i++) +<St_Para>({BLANK}*(\n|"\\ilinebr"))+{BLANK}*(\n|"\\ilinebr"){BLANK}* { + lineCount(yytext,yyleng); + if (g_insidePre) + { + g_token->chars=yytext; + return TK_WHITESPACE; + } + else { - unput(' '); + g_token->indent=computeIndent(yytext,(int)yyleng); + int i; + // put back the indentation (needed for list items) + for (i=0;i<g_token->indent;i++) + { + unput(' '); + } + // tell flex that after putting the last indent + // back we are at the beginning of the line + YY_CURRENT_BUFFER->yy_at_bol=1; + // start of a new paragraph + return TK_NEWPARA; } - // tell flex that after putting the last indent - // back we are at the beginning of the line - YY_CURRENT_BUFFER->yy_at_bol=1; - // start of a new paragraph - return TK_NEWPARA; } <St_CodeOpt>{BLANK}*"{"(".")?{LABELID}"}" { g_token->name = yytext; @@ -813,20 +843,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_CodeOpt>"\\ilinebr" | <St_CodeOpt>\n | <St_CodeOpt>. { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + unput_string(yytext,yyleng); BEGIN(St_Code); } <St_Code>{WS}*{CMD}"endcode" { + lineCount(yytext,yyleng); return RetVal_OK; } <St_XmlCode>{WS}*"</code>" { + lineCount(yytext,yyleng); return RetVal_OK; } <St_Code,St_XmlCode>[^\\@\n<]+ | <St_Code,St_XmlCode>\n | <St_Code,St_XmlCode>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_HtmlOnlyOption>" [block]" { // the space is added in commentscan.l g_token->name="block"; BEGIN(St_HtmlOnly); @@ -836,7 +869,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} BEGIN(St_HtmlOnly); } <St_HtmlOnlyOption>"\\ilinebr" { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + unput_string(yytext,yyleng); BEGIN(St_HtmlOnly); } <St_HtmlOnly>{CMD}"endhtmlonly" { @@ -845,77 +878,86 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_HtmlOnly>[^\\@\n$]+ | <St_HtmlOnly>\n | <St_HtmlOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_ManOnly>{CMD}"endmanonly" { return RetVal_OK; } <St_ManOnly>[^\\@\n$]+ | <St_ManOnly>\n | <St_ManOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_RtfOnly>{CMD}"endrtfonly" { return RetVal_OK; } <St_RtfOnly>[^\\@\n$]+ | <St_RtfOnly>\n | <St_RtfOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_LatexOnly>{CMD}"endlatexonly" { return RetVal_OK; } <St_LatexOnly>[^\\@\n]+ | <St_LatexOnly>\n | <St_LatexOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_XmlOnly>{CMD}"endxmlonly" { return RetVal_OK; } <St_XmlOnly>[^\\@\n]+ | <St_XmlOnly>\n | <St_XmlOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_DbOnly>{CMD}"enddocbookonly" { return RetVal_OK; } <St_DbOnly>[^\\@\n]+ | <St_DbOnly>\n | <St_DbOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_Verbatim>{CMD}"endverbatim" { - g_token->verb=stripEmptyLines(g_token->verb); + g_token->verb=stripEmptyLines(g_token->verb); return RetVal_OK; } <St_Verbatim>[^\\@\n]+ | <St_Verbatim>\n | <St_Verbatim>. { /* Verbatim text */ - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_Dot>{CMD}"enddot" { return RetVal_OK; } <St_Dot>[^\\@\n]+ | <St_Dot>\n | <St_Dot>. { /* dot text */ - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_Msc>{CMD}("endmsc") { return RetVal_OK; } <St_Msc>[^\\@\n]+ | <St_Msc>\n | <St_Msc>. { /* msc text */ - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_PlantUMLOpt>{BLANK}*"{"[^}]*"}" { // case 1: file name is specified as {filename} g_token->sectionId = QCString(yytext).stripWhiteSpace(); // skip curly brackets around the optional image name - g_token->sectionId = g_token->sectionId.mid(1,g_token->sectionId.length()-2).stripWhiteSpace(); + g_token->sectionId = g_token->sectionId.mid(1,g_token->sectionId.length()-2).stripWhiteSpace(); return RetVal_OK; } <St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}+/{ID}"=" { // case 2: plain file name specified followed by an attribute @@ -938,7 +980,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_PlantUMLOpt>"\n" | <St_PlantUMLOpt>. { g_token->sectionId = ""; - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + unput_string(yytext,yyleng); return RetVal_OK; } <St_PlantUML>{CMD}"enduml" { @@ -947,117 +989,126 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_PlantUML>[^\\@\n]+ | <St_PlantUML>\n | <St_PlantUML>. { /* plantuml text */ - g_token->verb+=yytext; - } -<St_Title>"\"" { // quoted title - BEGIN(St_TitleQ); - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } +<St_Title>"\"" { // quoted title + BEGIN(St_TitleQ); + } <St_Title>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } -<St_Title>. { // non-quoted title - unput(*yytext); - BEGIN(St_TitleN); +<St_Title>. { // non-quoted title + unput(*yytext); + BEGIN(St_TitleN); } -<St_Title>\n { +<St_Title>\n { unput(*yytext); - return 0; - } + return 0; + } <St_Title>"\\ilinebr" { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; + unput_string(yytext,yyleng); + return 0; } <St_TitleN>"&"{ID}";" { /* symbol */ g_token->name = yytext; - return TK_SYMBOL; + 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; + lineCount(yytext,yyleng); + } +<St_TitleN>\n { /* new line => end of title */ + unput(*yytext); + return 0; } -<St_TitleN>{SPCMD1} | -<St_TitleN>{SPCMD2} { /* special command */ +<St_TitleN>"\\ilinebr" { /* new line => end of title */ + unput_string(yytext,yyleng); + return 0; + } +<St_TitleN>{SPCMD1} | +<St_TitleN>{SPCMD2} { /* special command */ g_token->name = yytext+1; - g_token->paramDir=TokenInfo::Unspecified; + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } <St_TitleN>{ID}"=" { /* attribute */ if (yytext[0]=='%') // strip % if present - g_token->name = &yytext[1]; - else + g_token->name = &yytext[1]; + else g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_TitleN>[\-+0-9] | <St_TitleN>{WORD1} | <St_TitleN>{WORD2} { /* word */ + lineCount(yytext,yyleng); if (yytext[0]=='%') // strip % if present - g_token->name = &yytext[1]; - else + g_token->name = &yytext[1]; + else g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_TitleN>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } <St_TitleQ>"&"{ID}";" { /* symbol */ g_token->name = yytext; - return TK_SYMBOL; + 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; + unput_string(yytext,yyleng); + return 0; } -<St_TitleQ>{SPCMD1} | -<St_TitleQ>{SPCMD2} { /* special command */ +<St_TitleQ>{SPCMD1} | +<St_TitleQ>{SPCMD2} { /* special command */ g_token->name = yytext+1; - g_token->paramDir=TokenInfo::Unspecified; + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } <St_TitleQ>{WORD1NQ} | <St_TitleQ>{WORD2NQ} { /* word */ g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_TitleQ>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } -<St_TitleQ>"\"" { /* closing quote => end of title */ - BEGIN(St_TitleA); - return 0; +<St_TitleQ>"\"" { /* closing quote => end of title */ + BEGIN(St_TitleA); + 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(); - BEGIN(St_TitleV); - } + g_token->name = yytext; + g_token->name = g_token->name.left(g_token->name.find('=')).stripWhiteSpace(); + BEGIN(St_TitleV); + } <St_TitleV>[^ \t\r\n]+ { // attribute value - g_token->chars = yytext; - BEGIN(St_TitleN); - return TK_WORD; - } + lineCount(yytext,yyleng); + g_token->chars = yytext; + BEGIN(St_TitleN); + return TK_WORD; + } <St_TitleV,St_TitleA>. { - unput(*yytext); - return 0; + unput(*yytext); + return 0; } <St_TitleV,St_TitleA>(\n|"\\ilinebr") { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; + unput_string(yytext,yyleng); + return 0; } <St_Anchor>{LABELID}{WS}? { // anchor - g_token->name = QCString(yytext).stripWhiteSpace(); - return TK_WORD; - } -<St_Anchor>. { - unput(*yytext); - return 0; - } + lineCount(yytext,yyleng); + g_token->name = QCString(yytext).stripWhiteSpace(); + return TK_WORD; + } +<St_Anchor>. { + unput(*yytext); + return 0; + } <St_Cite>{CITEID} { // label to cite if (yytext[0] =='"') { @@ -1068,59 +1119,60 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} { g_token->name=yytext; } - return TK_WORD; - } + return TK_WORD; + } <St_Cite>{BLANK} { // white space - unput(' '); - return 0; + unput(' '); + return 0; } <St_Cite>(\n|"\\ilinebr") { // new line - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; - } -<St_Cite>. { // any other character + unput_string(yytext,yyleng); + return 0; + } +<St_Cite>. { // any other character unput(*yytext); - return 0; - } + return 0; + } <St_Ref>{REFWORD_NOCV}/{BLANK}("const")[a-z_A-Z0-9] { // see bug776988 - g_token->name=yytext; - return TK_WORD; + g_token->name=yytext; + return TK_WORD; } <St_Ref>{REFWORD_NOCV}/{BLANK}("volatile")[a-z_A-Z0-9] { // see bug776988 - g_token->name=yytext; - return TK_WORD; + g_token->name=yytext; + return TK_WORD; } <St_Ref>{REFWORD} { // label to refer to - g_token->name=yytext; - return TK_WORD; - } + g_token->name=yytext; + return TK_WORD; + } <St_Ref>{BLANK} { // white space - unput(' '); - return 0; + unput(' '); + return 0; } <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string - BEGIN(St_Ref2); + lineCount(yytext,yyleng); + BEGIN(St_Ref2); } <St_Ref>(\n|"\\ilinebr") { // new line - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; - } -<St_Ref>. { // any other character + unput_string(yytext,yyleng); + return 0; + } +<St_Ref>. { // any other character unput(*yytext); - return 0; - } + return 0; + } <St_IntRef>[A-Z_a-z0-9.:/#\-\+\(\)]+ { g_token->name = yytext; - return TK_WORD; - } + return TK_WORD; + } <St_IntRef>{BLANK}+"\"" { BEGIN(St_Ref2); } <St_SetScope>({SCOPEMASK}|{ANONNS}){BLANK}|{FILEMASK} { g_token->name = yytext; g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; - } + return TK_WORD; + } <St_SetScope>{SCOPEMASK}"<" { g_token->name = yytext; g_token->name = g_token->name.stripWhiteSpace(); @@ -1146,26 +1198,27 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } <St_Ref2>"&"{ID}";" { /* symbol */ g_token->name = yytext; - return TK_SYMBOL; + return TK_SYMBOL; } <St_Ref2>"\""|\n|"\\ilinebr" { /* " or \n => end of title */ - return 0; + lineCount(yytext,yyleng); + return 0; } -<St_Ref2>{SPCMD1} | -<St_Ref2>{SPCMD2} { /* special command */ +<St_Ref2>{SPCMD1} | +<St_Ref2>{SPCMD2} { /* special command */ g_token->name = yytext+1; - g_token->paramDir=TokenInfo::Unspecified; + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } <St_Ref2>{WORD1NQ} | <St_Ref2>{WORD2NQ} { /* word */ g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_Ref2>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } <St_XRefItem>{LABELID} { g_token->name=yytext; @@ -1174,39 +1227,41 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} BEGIN(St_XRefItem2); } <St_XRefItem2>[0-9]+"." { - QCString numStr=yytext; - numStr=numStr.left((int)yyleng-1); - g_token->id=numStr.toInt(); - return RetVal_OK; - } + QCString numStr=yytext; + numStr=numStr.left((int)yyleng-1); + g_token->id=numStr.toInt(); + return RetVal_OK; + } <St_Para,St_Title,St_Ref2>"<!--" { /* html style comment block */ g_commentState = YY_START; - BEGIN(St_Comment); + BEGIN(St_Comment); } <St_Param>"\""[^\n\"]+"\"" { - g_token->name = yytext+1; - g_token->name = g_token->name.left((int)yyleng-2); - return TK_WORD; + g_token->name = yytext+1; + g_token->name = g_token->name.left((int)yyleng-2); + return TK_WORD; } <St_Param>({PHPTYPE}{BLANK}*("["{BLANK}*"]")*{BLANK}*"|"{BLANK}*)*{PHPTYPE}{BLANK}*("["{BLANK}*"]")*{WS}+("&")?"$"{LABELID} { - QCString params = yytext; - int j = params.find('&'); - int i = params.find('$'); - if (j<i && j!=-1) i=j; - QCString types = params.left(i).stripWhiteSpace(); - g_token->name = types+"#"+params.mid(i); - return TK_WORD; - } + lineCount(yytext,yyleng); + QCString params = yytext; + int j = params.find('&'); + int i = params.find('$'); + if (j<i && j!=-1) i=j; + QCString types = params.left(i).stripWhiteSpace(); + g_token->name = types+"#"+params.mid(i); + return TK_WORD; + } <St_Param>[^ \t\n,@\\]+ { - g_token->name = yytext; + g_token->name = yytext; if (g_token->name.at(static_cast<uint>(yyleng)-1)==':') { g_token->name=g_token->name.left(static_cast<uint>(yyleng)-1); } - return TK_WORD; + return TK_WORD; } <St_Param>{WS}*","{WS}* /* param separator */ -<St_Param>{WS} { +<St_Param>{WS} { + lineCount(yytext,yyleng); g_token->chars=yytext; return TK_WHITESPACE; } @@ -1215,6 +1270,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } <St_Options>{WS}*","{WS}* <St_Options>{WS} { /* option separator */ + lineCount(yytext,yyleng); g_token->name+=","; } <St_Options>"}" { @@ -1234,25 +1290,35 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return 0; } <St_File>{FILEMASK} { - g_token->name = yytext; - return TK_WORD; - } -<St_File>"\""[^\n\"]+"\"" { - QCString text=yytext; - g_token->name = text.mid(1,text.length()-2); - return TK_WORD; - } -<St_Pattern>[^\r\n]+ { g_token->name = yytext; + return TK_WORD; + } +<St_File>"\""[^\n\"]+"\"" { + QCString text=yytext; + g_token->name = text.mid(1,text.length()-2); + return TK_WORD; + } +<St_Pattern>[^\\\r\n]+ { + g_token->name += yytext; + } +<St_Pattern>"\\ilinebr" { g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; - } + return TK_WORD; + } +<St_Pattern>\n { + lineCount(yytext,yyleng); + g_token->name = g_token->name.stripWhiteSpace(); + return TK_WORD; + } +<St_Pattern>. { + g_token->name += yytext; + } <St_Link>{LINKMASK}|{REFWORD} { g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_Comment>"-->" { /* end of html comment */ - BEGIN(g_commentState); + BEGIN(g_commentState); } <St_Comment>[^-]+ /* inside html comment */ <St_Comment>. /* inside html comment */ @@ -1260,13 +1326,17 @@ 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|"\\ilinebr") { return 0; } +<St_SkipTitle>(\n|"\\ilinebr") { + lineCount(yytext,yyleng); + return 0; + } - /* State for the pass used to find the anchors and sections */ + /* State for the pass used to find the anchors and sections */ <St_Sections>[^\n@\\<]+ <St_Sections>{CMD}("<"|{CMD}) <St_Sections>"<"{CAPTION}({WS}+{ATTRIB})*">" { + lineCount(yytext,yyleng); QCString tag=yytext; int s=tag.find("id="); if (s!=-1) // command has id attribute @@ -1284,142 +1354,146 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } } -<St_Sections>{CMD}"anchor"{BLANK}+ { - g_secType = SectionType::Anchor; - BEGIN(St_SecLabel1); +<St_Sections>{CMD}"anchor"{BLANK}+ { + g_secType = SectionType::Anchor; + BEGIN(St_SecLabel1); } -<St_Sections>{CMD}"section"{BLANK}+ { - g_secType = SectionType::Section; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"section"{BLANK}+ { + g_secType = SectionType::Section; + BEGIN(St_SecLabel2); } -<St_Sections>{CMD}"subsection"{BLANK}+ { - g_secType = SectionType::Subsection; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"subsection"{BLANK}+ { + g_secType = SectionType::Subsection; + BEGIN(St_SecLabel2); } -<St_Sections>{CMD}"subsubsection"{BLANK}+ { - g_secType = SectionType::Subsubsection; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"subsubsection"{BLANK}+ { + g_secType = SectionType::Subsubsection; + BEGIN(St_SecLabel2); } -<St_Sections>{CMD}"paragraph"{BLANK}+ { - g_secType = SectionType::Paragraph; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"paragraph"{BLANK}+ { + g_secType = SectionType::Paragraph; + BEGIN(St_SecLabel2); } <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] { g_endMarker="endverbatim"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] { g_endMarker="enddot"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"msc"/[^a-z_A-Z0-9] { g_endMarker="endmsc"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"startuml"/[^a-z_A-Z0-9] { g_endMarker="enduml"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] { g_endMarker="endhtmlonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"latexonly"/[^a-z_A-Z0-9] { g_endMarker="endlatexonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"manonly"/[^a-z_A-Z0-9] { g_endMarker="endmanonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"rtfonly"/[^a-z_A-Z0-9] { g_endMarker="endrtfonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] { g_endMarker="endxmlonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"docbookonly"/[^a-z_A-Z0-9] { g_endMarker="enddocbookonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"code"/[^a-z_A-Z0-9] { g_endMarker="endcode"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>"<!--" { g_endMarker="-->"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } -<St_SecSkip>{CMD}{ID} { +<St_SecSkip>{CMD}{ID} { if (qstrcmp(yytext+1,g_endMarker)==0) - { - BEGIN(St_Sections); - } + { + BEGIN(St_Sections); + } } -<St_SecSkip>"-->" { +<St_SecSkip>"-->" { if (qstrcmp(yytext,g_endMarker)==0) - { - BEGIN(St_Sections); - } + { + BEGIN(St_Sections); + } } <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+ <St_SecSkip>. <St_SecSkip>(\n|"\\ilinebr") <St_Sections>. <St_Sections>(\n|"\\ilinebr") -<St_SecLabel1>{LABELID} { +<St_SecLabel1>{LABELID} { + lineCount(yytext,yyleng); g_secLabel = yytext; processSection(); BEGIN(St_Sections); } -<St_SecLabel2>{LABELID}{BLANK}+ | -<St_SecLabel2>{LABELID} { +<St_SecLabel2>{LABELID}{BLANK}+ | +<St_SecLabel2>{LABELID} { g_secLabel = yytext; - g_secLabel = g_secLabel.stripWhiteSpace(); + g_secLabel = g_secLabel.stripWhiteSpace(); BEGIN(St_SecTitle); } <St_SecTitle>[^\n]+ | <St_SecTitle>[^\n]*\n { + lineCount(yytext,yyleng); g_secTitle = yytext; - g_secTitle = g_secTitle.stripWhiteSpace(); + g_secTitle = g_secTitle.stripWhiteSpace(); if (g_secTitle.right(8)=="\\ilinebr") { g_secTitle.left(g_secTitle.length()-8); } processSection(); BEGIN(St_Sections); - } + } <St_SecTitle,St_SecLabel1,St_SecLabel2>. { - warn(g_fileName,yylineno,"Unexpected character '%s' while looking for section label or title",yytext); + warn(g_fileName,g_yyLineNr,"Unexpected character '%s' while looking for section label or title",yytext); } <St_Snippet>[^\\\n]+ { - g_token->name += yytext; + g_token->name += yytext; } <St_Snippet>"\\" { - g_token->name += yytext; + g_token->name += yytext; } <St_Snippet>(\n|"\\ilinebr") { - g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; - } - - /* Generic rules that work for all states */ -<*>\n { - warn(g_fileName,yylineno,"Unexpected new line character"); - } + lineCount(yytext,yyleng); + g_token->name = g_token->name.stripWhiteSpace(); + return TK_WORD; + } + + /* Generic rules that work for all states */ +<*>\n { + lineCount(yytext,yyleng); + warn(g_fileName,g_yyLineNr,"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; - return TK_COMMAND_SEL(); + //warn(g_fileName,g_yyLineNr,"Unexpected character '%s', assuming command \\%s was meant.",yytext,yytext); + g_token->name = yytext; + return TK_COMMAND_SEL(); + } +<*>. { + warn(g_fileName,g_yyLineNr,"Unexpected character '%s'",yytext); } -<*>. { - warn(g_fileName,yylineno,"Unexpected character '%s'",yytext); - } %% //-------------------------------------------------------------------------- @@ -1435,7 +1509,7 @@ void doctokenizerYYFindSections(const char *input,const Definition *d, g_definition = d; g_fileName = fileName; BEGIN(St_Sections); - doctokenizerYYlineno = 1; + g_yyLineNr = 1; doctokenizerYYlex(); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } @@ -1565,6 +1639,7 @@ void doctokenizerYYsetStateFile() void doctokenizerYYsetStatePattern() { + g_token->name = ""; BEGIN(St_Pattern); } @@ -1672,6 +1747,17 @@ void doctokenizerYYendAutoList() // return retval; //} +void setDoctokinizerLineNr(int lineno) +{ + g_yyLineNr = lineno; +} + +int getDoctokinizerLineNr(void) +{ + return g_yyLineNr; +} + + #if USE_STATE2STRING #include "doctokenizer.l.h" #endif diff --git a/src/docvisitor.cpp b/src/docvisitor.cpp new file mode 100644 index 0000000..d46d8c0 --- /dev/null +++ b/src/docvisitor.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * 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. + */ + + +#include <unordered_map> + +#include "parserintf.h" +#include "docvisitor.h" +#include "util.h" +#include "types.h" +#include "doxygen.h" + +struct DocVisitor::Private +{ + int id; + std::unordered_map< std::string, std::unique_ptr<CodeParserInterface> > parserFactoryMap; +}; + +DocVisitor::DocVisitor(int id) : m_p(std::make_unique<Private>()) +{ + m_p->id = id; +} + +DocVisitor::~DocVisitor() +{ +} + +CodeParserInterface &DocVisitor::getCodeParser(const char *extension) +{ + std::string ext(extension?extension:""); + // for each extension we create a code parser once per visitor, so that + // the context of the same parser object is reused throughout multiple passes for instance + // for code fragments shown via dontinclude. + auto it = m_p->parserFactoryMap.find(ext); + if (it==m_p->parserFactoryMap.end()) + { + auto factory = Doxygen::parserManager->getCodeParserFactory(extension); + auto result = m_p->parserFactoryMap.insert(std::make_pair(ext,factory())); + it = result.first; + } + return *it->second.get(); +} + +int DocVisitor::id() const +{ + return m_p->id; +} diff --git a/src/docvisitor.h b/src/docvisitor.h index 0a53595..4d4b263 100644 --- a/src/docvisitor.h +++ b/src/docvisitor.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,6 +16,8 @@ #ifndef _DOCVISITOR_H #define _DOCVISITOR_H +#include <memory> + // ids const int DocVisitor_Html = 0; const int DocVisitor_Latex = 1; @@ -84,18 +83,21 @@ class DocSimpleSectSep; class DocHtmlBlockQuote; class DocVhdlFlow; class DocParBlock; +class CodeParserInterface; /*! @brief Abstract visitor that participates in the visitor pattern. */ class DocVisitor { - int m_id; + struct Private; + std::unique_ptr<Private> m_p; public: - DocVisitor(int id) : m_id(id) {} - virtual ~DocVisitor() {} - int id() const { return m_id; } + DocVisitor(int id); + virtual ~DocVisitor(); + int id() const; + CodeParserInterface &getCodeParser(const char *langExt); - /*! @name Visitor functions for leaf nodes + /*! @name Visitor functions for leaf nodes * @{ */ virtual void visit(DocWord *) = 0; @@ -117,7 +119,7 @@ class DocVisitor virtual void visit(DocCite *) = 0; /*! @} */ - /*! @name Visitor functions for internal nodes + /*! @name Visitor functions for internal nodes * @{ */ virtual void visitPre(DocAutoList *) = 0; @@ -167,7 +169,7 @@ class DocVisitor virtual void visitPre(DocDotFile *) = 0; virtual void visitPost(DocDotFile *) = 0; virtual void visitPre(DocMscFile *) = 0; - virtual void visitPost(DocMscFile *) = 0; + virtual void visitPost(DocMscFile *) = 0; virtual void visitPre(DocDiaFile *) = 0; virtual void visitPost(DocDiaFile *) = 0; virtual void visitPre(DocLink *) = 0; diff --git a/src/dotcallgraph.cpp b/src/dotcallgraph.cpp index 5e13f8e..cbd62ef 100644 --- a/src/dotcallgraph.cpp +++ b/src/dotcallgraph.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * -* Copyright (C) 1997-2019 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 @@ -20,10 +20,6 @@ #include "config.h" #include "util.h" -#define HIDE_SCOPE_NAMES Config_getBool(HIDE_SCOPE_NAMES) -#define DOT_GRAPH_MAX_NODES Config_getInt(DOT_GRAPH_MAX_NODES) -#define MAX_DOT_GRAPH_DEPTH Config_getInt(MAX_DOT_GRAPH_DEPTH) - static QCString getUniqueId(const MemberDef *md) { QCString result = md->getReference()+"$"+ @@ -34,51 +30,45 @@ static QCString getUniqueId(const MemberDef *md) void DotCallGraph::buildGraph(DotNode *n,const MemberDef *md,int distance) { - MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); - if (refs) + auto refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); + for (const auto &rmd : refs) { - refs->sort(); - MemberSDict::Iterator mri(*refs); - MemberDef *rmd; - for (;(rmd=mri.current());++mri) + if (rmd->showInCallGraph()) { - if (rmd->showInCallGraph()) + QCString uniqueId = getUniqueId(rmd); + DotNode *bn = m_usedNodes->find(uniqueId); + if (bn) // file is already a node in the graph + { + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + } + else { - QCString uniqueId = getUniqueId(rmd); - DotNode *bn = m_usedNodes->find(uniqueId); - if (bn) // file is already a node in the graph + QCString name; + if (Config_getBool(HIDE_SCOPE_NAMES)) { - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); + name = rmd->getOuterScope()==m_scope ? + rmd->name() : rmd->qualifiedName(); } else { - QCString name; - if (HIDE_SCOPE_NAMES) - { - name = rmd->getOuterScope()==m_scope ? - rmd->name() : rmd->qualifiedName(); - } - else - { - name = rmd->qualifiedName(); - } - QCString tooltip = rmd->briefDescriptionAsTooltip(); - bn = new DotNode( + name = rmd->qualifiedName(); + } + QCString tooltip = rmd->briefDescriptionAsTooltip(); + bn = new DotNode( getNextNodeNumber(), linkToText(rmd->getLanguage(),name,FALSE), tooltip, uniqueId, 0 //distance - ); - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); - m_usedNodes->insert(uniqueId,bn); + ); + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + m_usedNodes->insert(uniqueId,bn); - buildGraph(bn,rmd,distance+1); - } + buildGraph(bn,rmd,distance+1); } } } @@ -89,7 +79,7 @@ void DotCallGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes) while (queue.count()>0 && maxNodes>0) { DotNode *n = queue.take(0); - if (!n->isVisible() && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed + if (!n->isVisible() && n->distance()<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed { n->markAsVisible(); maxNodes--; @@ -121,9 +111,9 @@ void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue) const DotNode *dn; for (li.toFirst();(dn=li.current());++li) { - if (!dn->isVisible()) + if (!dn->isVisible()) truncated = TRUE; - else + else queue.append(dn); } } @@ -139,7 +129,7 @@ DotCallGraph::DotCallGraph(const MemberDef *md,bool inverse) m_scope = md->getOuterScope(); QCString uniqueId = getUniqueId(md); QCString name; - if (HIDE_SCOPE_NAMES) + if (Config_getBool(HIDE_SCOPE_NAMES)) { name = md->name(); } @@ -159,7 +149,7 @@ DotCallGraph::DotCallGraph(const MemberDef *md,bool inverse) m_usedNodes->insert(uniqueId,m_startNode); buildGraph(m_startNode,md,1); - int maxNodes = DOT_GRAPH_MAX_NODES; + int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes); @@ -198,7 +188,7 @@ QCString DotCallGraph::getMapLabel() const } QCString DotCallGraph::writeGraph( - FTextStream &out, + FTextStream &out, GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat, const char *path, @@ -216,7 +206,7 @@ bool DotCallGraph::isTrivial() const bool DotCallGraph::isTooBig() const { - return numNodes()>=DOT_GRAPH_MAX_NODES; + return numNodes()>=Config_getInt(DOT_GRAPH_MAX_NODES); } int DotCallGraph::numNodes() const diff --git a/src/dotclassgraph.cpp b/src/dotclassgraph.cpp index 84b7962..be318e4 100644 --- a/src/dotclassgraph.cpp +++ b/src/dotclassgraph.cpp @@ -20,12 +20,6 @@ #include "config.h" #include "util.h" -#define HIDE_SCOPE_NAMES Config_getBool(HIDE_SCOPE_NAMES) -#define MAX_DOT_GRAPH_DEPTH Config_getInt(MAX_DOT_GRAPH_DEPTH) -#define UML_LOOK Config_getBool(UML_LOOK) -#define TEMPLATE_RELATIONS Config_getBool(TEMPLATE_RELATIONS) -#define DOT_GRAPH_MAX_NODES Config_getInt(DOT_GRAPH_MAX_NODES) - void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot, const char *label,const char *usedName,const char *templSpec,bool base,int distance) { @@ -44,7 +38,7 @@ void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot, } else if (templSpec) // name has a template part { - className=insertTemplateSpecifierInScope(cd->name(),templSpec); + className=insertTemplateSpecifierInScope(cd->displayName(),templSpec); } else // just a normal name { @@ -71,7 +65,7 @@ void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot, else // new class { QCString displayName=className; - if (HIDE_SCOPE_NAMES) displayName=stripScope(displayName); + if (Config_getBool(HIDE_SCOPE_NAMES)) displayName=stripScope(displayName); QCString tmp_url; if (cd->isLinkable() && !cd->isHidden()) { @@ -162,7 +156,7 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, { DotNode *n = childQueue.take(0); int distance = n->distance(); - if (!n->isVisible() && distance<=MAX_DOT_GRAPH_DEPTH) // not yet processed + if (!n->isVisible() && distance<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed { if (distance>0) { @@ -191,7 +185,7 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, if (includeParents && parentQueue.count()>0) { DotNode *n = parentQueue.take(0); - if ((!n->isVisible() || firstNode) && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed + if ((!n->isVisible() || firstNode) && n->distance()<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed { firstNode=FALSE; int distance = n->distance(); @@ -220,7 +214,7 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, } } } - if (UML_LOOK) return FALSE; // UML graph are always top to bottom + if (Config_getBool(UML_LOOK)) return FALSE; // UML graph are always top to bottom int maxWidth=0; int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size()); uint i; @@ -266,18 +260,11 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista if (m_graphType == Inheritance || m_graphType==Collaboration) { - BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses(); - if (bcl) + for (const auto &bcd : base ? cd->baseClasses() : cd->subClasses()) { - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - //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); - } + //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); } } if (m_graphType == Collaboration) @@ -300,7 +287,7 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista } } } - if (TEMPLATE_RELATIONS && base) + if (Config_getBool(TEMPLATE_RELATIONS) && base) { ConstraintClassDict *dict = cd->templateTypeConstraints(); if (dict) @@ -318,7 +305,7 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista // ---- Add template instantiation relations - if (TEMPLATE_RELATIONS) + if (Config_getBool(TEMPLATE_RELATIONS)) { if (base) // template relations for base classes { @@ -383,7 +370,7 @@ DotClassGraph::DotClassGraph(const ClassDef *cd,GraphType t) buildGraph(cd,m_startNode,TRUE,1); if (t==Inheritance) buildGraph(cd,m_startNode,FALSE,1); - m_lrRank = determineVisibleNodes(m_startNode,DOT_GRAPH_MAX_NODES,t==Inheritance); + m_lrRank = determineVisibleNodes(m_startNode,Config_getInt(DOT_GRAPH_MAX_NODES),t==Inheritance); QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineTruncatedNodes(openNodeQueue,t==Inheritance); @@ -397,12 +384,12 @@ bool DotClassGraph::isTrivial() const if (m_graphType==Inheritance) return m_startNode->children()==0 && m_startNode->parents()==0; else - return !UML_LOOK && m_startNode->children()==0; + return !Config_getBool(UML_LOOK) && m_startNode->children()==0; } bool DotClassGraph::isTooBig() const { - return numNodes()>=DOT_GRAPH_MAX_NODES; + return numNodes()>=Config_getInt(DOT_GRAPH_MAX_NODES); } int DotClassGraph::numNodes() const diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 17f8cb7..285c0bb 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -174,6 +174,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, if (!ref.isEmpty()) { result = externalLinkTarget(true); + if (!result.isEmpty())targetAlreadySet=true; } result+= href+"=\""; result+=externalRef(relPath,ref,TRUE); @@ -460,7 +461,7 @@ bool DotFilePatcher::run() const convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context); if (!result.isEmpty()) { - t << "<map name=\"" << map->label << "\" id=\"" << correctId(map->label) << "\">" << endl; + t << "<map name=\"" << correctId(map->label) << "\" id=\"" << correctId(map->label) << "\">" << endl; t << result; t << "</map>" << endl; } diff --git a/src/dotgfxhierarchytable.cpp b/src/dotgfxhierarchytable.cpp index 3d56de8..c535acf 100644 --- a/src/dotgfxhierarchytable.cpp +++ b/src/dotgfxhierarchytable.cpp @@ -21,8 +21,6 @@ #include "doxygen.h" #include "classlist.h" -#define OPTIMIZE_OUTPUT_SLICE Config_getBool(OPTIMIZE_OUTPUT_SLICE) - QCString DotGfxHierarchyTable::getBaseName() const { QCString baseName; @@ -35,22 +33,19 @@ QCString DotGfxHierarchyTable::getBaseName() const void DotGfxHierarchyTable::computeTheGraph() { - QListIterator<DotNode> dnli2(*m_rootNodes); - DotNode *node; - FTextStream md5stream(&m_theGraph); writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy()); md5stream << " rankdir=\"LR\";" << endl; - for (dnli2.toFirst();(node=dnli2.current());++dnli2) + for (auto node : m_rootNodes) { - if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) { node->clearWriteFlag(); } } - for (dnli2.toFirst();(node=dnli2.current());++dnli2) + for (auto node : m_rootNodes) { - if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) { node->write(md5stream,Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE); } @@ -80,7 +75,7 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name); //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count()); - if (m_rootSubgraphs->count()==0) return; + if (m_rootSubgraphs.empty()) return; QDir d(path); // store the original directory @@ -92,10 +87,10 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, // put each connected subgraph of the hierarchy in a row of the HTML output out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl; - QListIterator<DotNode> dnli(*m_rootSubgraphs); - DotNode *n; int count=0; - for (dnli.toFirst();(n=dnli.current());++dnli) + std::sort(m_rootSubgraphs.begin(),m_rootSubgraphs.end(), + [](auto n1,auto n2) { return qstricmp(n1->label(),n2->label())<0; }); + for (auto n : m_rootSubgraphs) { out << "<tr><td>"; createGraph(n,out,path,fileName,count++); @@ -104,85 +99,81 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, out << "</table>" << endl; } -void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,bool hideSuper) +void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,ClassDefSet &visitedClasses) { //printf("addHierarchy '%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count()); - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + ClassDef *bClass=bcd.classDef; + //printf(" Trying sub class='%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); + if (bClass && bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) { - ClassDef *bClass=bcd->classDef; - //printf(" Trying sub class='%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); - if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) + auto it = m_usedNodes.find(bClass->name().str()); + //printf(" Node '%s' Found visible class='%s'\n",n->label().data(), + // bClass->name().data()); + DotNode *root = 0; + if (it!=m_usedNodes.end()) // node already present { - DotNode *bn; - //printf(" Node '%s' Found visible class='%s'\n",n->label().data(), - // bClass->name().data()); - if ((bn=m_usedNodes->find(bClass->name()))) // node already present + const auto &bn = it->second; + root = bn.get(); + if (n->children()==0 || n->children()->findRef(bn.get())==-1) // no arrow yet { - if (n->children()==0 || n->children()->findRef(bn)==-1) // no arrow yet - { - n->addChild(bn,bcd->prot); - bn->addParent(n); - //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n", - // n->label().data(), - // bn->label().data(), - // bn->children() ? bn->children()->count() : 0, - // bn->parents() ? bn->parents()->count() : 0 - // ); - } - //else - //{ - // printf(" Class already has an arrow!\n"); - //} + n->addChild(bn.get(),bcd.prot); + bn->addParent(n); + //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n", + // n->label().data(), + // bn->label().data(), + // bn->children() ? bn->children()->count() : 0, + // bn->parents() ? bn->parents()->count() : 0 + // ); } - else + //else + //{ + // printf(" Class already has an arrow!\n"); + //} + } + else + { + QCString tmp_url=""; + if (bClass->isLinkable() && !bClass->isHidden()) { - QCString tmp_url=""; - if (bClass->isLinkable() && !bClass->isHidden()) + tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); + if (!bClass->anchor().isEmpty()) { - tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); - if (!bClass->anchor().isEmpty()) - { - tmp_url+="#"+bClass->anchor(); - } + tmp_url+="#"+bClass->anchor(); } - QCString tooltip = bClass->briefDescriptionAsTooltip(); - bn = new DotNode(getNextNodeNumber(), + } + QCString tooltip = bClass->briefDescriptionAsTooltip(); + auto bn = std::make_unique<DotNode>(getNextNodeNumber(), bClass->displayName(), tooltip, tmp_url.data() - ); - n->addChild(bn,bcd->prot); - bn->addParent(n); - //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n", - // n->label().data(), - // bn->label().data(), - // bn->children() ? bn->children()->count() : 0, - // bn->parents() ? bn->parents()->count() : 0 - // ); - //printf(" inserting %s (%p)\n",bClass->name().data(),bn); - m_usedNodes->insert(bClass->name(),bn); // add node to the used list - } - if (!bClass->isVisited() && !hideSuper && bClass->subClasses()) - { - bool wasVisited=bClass->isVisited(); - bClass->setVisited(TRUE); - addHierarchy(bn,bClass,wasVisited); - } + ); + n->addChild(bn.get(),bcd.prot); + bn->addParent(n); + root = bn.get(); + //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n", + // n->label().data(), + // bn->label().data(), + // bn->children() ? bn->children()->count() : 0, + // bn->parents() ? bn->parents()->count() : 0 + // ); + //printf(" inserting %s (%p)\n",bClass->name().data(),bn); + m_usedNodes.insert(std::make_pair(bClass->name().str(),std::move(bn))); // add node to the used list + } + if (visitedClasses.find(bClass)==visitedClasses.end() && !bClass->subClasses().empty()) + { + visitedClasses.insert(bClass); + addHierarchy(root,bClass,visitedClasses); } } } //printf("end addHierarchy\n"); } -void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) +void DotGfxHierarchyTable::addClassList(const ClassLinkedMap &cl,ClassDefSet &visitedClasses) { - ClassSDict::Iterator cli(*cl); - ClassDef *cd; - for (cli.toLast();(cd=cli.current());--cli) + for (const auto &cd : cl) { //printf("Trying %s subClasses=%d\n",cd->name().data(),cd->subClasses()->count()); if (cd->getLanguage()==SrcLangExt_VHDL && @@ -191,7 +182,7 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) { continue; } - if (OPTIMIZE_OUTPUT_SLICE && cd->compoundType() != m_classType) + if (Config_getBool(OPTIMIZE_OUTPUT_SLICE) && cd->compoundType() != m_classType) { continue; } @@ -200,7 +191,7 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) ) // root node in the forest { QCString tmp_url=""; - if (cd->isLinkable() && !cd->isHidden()) + if (cd->isLinkable() && !cd->isHidden()) { tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); if (!cd->anchor().isEmpty()) @@ -210,18 +201,18 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) } //printf("Inserting root class %s\n",cd->name().data()); QCString tooltip = cd->briefDescriptionAsTooltip(); - DotNode *n = new DotNode(getNextNodeNumber(), + auto n = std::make_unique<DotNode>(getNextNodeNumber(), cd->displayName(), tooltip, tmp_url.data()); + DotNode *root = n.get(); - //m_usedNodes->clear(); - m_usedNodes->insert(cd->name(),n); - m_rootNodes->insert(0,n); - if (!cd->isVisited() && cd->subClasses()) + m_usedNodes.insert(std::make_pair(cd->name().str(),std::move(n))); + m_rootNodes.push_back(root); + if (visitedClasses.find(cd.get())==visitedClasses.end() && !cd->subClasses().empty()) { - addHierarchy(n,cd,cd->isVisited()); - cd->setVisited(TRUE); + addHierarchy(root,cd.get(),visitedClasses); + visitedClasses.insert(cd.get()); } } } @@ -231,28 +222,20 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound : m_prefix(prefix) , m_classType(ct) { - m_rootNodes = new QList<DotNode>; - m_usedNodes = new QDict<DotNode>(1009); - m_usedNodes->setAutoDelete(TRUE); - m_rootSubgraphs = new DotNodeList; - // build a graph with each class as a node and the inheritance relations // as edges - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); - addClassList(Doxygen::classSDict); - addClassList(Doxygen::hiddenClasses); + ClassDefSet visitedClasses; + addClassList(*Doxygen::classLinkedMap,visitedClasses); + addClassList(*Doxygen::hiddenClassLinkedMap,visitedClasses); // m_usedNodes now contains all nodes in the graph // color the graph into a set of independent subgraphs - bool done=FALSE; + bool done=FALSE; int curColor=0; - QListIterator<DotNode> dnli(*m_rootNodes); while (!done) // there are still nodes to color { - DotNode *n; done=TRUE; // we are done unless there are still uncolored nodes - for (dnli.toLast();(n=dnli.current());--dnli) + for (auto n : m_rootNodes) { if (n->subgraphId()==-1) // not yet colored { @@ -263,18 +246,16 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound n->colorConnectedNodes(curColor); curColor++; const DotNode *dn=n->findDocNode(); - if (dn!=0) - m_rootSubgraphs->inSort(dn); + if (dn!=0) + m_rootSubgraphs.push_back(const_cast<DotNode*>(dn)); else - m_rootSubgraphs->inSort(n); + m_rootSubgraphs.push_back(n); } } } //printf("Number of independent subgraphs: %d\n",curColor); - QListIterator<DotNode> dnli2(*m_rootSubgraphs); - DotNode *n; - for (dnli2.toFirst();(n=dnli2.current());++dnli2) + for (auto n : m_rootSubgraphs) { //printf("Node %s color=%d (c=%d,p=%d)\n", // n->label().data(),n->m_subgraphId, @@ -285,18 +266,3 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound } } -DotGfxHierarchyTable::~DotGfxHierarchyTable() -{ - //printf("DotGfxHierarchyTable::~DotGfxHierarchyTable\n"); - - //QDictIterator<DotNode> di(*m_usedNodes); - //DotNode *n; - //for (;(n=di.current());++di) - //{ - // printf("Node %p: %s\n",n,n->label().data()); - //} - - delete m_rootNodes; - delete m_usedNodes; - delete m_rootSubgraphs; -} diff --git a/src/dotgfxhierarchytable.h b/src/dotgfxhierarchytable.h index 5a5bcad..089ecd2 100644 --- a/src/dotgfxhierarchytable.h +++ b/src/dotgfxhierarchytable.h @@ -16,22 +16,28 @@ #ifndef DOTGFXHIERARCHYTABLE_H #define DOTGFXHIERARCHYTABLE_H +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + #include "classdef.h" #include "ftextstream.h" #include "dotgraph.h" #include "dotnode.h" +class ClassLinkedMap; + /** Represents a graphical class hierarchy */ class DotGfxHierarchyTable : public DotGraph { public: DotGfxHierarchyTable(const char *prefix="",ClassDef::CompoundType ct=ClassDef::Class); - ~DotGfxHierarchyTable(); void createGraph(DotNode *rootNode,FTextStream &t,const char *path, const char *fileName,int id); void writeGraph(FTextStream &t,const char *path, const char *fileName); - const DotNodeList *subGraphs() const { return m_rootSubgraphs; } + const std::vector<DotNode*> subGraphs() const { return m_rootSubgraphs; } protected: virtual QCString getBaseName() const; @@ -39,15 +45,16 @@ class DotGfxHierarchyTable : public DotGraph virtual void computeTheGraph(); private: - void addHierarchy(DotNode *n,const ClassDef *cd,bool hide); - void addClassList(const ClassSDict *cl); + void addHierarchy(DotNode *n,const ClassDef *cd,ClassDefSet &visited); + void addClassList(const ClassLinkedMap &cl,ClassDefSet &visited); + using DotNodeMap = std::unordered_multimap< std::string, std::unique_ptr<DotNode> >; int m_graphId; QCString m_prefix; ClassDef::CompoundType m_classType; - QList<DotNode> *m_rootNodes; - QDict<DotNode> *m_usedNodes; - DotNodeList *m_rootSubgraphs; + std::vector<DotNode*> m_rootNodes; + DotNodeMap m_usedNodes; + std::vector<DotNode*> m_rootSubgraphs; DotNode * m_rootSubgraphNode; }; diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index 1ad85e1..287793e 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -239,7 +239,7 @@ void DotGraph::generateCode(FTextStream &t) 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())) + if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, correctId(getMapLabel()))) { int mapId = DotManager::instance()-> createFilePatcher(m_fileName.data())-> diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index 8121657..655a0e8 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -23,8 +23,6 @@ #include "util.h" #include "config.h" -#define DOT_TRANSPARENT Config_getBool(DOT_TRANSPARENT) - DotGroupCollaboration::DotGroupCollaboration(const GroupDef* gd) { QCString tmp_url = gd->getReference()+"$"+gd->getOutputFileBase(); @@ -111,31 +109,21 @@ void DotGroupCollaboration::buildGraph(const GroupDef* gd) addMemberList( gd->getMemberList(MemberListType_allMembersList) ); // Add classes - if ( gd->getClasses() && gd->getClasses()->count() ) + for (const auto &def : gd->getClasses()) { - ClassSDict::Iterator defli(*gd->getClasses()); - ClassDef *def; - for (;(def=defli.current());++defli) + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + if (!def->anchor().isEmpty()) { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - if (!def->anchor().isEmpty()) - { - tmp_url+="#"+def->anchor(); - } - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass ); + tmp_url+="#"+def->anchor(); } + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass ); } // Add namespaces - if ( gd->getNamespaces() && gd->getNamespaces()->count() ) + for (const auto &def : gd->getNamespaces()) { - NamespaceSDict::Iterator defli(*gd->getNamespaces()); - NamespaceDef *def; - for (;(def=defli.current());++defli) - { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); - } + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); } // Add files @@ -379,7 +367,7 @@ void DotGroupCollaboration::writeGraphHeader(FTextStream &t,const QCString &titl } t << endl; t << "{" << endl; - if (DOT_TRANSPARENT) + if (Config_getBool(DOT_TRANSPARENT)) { t << " bgcolor=\"transparent\";" << endl; } diff --git a/src/dotnode.cpp b/src/dotnode.cpp index c02827f..86f99a2 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -97,6 +97,30 @@ static EdgeProperties umlEdgeProps = umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap }; +// Extracted from config setting "DOT_UML_DETAILS" +enum class UmlDetailLevel +{ + Default, // == NO, the default setting + Full, // == YES, include type and arguments + None // == NONE, don't include compartments for attributes and methods +}; + +// Local helper function for extracting the configured detail level +static UmlDetailLevel getUmlDetailLevelFromConfig() +{ + UmlDetailLevel result = UmlDetailLevel::Default; + QCString umlDetailsStr = Config_getEnum(DOT_UML_DETAILS).upper(); + if (umlDetailsStr == "YES") + { + result=UmlDetailLevel::Full; + } + else if (umlDetailsStr == "NONE") + { + result=UmlDetailLevel::None; + } + return result; +} + static QCString escapeTooltip(const QCString &tooltip) { QCString result; @@ -148,9 +172,25 @@ static void writeBoxMemberList(FTextStream &t, else { t << prot << " "; - t << DotNode::convertLabel(mma->name()); - if (!mma->isObjCMethod() && - (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()"; + QCString label; + if(getUmlDetailLevelFromConfig()==UmlDetailLevel::Full) + { + label+=mma->typeString(); + label+=" "; + } + label+=mma->name(); + if (!mma->isObjCMethod() && (mma->isFunction() || mma->isSlot() || mma->isSignal())) + { + if(getUmlDetailLevelFromConfig()==UmlDetailLevel::Full) + { + label+=mma->argsString(); + } + else + { + label+="()"; + } + } + t << DotNode::convertLabel(label); t << "\\l"; count++; } @@ -185,7 +225,7 @@ QCString DotNode::convertLabel(const QCString &l) int len=p.length(); int charsLeft=len; int sinceLast=0; - int foldLen=17; // ideal text length + int foldLen = Config_getInt(DOT_WRAP_THRESHOLD); // ideal text length while (idx < p.length()) { c = p[idx++]; @@ -412,45 +452,48 @@ void DotNode::writeBox(FTextStream &t, } //printf("DotNode::writeBox for %s\n",m_classDef->name().data()); - t << "{" << convertLabel(m_label); - t << "\\n|"; - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticAttribs),m_classDef,TRUE,&arrowNames); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_properties),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticAttribs),m_classDef,TRUE,&arrowNames); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticAttribs),m_classDef,TRUE,&arrowNames); - if (Config_getBool(EXTRACT_PRIVATE)) - { - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticAttribs),m_classDef,TRUE,&arrowNames); - } - t << "|"; - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubMethods),m_classDef); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubSlots),m_classDef); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacMethods),m_classDef); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proMethods),m_classDef); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proSlots),m_classDef); - if (Config_getBool(EXTRACT_PRIVATE)) - { - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priMethods),m_classDef); - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priSlots),m_classDef); - } - if (m_classDef->getLanguage()!=SrcLangExt_Fortran && - m_classDef->getMemberGroupSDict()) - { - MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict()); - MemberGroup *mg; - for (mgdi.toFirst();(mg=mgdi.current());++mgdi) + t << "{" << convertLabel(m_label) << "\\n"; + if (getUmlDetailLevelFromConfig()!=UmlDetailLevel::None) + { + t << "|"; + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticAttribs),m_classDef,TRUE,&arrowNames); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_properties),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticAttribs),m_classDef,TRUE,&arrowNames); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticAttribs),m_classDef,TRUE,&arrowNames); + if (Config_getBool(EXTRACT_PRIVATE)) { - if (mg->members()) + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticAttribs),m_classDef,TRUE,&arrowNames); + } + t << "|"; + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubMethods),m_classDef); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubSlots),m_classDef); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacMethods),m_classDef); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proMethods),m_classDef); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proSlots),m_classDef); + if (Config_getBool(EXTRACT_PRIVATE)) + { + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priMethods),m_classDef); + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priSlots),m_classDef); + } + if (m_classDef->getLanguage()!=SrcLangExt_Fortran && + m_classDef->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict()); + MemberGroup *mg; + for (mgdi.toFirst();(mg=mgdi.current());++mgdi) { - writeBoxMemberList(t,'*',mg->members(),m_classDef,FALSE,&arrowNames); + if (mg->members()) + { + writeBoxMemberList(t,'*',mg->members(),m_classDef,FALSE,&arrowNames); + } } } } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 4b5c267..3472f8f 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -32,6 +32,7 @@ #include <algorithm> #include <unordered_map> #include <memory> +#include <cinttypes> #include "version.h" #include "doxygen.h" @@ -105,6 +106,7 @@ #include "stlsupport.h" #include "threadpool.h" #include "clangparser.h" +#include "symbolresolver.h" // provided by the generated file resources.cpp extern void initResources(); @@ -115,17 +117,17 @@ extern void initResources(); #endif // globally accessible variables -ClassSDict *Doxygen::classSDict = 0; -ClassSDict *Doxygen::hiddenClasses = 0; -NamespaceSDict *Doxygen::namespaceSDict = 0; -MemberNameLinkedMap *Doxygen::memberNameLinkedMap = 0; -MemberNameLinkedMap *Doxygen::functionNameLinkedMap = 0; -FileNameLinkedMap *Doxygen::inputNameLinkedMap = 0; -GroupSDict *Doxygen::groupSDict = 0; -PageSDict *Doxygen::pageSDict = 0; -PageSDict *Doxygen::exampleSDict = 0; -StringDict Doxygen::aliasDict(257); // aliases -StringSet Doxygen::inputPaths; +ClassLinkedMap *Doxygen::classLinkedMap = 0; +ClassLinkedMap *Doxygen::hiddenClassLinkedMap = 0; +NamespaceLinkedMap *Doxygen::namespaceLinkedMap = 0; +MemberNameLinkedMap *Doxygen::memberNameLinkedMap = 0; +MemberNameLinkedMap *Doxygen::functionNameLinkedMap = 0; +FileNameLinkedMap *Doxygen::inputNameLinkedMap = 0; +GroupSDict *Doxygen::groupSDict = 0; +PageSDict *Doxygen::pageSDict = 0; +PageSDict *Doxygen::exampleSDict = 0; +StringDict Doxygen::aliasDict(257); // aliases +StringSet Doxygen::inputPaths; FileNameLinkedMap *Doxygen::includeNameLinkedMap = 0; // include names FileNameLinkedMap *Doxygen::exampleNameLinkedMap = 0; // examples FileNameLinkedMap *Doxygen::imageNameLinkedMap = 0; // images @@ -133,38 +135,37 @@ 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 -StringUnorderedSet Doxygen::expandAsDefinedSet; // all macros that should be expanded +StringDict Doxygen::tagDestinationDict(257); // all tag locations +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; -bool Doxygen::parseSourcesNeeded = FALSE; -SearchIndexIntf *Doxygen::searchIndex=0; -QDict<DefinitionIntf> *Doxygen::symbolMap = 0; -QDict<Definition> *Doxygen::clangUsrMap = 0; -bool Doxygen::outputToWizard=FALSE; -QDict<int> * Doxygen::htmlDirMap = 0; -QCache<LookupInfo> *Doxygen::lookupCache; -DirSDict *Doxygen::directories; -SDict<DirRelation> Doxygen::dirRelations(257); -ParserManager *Doxygen::parserManager = 0; -QCString Doxygen::htmlFileExtension; -bool Doxygen::suppressDocWarnings = FALSE; -QCString Doxygen::objDBFileName; -QCString Doxygen::entryDBFileName; -QCString Doxygen::filterDBFileName; -IndexList *Doxygen::indexList; -int Doxygen::subpageNestingLevel = 0; -bool Doxygen::userComments = FALSE; -QCString Doxygen::spaces; -bool Doxygen::generatingXmlOutput = FALSE; -GenericsSDict *Doxygen::genericsDict; -DefinesPerFileList Doxygen::macroDefinitions; -bool Doxygen::clangAssistedParsing = FALSE; +PageDef *Doxygen::mainPage = 0; +bool Doxygen::insideMainPage = FALSE; // are we generating docs for the main page? +NamespaceDefMutable *Doxygen::globalScope = 0; +bool Doxygen::parseSourcesNeeded = FALSE; +SearchIndexIntf *Doxygen::searchIndex=0; +SymbolMap<Definition> Doxygen::symbolMap; +QDict<Definition> *Doxygen::clangUsrMap = 0; +bool Doxygen::outputToWizard=FALSE; +QDict<int> * Doxygen::htmlDirMap = 0; +Cache<std::string,LookupInfo> *Doxygen::lookupCache; +DirSDict *Doxygen::directories; +SDict<DirRelation> Doxygen::dirRelations(257); +ParserManager *Doxygen::parserManager = 0; +QCString Doxygen::htmlFileExtension; +bool Doxygen::suppressDocWarnings = FALSE; +QCString Doxygen::objDBFileName; +QCString Doxygen::entryDBFileName; +QCString Doxygen::filterDBFileName; +IndexList *Doxygen::indexList; +int Doxygen::subpageNestingLevel = 0; +bool Doxygen::userComments = FALSE; +QCString Doxygen::spaces; +bool Doxygen::generatingXmlOutput = FALSE; +DefinesPerFileList Doxygen::macroDefinitions; +bool Doxygen::clangAssistedParsing = FALSE; // locally accessible globals -static std::unordered_map< std::string, const Entry* > g_classEntries; +static std::multimap< std::string, const Entry* > g_classEntries; static StringVector g_inputFiles; static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds static OutputList *g_outputList = 0; // list of output generating objects @@ -179,8 +180,9 @@ void clearAll() //g_excludeNameDict.clear(); //delete g_outputList; g_outputList=0; - Doxygen::classSDict->clear(); - Doxygen::namespaceSDict->clear(); + Doxygen::classLinkedMap->clear(); + Doxygen::hiddenClassLinkedMap->clear(); + Doxygen::namespaceLinkedMap->clear(); Doxygen::pageSDict->clear(); Doxygen::exampleSDict->clear(); Doxygen::inputNameLinkedMap->clear(); @@ -274,7 +276,7 @@ void statistics() -static void addMemberDocs(const Entry *root,MemberDef *md, const char *funcDecl, +static void addMemberDocs(const Entry *root,MemberDefMutable *md, const char *funcDecl, const ArgumentList *al,bool over_load,uint64 spec); static void findMember(const Entry *root, const QCString &relates, @@ -295,7 +297,7 @@ enum FindBaseClassRelation_Mode static bool findClassRelation( const Entry *root, Definition *context, - ClassDef *cd, + ClassDefMutable *cd, const BaseInfo *bi, QDict<int> *templateNames, /*bool insertUndocumented*/ @@ -305,7 +307,7 @@ static bool findClassRelation( //---------------------------------------------------------------------------- -static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n, +static Definition *findScopeFromQualifiedName(NamespaceDefMutable *startScope,const QCString &n, FileDef *fileScope,const TagInfo *tagInfo); static void addPageToContext(PageDef *pd,Entry *root) @@ -346,7 +348,9 @@ static void addRelatedPage(Entry *root) } PageDef *pd = addRelatedPage(root->name,root->args,doc, - root->docFile,root->docLine, + root->docFile, + root->docLine, + root->startLine, root->sli, gd,root->tagInfo(), FALSE, @@ -554,7 +558,7 @@ static void buildFileList(const Entry *root) for (const auto &e : root->children()) buildFileList(e.get()); } -static void addIncludeFile(ClassDef *cd,FileDef *ifd,const Entry *root) +static void addIncludeFile(ClassDefMutable *cd,FileDef *ifd,const Entry *root) { if ( (!root->doc.stripWhiteSpace().isEmpty() || @@ -708,13 +712,36 @@ static Definition *findScope(Entry *root,int level=0) } #endif +QCString stripTemplateSpecifiers(const QCString &s) +{ + int l = s.length(); + int count=0; + int round=0; + QCString result; + for (int i=0;i<l;i++) + { + char c=s.at(i); + if (c=='(') round++; + else if (c==')' && round>0) round--; + else if (c=='<' && round==0) count++; + if (count==0) + { + result+=c; + } + if (c=='>' && round==0 && count>0) count--; + } + //printf("stripTemplateSpecifiers(%s)=%s\n",s.data(),result.data()); + return result; +} + /*! returns the Definition object belonging to the first \a level levels of * full qualified name \a name. Creates an artificial scope if the scope is * not found and set the parent/child scope relation if the scope is found. */ -static Definition *buildScopeFromQualifiedName(const QCString name, - int level,SrcLangExt lang,const TagInfo *tagInfo) +static Definition *buildScopeFromQualifiedName(const QCString name_,SrcLangExt lang,const TagInfo *tagInfo) { + QCString name = stripTemplateSpecifiers(name_); + int level = name.contains("::"); //printf("buildScopeFromQualifiedName(%s) level=%d\n",name.data(),level); int i=0; int p=0,l; @@ -728,27 +755,31 @@ static Definition *buildScopeFromQualifiedName(const QCString name, if (nsName.isEmpty()) return prevScope; if (!fullScope.isEmpty()) fullScope+="::"; fullScope+=nsName; - NamespaceDef *nd=Doxygen::namespaceSDict->find(fullScope); - Definition *innerScope = nd; + NamespaceDef *nd=Doxygen::namespaceLinkedMap->find(fullScope); + DefinitionMutable *innerScope = toDefinitionMutable(nd); ClassDef *cd=0; if (nd==0) cd = getClass(fullScope); if (nd==0 && cd) // scope is a class { - innerScope = cd; + innerScope = toDefinitionMutable(cd); } else if (nd==0 && cd==0 && fullScope.find('<')==-1) // scope is not known and could be a namespace! { // introduce bogus namespace //printf("++ adding dummy namespace %s to %s tagInfo=%p\n",nsName.data(),prevScope->name().data(),tagInfo); - nd=createNamespaceDef( - "[generated]",1,1,fullScope, - tagInfo?tagInfo->tagName:QCString(), - tagInfo?tagInfo->fileName:QCString()); - nd->setLanguage(lang); + NamespaceDefMutable *newNd= + toNamespaceDefMutable( + Doxygen::namespaceLinkedMap->add(fullScope, + std::unique_ptr<NamespaceDef>( + createNamespaceDef( + "[generated]",1,1,fullScope, + tagInfo?tagInfo->tagName:QCString(), + tagInfo?tagInfo->fileName:QCString())))); + newNd->setLanguage(lang); + newNd->setArtificial(TRUE); // add namespace to the list - Doxygen::namespaceSDict->inSort(fullScope,nd); - innerScope = nd; + innerScope = newNd; } else // scope is a namespace { @@ -756,7 +787,11 @@ static Definition *buildScopeFromQualifiedName(const QCString name, if (innerScope) { // make the parent/child scope relation - prevScope->addInnerCompound(innerScope); + DefinitionMutable *prevScopeMutable = toDefinitionMutable(prevScope); + if (prevScopeMutable) + { + prevScopeMutable->addInnerCompound(toDefinition(innerScope)); + } innerScope->setOuterScope(prevScope); } else // current scope is a class, so return only the namespace part... @@ -765,17 +800,17 @@ static Definition *buildScopeFromQualifiedName(const QCString name, } // proceed to the next scope fragment p=idx+l+2; - prevScope=innerScope; + prevScope=toDefinition(innerScope); i++; } return prevScope; } -static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n, +static Definition *findScopeFromQualifiedName(NamespaceDefMutable *startScope,const QCString &n, FileDef *fileScope,const TagInfo *tagInfo) { //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data()); - Definition *resultScope=startScope; + Definition *resultScope=toDefinition(startScope); if (resultScope==0) resultScope=Doxygen::globalScope; QCString scope=stripTemplateSpecifiersFromScope(n,FALSE); int l1=0,i1; @@ -791,21 +826,17 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr QCString nestedNameSpecifier = scope.mid(i1,l1); Definition *orgScope = resultScope; //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data()); - resultScope = resultScope->findInnerCompound(nestedNameSpecifier); + resultScope = const_cast<Definition*>(resultScope->findInnerCompound(nestedNameSpecifier)); //printf(" resultScope=%p\n",resultScope); if (resultScope==0) { - NamespaceSDict *usedNamespaces; - if (orgScope==Doxygen::globalScope && fileScope && - (usedNamespaces = fileScope->getUsedNamespaces())) + if (orgScope==Doxygen::globalScope && fileScope && !fileScope->getUsedNamespaces().empty()) // also search for used namespaces { - NamespaceSDict::Iterator ni(*usedNamespaces); - NamespaceDef *nd; - for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni) + for (const auto &nd : fileScope->getUsedNamespaces()) { - // restart search within the used namespace - resultScope = findScopeFromQualifiedName(nd,n,fileScope,tagInfo); + resultScope = findScopeFromQualifiedName(toNamespaceDefMutable(nd),n,fileScope,tagInfo); + if (resultScope!=0) break; } if (resultScope) { @@ -837,8 +868,7 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr // so use this instead. QCString fqn = QCString(ui.currentKey())+ scope.right(scope.length()-p); - resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::"), - startScope->getLanguage(),0); + resultScope = buildScopeFromQualifiedName(fqn,startScope->getLanguage(),0); //printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope); if (resultScope) { @@ -870,7 +900,7 @@ std::unique_ptr<ArgumentList> getTemplateArgumentsFromName( auto alIt = tArgLists.begin(); while ((i=name.find("::",p))!=-1 && alIt!=tArgLists.end()) { - NamespaceDef *nd = Doxygen::namespaceSDict->find(name.left(i)); + NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(name.left(i)); if (nd==0) { ClassDef *cd = getClass(name.left(i)); @@ -970,7 +1000,7 @@ static void addClassToContext(const Entry *root) } // see if we already found the class before - ClassDef *cd = getClass(qualifiedName); + ClassDefMutable *cd = getClassMutable(qualifiedName); Debug::print(Debug::Classes,0, " Found class with name %s (qualifiedName=%s -> cd=%p)\n", cd ? qPrint(cd->name()) : qPrint(root->name), qPrint(qualifiedName),cd); @@ -1037,11 +1067,11 @@ static void addClassToContext(const Entry *root) // symbols imported via tag files may come without the parent scope, // so we artificially create it here { - buildScopeFromQualifiedName(fullName,fullName.contains("::"),root->lang,tagInfo); + buildScopeFromQualifiedName(fullName,root->lang,tagInfo); } } std::unique_ptr<ArgumentList> tArgList; - if ((root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java) && (i=fullName.find('<'))!=-1) + if ((root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java) && (i=fullName.findRev('<'))!=-1) { // a Java/C# generic class looks like a C++ specialization, so we need to split the // name and template arguments here @@ -1052,10 +1082,15 @@ static void addClassToContext(const Entry *root) { tArgList = getTemplateArgumentsFromName(fullName,root->tArgLists); } - cd=createClassDef(tagInfo?tagName:root->fileName,root->startLine,root->startColumn, - fullName,sec,tagName,refFileName,TRUE,root->spec&Entry::Enum); - Debug::print(Debug::Classes,0," New class '%s' (sec=0x%08x)! #tArgLists=%d tagInfo=%p\n", - qPrint(fullName),sec,root->tArgLists.size(), tagInfo); + // add class to the list + //printf("ClassDict.insert(%s)\n",fullName.data()); + cd = toClassDefMutable( + Doxygen::classLinkedMap->add(fullName, + std::unique_ptr<ClassDef>( + createClassDef(tagInfo?tagName:root->fileName,root->startLine,root->startColumn, + fullName,sec,tagName,refFileName,TRUE,root->spec&Entry::Enum) ))); + Debug::print(Debug::Classes,0," New class '%s' (sec=0x%08x)! #tArgLists=%d tagInfo=%p hidden=%d artificial=%d\n", + qPrint(fullName),sec,root->tArgLists.size(), tagInfo,root->hidden,root->artificial); cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); cd->setLanguage(root->lang); @@ -1086,15 +1121,7 @@ static void addClassToContext(const Entry *root) cd->insertUsedFile(fd); - // add class to the list - //printf("ClassDict.insert(%s)\n",fullName.data()); - Doxygen::classSDict->append(fullName,cd); - if (cd->isGeneric()) // generics are also stored in a separate dictionary for fast lookup of instances - { - //printf("inserting generic '%s' cd=%p\n",fullName.data(),cd); - Doxygen::genericsDict->insert(fullName,cd); - } } cd->addSectionsToDefinition(root->anchors); @@ -1148,8 +1175,7 @@ static void buildClassDocList(const Entry *root) static void resolveClassNestingRelations() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); + ClassDefSet visitedClasses; bool done=FALSE; int iteration=0; @@ -1157,38 +1183,53 @@ static void resolveClassNestingRelations() { done=TRUE; ++iteration; - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + struct ClassAlias + { + ClassAlias(const QCString &name,std::unique_ptr<ClassDef> cd) : + aliasFullName(name),aliasCd(std::move(cd)) {} + const QCString aliasFullName; + std::unique_ptr<ClassDef> aliasCd; + }; + std::vector<ClassAlias> aliases; + for (const auto &icd : *Doxygen::classLinkedMap) { - if (!cd->isVisited()) + ClassDefMutable *cd = toClassDefMutable(icd.get()); + if (cd && visitedClasses.find(icd.get())==visitedClasses.end()) { - QCString name = stripAnonymousNamespaceScope(cd->name()); + QCString name = stripAnonymousNamespaceScope(icd->name()); //printf("processing=%s, iteration=%d\n",cd->name().data(),iteration); // also add class to the correct structural context Definition *d = findScopeFromQualifiedName(Doxygen::globalScope, - name,cd->getFileDef(),0); + name,icd->getFileDef(),0); if (d) { //printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration); - d->addInnerCompound(cd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(cd); + } cd->setOuterScope(d); // for inline namespace add an alias of the class to the outer scope - while (d->definitionType()==DefinitionIntf::TypeNamespace) + while (d->definitionType()==Definition::TypeNamespace) { - NamespaceDef *nd = dynamic_cast<NamespaceDef*>(d); - //printf("d->isInline()=%d\n",nd->isInline()); - if (nd->isInline()) + NamespaceDef *nd = toNamespaceDef(d); + //printf("nd->isInline()=%d\n",nd->isInline()); + if (nd && nd->isInline()) { d = d->getOuterScope(); if (d) { - ClassDef *aliasCd = createClassDefAlias(d,cd); - d->addInnerCompound(aliasCd); - QCString aliasFullName = d->qualifiedName()+"::"+aliasCd->localName(); - Doxygen::classSDict->append(aliasFullName,aliasCd); - //printf("adding %s to %s as %s\n",qPrint(aliasCd->name()),qPrint(d->name()),qPrint(aliasFullName)); - aliasCd->setVisited(TRUE); + dm = toDefinitionMutable(d); + if (dm) + { + std::unique_ptr<ClassDef> aliasCd { createClassDefAlias(d,cd) }; + dm->addInnerCompound(aliasCd.get()); + QCString aliasFullName = d->qualifiedName()+"::"+aliasCd->localName(); + aliases.push_back(ClassAlias(aliasFullName,std::move(aliasCd))); + //printf("adding %s to %s as %s\n",qPrint(aliasCd->name()),qPrint(d->name()),qPrint(aliasFullName)); + } } } else @@ -1197,7 +1238,7 @@ static void resolveClassNestingRelations() } } - cd->setVisited(TRUE); + visitedClasses.insert(icd.get()); done=FALSE; } //else @@ -1206,25 +1247,34 @@ static void resolveClassNestingRelations() //} } } + // add aliases + for (auto &alias : aliases) + { + Doxygen::classLinkedMap->add(alias.aliasFullName,std::move(alias.aliasCd)); + } } //give warnings for unresolved compounds - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &icd : *Doxygen::classLinkedMap) { - if (!cd->isVisited()) + ClassDefMutable *cd = toClassDefMutable(icd.get()); + if (cd && visitedClasses.find(icd.get())==visitedClasses.end()) { QCString name = stripAnonymousNamespaceScope(cd->name()); //printf("processing unresolved=%s, iteration=%d\n",cd->name().data(),iteration); /// create the scope artificially // anyway, so we can at least relate scopes properly. - Definition *d = buildScopeFromQualifiedName(name,name.contains("::"),cd->getLanguage(),0); - if (d!=cd && !cd->getDefFileName().isEmpty()) + Definition *d = buildScopeFromQualifiedName(name,cd->getLanguage(),0); + if (d && d!=cd && !cd->getDefFileName().isEmpty()) // avoid recursion in case of redundant scopes, i.e: namespace N { class N::C {}; } // for this case doxygen assumes the existence of a namespace N::N in which C is to be found! // also avoid warning for stuff imported via a tagfile. { - d->addInnerCompound(cd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(cd); + } cd->setOuterScope(d); warn(cd->getDefFileName(),cd->getDefLine(), "Internal inconsistency: scope for class %s not " @@ -1241,47 +1291,48 @@ void distributeClassGroupRelations() //if (!inlineGroupedClasses) return; //printf("** distributeClassGroupRelations()\n"); - ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); - - ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + ClassDefSet visitedClasses; + for (const auto &cd : *Doxygen::classLinkedMap) { //printf("Checking %s\n",cd->name().data()); // distribute the group to nested classes as well - if (!cd->isVisited() && cd->partOfGroups()!=0 && cd->getClassSDict()) + if (visitedClasses.find(cd.get())==visitedClasses.end() && cd->partOfGroups()!=0) { //printf(" Candidate for merging\n"); - ClassSDict::Iterator ncli(*cd->getClassSDict()); - ClassDef *ncd; GroupDef *gd = cd->partOfGroups()->at(0); - for (ncli.toFirst();(ncd=ncli.current());++ncli) + for (const auto &ncd : cd->getClasses()) { - if (ncd->partOfGroups()==0) + ClassDefMutable *ncdm = toClassDefMutable(ncd); + if (ncdm && ncdm->partOfGroups()==0) { //printf(" Adding %s to group '%s'\n",ncd->name().data(), // gd->groupTitle()); - ncd->makePartOfGroup(gd); - gd->addClass(ncd); + ncdm->makePartOfGroup(gd); + gd->addClass(ncdm); } } - cd->setVisited(TRUE); // only visit every class once + visitedClasses.insert(cd.get()); // only visit every class once } } } //---------------------------- -static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QCString &fieldName) +static ClassDefMutable *createTagLessInstance(const ClassDef *rootCd,const ClassDef *templ,const QCString &fieldName) { QCString fullName = removeAnonymousScopes(templ->name()); if (fullName.right(2)=="::") fullName=fullName.left(fullName.length()-2); fullName+="."+fieldName; - ClassDef *cd = createClassDef(templ->getDefFileName(), + + //printf("** adding class %s based on %s\n",fullName.data(),templ->name().data()); + ClassDefMutable *cd = toClassDefMutable( + Doxygen::classLinkedMap->add(fullName, + std::unique_ptr<ClassDef>( + createClassDef(templ->getDefFileName(), templ->getDefLine(), templ->getDefColumn(), fullName, - templ->compoundType()); + templ->compoundType())))); cd->setDocumentation(templ->documentation(),templ->docFile(),templ->docLine()); // copy docs to definition cd->setBriefDescription(templ->briefDescription(),templ->briefFile(),templ->briefLine()); cd->setLanguage(templ->getLanguage()); @@ -1291,7 +1342,11 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC cd->setOuterScope(rootCd->getOuterScope()); if (rootCd->getOuterScope()!=Doxygen::globalScope) { - rootCd->getOuterScope()->addInnerCompound(cd); + DefinitionMutable *outerScope = toDefinitionMutable(rootCd->getOuterScope()); + if (outerScope) + { + outerScope->addInnerCompound(cd); + } } FileDef *fd = templ->getFileDef(); @@ -1311,8 +1366,6 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC gd->addClass(cd); } } - //printf("** adding class %s based on %s\n",fullName.data(),templ->name().data()); - Doxygen::classSDict->append(fullName,cd); MemberList *ml = templ->getMemberList(MemberListType_pubAttribs); if (ml) @@ -1322,7 +1375,7 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC for (li.toFirst();(md=li.current());++li) { //printf(" Member %s type=%s\n",md->name().data(),md->typeString()); - MemberDef *imd = createMemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(), + MemberDefMutable *imd = createMemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(), md->typeString(),md->name(),md->argsString(),md->excpString(), md->protection(),md->virtualness(),md->isStatic(),Member, md->memberType(), @@ -1352,14 +1405,14 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC * recursively. Later on we need to patch the member types so we keep * track of the hierarchy of classes we create. */ -static void processTagLessClasses(ClassDef *rootCd, - ClassDef *cd, - ClassDef *tagParentCd, +static void processTagLessClasses(const ClassDef *rootCd, + const ClassDef *cd, + ClassDefMutable *tagParentCd, const QCString &prefix,int count) { //printf("%d: processTagLessClasses %s\n",count,cd->name().data()); //printf("checking members for %s\n",cd->name().data()); - if (cd->getClassSDict()) + if (tagParentCd && !cd->getClasses().empty()) { MemberList *ml = cd->getMemberList(MemberListType_pubAttribs); if (ml) @@ -1371,22 +1424,19 @@ static void processTagLessClasses(ClassDef *rootCd, QCString type = md->typeString(); if (type.find("::@")!=-1) // member of tag less struct/union { - ClassSDict::Iterator it(*cd->getClassSDict()); - ClassDef *icd; - for (it.toFirst();(icd=it.current());++it) + for (const auto &icd : cd->getClasses()) { //printf(" member %s: type='%s'\n",md->name().data(),type.data()); //printf(" comparing '%s'<->'%s'\n",type.data(),icd->name().data()); if (type.find(icd->name())!=-1) // matching tag less struct/union { QCString name = md->name(); - if (md->isAnonymous()) name = "__unnamed__"; + if (md->isAnonymous()) name = "__unnamed" + name.right(name.length()-1)+"__"; if (!prefix.isEmpty()) name.prepend(prefix+"."); //printf(" found %s for class %s\n",name.data(),cd->name().data()); - ClassDef *ncd = createTagLessInstance(rootCd,icd,name); + ClassDefMutable *ncd = createTagLessInstance(rootCd,icd,name); processTagLessClasses(rootCd,icd,ncd,name,count+1); //printf(" addTagged %s to %s\n",ncd->name().data(),tagParentCd->name().data()); - tagParentCd->addTaggedInnerClass(ncd); ncd->setTagLessReference(icd); // replace tag-less type for generated/original member @@ -1403,9 +1453,10 @@ static void processTagLessClasses(ClassDef *rootCd, MemberDef *pmd; for (pli.toFirst();(pmd=pli.current());++pli) { - if (pmd->name()==md->name()) + MemberDefMutable *pmdm = toMemberDefMutable(pmd); + if (pmdm && pmd->name()==md->name()) { - pmd->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name())); + pmdm->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name())); //pmd->setType(substitute(pmd->typeString(),icd->name(),ncd->name())); } } @@ -1418,34 +1469,27 @@ static void processTagLessClasses(ClassDef *rootCd, } } -static void findTagLessClasses(ClassDef *cd) +static void findTagLessClasses(const ClassDef *cd) { - if (cd->getClassSDict()) + for (const auto &icd : cd->getClasses()) { - ClassSDict::Iterator it(*cd->getClassSDict()); - ClassDef *icd; - for (it.toFirst();(icd=it.current());++it) + if (icd->name().find("@")==-1) // process all non-anonymous inner classes { - if (icd->name().find("@")==-1) // process all non-anonymous inner classes - { - findTagLessClasses(icd); - } + findTagLessClasses(icd); } } - processTagLessClasses(cd,cd,cd,"",0); // process tag less inner struct/classes (if any) + processTagLessClasses(cd,cd,toClassDefMutable(cd),"",0); // process tag less inner struct/classes (if any) } static void findTagLessClasses() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) // for each class + for (const auto &cd : *Doxygen::classLinkedMap) { Definition *scope = cd->getOuterScope(); if (scope && scope->definitionType()!=Definition::TypeClass) // that is not nested { - findTagLessClasses(cd); + findTagLessClasses(cd.get()); } } } @@ -1477,8 +1521,8 @@ static void buildNamespaceList(const Entry *root) { //printf("Found namespace %s in %s at line %d\n",root->name.data(), // root->fileName.data(), root->startLine); - NamespaceDef *nd; - if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace + NamespaceDefMutable *nd; + if ((nd=toNamespaceDefMutable(Doxygen::namespaceLinkedMap->find(fullName)))) // existing namespace { nd->setDocumentation(root->doc,root->docFile,root->docLine); nd->setName(fullName); // change name to match docs @@ -1515,9 +1559,13 @@ 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()); - nd=createNamespaceDef(tagInfo?tagName:root->fileName,root->startLine, + // add namespace to the list + nd = toNamespaceDefMutable( + Doxygen::namespaceLinkedMap->add(fullName, + std::unique_ptr<NamespaceDef>( + createNamespaceDef(tagInfo?tagName:root->fileName,root->startLine, root->startColumn,fullName,tagName,tagFileName, - root->type,root->spec&Entry::Published); + root->type,root->spec&Entry::Published)))); nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); nd->addSectionsToDefinition(root->anchors); @@ -1542,8 +1590,6 @@ static void buildNamespaceList(const Entry *root) nd->insertUsedFile(fd); nd->setBodySegment(root->startLine,root->bodyLine,root->endBodyLine); nd->setBodyDef(fd); - // add class to the list - Doxygen::namespaceSDict->inSort(fullName,nd); // also add namespace to the correct structural context Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName,0,tagInfo); @@ -1551,28 +1597,43 @@ 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. { - d = buildScopeFromQualifiedName(fullName,fullName.contains("::"),nd->getLanguage(),tagInfo); - d->addInnerCompound(nd); + d = buildScopeFromQualifiedName(fullName,nd->getLanguage(),tagInfo); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(nd); + } nd->setOuterScope(d); // TODO: Due to the order in which the tag file is written // a nested class can be found before its parent! } else { - d->addInnerCompound(nd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(nd); + } nd->setOuterScope(d); // in case of d is an inline namespace, alias insert nd in the part scope of d. - while (d->definitionType()==DefinitionIntf::TypeNamespace) + while (d->definitionType()==Definition::TypeNamespace) { - NamespaceDef *pnd = dynamic_cast<NamespaceDef*>(d); - if (pnd->isInline()) + NamespaceDef *pnd = toNamespaceDef(d); + if (pnd && pnd->isInline()) { d = d->getOuterScope(); if (d) { - NamespaceDef *aliasNd = createNamespaceDefAlias(d,nd); - //printf("adding %s to %s\n",qPrint(aliasNd->name()),qPrint(d->name())); - d->addInnerCompound(aliasNd); + dm = toDefinitionMutable(d); + if (dm) + { + NamespaceDef *aliasNd = createNamespaceDefAlias(d,nd); + //printf("adding %s to %s\n",qPrint(aliasNd->name()),qPrint(d->name())); + dm->addInnerCompound(aliasNd); + QCString aliasName = aliasNd->name(); + Doxygen::namespaceLinkedMap->add( + aliasName,std::unique_ptr<NamespaceDef>(aliasNd)); + } } } else @@ -1589,21 +1650,15 @@ static void buildNamespaceList(const Entry *root) //---------------------------------------------------------------------- -static const NamespaceDef *findUsedNamespace(const NamespaceSDict *unl, +static const NamespaceDef *findUsedNamespace(const LinkedRefMap<const NamespaceDef> &unl, const QCString &name) { const NamespaceDef *usingNd =0; - if (unl) + for (const auto &und : unl) { - //printf("Found namespace dict %d\n",unl->count()); - NamespaceSDict::Iterator unli(*unl); - const NamespaceDef *und; - for (unli.toFirst();(und=unli.current());++unli) - { - QCString uScope=und->name()+"::"; - usingNd = getResolvedNamespace(uScope+name); - //printf("Also trying with scope='%s' usingNd=%p\n",(uScope+name).data(),usingNd); - } + QCString uScope=und->name()+"::"; + usingNd = getResolvedNamespace(uScope+name); + if (usingNd!=0) break; } return usingNd; } @@ -1622,7 +1677,7 @@ static void findUsingDirectives(const Entry *root) if (!name.isEmpty()) { const NamespaceDef *usingNd = 0; - NamespaceDef *nd = 0; + NamespaceDefMutable *nd = 0; FileDef *fd = root->fileDef(); QCString nsName; @@ -1635,7 +1690,7 @@ static void findUsingDirectives(const Entry *root) nsName=stripAnonymousNamespaceScope(root->parent()->name); if (!nsName.isEmpty()) { - nd = getResolvedNamespace(nsName); + nd = getResolvedNamespaceMutable(nsName); } } @@ -1663,17 +1718,17 @@ static void findUsingDirectives(const Entry *root) if (usingNd==0 && nd) // not found, try used namespaces in this scope // or in one of the parent namespace scopes { - const NamespaceDef *pnd = nd; + const NamespaceDefMutable *pnd = nd; while (pnd && usingNd==0) { // also try with one of the used namespaces found earlier - usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name); + usingNd = toNamespaceDefMutable(findUsedNamespace(pnd->getUsedNamespaces(),name)); // goto the parent const Definition *s = pnd->getOuterScope(); if (s && s->definitionType()==Definition::TypeNamespace) { - pnd = dynamic_cast<const NamespaceDef*>(s); + pnd = toNamespaceDefMutable(toNamespaceDef(s)); } else { @@ -1707,7 +1762,11 @@ 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()); - nd=createNamespaceDef(root->fileName,root->startLine,root->startColumn,name); + // add namespace to the list + nd = toNamespaceDefMutable( + Doxygen::namespaceLinkedMap->add(name, + std::unique_ptr<NamespaceDef>( + 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); @@ -1739,8 +1798,6 @@ static void findUsingDirectives(const Entry *root) // the empty string test is needed for extract all case nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); nd->insertUsedFile(fd); - // add class to the list - Doxygen::namespaceSDict->inSort(name,nd); nd->setRefItems(root->sli); } } @@ -1782,8 +1839,8 @@ static void findUsingDeclarations(const Entry *root) // rootNav->parent()->section()); if (!root->name.isEmpty()) { - ClassDef *usingCd = 0; - NamespaceDef *nd = 0; + ClassDefMutable *usingCd = 0; + NamespaceDefMutable *nd = 0; FileDef *fd = root->fileDef(); QCString scName; @@ -1794,7 +1851,7 @@ static void findUsingDeclarations(const Entry *root) scName=root->parent()->name; if (!scName.isEmpty()) { - nd = getResolvedNamespace(scName); + nd = getResolvedNamespaceMutable(scName); } } @@ -1805,16 +1862,17 @@ static void findUsingDeclarations(const Entry *root) // file scope). QCString name = substitute(root->name,".","::"); //Java/C# scope->internal - usingCd = getClass(name); // try direct lookup first, this is needed to get + usingCd = getClassMutable(name); // try direct lookup first, this is needed to get // builtin STL classes to properly resolve, e.g. // vector -> std::vector if (usingCd==0) { - usingCd = const_cast<ClassDef*>(getResolvedClass(nd,fd,name)); // try via resolving (see also bug757509) + SymbolResolver resolver(fd); + usingCd = resolver.resolveClassMutable(nd,name); // try via resolving (see also bug757509) } if (usingCd==0) { - usingCd = Doxygen::hiddenClasses->find(name); // check if it is already hidden + usingCd = toClassDefMutable(Doxygen::hiddenClassLinkedMap->find(name)); // check if it is already hidden } //printf("%s -> %p\n",root->name.data(),usingCd); @@ -1822,11 +1880,10 @@ static void findUsingDeclarations(const Entry *root) { Debug::print(Debug::Classes,0," New using class '%s' (sec=0x%08x)! #tArgLists=%d\n", qPrint(name),root->section,root->tArgLists.size()); - usingCd = createClassDef( - "<using>",1,1, - name, - ClassDef::Class); - Doxygen::hiddenClasses->append(root->name,usingCd); + usingCd = toClassDefMutable( + Doxygen::hiddenClassLinkedMap->add(name, + std::unique_ptr<ClassDef>( + createClassDef( "<using>",1,1, name, ClassDef::Class)))); usingCd->setArtificial(TRUE); usingCd->setLanguage(root->lang); } @@ -1867,7 +1924,7 @@ static void findUsingDeclImports(const Entry *root) QCString fullName=removeRedundantWhiteSpace(root->parent()->name); fullName=stripAnonymousNamespaceScope(fullName); fullName=stripTemplateSpecifiersFromScope(fullName); - ClassDef *cd = getClass(fullName); + ClassDefMutable *cd = getClassMutable(fullName); if (cd) { //printf("found class %s\n",cd->name().data()); @@ -1876,7 +1933,8 @@ static void findUsingDeclImports(const Entry *root) { QCString scope=root->name.left(i); QCString memName=root->name.right(root->name.length()-i-2); - const ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter + SymbolResolver resolver; + const ClassDef *bcd = resolver.resolveClass(cd,scope); // todo: file in fileScope parameter if (bcd && bcd!=cd) { //printf("found class %s memName=%s\n",bcd->name().data(),memName.data()); @@ -1897,7 +1955,7 @@ static void findUsingDeclImports(const Entry *root) } const ArgumentList &templAl = md->templateArguments(); const ArgumentList &al = md->templateArguments(); - std::unique_ptr<MemberDef> newMd { createMemberDef( + std::unique_ptr<MemberDefMutable> newMd { createMemberDef( fileName,root->startLine,root->startColumn, md->typeString(),memName,md->argsString(), md->excpString(),root->protection,root->virt, @@ -1950,25 +2008,15 @@ static void findUsingDeclImports(const Entry *root) static void findIncludedUsingDirectives() { - // first mark all files as not visited - for (const auto &fn : *Doxygen::inputNameLinkedMap) - { - for (const auto &fd : *fn) - { - fd->setVisited(FALSE); - } - } + FileDefSet visitedFiles; // then recursively add using directives found in #include files // to files that have not been visited. for (const auto &fn : *Doxygen::inputNameLinkedMap) { for (const auto &fd : *fn) { - if (!fd->isVisited()) - { - //printf("----- adding using directives for file %s\n",fd->name().data()); - fd->addIncludedUsingDirectives(); - } + //printf("----- adding using directives for file %s\n",fd->name().data()); + fd->addIncludedUsingDirectives(visitedFiles); } } } @@ -1977,7 +2025,7 @@ static void findIncludedUsingDirectives() static MemberDef *addVariableToClass( const Entry *root, - ClassDef *cd, + ClassDefMutable *cd, MemberType mtype, const QCString &type, const QCString &name, @@ -2052,11 +2100,12 @@ static MemberDef *addVariableToClass( MemberName *mn=Doxygen::memberNameLinkedMap->find(name); if (mn) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n", // md->getClassDef(),cd,type.data(),md->typeString()); - if (!md->isAlias() && + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->getClassDef()==cd && removeRedundantWhiteSpace(type)==md->typeString()) // member already in the scope @@ -2068,11 +2117,11 @@ static MemberDef *addVariableToClass( { // Objective-C 2.0 property // turn variable into a property md->setProtection(root->protection); - cd->reclassifyMember(md.get(),MemberType_Property); + cd->reclassifyMember(md,MemberType_Property); } - addMemberDocs(root,md.get(),def,0,FALSE,root->spec); + addMemberDocs(root,md,def,0,FALSE,root->spec); //printf(" Member already found!\n"); - return md.get(); + return md; } } } @@ -2084,7 +2133,7 @@ static MemberDef *addVariableToClass( } // new member variable, typedef or enum value - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,root->exception, prot,Normal,root->stat,related, @@ -2179,7 +2228,7 @@ static MemberDef *addVariableToFile( if (s>=0) { QCString typeValue = ttype.mid(s,l); - ClassDef *cd = getClass(typeValue); + ClassDefMutable *cd = getClassMutable(typeValue); if (cd) { // this typedef should hide compound name cd, so we @@ -2194,15 +2243,11 @@ static MemberDef *addVariableToFile( } // see if the function is inside a namespace - NamespaceDef *nd = 0; + NamespaceDefMutable *nd = 0; if (!scope.isEmpty()) { if (scope.find('@')!=-1) return 0; // anonymous scope! - //nscope=removeAnonymousScopes(scope); - //if (!nscope.isEmpty()) - //{ - nd = getResolvedNamespace(scope); - //} + nd = getResolvedNamespaceMutable(scope); } QCString def; @@ -2266,11 +2311,12 @@ static MemberDef *addVariableToFile( //if (!nscope.isEmpty()) if (!scope.isEmpty()) { - nd = getResolvedNamespace(scope); + nd = getResolvedNamespaceMutable(scope); } - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (!md->isAlias() && + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() && root->fileName==md->getFileDef()->absFilePath() ) // both variable names in the same file @@ -2296,7 +2342,7 @@ static MemberDef *addVariableToFile( { Debug::print(Debug::Variables,0, " variable already found: scope=%s\n",qPrint(md->getOuterScope()->name())); - addMemberDocs(root,md.get(),def,0,FALSE,root->spec); + addMemberDocs(root,md,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 @@ -2311,7 +2357,7 @@ static MemberDef *addVariableToFile( { md->setDeclFile(root->fileName,root->startLine,root->startColumn); } - return md.get(); + return md; } } } @@ -2326,12 +2372,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 - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> 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) }; + root->argList, root->metaData) }; md->setTagInfo(root->tagInfo()); md->setMemberSpecifiers(root->spec); md->setDocumentation(root->doc,root->docFile,root->docLine); @@ -2426,11 +2472,13 @@ static bool isVarWithConstructor(const Entry *root) static QRegExp initChars("[0-9\"'&*!^]+"); static QRegExp idChars("[a-z_A-Z][a-z_A-Z0-9]*"); bool result=FALSE; - bool typeIsClass; + bool typeIsClass = false; + bool typePtrType = false; QCString type; Definition *ctx = 0; - FileDef *fd = 0; + FileDef *fd = root->fileDef(); int ti; + SymbolResolver resolver(fd); //printf("isVarWithConstructor(%s)\n",rootNav->name().data()); if (root->parent()->section & Entry::COMPOUND_MASK) @@ -2438,9 +2486,7 @@ static bool isVarWithConstructor(const Entry *root) result=FALSE; goto done; } - else if ((fd = root->fileDef()) && - (fd->name().right(2)==".c" || fd->name().right(2)==".h") - ) + else if ((fd != nullptr) && (fd->name().right(2)==".c" || fd->name().right(2)==".h")) { // inside a .c file result=FALSE; goto done; @@ -2452,18 +2498,22 @@ static bool isVarWithConstructor(const Entry *root) } if (!root->parent()->name.isEmpty()) { - ctx=Doxygen::namespaceSDict->find(root->parent()->name); + ctx=Doxygen::namespaceLinkedMap->find(root->parent()->name); } type = root->type; // remove qualifiers findAndRemoveWord(type,"const"); findAndRemoveWord(type,"static"); findAndRemoveWord(type,"volatile"); + typePtrType = type.find('*')!=-1 || type.find('&')!=-1; //if (type.left(6)=="const ") type=type.right(type.length()-6); - typeIsClass=getResolvedClass(ctx,fd,type)!=0; - if (!typeIsClass && (ti=type.find('<'))!=-1) + if (!typePtrType) { - typeIsClass=getResolvedClass(ctx,fd,type.left(ti))!=0; + typeIsClass = resolver.resolveClass(ctx,type)!=0; + if (!typeIsClass && (ti=type.find('<'))!=-1) + { + typeIsClass=resolver.resolveClass(ctx,type.left(ti))!=0; + } } if (typeIsClass) // now we still have to check if the arguments are // types or values. Since we do not have complete type info @@ -2489,7 +2539,15 @@ static bool isVarWithConstructor(const Entry *root) } goto done; } - if (a.type.isEmpty() || getResolvedClass(ctx,fd,a.type)!=0) + if (!a.type.isEmpty() && + (a.type.at(a.type.length()-1)=='*' || + a.type.at(a.type.length()-1)=='&')) + // type ends with * or & => pointer or reference + { + result=FALSE; + goto done; + } + if (a.type.isEmpty() || resolver.resolveClass(ctx,a.type)!=0) { result=FALSE; // arg type is a known type goto done; @@ -2500,13 +2558,6 @@ static bool isVarWithConstructor(const Entry *root) result=FALSE; // argument is a typedef goto done; } - if (a.type.at(a.type.length()-1)=='*' || - a.type.at(a.type.length()-1)=='&') - // type ends with * or & => pointer or reference - { - result=FALSE; - goto done; - } if (a.type.find(initChars)==0) { result=TRUE; // argument type starts with typical initializer char @@ -2617,7 +2668,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) MemberType mtype; type=type.stripWhiteSpace(); - ClassDef *cd=0; + ClassDefMutable *cd=0; bool isRelated=FALSE; bool isMemberOf=FALSE; @@ -2630,7 +2681,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) if (type=="friend class" || type=="friend struct" || type=="friend union") { - cd=getClass(scope); + cd=getClassMutable(scope); if (cd) { addVariableToClass(root, // entry @@ -2681,8 +2732,8 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) scope=root->relates; } - cd=getClass(scope); - if (cd==0 && classScope!=scope) cd=getClass(classScope); + cd=getClassMutable(scope); + if (cd==0 && classScope!=scope) cd=getClassMutable(classScope); if (cd) { MemberDef *md=0; @@ -2700,7 +2751,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) if (si!=-1 && !inlineSimpleStructs) // anonymous scope or type { QCString pScope; - ClassDef *pcd=0; + ClassDefMutable *pcd=0; pScope = scope.left(QMAX(si-2,0)); // scope without tag less parts if (!pScope.isEmpty()) pScope.prepend(annScopePrefix); @@ -2708,7 +2759,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) pScope=annScopePrefix.left(annScopePrefix.length()-2); if (name.at(0)!='@') { - if (!pScope.isEmpty() && (pcd=getClass(pScope))) + if (!pScope.isEmpty() && (pcd=getClassMutable(pScope))) { md=addVariableToClass(root, // entry pcd, // class to add member to @@ -2844,7 +2895,7 @@ static void buildVarList(const Entry *root) static void addInterfaceOrServiceToServiceOrSingleton( const Entry *root, - ClassDef *const cd, + ClassDefMutable *cd, QCString const& rname) { FileDef *fd = root->fileDef(); @@ -2856,7 +2907,7 @@ static void addInterfaceOrServiceToServiceOrSingleton( { fileName = root->tagInfo()->tagName; } - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName, root->startLine, root->startColumn, root->type, rname, "", "", root->protection, root->virt, root->stat, Member, type, ArgumentList(), root->argList, root->metaData) }; @@ -2940,7 +2991,7 @@ static void buildInterfaceAndServiceList(const Entry *root) if (!rname.isEmpty()) { QCString scope = root->parent()->name; - ClassDef *cd = getClass(scope); + ClassDefMutable *cd = getClassMutable(scope); assert(cd); if (cd && ((ClassDef::Interface == cd->compoundType()) || (ClassDef::Service == cd->compoundType()) || @@ -2976,7 +3027,7 @@ static void buildInterfaceAndServiceList(const Entry *root) // Searches the Entry tree for Function sections. // If found they are stored in their class or in the global list. -static void addMethodToClass(const Entry *root,ClassDef *cd, +static void addMethodToClass(const Entry *root,ClassDefMutable *cd, const QCString &rtype,const QCString &rname,const QCString &rargs, bool isFriend, Protection protection,bool stat,Specifier virt,uint64 spec, @@ -3037,7 +3088,7 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, // ); // adding class member - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,root->exception, protection,virt, @@ -3133,8 +3184,7 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, //------------------------------------------------------------------------------------------ -void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &sc, - NamespaceDef *nd) +static void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &sc) { QCString scope = sc; Debug::print(Debug::Functions,0," --> new function %s found!\n",qPrint(rname)); @@ -3143,7 +3193,7 @@ void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &s // new global function QCString name=removeRedundantWhiteSpace(rname); - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, root->type,name,root->args,root->exception, root->protection,root->virt,root->stat,Member, @@ -3168,15 +3218,16 @@ void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &s md->setMemberSpecifiers(root->spec); md->setMemberGroupId(root->mGrpId); + NamespaceDefMutable *nd = 0; // 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 ) + if (root->parent()->section == Entry::NAMESPACE_SEC ) { //QCString nscope=removeAnonymousScopes(root->parent()->name); QCString nscope=root->parent()->name; if (!nscope.isEmpty()) { - nd = getResolvedNamespace(nscope); + nd = getResolvedNamespaceMutable(nscope); } } @@ -3281,7 +3332,7 @@ static void buildFunctionList(const Entry *root) QCString scope=root->parent()->name; //stripAnonymousNamespaceScope(root->parent->name); if (!rname.isEmpty() && scope.find('@')==-1) { - ClassDef *cd=0; + ClassDefMutable *cd=0; // check if this function's parent is a class scope=stripTemplateSpecifiersFromScope(scope,FALSE); @@ -3289,14 +3340,13 @@ static void buildFunctionList(const Entry *root) int memIndex=rname.findRev("::"); - cd=getClass(scope); + cd=getClassMutable(scope); if (cd && scope+"::"==rname.left(scope.length()+2)) // found A::f inside A { // strip scope from name rname=rname.right(rname.length()-root->parent()->name.length()-2); } - NamespaceDef *nd = 0; bool isMember=FALSE; if (memIndex!=-1) { @@ -3307,7 +3357,7 @@ static void buildFunctionList(const Entry *root) // note: the following code was replaced by inMember=TRUE to deal with a // function rname='X::foo' of class X inside a namespace also called X... // bug id 548175 - //nd = Doxygen::namespaceSDict->find(rname.left(memIndex)); + //nd = Doxygen::namespaceLinkedMap->find(rname.left(memIndex)); //isMember = nd==0; //if (nd) //{ @@ -3364,9 +3414,10 @@ static void buildFunctionList(const Entry *root) if ((mn=Doxygen::functionNameLinkedMap->find(rname))) { Debug::print(Debug::Functions,0," --> function %s already found!\n",qPrint(rname)); - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (!md->isAlias()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { const NamespaceDef *mnd = md->getNamespaceDef(); NamespaceDef *rnd = 0; @@ -3386,7 +3437,7 @@ static void buildFunctionList(const Entry *root) if (rnd) rnsName = rnd->name().copy(); //printf("matching arguments for %s%s %s%s\n", // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data()); - ArgumentList &mdAl = md->argumentList(); + const ArgumentList &mdAl = md->argumentList(); const ArgumentList &mdTempl = md->templateArguments(); // in case of template functions, we need to check if the @@ -3444,7 +3495,7 @@ static void buildFunctionList(const Entry *root) { // merge argument lists ArgumentList mergedArgList = root->argList; - mergeArguments(mdAl,mergedArgList,!root->doc.isEmpty()); + mergeArguments(const_cast<ArgumentList&>(mdAl),mergedArgList,!root->doc.isEmpty()); // merge documentation if (md->documentation().isEmpty() && !root->doc.isEmpty()) { @@ -3484,7 +3535,7 @@ static void buildFunctionList(const Entry *root) // merge ingroup specifiers if (md->getGroupDef()==0 && !root->groups.empty()) { - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } else if (md->getGroupDef()!=0 && root->groups.empty()) { @@ -3512,14 +3563,14 @@ static void buildFunctionList(const Entry *root) } if (found) { - md_found = md.get(); + md_found = md; break; } } } if (!found) /* global function is unique with respect to the file */ { - addGlobalFunction(root,rname,scope,nd); + addGlobalFunction(root,rname,scope); } else { @@ -3563,29 +3614,29 @@ static void findFriends() { // there are members with the same name //printf("Function name is also a member name\n"); // for each function with that name - for (const auto &fmd : *fn) + for (const auto &ifmd : *fn) { - const MemberDef *cfmd = fmd.get(); + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); // for each member with that name - for (const auto &mmd : *mn) + for (const auto &immd : *mn) { - const MemberDef *cmmd = mmd.get(); + MemberDefMutable *mmd = toMemberDefMutable(immd.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(), + if (fmd && mmd && + (mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) && + matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), &mmd->argumentList(), + fmd->getOuterScope(), fmd->getFileDef(), &fmd->argumentList(), TRUE ) ) // if the member is related and the arguments match then the // function is actually a friend. { - ArgumentList &mmdAl = mmd->argumentList(); - ArgumentList &fmdAl = fmd->argumentList(); - mergeArguments(mmdAl,fmdAl); + const ArgumentList &mmdAl = mmd->argumentList(); + const ArgumentList &fmdAl = fmd->argumentList(); + mergeArguments(const_cast<ArgumentList&>(mmdAl),const_cast<ArgumentList&>(fmdAl)); if (!fmd->documentation().isEmpty()) { mmd->setDocumentation(fmd->documentation(),fmd->docFile(),fmd->docLine()); @@ -3652,19 +3703,21 @@ static void transferFunctionDocumentation() { //printf("memberName=%s count=%d\n",mn->memberName(),mn->count()); /* find a matching function declaration and definition for this function */ - for (const auto &mdec : *mn) + for (const auto &imdec : *mn) { - if (mdec->isPrototype() || - (mdec->isVariable() && mdec->isExternal()) - ) + MemberDefMutable *mdec = toMemberDefMutable(imdec.get()); + if (mdec && + (mdec->isPrototype() || + (mdec->isVariable() && mdec->isExternal()) + )) { - for (const auto &mdef : *mn) + for (const auto &imdef : *mn) { - if (mdec!=mdef && - !mdec->isAlias() && !mdef->isAlias() && + MemberDefMutable *mdef = toMemberDefMutable(imdef.get()); + if (mdef && mdec!=mdef && mdec->getNamespaceDef()==mdef->getNamespaceDef()) { - combineDeclarationAndDefinition(mdec.get(),mdef.get()); + combineDeclarationAndDefinition(mdec,mdef); } } } @@ -3678,87 +3731,41 @@ static void transferFunctionReferences() { for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *mdef=0,*mdec=0; + MemberDefMutable *mdef=0,*mdec=0; /* find a matching function declaration and definition for this function */ - for (const auto &md_p : *mn) + for (const auto &imd : *mn) { - MemberDef *md = md_p.get(); - if (md->isPrototype()) - mdec=md; - else if (md->isVariable() && md->isExternal()) - mdec=md; + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + if (md->isPrototype()) + mdec=md; + else if (md->isVariable() && md->isExternal()) + mdec=md; - if (md->isFunction() && !md->isStatic() && !md->isPrototype()) - mdef=md; - else if (md->isVariable() && !md->isExternal() && !md->isStatic()) - mdef=md; + if (md->isFunction() && !md->isStatic() && !md->isPrototype()) + 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(); + const ArgumentList &mdefAl = mdef->argumentList(); + const ArgumentList &mdecAl = mdec->argumentList(); if ( - matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, - mdec->getOuterScope(),mdec->getFileDef(),&mdecAl, + matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),const_cast<ArgumentList*>(&mdefAl), + mdec->getOuterScope(),mdec->getFileDef(),const_cast<ArgumentList*>(&mdecAl), TRUE ) ) /* match found */ { - MemberSDict *defDict = mdef->getReferencesMembers(); - MemberSDict *decDict = mdec->getReferencesMembers(); - if (defDict!=0) - { - MemberSDict::IteratorDict msdi(*defDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (decDict==0 || decDict->find(rmd->name())==0) - { - mdec->addSourceReferences(rmd); - } - } - } - if (decDict!=0) - { - MemberSDict::IteratorDict msdi(*decDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (defDict==0 || defDict->find(rmd->name())==0) - { - mdef->addSourceReferences(rmd); - } - } - } - - defDict = mdef->getReferencedByMembers(); - decDict = mdec->getReferencedByMembers(); - if (defDict!=0) - { - MemberSDict::IteratorDict msdi(*defDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (decDict==0 || decDict->find(rmd->name())==0) - { - mdec->addSourceReferencedBy(rmd); - } - } - } - if (decDict!=0) - { - MemberSDict::IteratorDict msdi(*decDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (defDict==0 || defDict->find(rmd->name())==0) - { - mdef->addSourceReferencedBy(rmd); - } - } - } + mdef->mergeReferences(mdec); + mdec->mergeReferences(mdef); + mdef->mergeReferencedBy(mdec); + mdec->mergeReferencedBy(mdef); } } } @@ -3774,32 +3781,37 @@ static void transferRelatedFunctionDocumentation() { /* find a matching function declaration and definition for this function */ // for each global function - for (const auto &md : *mn) + for (const auto &imd : *mn) { - //printf(" Function '%s'\n",md->name().data()); - MemberName *rmn; - if ((rmn=Doxygen::memberNameLinkedMap->find(md->name()))) // check if there is a member with the same name + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { - //printf(" Member name found\n"); - // for each member with the same name - for (const auto &rmd : *rmn) + //printf(" Function '%s'\n",md->name().data()); + MemberName *rmn; + if ((rmn=Doxygen::memberNameLinkedMap->find(md->name()))) // check if there is a member with the same name { - //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(), - TRUE - ) - ) + //printf(" Member name found\n"); + // for each member with the same name + for (const auto &irmd : *rmn) { - //printf(" Found related member '%s'\n",md->name().data()); - if (rmd->relatedAlso()) - md->setRelatedAlso(rmd->relatedAlso()); - else if (rmd->isForeign()) - md->makeForeign(); - else - md->makeRelated(); + MemberDefMutable *rmd = toMemberDefMutable(irmd.get()); + //printf(" Member found: related='%d'\n",rmd->isRelated()); + if (rmd && + (rmd->isRelated() || rmd->isForeign()) && // related function + matchArguments2( md->getOuterScope(), md->getFileDef(), &md->argumentList(), + rmd->getOuterScope(),rmd->getFileDef(),&rmd->argumentList(), + TRUE + ) + ) + { + //printf(" Found related member '%s'\n",md->name().data()); + if (rmd->relatedAlso()) + md->setRelatedAlso(rmd->relatedAlso()); + else if (rmd->isForeign()) + md->makeForeign(); + else + md->makeRelated(); + } } } } @@ -3850,24 +3862,22 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co return result; } FileDef *fd=cd->getFileDef(); + SymbolResolver resolver(fd); if (context && cd!=context) { - result = const_cast<ClassDef*>(getResolvedClass(context,0,name,0,0,TRUE,TRUE)); + result = const_cast<ClassDef*>(resolver.resolveClass(context,name,true,true)); } + //printf("1. result=%p\n",result); if (result==0) { - result = const_cast<ClassDef*>(getResolvedClass(cd,fd,name,0,0,TRUE,TRUE)); + result = const_cast<ClassDef*>(resolver.resolveClass(cd,name,true,true)); } + //printf("2. result=%p\n",result); if (result==0) // try direct class, needed for namespaced classes imported via tag files (see bug624095) { result = getClass(name); } - if (result==0 && - (cd->getLanguage()==SrcLangExt_CSharp || cd->getLanguage()==SrcLangExt_Java) && - name.find('<')!=-1) - { - result = Doxygen::genericsDict->find(name); - } + //printf("3. result=%p\n",result); //printf("** Trying to find %s within context %s class %s result=%s lookup=%p\n", // name.data(), // context ? context->name().data() : "<none>", @@ -3881,14 +3891,13 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co static void findUsedClassesForClass(const Entry *root, Definition *context, - ClassDef *masterCd, - ClassDef *instanceCd, + ClassDefMutable *masterCd, + ClassDefMutable *instanceCd, bool isArtificial, const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(), QDict<int> *templateNames=0 ) { - masterCd->setVisited(TRUE); const ArgumentList &formalArgs = masterCd->templateArguments(); for (auto &mni : masterCd->memberNameInfoLinkedMap()) { @@ -3915,12 +3924,8 @@ static void findUsedClassesForClass(const Entry *root, 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 - ); + SymbolResolver resolver(masterCd->getFileDef()); + const ClassDefMutable *typeCd = resolver.resolveClassMutable(masterCd,usedClassName,false,true); //printf("====> usedClassName=%s -> typeCd=%s\n", // usedClassName.data(),typeCd?typeCd->name().data():"<none>"); if (typeCd) @@ -3956,19 +3961,21 @@ static void findUsedClassesForClass(const Entry *root, found=TRUE; Debug::print(Debug::Classes,0," New used class '%s'\n", qPrint(usedName)); - ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName); + ClassDefMutable *usedCd = toClassDefMutable(Doxygen::hiddenClassLinkedMap->find(usedName)); if (usedCd==0) { - usedCd = createClassDef( - masterCd->getDefFileName(),masterCd->getDefLine(), - masterCd->getDefColumn(), - usedName, - ClassDef::Class); + usedCd = toClassDefMutable( + Doxygen::hiddenClassLinkedMap->add(usedName, + std::unique_ptr<ClassDef>( + 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())); @@ -3979,7 +3986,7 @@ static void findUsedClassesForClass(const Entry *root, if (!found) { - ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName); + ClassDefMutable *usedCd=toClassDefMutable(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>"); @@ -3999,7 +4006,7 @@ static void findUsedClassesForClass(const Entry *root, } if (!found && !type.isEmpty()) // used class is not documented in any scope { - ClassDef *usedCd = Doxygen::hiddenClasses->find(type); + ClassDefMutable *usedCd = toClassDefMutable(Doxygen::hiddenClassLinkedMap->find(type)); if (usedCd==0 && !Config_getBool(HIDE_UNDOC_RELATIONS)) { if (type.right(2)=="(*" || type.right(2)=="(^") // type is a function pointer @@ -4007,13 +4014,15 @@ static void findUsedClassesForClass(const Entry *root, 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 = toClassDefMutable( + Doxygen::hiddenClassLinkedMap->add(type, + std::unique_ptr<ClassDef>( + createClassDef( + masterCd->getDefFileName(),masterCd->getDefLine(), + masterCd->getDefColumn(), + type,ClassDef::Class)))); usedCd->setUsedOnly(TRUE); usedCd->setLanguage(masterCd->getLanguage()); - Doxygen::hiddenClasses->append(type,usedCd); } if (usedCd) { @@ -4031,22 +4040,20 @@ static void findUsedClassesForClass(const Entry *root, static void findBaseClassesForClass( const Entry *root, Definition *context, - ClassDef *masterCd, - ClassDef *instanceCd, + ClassDefMutable *masterCd, + ClassDefMutable *instanceCd, FindBaseClassRelation_Mode mode, bool isArtificial, const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(), QDict<int> *templateNames=0 ) { - //if (masterCd->visited) return; - masterCd->setVisited(TRUE); // The base class could ofcouse also be a non-nested class const ArgumentList &formalArgs = masterCd->templateArguments(); for (const BaseInfo &bi : root->extends) { - //printf("masterCd=%s bi->name='%s' #actualArgs=%d\n", - // masterCd->localName().data(),bi->name.data(),actualArgs?(int)actualArgs->count():-1); + //printf("masterCd=%s bi.name='%s' #actualArgs=%d\n", + // masterCd->localName().data(),bi.name.data(),actualArgs ? (int)actualArgs->size() : -1); bool delTempNames=FALSE; if (templateNames==0) { @@ -4088,7 +4095,7 @@ static void findBaseClassesForClass( static bool findTemplateInstanceRelation(const Entry *root, Definition *context, - ClassDef *templateClass,const QCString &templSpec, + ClassDefMutable *templateClass,const QCString &templSpec, QDict<int> *templateNames, bool isArtificial) { @@ -4108,26 +4115,26 @@ static bool findTemplateInstanceRelation(const Entry *root, //printf("\n"); bool existingClass = (templSpec == - tempArgListToString(templateClass->templateArguments(),root->lang) + tempArgListToString(templateClass->templateArguments(),root->lang,false) ); if (existingClass) return TRUE; bool freshInstance=FALSE; - ClassDef *instanceClass = templateClass->insertTemplateInstance( - root->fileName,root->startLine,root->startColumn,templSpec,freshInstance); + ClassDefMutable *instanceClass = toClassDefMutable( + templateClass->insertTemplateInstance( + root->fileName,root->startLine,root->startColumn,templSpec,freshInstance)); if (isArtificial) instanceClass->setArtificial(TRUE); instanceClass->setLanguage(root->lang); if (freshInstance) { Debug::print(Debug::Classes,0," found fresh instance '%s'!\n",qPrint(instanceClass->name())); - Doxygen::classSDict->append(instanceClass->name(),instanceClass); instanceClass->setTemplateBaseClassNames(templateNames); // search for new template instances caused by base classes of // instanceClass - auto it = g_classEntries.find(templateClass->name().data()); - if (it!=g_classEntries.end()) + auto it_pair = g_classEntries.equal_range(templateClass->name().data()); + for (auto it=it_pair.first ; it!=it_pair.second ; ++it) { const Entry *templateRoot = it->second; Debug::print(Debug::Classes,0," template root found %s templSpec=%s!\n", @@ -4139,11 +4146,6 @@ static bool findTemplateInstanceRelation(const Entry *root, findUsedClassesForClass(templateRoot,context,templateClass,instanceClass, isArtificial,templArgs,templateNames); } - else - { - Debug::print(Debug::Classes,0," no template root entry found!\n"); - // TODO: what happened if we get here? - } //Debug::print(Debug::Classes,0," Template instance %s : \n",instanceClass->name().data()); //ArgumentList *tl = templateClass->templateArguments(); @@ -4246,10 +4248,40 @@ static int findEndOfTemplate(const QCString &s,int startPos) return brCount==0 ? e : -1; } +static int findTemplateSpecializationPosition(const char *name) +{ + if (name==0 || name[0]=='\0') return 0; + int l = static_cast<int>(strlen(name)); + if (name[l-1]=='>') // search backward to find the matching <, allowing nested <...> and strings. + { + int count=1; + int i=l-2; + char insideQuote=0; + while (count>0 && i>=0) + { + char c = name[i--]; + switch (c) + { + case '>': if (!insideQuote) count++; break; + case '<': if (!insideQuote) count--; break; + case '\'': if (!insideQuote) insideQuote=c; + else if (insideQuote==c && (i<0 || name[i]!='\\')) insideQuote=0; + break; + case '"': if (!insideQuote) insideQuote=c; + else if (insideQuote==c && (i<0 || name[i]!='\\')) insideQuote=0; + break; + default: break; + } + } + if (i>=0) l=i+1; + } + return l; +} + static bool findClassRelation( const Entry *root, Definition *context, - ClassDef *cd, + ClassDefMutable *cd, const BaseInfo *bi, QDict<int> *templateNames, FindBaseClassRelation_Mode mode, @@ -4299,17 +4331,14 @@ static bool findClassRelation( //baseClassName=stripTemplateSpecifiersFromScope // (removeRedundantWhiteSpace(baseClassName),TRUE, // &stripped); - const MemberDef *baseClassTypeDef=0; - QCString templSpec; - ClassDef *baseClass=const_cast<ClassDef*>( - getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), + SymbolResolver resolver(cd->getFileDef()); + ClassDefMutable *baseClass = resolver.resolveClassMutable(explicitGlobalScope ? Doxygen::globalScope : context, baseClassName, - &baseClassTypeDef, - &templSpec, mode==Undocumented, - TRUE - )); + true + ); + const MemberDef *baseClassTypeDef = resolver.getTypedef(); + QCString templSpec = resolver.getTemplateSpec(); //printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n", // baseClassName.data(),baseClass,cd,explicitGlobalScope); //printf(" scope='%s' baseClassName='%s' baseClass=%s templSpec=%s\n", @@ -4340,16 +4369,10 @@ static bool findClassRelation( qPrint(templSpec) ); - int i=baseClassName.find('<'); - int si=baseClassName.findRev("::",i==-1 ? baseClassName.length() : i); + int i=findTemplateSpecializationPosition(baseClassName); + int si=baseClassName.findRev("::",i); if (si==-1) si=0; - if (baseClass==0 && (root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java)) - { - // for Java/C# strip the template part before looking for matching - baseClass = Doxygen::genericsDict->find(baseClassName.left(i)); - //printf("looking for '%s' result=%p\n",baseClassName.data(),baseClass); - } - if (baseClass==0 && i!=-1) + if (baseClass==0 && static_cast<uint>(i)!=baseClassName.length()) // base class has template specifiers { // TODO: here we should try to find the correct template specialization @@ -4358,17 +4381,14 @@ static bool findClassRelation( //printf("baseClass==0 i=%d e=%d\n",i,e); if (e!=-1) // end of template was found at e { - templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i)); - baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e); - baseClass=const_cast<ClassDef*>( - getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), + templSpec = removeRedundantWhiteSpace(baseClassName.mid(i,e-i)); + baseClassName = baseClassName.left(i)+baseClassName.right(baseClassName.length()-e); + baseClass = resolver.resolveClassMutable(explicitGlobalScope ? Doxygen::globalScope : context, baseClassName, - &baseClassTypeDef, - 0, //&templSpec, mode==Undocumented, - TRUE - )); + true + ); + baseClassTypeDef = resolver.getTypedef(); //printf("baseClass=%p -> baseClass=%s templSpec=%s\n", // baseClass,baseClassName.data(),templSpec.data()); } @@ -4379,8 +4399,8 @@ static bool findClassRelation( // instance (for instance if a class // derived from a template argument) { - //printf("baseClass=%p templSpec=%s\n",baseClass,templSpec.data()); - ClassDef *templClass=getClass(baseClass->name()+templSpec); + //printf("baseClass=%s templSpec=%s\n",baseClass->name().data(),templSpec.data()); + ClassDefMutable *templClass=getClassMutable(baseClass->name()+templSpec); if (templClass) { // use the template instance instead of the template base. @@ -4394,38 +4414,29 @@ static bool findClassRelation( //printf("1. found=%d\n",found); if (!found && si!=-1) { - QCString tmpTemplSpec; // replace any namespace aliases replaceNamespaceAliases(baseClassName,si); - baseClass=const_cast<ClassDef*>( - getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), + baseClass = resolver.resolveClassMutable(explicitGlobalScope ? Doxygen::globalScope : context, baseClassName, - &baseClassTypeDef, - &tmpTemplSpec, mode==Undocumented, - TRUE - )); + true + ); + baseClassTypeDef = resolver.getTypedef(); + QCString tmpTemplSpec = resolver.getTemplateSpec(); found=baseClass!=0 && baseClass!=cd; if (found) templSpec = tmpTemplSpec; } //printf("2. found=%d\n",found); - //printf("root->name=%s biName=%s baseClassName=%s\n", - // root->name.data(),biName.data(),baseClassName.data()); - //if (cd->isCSharp() && i!=-1) // C# generic -> add internal -g postfix - //{ - // baseClassName+="-g"; - //} - if (!found) { - baseClass=findClassWithinClassContext(context,cd,baseClassName); + baseClass=toClassDefMutable(findClassWithinClassContext(context,cd,baseClassName)); //printf("findClassWithinClassContext(%s,%s)=%p\n", // cd->name().data(),baseClassName.data(),baseClass); found = baseClass!=0 && baseClass!=cd; } + //printf("3. found=%d\n",found); if (!found) { // for PHP the "use A\B as C" construct map class C to A::B, so we lookup @@ -4433,7 +4444,7 @@ static bool findClassRelation( auto it = Doxygen::namespaceAliasMap.find(baseClassName.data()); if (it!=Doxygen::namespaceAliasMap.end()) // see if it is indeed a class. { - baseClass=getClass(it->second.c_str()); + baseClass=getClassMutable(it->second.c_str()); found = baseClass!=0 && baseClass!=cd; } } @@ -4442,7 +4453,7 @@ static bool findClassRelation( // warning: the following line doesn't work for Mixin classes (see bug 560623) // templSpec = getCanonicalTemplateSpec(cd, cd->getFileDef(), templSpec); - //printf("3. found=%d\n",found); + //printf("4. found=%d\n",found); if (found) { Debug::print(Debug::Classes,0," Documented base class '%s' templSpec=%s\n",qPrint(biName),qPrint(templSpec)); @@ -4466,7 +4477,7 @@ static bool findClassRelation( if (baseClassTypeDef==0) { //printf(" => findTemplateInstanceRelation: %p\n",baseClassTypeDef); - findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,isArtificial); + findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,baseClass->isArtificial()); } } else if (mode==DocumentedOnly || mode==Undocumented) @@ -4506,28 +4517,33 @@ static bool findClassRelation( baseClass=0; if (isATemplateArgument) { - baseClass=Doxygen::hiddenClasses->find(baseClassName); + baseClass=toClassDefMutable(Doxygen::hiddenClassLinkedMap->find(baseClassName)); if (baseClass==0) { - baseClass=createClassDef(root->fileName,root->startLine,root->startColumn, + baseClass= toClassDefMutable( + Doxygen::hiddenClassLinkedMap->add(baseClassName, + std::unique_ptr<ClassDef>( + createClassDef(root->fileName,root->startLine,root->startColumn, baseClassName, - ClassDef::Class); - Doxygen::hiddenClasses->append(baseClassName,baseClass); + ClassDef::Class)))); if (isArtificial) baseClass->setArtificial(TRUE); baseClass->setLanguage(root->lang); + } } else { - baseClass=Doxygen::classSDict->find(baseClassName); + baseClass=toClassDefMutable(Doxygen::classLinkedMap->find(baseClassName)); //printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n", // baseClassName.data(),baseClass,biName.data(),templSpec.data()); if (baseClass==0) { - baseClass=createClassDef(root->fileName,root->startLine,root->startColumn, - baseClassName, - ClassDef::Class); - Doxygen::classSDict->append(baseClassName,baseClass); + baseClass = toClassDefMutable( + Doxygen::classLinkedMap->add(baseClassName, + std::unique_ptr<ClassDef>( + createClassDef(root->fileName,root->startLine,root->startColumn, + baseClassName, + ClassDef::Class)))); if (isArtificial) baseClass->setArtificial(TRUE); baseClass->setLanguage(root->lang); si = baseClassName.findRev("::"); @@ -4551,7 +4567,13 @@ static bool findClassRelation( baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec); // the undocumented base was found in this file baseClass->insertUsedFile(root->fileDef()); - baseClass->setOuterScope(Doxygen::globalScope); + + Definition *scope = buildScopeFromQualifiedName(baseClass->name(),root->lang,0); + if (scope!=baseClass) + { + baseClass->setOuterScope(scope); + } + if (baseClassName.right(2)=="-p") { baseClass->setCompoundType(ClassDef::Protocol); @@ -4630,7 +4652,7 @@ static void findClassEntries(const Entry *root) { if (isClassSection(root)) { - g_classEntries.insert({root->name.data(),root}); + g_classEntries.insert({root->name.str(),root}); } for (const auto &e : root->children()) findClassEntries(e.get()); } @@ -4658,8 +4680,7 @@ static QCString extractClassName(const Entry *root) */ static void findInheritedTemplateInstances() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); + ClassDefSet visitedClasses; for (const auto &kv : g_classEntries) { const Entry *root = kv.second; @@ -4668,16 +4689,18 @@ static void findInheritedTemplateInstances() Debug::print(Debug::Classes,0," Inheritance: Class %s : \n",qPrint(bName)); if ((cd=getClass(bName))) { - //printf("Class %s %d\n",cd->name().data(),root->extends->count()); - findBaseClassesForClass(root,cd,cd,cd,TemplateInstances,FALSE); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + //printf("Class %s %zu\n",cd->name().data(),root->extends.size()); + findBaseClassesForClass(root,cd,cdm,cdm,TemplateInstances,FALSE); + } } } } static void findUsedTemplateInstances() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); for (const auto &kv : g_classEntries) { const Entry *root = kv.second; @@ -4686,24 +4709,26 @@ static void findUsedTemplateInstances() Debug::print(Debug::Classes,0," Usage: Class %s : \n",qPrint(bName)); if ((cd=getClass(bName))) { - findUsedClassesForClass(root,cd,cd,cd,TRUE); - cd->addTypeConstraints(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + findUsedClassesForClass(root,cd,cdm,cdm,TRUE); + cdm->addTypeConstraints(); + } } } } static void computeClassRelations() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); for (const auto &kv : g_classEntries) { const Entry *root = kv.second; - ClassDef *cd; + ClassDefMutable *cd; QCString bName = extractClassName(root); Debug::print(Debug::Classes,0," Relations: Class %s : \n",qPrint(bName)); - if ((cd=getClass(bName))) + if ((cd=getClassMutable(bName))) { findBaseClassesForClass(root,cd,cd,cd,DocumentedOnly,FALSE); } @@ -4733,65 +4758,69 @@ static void computeTemplateClassRelations() const Entry *root = kv.second; QCString bName=stripAnonymousNamespaceScope(root->name); bName=stripTemplateSpecifiersFromScope(bName); - ClassDef *cd=getClass(bName); + ClassDefMutable *cd=getClassMutable(bName); // strip any anonymous scopes first QDict<ClassDef> *templInstances = 0; if (cd && (templInstances=cd->getTemplateInstances())) { Debug::print(Debug::Classes,0," Template class %s : \n",qPrint(cd->name())); QDictIterator<ClassDef> tdi(*templInstances); - ClassDef *tcd; - for (tdi.toFirst();(tcd=tdi.current());++tdi) // for each template instance - { - Debug::print(Debug::Classes,0," Template instance %s : \n",qPrint(tcd->name())); - QCString templSpec = tdi.currentKey(); - std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(tcd->getLanguage(),templSpec); - for (const BaseInfo &bi : root->extends) - { - // check if the base class is a template argument - BaseInfo tbi = bi; - const ArgumentList &tl = cd->templateArguments(); - if (!tl.empty()) + ClassDef *itcd; + for (tdi.toFirst();(itcd=tdi.current());++tdi) // for each template instance + { + ClassDefMutable *tcd=toClassDefMutable(itcd); + if (tcd) + { + Debug::print(Debug::Classes,0," Template instance %s : \n",qPrint(tcd->name())); + QCString templSpec = tdi.currentKey(); + std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(tcd->getLanguage(),templSpec); + for (const BaseInfo &bi : root->extends) { - QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames(); - QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi.name); - // for each template name that we inherit from we need to - // substitute the formal with the actual arguments - QDict<int> *actualTemplateNames = new QDict<int>(17); - actualTemplateNames->setAutoDelete(TRUE); - QDictIterator<int> qdi(*templateNames); - for (qdi.toFirst();qdi.current();++qdi) + // check if the base class is a template argument + BaseInfo tbi = bi; + const ArgumentList &tl = cd->templateArguments(); + if (!tl.empty()) { - int templIndex = *qdi.current(); - Argument actArg; - bool hasActArg=FALSE; - if (templIndex<(int)templArgs->size()) + QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames(); + QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi.name); + // for each template name that we inherit from we need to + // substitute the formal with the actual arguments + QDict<int> *actualTemplateNames = new QDict<int>(17); + actualTemplateNames->setAutoDelete(TRUE); + QDictIterator<int> qdi(*templateNames); + for (qdi.toFirst();qdi.current();++qdi) { - actArg=templArgs->at(templIndex); - hasActArg=TRUE; + int templIndex = *qdi.current(); + Argument actArg; + bool hasActArg=FALSE; + if (templIndex<(int)templArgs->size()) + { + actArg=templArgs->at(templIndex); + hasActArg=TRUE; + } + if (hasActArg && + baseClassNames!=0 && + baseClassNames->find(actArg.type)!=0 && + actualTemplateNames->find(actArg.type)==0 + ) + { + actualTemplateNames->insert(actArg.type,new int(templIndex)); + } } - if (hasActArg && - baseClassNames!=0 && - baseClassNames->find(actArg.type)!=0 && - actualTemplateNames->find(actArg.type)==0 - ) + delete templateNames; + + tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs); + // find a documented base class in the correct scope + if (!findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE)) { - actualTemplateNames->insert(actArg.type,new int(templIndex)); + // no documented base class -> try to find an undocumented one + findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,Undocumented,TRUE); } + delete actualTemplateNames; } - delete templateNames; - - tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs); - // find a documented base class in the correct scope - if (!findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE)) - { - // no documented base class -> try to find an undocumented one - findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,Undocumented,TRUE); - } - delete actualTemplateNames; } } - } // class has no base classes + } } } } @@ -4801,11 +4830,13 @@ static void computeTemplateClassRelations() static void computeMemberReferences() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->computeAnchors(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->computeAnchors(); + } } for (const auto &fn : *Doxygen::inputNameLinkedMap) { @@ -4814,11 +4845,13 @@ static void computeMemberReferences() fd->computeAnchors(); } } - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd=0; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->computeAnchors(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->computeAnchors(); + } } GroupSDict::Iterator gli(*Doxygen::groupSDict); GroupDef *gd; @@ -4832,13 +4865,12 @@ static void computeMemberReferences() static void addListReferences() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - if (!cd->isAlias()) + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) { - cd->addListReferences(); + cdm->addListReferences(); } } @@ -4850,13 +4882,12 @@ static void addListReferences() } } - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd=0; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (!nd->isAlias()) + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) { - nd->addListReferences(); + ndm->addListReferences(); } } @@ -4918,7 +4949,7 @@ static void generateXRefPages() // over_load is set the standard overload text is added. static void addMemberDocs(const Entry *root, - MemberDef *md, const char *funcDecl, + MemberDefMutable *md, const char *funcDecl, const ArgumentList *al, bool over_load, uint64 spec @@ -4934,7 +4965,7 @@ static void addMemberDocs(const Entry *root, md->enableCallerGraph(root->callerGraph); md->enableReferencedByRelation(root->referencedByRelation); md->enableReferencesRelation(root->referencesRelation); - ClassDef *cd=md->getClassDef(); + ClassDefMutable *cd=md->getClassDefMutable(); const NamespaceDef *nd=md->getNamespaceDef(); QCString fullName; if (cd) @@ -4949,17 +4980,17 @@ static void addMemberDocs(const Entry *root, // TODO determine scope based on root not md Definition *rscope = md->getOuterScope(); - ArgumentList &mdAl = md->argumentList(); + const ArgumentList &mdAl = md->argumentList(); if (al) { ArgumentList mergedAl = *al; //printf("merging arguments (1) docs=%d\n",root->doc.isEmpty()); - mergeArguments(mdAl,mergedAl,!root->doc.isEmpty()); + mergeArguments(const_cast<ArgumentList&>(mdAl),mergedAl,!root->doc.isEmpty()); } else { if ( - matchArguments2( md->getOuterScope(), md->getFileDef(), &mdAl, + matchArguments2( md->getOuterScope(), md->getFileDef(),const_cast<ArgumentList*>(&mdAl), rscope,rfd,&root->argList, TRUE ) @@ -4967,7 +4998,7 @@ static void addMemberDocs(const Entry *root, { //printf("merging arguments (2)\n"); ArgumentList mergedArgList = root->argList; - mergeArguments(mdAl,mergedArgList,!root->doc.isEmpty()); + mergeArguments(const_cast<ArgumentList&>(mdAl),mergedArgList,!root->doc.isEmpty()); } } if (over_load) // the \overload keyword was used @@ -5065,7 +5096,8 @@ static void addMemberDocs(const Entry *root, static const ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, const char *scopeName) { - const ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE); + SymbolResolver resolver(fd); + const ClassDef *tcd = resolver.resolveClass(nd,scopeName,true,true); return tcd; } @@ -5106,24 +5138,68 @@ static bool findGlobalMember(const Entry *root, if (md->isAlias() && md->getOuterScope() && md->getOuterScope()->definitionType()==Definition::TypeNamespace) { - nd = dynamic_cast<const NamespaceDef *>(md->getOuterScope()); + nd = toNamespaceDef(md->getOuterScope()); } else { nd = md->getNamespaceDef(); } - //const Definition *scope=md->getOuterScope(); - //md = md->resolveAlias(); + + // special case for strong enums + int enumNamePos=0; + if (nd && md->isEnumValue() && (enumNamePos=namespaceName.findRev("::"))!=-1) + { // md part of a strong enum in a namespace? + QCString enumName = namespaceName.mid(enumNamePos+2); + if (namespaceName.left(enumNamePos)==nd->name()) + { + MemberName *enumMn=Doxygen::functionNameLinkedMap->find(enumName); + if (enumMn) + { + for (const auto &emd : *enumMn) + { + found = emd->isStrong() && md->getEnumScope()==emd.get(); + if (found) + { + addMemberDocs(root,toMemberDefMutable(md->resolveAlias()),decl,0,FALSE,root->spec); + break; + } + } + } + } + if (found) + { + break; + } + } + else if (nd==0 && md->isEnumValue()) // md part of global strong enum? + { + MemberName *enumMn=Doxygen::functionNameLinkedMap->find(namespaceName); + if (enumMn) + { + for (const auto &emd : *enumMn) + { + found = emd->isStrong() && md->getEnumScope()==emd.get(); + if (found) + { + addMemberDocs(root,toMemberDefMutable(md->resolveAlias()),decl,0,FALSE,root->spec); + break; + } + } + } + } const FileDef *fd=root->fileDef(); //printf("File %s\n",fd ? fd->name().data() : "<none>"); - NamespaceSDict *nl = fd ? fd->getUsedNamespaces() : 0; - //SDict<Definition> *cl = fd ? fd->getUsedClasses() : 0; + LinkedRefMap<const NamespaceDef> nl; + if (fd) + { + nl = fd->getUsedNamespaces(); + } //printf("NamespaceList %p\n",nl); // search in the list of namespaces that are imported via a // using declaration - bool viaUsingDirective = nl && nd && nl->find(nd->qualifiedName())!=0; + bool viaUsingDirective = nd && nl.find(nd->qualifiedName())!=0; if ((namespaceName.isEmpty() && nd==0) || // not in a namespace (nd && nd->name()==namespaceName) || // or in the same namespace @@ -5134,7 +5210,7 @@ static bool findGlobalMember(const Entry *root, qPrint(md->name()),qPrint(namespaceName)); NamespaceDef *rnd = 0; - if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName); + if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceLinkedMap->find(namespaceName); const ArgumentList &mdAl = const_cast<const MemberDef *>(md.get())->argumentList(); bool matching= @@ -5187,7 +5263,7 @@ static bool findGlobalMember(const Entry *root, if (matching) // add docs to the member { Debug::print(Debug::FindMembers,0,"5. Match found\n"); - addMemberDocs(root,md->resolveAlias(),decl,&root->argList,FALSE,root->spec); + addMemberDocs(root,toMemberDefMutable(md->resolveAlias()),decl,&root->argList,FALSE,root->spec); found=TRUE; break; } @@ -5252,7 +5328,7 @@ static bool scopeIsTemplate(const Definition *d) bool result=FALSE; if (d && d->definitionType()==Definition::TypeClass) { - result = !(dynamic_cast<const ClassDef*>(d))->templateArguments().empty() || + result = !(toClassDef(d))->templateArguments().empty() || scopeIsTemplate(d->getOuterScope()); } return result; @@ -5385,13 +5461,13 @@ static void addLocalObjCMethod(const Entry *root, uint64 spec) { //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); - ClassDef *cd=0; - if (Config_getBool(EXTRACT_LOCAL_METHODS) && (cd=getClass(scopeName))) + ClassDefMutable *cd=0; + if (Config_getBool(EXTRACT_LOCAL_METHODS) && (cd=getClassMutable(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( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt,root->stat,Member, @@ -5455,16 +5531,19 @@ static void addMemberFunction(const Entry *root, int count=0; int noMatchCount=0; bool memFound=FALSE; - for (const auto &md : *mn) + for (const auto &imd : *mn) { - ClassDef *cd=md->getClassDef(); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md==0) continue; + ClassDefMutable *cd=md->getClassDefMutable(); 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()); + //printf("Member %s (member scopeName=%s) (this scopeName=%s) isEnumValue()=%d\n", + // md->name().data(),cd->name().data(),scopeName.data(),md->isEnumValue()); FileDef *fd=root->fileDef(); NamespaceDef *nd=0; if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName); @@ -5472,6 +5551,33 @@ static void addMemberFunction(const Entry *root, //printf("scopeName %s->%s\n",scopeName.data(), // stripTemplateSpecifiersFromScope(scopeName,FALSE).data()); + // if the member we are searching for is an enum value that is part of + // a "strong" enum, we need to look into the fields of the enum for a match + int enumNamePos=0; + if (md->isEnumValue() && (enumNamePos=className.findRev("::"))!=-1) + { + QCString enumName = className.mid(enumNamePos+2); + if (className.left(enumNamePos)==cd->name()) + { + MemberName *enumMn=Doxygen::memberNameLinkedMap->find(enumName); + //printf("enumMn(%s)=%p\n",className.data(),enumMn); + if (enumMn) + { + for (const auto &emd : *enumMn) + { + memFound = emd->isStrong() && md->getEnumScope()==emd.get(); + if (memFound) + { + addMemberDocs(root,md,funcDecl,0,overloaded,spec); + count++; + } + if (memFound) break; + } + } + } + } + if (memFound) break; + const ClassDef *tcd=findClassDefinition(fd,nd,scopeName); if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName) { @@ -5606,7 +5712,7 @@ static void addMemberFunction(const Entry *root, } if (matching) { - addMemberDocs(root,md.get(),funcDecl,0,overloaded,spec); + addMemberDocs(root,md,funcDecl,0,overloaded,spec); count++; memFound=TRUE; } @@ -5633,7 +5739,7 @@ static void addMemberFunction(const Entry *root, //printf("Assume template class\n"); for (const auto &md : *mn) { - ClassDef *ccd=md->getClassDef(); + ClassDefMutable *ccd=md->getClassDefMutable(); MemberDef *cmd=md.get(); //printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data()); if (ccd!=0 && rightScopeMatch(ccd->name(),className)) @@ -5673,7 +5779,7 @@ static void addMemberFunction(const Entry *root, { // 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); + addMemberDocs(root,toMemberDefMutable(umd),funcDecl,0,overloaded,spec); return; } else if (candidates>1 && ecd && emd) @@ -5681,7 +5787,7 @@ static void addMemberFunction(const Entry *root, // 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); + addMemberDocs(root,toMemberDefMutable(emd),funcDecl,0,overloaded,spec); return; } } @@ -5709,7 +5815,7 @@ static void addMemberFunction(const Entry *root, warnMsg+="Possible candidates:\n"; for (const auto &md : *mn) { - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if (cd!=0 && rightScopeMatch(cd->name(),className)) { const ArgumentList &templAl = md->templateArguments(); @@ -5751,7 +5857,7 @@ static void addMemberFunction(const Entry *root, static void addMemberSpecialization(const Entry *root, MemberName *mn, - ClassDef *cd, + ClassDefMutable *cd, const QCString &funcType, const QCString &funcName, const QCString &funcArgs, @@ -5773,7 +5879,7 @@ static void addMemberSpecialization(const Entry *root, MemberType mtype=MemberType_Function; ArgumentList tArgList; // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, declMd ? declMd->protection() : root->protection, @@ -5827,7 +5933,7 @@ static void addOverloaded(const Entry *root,MemberName *mn, } if (sameClass) { - ClassDef *cd = mn->front()->getClassDef(); + ClassDefMutable *cd = mn->front()->getClassDefMutable(); MemberType mtype; if (root->mtype==Signal) mtype=MemberType_Signal; else if (root->mtype==Slot) mtype=MemberType_Slot; @@ -5838,7 +5944,7 @@ static void addOverloaded(const Entry *root,MemberName *mn, 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( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt,root->stat,Related, @@ -6017,7 +6123,7 @@ static void findMember(const Entry *root, { QCString joinedName = root->parent()->name+"::"+scopeName; if (!scopeName.isEmpty() && - (getClass(joinedName) || Doxygen::namespaceSDict->find(joinedName))) + (getClass(joinedName) || Doxygen::namespaceLinkedMap->find(joinedName))) { scopeName = joinedName; } @@ -6031,20 +6137,13 @@ static void findMember(const Entry *root, FileDef *fd=root->fileDef(); if (fd) { - NamespaceSDict *fnl = fd->getUsedNamespaces(); - if (fnl) + for (const auto &fnd : fd->getUsedNamespaces()) { - QCString joinedName; - NamespaceDef *fnd; - NamespaceSDict::Iterator nsdi(*fnl); - for (nsdi.toFirst();(fnd=nsdi.current());++nsdi) + QCString joinedName = fnd->name()+"::"+scopeName; + if (Doxygen::namespaceLinkedMap->find(joinedName)) { - joinedName = fnd->name()+"::"+scopeName; - if (Doxygen::namespaceSDict->find(joinedName)) - { - scopeName=joinedName; - break; - } + scopeName=joinedName; + break; } } } @@ -6099,7 +6198,7 @@ static void findMember(const Entry *root, //printf("new scope='%s'\n",scopeName.data()); QCString tempScopeName=scopeName; - ClassDef *cd=getClass(scopeName); + ClassDefMutable *cd=getClassMutable(scopeName); if (cd) { if (funcSpec.isEmpty()) @@ -6193,15 +6292,42 @@ static void findMember(const Entry *root, isFunc ); - MemberName *mn=0; if (!funcName.isEmpty()) // function name is valid { Debug::print(Debug::FindMembers,0, "1. funcName='%s'\n",funcName.data()); + + // check if 'className' is actually a scoped enum, in which case we need to + // process it as a global, see issue #6471 + bool strongEnum = false; + MemberName *mn=0; + if (!className.isEmpty() && (mn=Doxygen::functionNameLinkedMap->find(className))) + { + for (const auto &imd : *mn) + { + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isEnumerate() && md->isStrong()) + { + Debug::print(Debug::FindMembers,0,"%s is a strong enum!\n",qPrint(md->name())); + strongEnum = true; + // pass the scope name name as a 'namespace' to the findGlobalMember function + if (!namespaceName.isEmpty()) + { + namespaceName+="::"+className; + } + else + { + namespaceName=className; + } + } + } + } + if (funcName.left(9)=="operator ") // strip class scope from cast operator { funcName = substitute(funcName,className+"::",""); } + mn = 0; if (!funcTempList.isEmpty()) // try with member specialization { mn=Doxygen::memberNameLinkedMap->find(funcName+funcTempList); @@ -6210,7 +6336,7 @@ static void findMember(const Entry *root, { mn=Doxygen::memberNameLinkedMap->find(funcName); } - if (!isRelated && mn) // function name already found + if (!isRelated && !strongEnum && mn) // function name already found { Debug::print(Debug::FindMembers,0, "2. member name exists (%d members with this name)\n",mn->size()); @@ -6255,19 +6381,20 @@ static void findMember(const Entry *root, " scopeName=%s className=%s\n",qPrint(scopeName),qPrint(className)); if (className.isEmpty()) className=relates; //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); - if ((cd=getClass(scopeName))) + if ((cd=getClassMutable(scopeName))) { bool newMember=TRUE; // assume we have a new member - MemberDef *mdDefine=0; + MemberDefMutable *mdDefine=0; { mn = Doxygen::functionNameLinkedMap->find(funcName); if (mn) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->isDefine()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isDefine()) { - mdDefine = md.get(); + mdDefine = md; break; } } @@ -6283,19 +6410,23 @@ static void findMember(const Entry *root, else { // see if we got another member with matching arguments - MemberDef *rmd_found = 0; - for (const auto &rmd : *mn) + MemberDefMutable *rmd_found = 0; + for (const auto &irmd : *mn) { - const ArgumentList &rmdAl = rmd->argumentList(); - - newMember= - className!=rmd->getOuterScope()->name() || - !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, - cd,fd,&root->argList, - TRUE); - if (!newMember) + MemberDefMutable *rmd = toMemberDefMutable(irmd.get()); + if (rmd) { - rmd_found = rmd.get(); + const ArgumentList &rmdAl = rmd->argumentList(); + + newMember= + className!=rmd->getOuterScope()->name() || + !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, + cd,fd,&root->argList, + TRUE); + if (!newMember) + { + rmd_found = rmd; + } } } if (rmd_found) // member already exists as rmd -> add docs @@ -6337,7 +6468,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. - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt, @@ -6379,20 +6510,24 @@ static void findMember(const Entry *root, MemberName *rmn=Doxygen::functionNameLinkedMap->find(funcName); if (rmn) { - const MemberDef *rmd_found=0; - for (const auto &rmd : *rmn) + const MemberDefMutable *rmd_found=0; + for (const auto &irmd : *rmn) { - const ArgumentList &rmdAl = rmd->argumentList(); - // check for matching argument lists - if ( - matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, - cd,fd,&root->argList, - TRUE) - ) + MemberDefMutable *rmd = toMemberDefMutable(irmd.get()); + if (rmd) { - found=TRUE; - rmd_found = rmd.get(); - break; + const ArgumentList &rmdAl = rmd->argumentList(); + // check for matching argument lists + if ( + matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, + cd,fd,&root->argList, + TRUE) + ) + { + found=TRUE; + rmd_found = rmd; + break; + } } } if (rmd_found) // member found -> copy line number info @@ -6711,9 +6846,9 @@ static void findEnums(const Entry *root) { if (root->section==Entry::ENUM_SEC) { - ClassDef *cd=0; - FileDef *fd=0; - NamespaceDef *nd=0; + ClassDefMutable *cd=0; + FileDef *fd=0; + NamespaceDefMutable *nd=0; MemberNameLinkedMap *mnsd=0; bool isGlobal; bool isRelated=FALSE; @@ -6728,7 +6863,7 @@ static void findEnums(const Entry *root) { scope=root->name.left(i); // extract scope name=root->name.right(root->name.length()-i-2); // extract name - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } else // no scope, check the scope in which the docs where found { @@ -6737,7 +6872,7 @@ static void findEnums(const Entry *root) ) // found enum docs inside a compound { scope=root->parent()->name; - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } name=root->name; } @@ -6750,7 +6885,7 @@ static void findEnums(const Entry *root) scope=mergeScopes(scope,root->relates); else scope=root->relates.copy(); - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } if (cd && !name.isEmpty()) // found a enum inside a compound @@ -6775,7 +6910,7 @@ static void findEnums(const Entry *root) if (!name.isEmpty()) { // new enum type - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, 0,name,0,0, root->protection,Normal,FALSE, @@ -6798,7 +6933,7 @@ static void findEnums(const Entry *root) md->enableCallerGraph(root->callerGraph); md->enableReferencedByRelation(root->referencedByRelation); md->enableReferencesRelation(root->referencesRelation); - //printf("%s::setRefItems(%d)\n",md->name().data(),root->sli?root->sli->count():-1); + //printf("%s::setRefItems(%zu)\n",md->name().data(),root->sli.size()); md->setRefItems(root->sli); //printf("found enum %s nd=%p\n",md->name().data(),nd); bool defSet=FALSE; @@ -6879,9 +7014,9 @@ static void addEnumValuesToEnums(const Entry *root) if (root->section==Entry::ENUM_SEC) // non anonymous enumeration { - ClassDef *cd=0; - FileDef *fd=0; - NamespaceDef *nd=0; + ClassDefMutable *cd=0; + FileDef *fd=0; + NamespaceDefMutable *nd=0; MemberNameLinkedMap *mnsd=0; bool isGlobal; bool isRelated=FALSE; @@ -6895,7 +7030,7 @@ static void addEnumValuesToEnums(const Entry *root) { scope=root->name.left(i); // extract scope name=root->name.right(root->name.length()-i-2); // extract name - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } else // no scope, check the scope in which the docs where found { @@ -6904,7 +7039,7 @@ static void addEnumValuesToEnums(const Entry *root) ) // found enum docs inside a compound { scope=root->parent()->name; - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } name=root->name; } @@ -6912,11 +7047,11 @@ static void addEnumValuesToEnums(const Entry *root) if (!root->relates.isEmpty()) { // related member, prefix user specified scope isRelated=TRUE; - if (getClass(root->relates)==0 && !scope.isEmpty()) + if (getClassMutable(root->relates)==0 && !scope.isEmpty()) scope=mergeScopes(scope,root->relates); else scope=root->relates.copy(); - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } if (cd && !name.isEmpty()) // found a enum inside a compound @@ -6946,12 +7081,20 @@ static void addEnumValuesToEnums(const Entry *root) MemberName *mn = mnsd->find(name); // for all members with this name if (mn) { - std::vector< std::unique_ptr<MemberDef> > extraMembers; + struct EnumValueInfo + { + EnumValueInfo(const QCString &n,std::unique_ptr<MemberDefMutable> &md) : + name(n), member(std::move(md)) {} + QCString name; + std::unique_ptr<MemberDefMutable> member; + }; + std::vector< EnumValueInfo > extraMembers; // for each enum in this list - for (const auto &md : *mn) + for (const auto &imd : *mn) { + MemberDefMutable *md = toMemberDefMutable(imd.get()); // use raw pointer in this loop, since we modify mn and can then invalidate mdp. - if (!md->isAlias() && md->isEnumerate() && !root->children().empty()) + if (md && md->isEnumerate() && !root->children().empty()) { //printf(" enum with %d children\n",root->children()->count()); for (const auto &e : root->children()) @@ -6983,14 +7126,18 @@ static void addEnumValuesToEnums(const Entry *root) { fileName = e->tagInfo()->tagName; } - std::unique_ptr<MemberDef> fmd { createMemberDef( + std::unique_ptr<MemberDefMutable> 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) }; - if (md->getClassDef()) fmd->setMemberClass(md->getClassDef()); - else if (md->getNamespaceDef()) fmd->setNamespace(md->getNamespaceDef()); - else if (md->getFileDef()) fmd->setFileDef(md->getFileDef()); + const NamespaceDef *mnd = md->getNamespaceDef(); + if (md->getClassDef()) + fmd->setMemberClass(md->getClassDef()); + else if (mnd && (mnd->isLinkable() || mnd->isAnonymous())) + fmd->setNamespace(mnd); + else if (md->getFileDef()) + fmd->setFileDef(md->getFileDef()); fmd->setOuterScope(md->getOuterScope()); fmd->setTagInfo(e->tagInfo()); fmd->setLanguage(e->lang); @@ -7005,9 +7152,8 @@ static void addEnumValuesToEnums(const Entry *root) fmd->setRefItems(e->sli); fmd->setAnchor(); md->insertEnumField(fmd.get()); - fmd->setEnumScope(md.get(),TRUE); - mn=mnsd->add(e->name); - extraMembers.push_back(std::move(fmd)); + fmd->setEnumScope(md,TRUE); + extraMembers.push_back(EnumValueInfo(e->name,fmd)); } } else @@ -7018,9 +7164,10 @@ static void addEnumValuesToEnums(const Entry *root) if (!e->name.isEmpty() && (fmn=emnsd->find(e->name))) // get list of members with the same name as the field { - for (const auto &fmd : *fmn) + for (const auto &ifmd : *fmn) { - if (fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); + if (fmd && fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope { //printf("found enum value with same name %s in scope %s\n", // fmd->name().data(),fmd->getOuterScope()->name().data()); @@ -7029,8 +7176,8 @@ static void addEnumValuesToEnums(const Entry *root) const NamespaceDef *fnd=fmd->getNamespaceDef(); if (fnd==nd) // enum value is inside a namespace { - md->insertEnumField(fmd.get()); - fmd->setEnumScope(md.get()); + md->insertEnumField(fmd); + fmd->setEnumScope(md); } } else if (isGlobal) @@ -7038,19 +7185,19 @@ static void addEnumValuesToEnums(const Entry *root) const FileDef *ffd=fmd->getFileDef(); if (ffd==fd) // enum value has file scope { - md->insertEnumField(fmd.get()); - fmd->setEnumScope(md.get()); + md->insertEnumField(fmd); + fmd->setEnumScope(md); } } else if (isRelated && cd) // reparent enum value to // match the enum's scope { - md->insertEnumField(fmd.get()); // add field def to list - fmd->setEnumScope(md.get()); // cross ref with enum name + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name fmd->setEnumClassScope(cd); // cross ref with enum name fmd->setOuterScope(cd); fmd->makeRelated(); - cd->insertMember(fmd.get()); + cd->insertMember(fmd); } else { @@ -7059,8 +7206,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.get()); // add field def to list - fmd->setEnumScope(md.get()); // cross ref with enum name + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name } } } @@ -7071,9 +7218,10 @@ static void addEnumValuesToEnums(const Entry *root) } } // move the newly added members into mn - for (auto &md : extraMembers) + for (auto &e : extraMembers) { - mn->push_back(std::move(md)); + MemberName *emn=mnsd->add(e.name); + emn->push_back(std::move(e.member)); } } } @@ -7084,6 +7232,42 @@ static void addEnumValuesToEnums(const Entry *root) } } +//---------------------------------------------------------------------- + +static void addEnumDocs(const Entry *root,MemberDefMutable *md) +{ + // documentation outside a compound overrides the documentation inside it + { + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setDocsForDefinition(!root->proto); + } + + // brief descriptions inside a compound override the documentation + // outside it + { + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); + } + + if (!md->inbodyDocumentation() || !root->parent()->name.isEmpty()) + { + md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); + } + + if (root->mGrpId!=-1 && md->getMemberGroupId()==-1) + { + md->setMemberGroupId(root->mGrpId); + } + + md->addSectionsToDefinition(root->anchors); + md->setRefItems(root->sli); + + const GroupDef *gd=md->getGroupDef(); + if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is + { + addMemberToGroups(root,md); + } +} + //---------------------------------------------------------------------- // find the documentation blocks for the enumerations @@ -7095,8 +7279,6 @@ static void findEnumDocumentation(const Entry *root) && root->name.at(0)!='@' // skip anonymous enums ) { - //printf("Found docs for enum with name '%s' in context %s\n", - // root->name.data(),root->parent->name.data()); int i; QCString name; QCString scope; @@ -7117,93 +7299,55 @@ static void findEnumDocumentation(const Entry *root) if (!scope.isEmpty()) scope.prepend("::"); scope.prepend(root->parent()->name); } - ClassDef *cd=getClass(scope); + const ClassDef *cd = getClass(scope); + const NamespaceDef *nd=Doxygen::namespaceLinkedMap->find(scope); + const FileDef *fd = root->fileDef(); + Debug::print(Debug::FindMembers,0,"1. Found docs for enum with name '%s' and scope '%s' in context %s cd=%s, nd=%s fd=%s\n", + name.data(),scope.data(),root->parent()->name.data(), + cd?cd->name().data():"<none>", + nd?nd->name().data():"<none>", + fd?fd->name().data():"<none>"); if (!name.isEmpty()) { bool found=FALSE; + MemberName *mn; if (cd) { - //printf("Enum: scope='%s' name='%s'\n",cd->name(),name.data()); - QCString className=cd->name().copy(); - MemberName *mn=Doxygen::memberNameLinkedMap->find(name); - if (mn) + mn = Doxygen::memberNameLinkedMap->find(name); + } + else + { + mn = Doxygen::functionNameLinkedMap->find(name); + } + if (mn) + { + for (const auto &imd : *mn) { - for (const auto &md : *mn) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isEnumerate()) { - cd=md->getClassDef(); - if (cd && cd->name()==className && md->isEnumerate()) + const ClassDef *mcd = md->getClassDef(); + const NamespaceDef *mnd = md->getNamespaceDef(); + const FileDef *mfd = md->getFileDef(); + if (mcd==cd) { - // documentation outside a compound overrides the documentation inside it -#if 0 - if (!md->documentation() || root->parent()->name.isEmpty()) -#endif - { - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setDocsForDefinition(!root->proto); - } - - // brief descriptions inside a compound override the documentation - // outside it -#if 0 - if (!md->briefDescription() || !root->parent()->name.isEmpty()) -#endif - { - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - } - - if (!md->inbodyDocumentation() || !root->parent()->name.isEmpty()) - { - md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - } - - if (root->mGrpId!=-1 && md->getMemberGroupId()==-1) - { - md->setMemberGroupId(root->mGrpId); - } - - md->addSectionsToDefinition(root->anchors); - md->setRefItems(root->sli); - - const GroupDef *gd=md->getGroupDef(); - if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is - { - addMemberToGroups(root,md.get()); - } - + Debug::print(Debug::FindMembers,0,"2. Match found for class scope\n"); + addEnumDocs(root,md); found=TRUE; break; } - } - } - else - { - //printf("MemberName %s not found!\n",name.data()); - } - } - else // enum outside class - { - //printf("Enum outside class: %s grpId=%d\n",name.data(),root->mGrpId); - MemberName *mn=Doxygen::functionNameLinkedMap->find(name); - if (mn) - { - for (const auto &md : *mn) - { - if (md->isEnumerate()) + else if (cd==0 && mcd==0 && nd!=0 && mnd==nd) { - 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->addSectionsToDefinition(root->anchors); - md->setMemberGroupId(root->mGrpId); - - const GroupDef *gd=md->getGroupDef(); - if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is - { - addMemberToGroups(root,md.get()); - } - + Debug::print(Debug::FindMembers,0,"2. Match found for namespace scope\n"); + addEnumDocs(root,md); + found=TRUE; + break; + } + else if (cd==0 && nd==0 && mcd==0 && mnd==0 && fd==mfd) + { + Debug::print(Debug::FindMembers,0,"2. Match found for global scope\n"); + addEnumDocs(root,md); found=TRUE; break; } @@ -7230,9 +7374,10 @@ static void findDEV(const MemberNameLinkedMap &mnsd) for (const auto &mn : mnsd) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->isEnumerate()) // member is an enum + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isEnumerate()) // member is an enum { const MemberList *fmdl = md->enumFieldList(); int documentedEnumValues=0; @@ -7278,17 +7423,18 @@ static void addMembersToIndex() for (const auto &mn : *Doxygen::functionNameLinkedMap) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (!md->isAlias()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { if (md->getNamespaceDef()) { - addNamespaceMemberNameToIndex(md.get()); + addNamespaceMemberNameToIndex(md); } else { - addFileMemberNameToIndex(md.get()); + addFileMemberNameToIndex(md); } } } @@ -7303,18 +7449,26 @@ static void vhdlCorrectMemberProperties() for (const auto &mn : *Doxygen::memberNameLinkedMap) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - VhdlDocGen::correctMemberProperties(md.get()); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + VhdlDocGen::correctMemberProperties(md); + } } } // for each member name for (const auto &mn : *Doxygen::functionNameLinkedMap) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - VhdlDocGen::correctMemberProperties(md.get()); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + VhdlDocGen::correctMemberProperties(md); + } } } } @@ -7330,56 +7484,65 @@ static void computeMemberRelations() for (const auto &mn : *Doxygen::memberNameLinkedMap) { // for each member with a specific name - for (const auto &md : *mn) + for (const auto &imd : *mn) { - // for each other member with the same name - for ( const auto &bmd : *mn) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { - if (md!=bmd) + // for each other member with the same name + for ( const auto &ibmd : *mn) { - const ClassDef *mcd = md->getClassDef(); - if (mcd && mcd->baseClasses()) + MemberDefMutable *bmd = toMemberDefMutable(ibmd.get()); + if (bmd && md!=bmd) { - 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 (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)) + const ClassDef *mcd = md->getClassDef(); + if (mcd && !mcd->baseClasses().empty()) { - //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.get(), + // bmcd->name().data(),bmd->name().data(),bmd.get() // ); - 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).data(), + // argListToString(mdAl).data() + // ); + if ( + matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),&bmdAl, + md->getOuterScope(), md->getFileDef(), &mdAl, + TRUE + ) ) { - //printf("setting (new) reimplements member\n"); - md->setReimplements(bmd.get()); + //printf("match!\n"); + MemberDef *rmd; + if ((rmd=md->reimplements())==0 || + minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef()) + ) + { + //printf("setting (new) reimplements member\n"); + md->setReimplements(bmd); + } + //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data()); + bmd->insertReimplementedBy(md); + } + else + { + //printf("no match!\n"); } - //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data()); - bmd->insertReimplementedBy(md.get()); } } } @@ -7389,26 +7552,12 @@ static void computeMemberRelations() } } - -//---------------------------------------------------------------------------- -//static void computeClassImplUsageRelations() -//{ -// ClassDef *cd; -// ClassSDict::Iterator cli(*Doxygen::classSDict); -// for (;(cd=cli.current());++cli) -// { -// cd->determineImplUsageRelation(); -// } -//} - //---------------------------------------------------------------------------- static void createTemplateInstanceMembers() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; // for each class - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { // that is a template QDict<ClassDef> *templInstances = cd->getTemplateInstances(); @@ -7419,7 +7568,11 @@ static void createTemplateInstanceMembers() // for each instance of the template for (qdi.toFirst();(tcd=qdi.current());++qdi) { - tcd->addMembersToTemplateInstance(cd,qdi.currentKey()); + ClassDefMutable *tcdm = toClassDefMutable(tcd); + if (tcdm) + { + tcdm->addMembersToTemplateInstance(cd.get(),cd->templateArguments(),qdi.currentKey()); + } } } } @@ -7429,21 +7582,19 @@ static void createTemplateInstanceMembers() static void mergeCategories() { - ClassDef *cd; - ClassSDict::Iterator cli(*Doxygen::classSDict); // merge members of categories into the class they extend - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { int i=cd->name().find('('); if (i!=-1) // it is an Objective-C category { QCString baseName=cd->name().left(i); - ClassDef *baseClass=Doxygen::classSDict->find(baseName); + ClassDefMutable *baseClass=toClassDefMutable(Doxygen::classLinkedMap->find(baseName)); if (baseClass) { //printf("*** merging members of category %s into %s\n", // cd->name().data(),baseClass->name().data()); - baseClass->mergeCategory(cd); + baseClass->mergeCategory(cd.get()); } } } @@ -7453,23 +7604,29 @@ static void mergeCategories() static void buildCompleteMemberLists() { - ClassDef *cd; - ClassSDict::Iterator cli(*Doxygen::classSDict); // merge the member list of base classes into the inherited classes. - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (// !cd->isReference() && // not an external class - cd->subClasses()==0 && // is a root of the hierarchy - cd->baseClasses()) // and has at least one base class + cd->subClasses().empty() && // is a root of the hierarchy + !cd->baseClasses().empty()) // and has at least one base class { - //printf("*** merging members for %s\n",cd->name().data()); - cd->mergeMembers(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + //printf("*** merging members for %s\n",cd->name().data()); + cdm->mergeMembers(); + } } } // now sort the member list of all members for all classes. - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->sortAllMembersList(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->sortAllMembersList(); + } } } @@ -7499,15 +7656,20 @@ static void generateFileSources() { for (const auto &fd : *fn) { - if (fd->isSource() && !fd->isReference()) + if (fd->isSource() && !fd->isReference() && + ((fd->generateSourceFile() && !g_useOutputTemplate) || + (!fd->isReference() && Doxygen::parseSourcesNeeded) + ) + ) { 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()); clangParser->parse(); - fd->writeSource(*g_outputList,clangParser.get()); - + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,clangParser.get()); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7531,7 +7693,9 @@ static void generateFileSources() if (ifd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output { msg(" Generating code for file %s...\n",ifd->docName().data()); - ifd->writeSource(*g_outputList,clangParser.get()); + ifd->writeSourceHeader(*g_outputList); + ifd->writeSourceBody(*g_outputList,clangParser.get()); + ifd->writeSourceFooter(*g_outputList); } else if (!ifd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7554,20 +7718,24 @@ static void generateFileSources() { if (processedFiles.find(fd->absFilePath().str())==processedFiles.end()) // not yet processed { - auto clangParser = ClangParser::instance()->createTUParser(fd.get()); if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output { + auto clangParser = ClangParser::instance()->createTUParser(fd.get()); msg("Generating code for file %s...\n",fd->docName().data()); clangParser->parse(); - fd->writeSource(*g_outputList,clangParser.get()); - + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,clangParser.get()); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them { + auto clangParser = ClangParser::instance()->createTUParser(fd.get()); msg("Parsing code for file %s...\n",fd->docName().data()); clangParser->parse(); - fd->parseSource(clangParser.get()); + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,clangParser.get()); + fd->writeSourceFooter(*g_outputList); } } } @@ -7576,6 +7744,65 @@ static void generateFileSources() else #endif { +#define MULTITHREADED_SOURCE_GENERATOR 0 // not ready to be enabled yet +#if MULTITHREADED_SOURCE_GENERATOR + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) + { + numThreads = std::thread::hardware_concurrency(); + } + msg("Generating code files using %zu threads.\n",numThreads); + struct SourceContext + { + SourceContext(FileDef *fd_,bool gen_,OutputList ol_) + : fd(fd_), generateSourceFile(gen_), ol(ol_) {} + FileDef *fd; + bool generateSourceFile; + OutputList ol; + }; + ThreadPool threadPool(numThreads); + std::vector< std::future< std::shared_ptr<SourceContext> > > results; + for (const auto &fn : *Doxygen::inputNameLinkedMap) + { + for (const auto &fd : *fn) + { + bool generateSourceFile = fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate; + auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList); + if (generateSourceFile) + { + msg("Generating code for file %s...\n",fd->docName().data()); + fd->writeSourceHeader(ctx->ol); + } + else + { + msg("Parsing code for file %s...\n",fd->docName().data()); + } + auto processFile = [ctx]() { + StringVector filesInSameTu; + ctx->fd->getAllIncludeFilesRecursively(filesInSameTu); + if (ctx->generateSourceFile) // sources need to be shown in the output + { + ctx->fd->writeSourceBody(ctx->ol,nullptr); + } + else if (!ctx->fd->isReference() && Doxygen::parseSourcesNeeded) + // we needed to parse the sources even if we do not show them + { + ctx->fd->parseSource(nullptr); + } + return ctx; + }; + results.emplace_back(threadPool.queue(processFile)); + } + } + for (auto &f : results) + { + auto ctx = f.get(); + if (ctx->generateSourceFile) + { + ctx->fd->writeSourceFooter(ctx->ol); + } + } +#else // single threaded version for (const auto &fn : *Doxygen::inputNameLinkedMap) { for (const auto &fd : *fn) @@ -7585,8 +7812,9 @@ static void generateFileSources() if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output { msg("Generating code for file %s...\n",fd->docName().data()); - fd->writeSource(*g_outputList,nullptr); - + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,nullptr); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7596,6 +7824,7 @@ static void generateFileSources() } } } +#endif } } } @@ -7628,25 +7857,21 @@ static void generateFileDocs() static void addSourceReferences() { // add source references for class definitions - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { FileDef *fd=cd->getBodyDef(); if (fd && cd->isLinkableInProject() && cd->getStartDefLine()!=-1) { - fd->addSourceRef(cd->getStartDefLine(),cd,0); + fd->addSourceRef(cd->getStartDefLine(),cd.get(),0); } } // add source references for namespace definitions - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd=0; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { FileDef *fd=nd->getBodyDef(); if (fd && nd->isLinkableInProject() && nd->getStartDefLine()!=-1) { - fd->addSourceRef(nd->getStartDefLine(),nd,0); + fd->addSourceRef(nd->getStartDefLine(),nd.get(),0); } } @@ -7708,7 +7933,7 @@ static void buildDefineList() { for (const auto &def : it->second) { - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( def.fileName,def.lineNr,def.columnNr, "#define",def.name,def.args,0, Public,Normal,FALSE,Member,MemberType_Define, @@ -7738,19 +7963,23 @@ static void buildDefineList() static void sortMemberLists() { // sort class member lists - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->sortMemberLists(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->sortMemberLists(); + } } // sort namespace member lists - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd=0; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->sortMemberLists(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->sortMemberLists(); + } } // sort file member lists @@ -7773,13 +8002,36 @@ static void sortMemberLists() //---------------------------------------------------------------------------- +static bool isSymbolHidden(const Definition *d) +{ + bool hidden = d->isHidden(); + const Definition *parent = d->getOuterScope(); + return parent ? hidden || isSymbolHidden(parent) : hidden; +} + +static void computeTooltipTexts() +{ + for (const auto &kv : Doxygen::symbolMap) + { + DefinitionMutable *dm = toDefinitionMutable(kv.second); + if (dm && !isSymbolHidden(toDefinition(dm)) && toDefinition(dm)->isLinkableInProject()) + { + dm->computeTooltip(); + } + } +} + +//---------------------------------------------------------------------------- + static void setAnonymousEnumType() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->setAnonymousEnumType(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->setAnonymousEnumType(); + } } } @@ -7787,18 +8039,22 @@ static void setAnonymousEnumType() static void countMembers() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->countMembers(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->countMembers(); + } } - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd=0; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->countMembers(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->countMembers(); + } } for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -7821,12 +8077,11 @@ static void countMembers() //---------------------------------------------------------------------------- // generate the documentation of all classes -static void generateClassList(ClassSDict &classSDict) +static void generateClassList(const ClassLinkedMap &classList) { - ClassSDict::Iterator cli(classSDict); - for ( ; cli.current() ; ++cli ) + for (const auto &cdi : classList) { - ClassDef *cd=cli.current(); + ClassDefMutable *cd=toClassDefMutable(cdi.get()); //printf("cd=%s getOuterScope=%p global=%p\n",cd->name().data(),cd->getOuterScope(),Doxygen::globalScope); if (cd && @@ -7852,8 +8107,8 @@ static void generateClassList(ClassSDict &classSDict) static void generateClassDocs() { - generateClassList(*Doxygen::classSDict); - generateClassList(*Doxygen::hiddenClasses); + generateClassList(*Doxygen::classLinkedMap); + generateClassList(*Doxygen::hiddenClassLinkedMap); } //---------------------------------------------------------------------------- @@ -7862,10 +8117,12 @@ static void inheritDocumentation() { for (const auto &mn : *Doxygen::memberNameLinkedMap) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - //printf("%04d Member '%s'\n",count++,md->name().data()); - if (md->documentation().isEmpty() && md->briefDescription().isEmpty()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + //static int count=0; + //printf("%04d Member '%s'\n",count++,md->qualifiedName().data()); + if (md && md->documentation().isEmpty() && md->briefDescription().isEmpty()) { // no documentation yet MemberDef *bmd = md->reimplements(); while (bmd && bmd->documentation().isEmpty() && @@ -7898,27 +8155,19 @@ static void combineUsingRelations() { for (const auto &fd : *fn) { - fd->setVisited(FALSE); - } - } - for (const auto &fn : *Doxygen::inputNameLinkedMap) - { - for (const auto &fd : *fn) - { fd->combineUsingRelations(); } } // for each namespace - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for (nli.toFirst() ; (nd=nli.current()) ; ++nli ) + NamespaceDefSet visitedNamespaces; + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->setVisited(FALSE); - } - for (nli.toFirst() ; (nd=nli.current()) ; ++nli ) - { - nd->combineUsingRelations(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->combineUsingRelations(visitedNamespaces); + } } } @@ -7927,11 +8176,13 @@ static void combineUsingRelations() static void addMembersToMemberGroup() { // for each class - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for ( ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->addMembersToMemberGroup(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->addMembersToMemberGroup(); + } } // for each file for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -7942,11 +8193,13 @@ static void addMembersToMemberGroup() } } // for each namespace - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for ( ; (nd=nli.current()) ; ++nli ) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->addMembersToMemberGroup(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->addMembersToMemberGroup(); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -7962,11 +8215,13 @@ static void addMembersToMemberGroup() static void distributeMemberGroupDocumentation() { // for each class - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for ( ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->distributeMemberGroupDocumentation(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->distributeMemberGroupDocumentation(); + } } // for each file for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -7977,11 +8232,13 @@ static void distributeMemberGroupDocumentation() } } // for each namespace - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for ( ; (nd=nli.current()) ; ++nli ) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->distributeMemberGroupDocumentation(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->distributeMemberGroupDocumentation(); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -7997,11 +8254,13 @@ static void distributeMemberGroupDocumentation() static void findSectionsInDocumentation() { // for each class - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for ( ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { - cd->findSectionsInDocumentation(); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm) + { + cdm->findSectionsInDocumentation(); + } } // for each file for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -8012,11 +8271,13 @@ static void findSectionsInDocumentation() } } // for each namespace - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for ( ; (nd=nli.current()) ; ++nli ) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - nd->findSectionsInDocumentation(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + ndm->findSectionsInDocumentation(); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -8041,24 +8302,30 @@ static void flushCachedTemplateRelations() // as there can be new template instances in the inheritance path // to this class. Optimization: only remove those classes that // have inheritance instances as direct or indirect sub classes. - QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache); - LookupInfo *li=0; - for (ci.toFirst();(li=ci.current());++ci) + StringVector elementsToRemove; + for (const auto &ci : *Doxygen::lookupCache) { - if (li->classDef) + const LookupInfo &li = ci.second; + if (li.classDef) { - Doxygen::lookupCache->remove(ci.currentKey()); + elementsToRemove.push_back(ci.first); } } + for (const auto &k : elementsToRemove) + { + Doxygen::lookupCache->remove(k); + } + // remove all cached typedef resolutions whose target is a // template class as this may now be a template instance // for each global function name for (const auto &fn : *Doxygen::functionNameLinkedMap) { // for each function with that name - for (const auto &fmd : *fn) + for (const auto &ifmd : *fn) { - if (fmd->isTypedefValCached()) + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); + if (fmd && fmd->isTypedefValCached()) { const ClassDef *cd = fmd->getCachedTypedefVal(); if (cd->isTemplate()) fmd->invalidateTypedefValCache(); @@ -8069,9 +8336,10 @@ static void flushCachedTemplateRelations() for (const auto &nm : *Doxygen::memberNameLinkedMap) { // for each function with that name - for (const auto &md : *nm) + for (const auto &imd : *nm) { - if (md->isTypedefValCached()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isTypedefValCached()) { const ClassDef *cd = md->getCachedTypedefVal(); if (cd->isTemplate()) md->invalidateTypedefValCache(); @@ -8093,33 +8361,45 @@ static void flushUnresolvedRelations() // class A { class I {} }; // class B : public A {}; // class C : public B::I {}; - // - QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache); - LookupInfo *li=0; - for (ci.toFirst();(li=ci.current());++ci) + + StringVector elementsToRemove; + for (const auto &ci : *Doxygen::lookupCache) { - if (li->classDef==0 && li->typeDef==0) + const LookupInfo &li = ci.second; + if (li.classDef==0 && li.typeDef==0) { - Doxygen::lookupCache->remove(ci.currentKey()); + elementsToRemove.push_back(ci.first); } } + for (const auto &k : elementsToRemove) + { + Doxygen::lookupCache->remove(k); + } // for each global function name for (const auto &fn : *Doxygen::functionNameLinkedMap) { // for each function with that name - for (const auto &fmd : *fn) + for (const auto &ifmd : *fn) { - fmd->invalidateCachedArgumentTypes(); + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); + if (fmd) + { + fmd->invalidateCachedArgumentTypes(); + } } } // for each class method name for (const auto &nm : *Doxygen::memberNameLinkedMap) { // for each function with that name - for (const auto &md : *nm) + for (const auto &imd : *nm) { - md->invalidateCachedArgumentTypes(); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + md->invalidateCachedArgumentTypes(); + } } } @@ -8138,7 +8418,7 @@ static void findDefineDocumentation(Entry *root) if (root->tagInfo() && !root->name.isEmpty()) // define read from a tag file { - std::unique_ptr<MemberDef> md { createMemberDef(root->tagInfo()->tagName,1,1, + std::unique_ptr<MemberDefMutable> md { createMemberDef(root->tagInfo()->tagName,1,1, "#define",root->name,root->args,0, Public,Normal,FALSE,Member,MemberType_Define, ArgumentList(),ArgumentList(),"") }; @@ -8160,9 +8440,10 @@ static void findDefineDocumentation(Entry *root) } if (count==1) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->memberType()==MemberType_Define) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->memberType()==MemberType_Define) { md->setDocumentation(root->doc,root->docFile,root->docLine); md->setDocsForDefinition(!root->proto); @@ -8177,7 +8458,7 @@ static void findDefineDocumentation(Entry *root) md->setMaxInitLines(root->initLines); md->setRefItems(root->sli); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } } } @@ -8190,27 +8471,18 @@ 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 (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->memberType()==MemberType_Define) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->memberType()==MemberType_Define) { const FileDef *fd=md->getFileDef(); if (fd && fd->absFilePath()==root->fileName) // doc and define in the same file assume they belong together. { -#if 0 - if (md->documentation().isEmpty()) -#endif - { - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setDocsForDefinition(!root->proto); - } -#if 0 - if (md->briefDescription().isEmpty()) -#endif - { - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - } + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setDocsForDefinition(!root->proto); + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); if (md->inbodyDocumentation().isEmpty()) { md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); @@ -8221,7 +8493,7 @@ static void findDefineDocumentation(Entry *root) md->setRefItems(root->sli); md->setLanguage(root->lang); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } } } @@ -8352,6 +8624,7 @@ static void findMainPage(Entry *root) { if (Doxygen::mainPage==0 && root->tagInfo()==0) { + //printf("mainpage: docLine=%d startLine=%d\n",root->docLine,root->startLine); //printf("Found main page! \n======\n%s\n=======\n",root->doc.data()); QCString title=root->args.stripWhiteSpace(); //QCString indexName=Config_getBool(GENERATE_TREEVIEW)?"main":"index"; @@ -8360,6 +8633,7 @@ static void findMainPage(Entry *root) indexName, root->brief+root->doc+root->inbodyDocs,title); //setFileNameForSections(root->anchors,"index",Doxygen::mainPage); Doxygen::mainPage->setBriefDescription(root->brief,root->briefFile,root->briefLine); + Doxygen::mainPage->setBodySegment(root->startLine,root->startLine,-1); Doxygen::mainPage->setFileName(indexName); Doxygen::mainPage->setLocalToc(root->localToc); addPageToContext(Doxygen::mainPage,root); @@ -8395,7 +8669,7 @@ static void findMainPage(Entry *root) { warn(root->fileName,root->startLine, "found more than one \\mainpage comment block! (first occurrence: %s, line %d), Skipping current block!", - Doxygen::mainPage->docFile().data(),Doxygen::mainPage->docLine()); + Doxygen::mainPage->docFile().data(),Doxygen::mainPage->getStartBodyLine()); } } for (const auto &e : root->children()) findMainPage(e.get()); @@ -8514,7 +8788,7 @@ static void resolveUserReferences() const GroupDef *gd=0; if (si->definition()->definitionType()==Definition::TypeMember) { - gd = (dynamic_cast<MemberDef *>(si->definition()))->getGroupDef(); + gd = (toMemberDef(si->definition()))->getGroupDef(); } if (gd) @@ -8618,8 +8892,8 @@ static void generateExampleDocs() for (pdi.toFirst();(pd=pdi.current());++pdi) { msg("Generating docs for example %s...\n",pd->name().data()); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type + intf->resetCodeParserState(); QCString n=pd->getOutputFileBase(); startFile(*g_outputList,n,n,pd->name()); startTitle(*g_outputList,n); @@ -8684,26 +8958,28 @@ static void generateGroupDocs() //---------------------------------------------------------------------------- // generate module pages -static void generateNamespaceClassDocs(ClassSDict *d) +static void generateNamespaceClassDocs(const ClassLinkedRefMap &classList) { // for each class in the namespace... - ClassSDict::Iterator cli(*d); - ClassDef *cd; - for ( ; (cd=cli.current()) ; ++cli ) - { - if ( ( cd->isLinkableInProject() && - cd->templateMaster()==0 - ) // skip external references, anonymous compounds and - // template instances and nested classes - && !cd->isHidden() && !cd->isEmbeddedInOuterScope() - ) + for (const auto &cd : classList) + { + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) { - msg("Generating docs for compound %s...\n",cd->name().data()); + if ( ( cd->isLinkableInProject() && + cd->templateMaster()==0 + ) // skip external references, anonymous compounds and + // template instances and nested classes + && !cd->isHidden() && !cd->isEmbeddedInOuterScope() + ) + { + msg("Generating docs for compound %s...\n",cd->name().data()); - cd->writeDocumentation(*g_outputList); - cd->writeMemberList(*g_outputList); + cdm->writeDocumentation(*g_outputList); + cdm->writeMemberList(*g_outputList); + } + cdm->writeDocumentationForInnerClasses(*g_outputList); } - cd->writeDocumentationForInnerClasses(*g_outputList); } } @@ -8713,24 +8989,25 @@ static void generateNamespaceDocs() //writeNamespaceIndex(*g_outputList); - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; // for each namespace... - for (;(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (nd->isLinkableInProject()) { - msg("Generating docs for namespace %s\n",nd->name().data()); - nd->writeDocumentation(*g_outputList); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm) + { + msg("Generating docs for namespace %s\n",nd->name().data()); + ndm->writeDocumentation(*g_outputList); + } } - generateNamespaceClassDocs(nd->getClassSDict()); + generateNamespaceClassDocs(nd->getClasses()); if (sliceOpt) { - generateNamespaceClassDocs(nd->getInterfaceSDict()); - generateNamespaceClassDocs(nd->getStructSDict()); - generateNamespaceClassDocs(nd->getExceptionSDict()); + generateNamespaceClassDocs(nd->getInterfaces()); + generateNamespaceClassDocs(nd->getStructs()); + generateNamespaceClassDocs(nd->getExceptions()); } } } @@ -9016,8 +9293,8 @@ static void generateDiskNames() // 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 first_path_size = static_cast<int>(first.path.size())-1; // -1 to skip trailing slash + int last_path_size = static_cast<int>(last.path.size())-1; // -1 to skip trailing slash int j=0; for (int i=0;i<first_path_size && i<last_path_size;i++) { @@ -9467,7 +9744,7 @@ static int readDir(QFileInfo *fi, { if (errorIfNotExist) { - warn_uncond("source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data()); + warn_uncond("source '%s' is not a readable file or directory... skipping.\n",cfi->absFilePath().data()); } } else if (cfi->isFile() && @@ -9547,7 +9824,7 @@ int readFileOrDirectory(const char *s, { if (errorIfNotExist) { - warn_uncond("source %s is not a readable file or directory... skipping.\n",s); + warn_uncond("source '%s' is not a readable file or directory... skipping.\n",s); } } else if (!Config_getBool(EXCLUDE_SYMLINKS) || !fi.isSymLink()) @@ -9625,6 +9902,7 @@ static void escapeAliases() newValue+=value.mid(p,in-p); // expand \n's except if \n is part of a built-in command. if (value.mid(in,5)!="\\note" && + value.mid(in,5)!="\\noop" && value.mid(in,5)!="\\name" && value.mid(in,10)!="\\namespace" && value.mid(in,14)!="\\nosubgrouping" @@ -9698,7 +9976,7 @@ static void dumpSymbol(FTextStream &t,Definition *d) QCString anchor; if (d->definitionType()==Definition::TypeMember) { - MemberDef *md = dynamic_cast<MemberDef *>(d); + MemberDef *md = toMemberDef(d); anchor=":"+md->anchor(); } QCString scope; @@ -9721,25 +9999,9 @@ static void dumpSymbolMap() if (f.open(IO_WriteOnly)) { FTextStream t(&f); - QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap); - DefinitionIntf *intf; - for (;(intf=di.current());++di) + for (const auto &kv : Doxygen::symbolMap) { - if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols - { - DefinitionListIterator dli(*(DefinitionList*)intf); - Definition *d; - // for each symbol - for (dli.toFirst();(d=dli.current());++dli) - { - dumpSymbol(t,d); - } - } - else // single symbol - { - Definition *d = (Definition *)intf; - if (d!=Doxygen::globalScope) dumpSymbol(t,d); - } + dumpSymbol(t,kv.second); } } } @@ -9819,7 +10081,7 @@ class NullOutlineParser : public OutlineParserInterface }; -template<class T> std::function< std::unique_ptr<T>() > make_output_parser_factory() +template<class T> std::function< std::unique_ptr<T>() > make_parser_factory() { return []() { return std::make_unique<T>(); }; } @@ -9836,26 +10098,26 @@ void initDoxygen() Portable::correct_path(); Debug::startTimer(); - Doxygen::parserManager = new ParserManager( make_output_parser_factory<NullOutlineParser>(), - std::make_unique<FileCodeParser>()); - Doxygen::parserManager->registerParser("c", make_output_parser_factory<COutlineParser>(), - std::make_unique<CCodeParser>()); - Doxygen::parserManager->registerParser("python", make_output_parser_factory<PythonOutlineParser>(), - std::make_unique<PythonCodeParser>()); - Doxygen::parserManager->registerParser("fortran", make_output_parser_factory<FortranOutlineParser>(), - std::make_unique<FortranCodeParser>()); - Doxygen::parserManager->registerParser("fortranfree", make_output_parser_factory<FortranOutlineParserFree>(), - std::make_unique<FortranCodeParserFree>()); - Doxygen::parserManager->registerParser("fortranfixed", make_output_parser_factory<FortranOutlineParserFixed>(), - std::make_unique<FortranCodeParserFixed>()); - Doxygen::parserManager->registerParser("vhdl", make_output_parser_factory<VHDLOutlineParser>(), - std::make_unique<VHDLCodeParser>()); - Doxygen::parserManager->registerParser("xml", make_output_parser_factory<NullOutlineParser>(), - std::make_unique<XMLCodeParser>()); - Doxygen::parserManager->registerParser("sql", make_output_parser_factory<NullOutlineParser>(), - std::make_unique<SQLCodeParser>()); - Doxygen::parserManager->registerParser("md", make_output_parser_factory<MarkdownOutlineParser>(), - std::make_unique<FileCodeParser>()); + Doxygen::parserManager = new ParserManager( make_parser_factory<NullOutlineParser>(), + make_parser_factory<FileCodeParser>()); + Doxygen::parserManager->registerParser("c", make_parser_factory<COutlineParser>(), + make_parser_factory<CCodeParser>()); + Doxygen::parserManager->registerParser("python", make_parser_factory<PythonOutlineParser>(), + make_parser_factory<PythonCodeParser>()); + Doxygen::parserManager->registerParser("fortran", make_parser_factory<FortranOutlineParser>(), + make_parser_factory<FortranCodeParser>()); + Doxygen::parserManager->registerParser("fortranfree", make_parser_factory<FortranOutlineParserFree>(), + make_parser_factory<FortranCodeParserFree>()); + Doxygen::parserManager->registerParser("fortranfixed", make_parser_factory<FortranOutlineParserFixed>(), + make_parser_factory<FortranCodeParserFixed>()); + Doxygen::parserManager->registerParser("vhdl", make_parser_factory<VHDLOutlineParser>(), + make_parser_factory<VHDLCodeParser>()); + Doxygen::parserManager->registerParser("xml", make_parser_factory<NullOutlineParser>(), + make_parser_factory<XMLCodeParser>()); + Doxygen::parserManager->registerParser("sql", make_parser_factory<NullOutlineParser>(), + make_parser_factory<SQLCodeParser>()); + Doxygen::parserManager->registerParser("md", make_parser_factory<MarkdownOutlineParser>(), + make_parser_factory<FileCodeParser>()); // register any additional parsers here... @@ -9864,7 +10126,6 @@ void initDoxygen() initNamespaceMemberIndices(); initFileMemberIndices(); - Doxygen::symbolMap = new QDict<DefinitionIntf>(50177); #ifdef USE_LIBCLANG Doxygen::clangUsrMap = new QDict<Definition>(50177); #endif @@ -9872,12 +10133,9 @@ void initDoxygen() Doxygen::functionNameLinkedMap = new MemberNameLinkedMap; Doxygen::groupSDict = new GroupSDict(17); Doxygen::groupSDict->setAutoDelete(TRUE); - Doxygen::namespaceSDict = new NamespaceSDict(20); - Doxygen::namespaceSDict->setAutoDelete(TRUE); - Doxygen::classSDict = new ClassSDict(1009); - Doxygen::classSDict->setAutoDelete(TRUE); - Doxygen::hiddenClasses = new ClassSDict(257); - Doxygen::hiddenClasses->setAutoDelete(TRUE); + Doxygen::namespaceLinkedMap = new NamespaceLinkedMap; + Doxygen::classLinkedMap = new ClassLinkedMap; + Doxygen::hiddenClassLinkedMap = new ClassLinkedMap; Doxygen::directories = new DirSDict(17); Doxygen::directories->setAutoDelete(TRUE); Doxygen::pageSDict = new PageSDict(1009); // all doc pages @@ -9887,7 +10145,6 @@ void initDoxygen() Doxygen::memGrpInfoDict.setAutoDelete(TRUE); Doxygen::tagDestinationDict.setAutoDelete(TRUE); Doxygen::dirRelations.setAutoDelete(TRUE); - Doxygen::genericsDict = new GenericsSDict; Doxygen::indexList = new IndexList; // initialisation of these globals depends on @@ -9920,7 +10177,6 @@ void cleanUpDoxygen() SectionManager::instance().clear(); delete Doxygen::indexList; - delete Doxygen::genericsDict; delete Doxygen::inputNameLinkedMap; delete Doxygen::includeNameLinkedMap; delete Doxygen::exampleNameLinkedMap; @@ -9937,40 +10193,13 @@ void cleanUpDoxygen() delete g_outputList; Mappers::freeMappers(); - if (Doxygen::symbolMap) - { - // iterate through Doxygen::symbolMap and delete all - // DefinitionList objects, since they have no owner - QDictIterator<DefinitionIntf> dli(*Doxygen::symbolMap); - DefinitionIntf *di; - for (dli.toFirst();(di=dli.current());) - { - if (di->definitionType()==DefinitionIntf::TypeSymbolList) - { - DefinitionIntf *tmp = Doxygen::symbolMap->take(dli.currentKey()); - delete (DefinitionList *)tmp; - } - else - { - ++dli; - } - } - } - delete Doxygen::memberNameLinkedMap; delete Doxygen::functionNameLinkedMap; delete Doxygen::groupSDict; - delete Doxygen::classSDict; - delete Doxygen::hiddenClasses; - delete Doxygen::namespaceSDict; + delete Doxygen::namespaceLinkedMap; 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 - // dynamic first } static int computeIdealCacheParam(uint v) @@ -10031,15 +10260,15 @@ void readConfiguration(int argc, char **argv) debugLabel=getArg(argc,argv,optind); if (!debugLabel) { - err("option \"-d\" is missing debug specifier.\n"); devUsage(); cleanUpDoxygen(); - exit(1); + exit(0); } retVal = Debug::setFlag(debugLabel); if (!retVal) { err("option \"-d\" has unknown debug specifier: \"%s\".\n",debugLabel); + devUsage(); cleanUpDoxygen(); exit(1); } @@ -10434,7 +10663,7 @@ void adjustConfiguration() } else { - msg("Adding custom extension mapping: .%s will be treated as language %s\n", + msg("Adding custom extension mapping: '%s' will be treated as language '%s'\n", ext.data(),language.data()); } } @@ -10510,18 +10739,22 @@ static void writeTagFile() } } // for each class - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for ( ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { - if (cd->isLinkableInProject()) cd->writeTagFile(tagFile); + ClassDefMutable *cdm = toClassDefMutable(cd.get()); + if (cdm && cdm->isLinkableInProject()) + { + cdm->writeTagFile(tagFile); + } } // for each namespace - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for ( ; (nd=nli.current()) ; ++nli ) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (nd->isLinkableInProject()) nd->writeTagFile(tagFile); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd.get()); + if (ndm && nd->isLinkableInProject()) + { + ndm->writeTagFile(tagFile); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -10832,14 +11065,14 @@ void parseInput() if (!dir.mkdir(outputDirectory)) { err("tag OUTPUT_DIRECTORY: Output directory '%s' does not " - "exist and cannot be created\n",outputDirectory.data()); + "exist and cannot be created\n",outputDirectory.data()); cleanUpDoxygen(); exit(1); } else { - msg("Notice: Output directory '%s' does not exist. " - "I have created it for you.\n", outputDirectory.data()); + msg("Notice: Output directory '%s' does not exist. " + "I have created it for you.\n", outputDirectory.data()); } dir.cd(outputDirectory); } @@ -10855,8 +11088,7 @@ void parseInput() if (cacheSize<0) cacheSize=0; if (cacheSize>9) cacheSize=9; uint lookupSize = 65536 << cacheSize; - Doxygen::lookupCache = new QCache<LookupInfo>(lookupSize,lookupSize); - Doxygen::lookupCache->setAutoDelete(TRUE); + Doxygen::lookupCache = new Cache<std::string,LookupInfo>(lookupSize); #ifdef HAS_SIGNALS signal(SIGINT, stopDoxygen); @@ -11230,6 +11462,24 @@ void parseInput() )<0; }; + auto classComp = [](const ClassLinkedMap::Ptr &c1,const ClassLinkedMap::Ptr &c2) + { + if (Config_getBool(SORT_BY_SCOPE_NAME)) + { + return qstricmp(c1->name(), c2->name())<0; + } + else + { + int i = qstricmp(c1->className(), c2->className()); + return i==0 ? qstricmp(c1->name(), c2->name())<0 : i<0; + } + }; + + auto namespaceComp = [](const NamespaceLinkedMap::Ptr &n1,const NamespaceLinkedMap::Ptr &n2) + { + return qstricmp(n1->name(),n2->name())<0; + }; + g_s.begin("Sorting lists...\n"); std::sort(Doxygen::memberNameLinkedMap->begin(), Doxygen::memberNameLinkedMap->end(), @@ -11237,8 +11487,15 @@ void parseInput() std::sort(Doxygen::functionNameLinkedMap->begin(), Doxygen::functionNameLinkedMap->end(), memberNameComp); - Doxygen::hiddenClasses->sort(); - Doxygen::classSDict->sort(); + std::sort(Doxygen::hiddenClassLinkedMap->begin(), + Doxygen::hiddenClassLinkedMap->end(), + classComp); + std::sort(Doxygen::classLinkedMap->begin(), + Doxygen::classLinkedMap->end(), + classComp); + std::sort(Doxygen::namespaceLinkedMap->begin(), + Doxygen::namespaceLinkedMap->end(), + namespaceComp); g_s.end(); QDir thisDir; @@ -11345,6 +11602,10 @@ void parseInput() vhdlCorrectMemberProperties(); g_s.end(); + g_s.begin("Computing tooltip texts...\n"); + computeTooltipTexts(); + g_s.end(); + if (Config_getBool(SORT_GROUP_NAMES)) { Doxygen::groupSDict->sort(); @@ -11383,10 +11644,10 @@ void generateOutput() bool generateDocbook = Config_getBool(GENERATE_DOCBOOK); - g_outputList = new OutputList(TRUE); + g_outputList = new OutputList; if (generateHtml) { - g_outputList->add(new HtmlGenerator); + g_outputList->add<HtmlGenerator>(); HtmlGenerator::init(); // add HTML indexers that are enabled @@ -11405,22 +11666,22 @@ void generateOutput() } if (generateLatex) { - g_outputList->add(new LatexGenerator); + g_outputList->add<LatexGenerator>(); LatexGenerator::init(); } if (generateDocbook) { - g_outputList->add(new DocbookGenerator); + g_outputList->add<DocbookGenerator>(); DocbookGenerator::init(); } if (generateMan) { - g_outputList->add(new ManGenerator); + g_outputList->add<ManGenerator>(); ManGenerator::init(); } if (generateRtf) { - g_outputList->add(new RTFGenerator); + g_outputList->add<RTFGenerator>(); RTFGenerator::init(); } if (Config_getBool(USE_HTAGS)) @@ -11498,6 +11759,8 @@ void generateOutput() generateExampleDocs(); g_s.end(); + warn_flush(); + g_s.begin("Generating file sources...\n"); generateFileSources(); g_s.end(); @@ -11533,7 +11796,7 @@ void generateOutput() generateDirDocs(*g_outputList); g_s.end(); - if (g_outputList->count()>0) + if (g_outputList->size()>0) { writeIndexHierarchy(*g_outputList); } @@ -11602,6 +11865,8 @@ void generateOutput() if (g_useOutputTemplate) generateOutputViaTemplate(); + warn_flush(); + if (generateRtf) { g_s.begin("Combining RTF output...\n"); @@ -11612,10 +11877,14 @@ void generateOutput() g_s.end(); } + warn_flush(); + g_s.begin("Running plantuml with JAVA...\n"); PlantumlManager::instance()->run(); g_s.end(); + warn_flush(); + if (Config_getBool(HAVE_DOT)) { g_s.begin("Running dot...\n"); @@ -11663,6 +11932,9 @@ void generateOutput() QDir::setCurrent(oldDir); g_s.end(); } + + warn_flush(); + if ( generateHtml && Config_getBool(GENERATE_QHP) && !Config_getString(QHG_LOCATION).isEmpty()) @@ -11685,9 +11957,9 @@ void generateOutput() } int cacheParam; - msg("lookup cache used %d/%d hits=%d misses=%d\n", - Doxygen::lookupCache->count(), + msg("lookup cache used %zu/%zu hits=%" PRIu64 " misses=%" PRIu64 "\n", Doxygen::lookupCache->size(), + Doxygen::lookupCache->capacity(), Doxygen::lookupCache->hits(), Doxygen::lookupCache->misses()); cacheParam = computeIdealCacheParam(Doxygen::lookupCache->misses()*2/3); // part of the cache is flushed, hence the 2/3 correction factor @@ -11720,9 +11992,9 @@ void generateOutput() QDir thisDir; thisDir.remove(Doxygen::objDBFileName); thisDir.remove(Doxygen::filterDBFileName); + finishWarnExit(); Config::deinit(); QTextCodec::deleteAllCodecs(); - delete Doxygen::symbolMap; delete Doxygen::clangUsrMap; g_successfulRun=TRUE; } diff --git a/src/doxygen.h b/src/doxygen.h index dc05750..fb984f6 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -17,7 +17,6 @@ #define DOXYGEN_H #include <qdatetime.h> -#include <qcache.h> #include <qstrlist.h> #include <qdict.h> #include <qintdict.h> @@ -29,6 +28,8 @@ #include "dirdef.h" #include "memberlist.h" #include "define.h" +#include "cache.h" +#include "symbolmap.h" #define THREAD_LOCAL thread_local #define AtomicInt std::atomic_int @@ -48,13 +49,12 @@ class GroupDef; class GroupSDict; class FileDef; class ClassDef; -class ClassSDict; +class ClassLinkedMap; class GenericsSDict; class MemberNameLinkedMap; class FileNameLinkedMap; -class NamespaceSDict; +class NamespaceLinkedMap; class NamespaceDef; -class DefinitionIntf; class DirSDict; class DirRelation; class IndexList; @@ -63,11 +63,10 @@ class FormulaDict; class FormulaNameDict; class Preprocessor; struct MemberGroupInfo; +class NamespaceDefMutable; typedef QList<QCString> StringList; typedef QListIterator<QCString> StringListIterator; -//typedef QDict<FileDef> FileDict; -//typedef QDict<GroupDef> GroupDict; class StringDict : public QDict<QCString> { @@ -78,11 +77,11 @@ class StringDict : public QDict<QCString> struct LookupInfo { - LookupInfo() : classDef(0), typeDef(0) {} + LookupInfo() = default; LookupInfo(const ClassDef *cd,const MemberDef *td,QCString ts,QCString rt) : classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {} - const ClassDef *classDef; - const MemberDef *typeDef; + const ClassDef *classDef = 0; + const MemberDef *typeDef = 0; QCString templSpec; QCString resolvedType; }; @@ -96,8 +95,8 @@ extern QCString g_spaces; class Doxygen { public: - static ClassSDict *classSDict; - static ClassSDict *hiddenClasses; + static ClassLinkedMap *classLinkedMap; + static ClassLinkedMap *hiddenClassLinkedMap; static PageSDict *exampleSDict; static PageSDict *pageSDict; static PageDef *mainPage; @@ -114,20 +113,20 @@ class Doxygen static MemberNameLinkedMap *functionNameLinkedMap; static StringUnorderedMap namespaceAliasMap; static GroupSDict *groupSDict; - static NamespaceSDict *namespaceSDict; + static NamespaceLinkedMap *namespaceLinkedMap; static StringDict tagDestinationDict; static StringDict aliasDict; static QIntDict<MemberGroupInfo> memGrpInfoDict; static StringUnorderedSet expandAsDefinedSet; - static NamespaceDef *globalScope; + static NamespaceDefMutable *globalScope; static QCString htmlFileExtension; static bool parseSourcesNeeded; static SearchIndexIntf *searchIndex; - static QDict<DefinitionIntf> *symbolMap; + static SymbolMap<Definition> symbolMap; static QDict<Definition> *clangUsrMap; static bool outputToWizard; static QDict<int> *htmlDirMap; - static QCache<LookupInfo> *lookupCache; + static Cache<std::string,LookupInfo> *lookupCache; static DirSDict *directories; static SDict<DirRelation> dirRelations; static ParserManager *parserManager; @@ -140,7 +139,6 @@ class Doxygen static int subpageNestingLevel; static QCString spaces; static bool generatingXmlOutput; - static GenericsSDict *genericsDict; static DefinesPerFileList macroDefinitions; static bool clangAssistedParsing; }; diff --git a/src/doxygen.md b/src/doxygen.md index d8db231..e3db534 100644 --- a/src/doxygen.md +++ b/src/doxygen.md @@ -7,7 +7,7 @@ Introduction This page provides a high-level overview of the internals of doxygen, with links to the relevant parts of the code. This document is intended for developers who want to work on doxygen. Users of doxygen are referred to the -[User Manual](http://www.doxygen.nl/manual/index.html). +[User Manual](https://www.doxygen.nl/manual/index.html). The generic starting point of the application is of course the main() function. @@ -15,13 +15,13 @@ Configuration options ===================== Configuration file data is stored in singleton class Config and can be -accessed using wrapper macros +accessed using wrapper macros Config_getString(), Config_getInt(), Config_getList(), Config_getEnum(), and Config_getBool() depending on the type of the -option. +option. The format of the configuration file (options and types) is defined -by the file `config.xml`. As part of the build process, +by the file `config.xml`. As part of the build process, the python script `configgen.py` will create a file `configoptions.cpp` from this, which serves as the input for the configuration file parser that is invoked using Config::parse(). The script `configgen.py` will also @@ -43,18 +43,18 @@ for each file. Each parser implements the abstract interface ParserInterface. If the parser indicates it needs preprocessing via ParserInterface::needsPreprocessing(), doxygen will call preprocessFile() -on the file. +on the file. A second step is to convert multiline C++-style comments into C style comments -for easier processing later on. As side effect of this step also -aliases (ALIASES option) are resolved. The function that performs these +for easier processing later on. As side effect of this step also +aliases (ALIASES option) are resolved. The function that performs these 2 tasks is called convertCppComments(). *Note:* Alias resolution should better be done in a separate step as it is now coupled to C/C++ code and does not work automatically for other languages! -The third step is the actual language parsing and is done by calling -ParserInterface::parseInput() on the parser interface returned by +The third step is the actual language parsing and is done by calling +ParserInterface::parseInput() on the parser interface returned by the ParserManager. The result of parsing is a tree of Entry objects. @@ -67,19 +67,19 @@ converted into a Definition object. When a parser finds a special comment block in the input, it will do a first pass parsing via parseCommentBlock(). During this pass the comment block is split into multiple parts if needed. Some data that is later needed is -extracted like section labels, xref items, and formulas. +extracted like section labels, xref items, and formulas. Also Markdown markup is processed using processMarkdown() during this pass. Resolving relations =================== -The Entry objects created and filled during parsing are stored on disk -(to keep memory needs low). The name, parent/child relation, and -location on disk of each Entry is stored as a tree of EntryNav nodes, which is +The Entry objects created and filled during parsing are stored on disk +(to keep memory needs low). The name, parent/child relation, and +location on disk of each Entry is stored as a tree of EntryNav nodes, which is kept in memory. Doxygen does a number of tree walks over the EntryNav nodes in the tree to -build up the data structures needed to produce the output. +build up the data structures needed to produce the output. The resulting data structures are all children of the generic base class called Definition which holds all non-specific data for a symbol definition. @@ -141,9 +141,9 @@ easy ways to get debug information. - classes<br> Gives of classes en modules its scope and other relevant information. - preprocessor<br> - Shows the results of the preprocessing phase, i.e. results from include files, + Shows the results of the preprocessing phase, i.e. results from include files, <tt>\#define</tt> statements etc., definitions in the doxygen configuration file like: - `EXPAND_ONLY_PREDEF`, `PREDEFINED` and `MACRO_EXPANSION`. + `EXPAND_ONLY_PREDEF`, `PREDEFINED` and `MACRO_EXPANSION`. - commentcnv<br> Shows the results of the comment conversion, the comment conversion does the following: @@ -216,8 +216,8 @@ Topics TODO - perlmod - i18n via Translator and language.cpp - Customizing the layout via LayoutDocManager -- Parsers - - C Preprocessing +- Parsers + - C Preprocessing - const expression evaluation - C link languages - Python diff --git a/src/filedef.cpp b/src/filedef.cpp index 15fd1e5..e8d6066 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -48,14 +48,14 @@ //--------------------------------------------------------------------------- -class FileDefImpl : public DefinitionImpl, public FileDef +class FileDefImpl : public DefinitionMixin<FileDef> { public: FileDefImpl(const char *p,const char *n,const char *ref=0,const char *dn=0); virtual ~FileDefImpl(); virtual DefType definitionType() const { return TypeFile; } - virtual const QCString &name() const; + virtual QCString name() const; virtual QCString displayName(bool=TRUE) const { return name(); } virtual QCString fileName() const { return m_fileName; } @@ -78,16 +78,16 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual bool isIncluded(const QCString &name) const; virtual PackageDef *packageDef() const { return m_package; } virtual DirDef *getDirDef() const { return m_dir; } - virtual NamespaceSDict *getUsedNamespaces() const; - virtual SDict<Definition> *getUsedClasses() const { return m_usingDeclList; } + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const; + virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return m_usingDeclList; } virtual QList<IncludeInfo> *includeFileList() const { return m_includeList; } virtual QList<IncludeInfo> *includedByFileList() const { return m_includedByList; } 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; } - virtual NamespaceSDict *getNamespaceSDict() const { return m_namespaceSDict; } - virtual ClassSDict *getClassSDict() const { return m_classSDict; } + virtual NamespaceLinkedRefMap getNamespaces() const { return m_namespaces; } + virtual ClassLinkedRefMap getClasses() const { return m_classes; } virtual QCString title() const; virtual bool hasDetailedDescription() const; virtual QCString fileVersion() const; @@ -101,17 +101,19 @@ 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 writeSource(OutputList &ol,ClangTUParser *clangParser); + virtual void writeSourceHeader(OutputList &ol); + virtual void writeSourceBody(OutputList &ol,ClangTUParser *clangParser); + virtual void writeSourceFooter(OutputList &ol); virtual void parseSource(ClangTUParser *clangParser); virtual void setDiskName(const QCString &name); virtual void insertMember(MemberDef *md); - virtual void insertClass(ClassDef *cd); - virtual void insertNamespace(NamespaceDef *nd); + virtual void insertClass(const ClassDef *cd); + virtual void insertNamespace(const NamespaceDef *nd); virtual void computeAnchors(); virtual void setPackageDef(PackageDef *pd) { m_package=pd; } virtual void setDirDef(DirDef *dd) { m_dir=dd; } virtual void addUsingDirective(const NamespaceDef *nd); - virtual void addUsingDeclaration(Definition *def); + virtual void addUsingDeclaration(const ClassDef *cd); virtual void combineUsingRelations(); virtual bool generateSourceFile() const; virtual void sortMemberLists(); @@ -120,13 +122,10 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void addMembersToMemberGroup(); virtual void distributeMemberGroupDocumentation(); virtual void findSectionsInDocumentation(); - virtual void addIncludedUsingDirectives(); + virtual void addIncludedUsingDirectives(FileDefSet &visitedFiles); virtual void addListReferences(); - virtual void setVisited(bool v) { m_visited = v; } - virtual bool isVisited() const { return m_visited; } private: - bool m_visited; void acquireFileVersion(); MemberList *createMemberList(MemberListType lt); void addMemberToList(MemberListType lt,MemberDef *md); @@ -140,7 +139,7 @@ class FileDefImpl : public DefinitionImpl, public FileDef void writeSourceLink(OutputList &ol); void writeNamespaceDeclarations(OutputList &ol,const QCString &title, bool isConstantGroup); - void writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d); + void writeClassDeclarations(OutputList &ol,const QCString &title,const ClassLinkedRefMap &list); void writeInlineClasses(OutputList &ol); void startMemberDeclarations(OutputList &ol); void endMemberDeclarations(OutputList &ol); @@ -148,14 +147,14 @@ class FileDefImpl : public DefinitionImpl, public FileDef void endMemberDocumentation(OutputList &ol); void writeDetailedDescription(OutputList &ol,const QCString &title); void writeBriefDescription(OutputList &ol); - void writeClassesToTagFile(FTextStream &t,ClassSDict *d); + void writeClassesToTagFile(FTextStream &t,const ClassLinkedRefMap &list); QDict<IncludeInfo> *m_includeDict; QList<IncludeInfo> *m_includeList; QDict<IncludeInfo> *m_includedByDict; QList<IncludeInfo> *m_includedByList; - NamespaceSDict *m_usingDirList; - SDict<Definition> *m_usingDeclList; + LinkedRefMap<const NamespaceDef> m_usingDirList; + LinkedRefMap<const ClassDef> m_usingDeclList; QCString m_path; QCString m_filePath; QCString m_inclDepFileName; @@ -171,11 +170,11 @@ class FileDefImpl : public DefinitionImpl, public FileDef DirDef *m_dir; QList<MemberList> m_memberLists; MemberGroupSDict *m_memberGroupSDict; - NamespaceSDict *m_namespaceSDict; - ClassSDict *m_classSDict; - ClassSDict *m_interfaceSDict; - ClassSDict *m_structSDict; - ClassSDict *m_exceptionSDict; + NamespaceLinkedRefMap m_namespaces; + ClassLinkedRefMap m_classes; + ClassLinkedRefMap m_interfaces; + ClassLinkedRefMap m_structs; + ClassLinkedRefMap m_exceptions; bool m_subGrouping; }; @@ -208,6 +207,8 @@ class DevNullCodeDocInterface : public CodeOutputInterface virtual void linkableSymbol(int, const char *,Definition *,Definition *) {} virtual void setCurrentDoc(const Definition *,const char *,bool) {} virtual void addWord(const char *,bool) {} + virtual void startCodeFragment(const char *) {} + virtual void endCodeFragment(const char *) {} }; //--------------------------------------------------------------------------- @@ -218,31 +219,23 @@ class DevNullCodeDocInterface : public CodeOutputInterface */ FileDefImpl::FileDefImpl(const char *p,const char *nm, const char *lref,const char *dn) - : DefinitionImpl((QCString)p+nm,1,1,nm) + : DefinitionMixin((QCString)p+nm,1,1,nm) { m_path=p; m_filePath=m_path+nm; m_fileName=nm; setReference(lref); setDiskName(dn?dn:nm); - m_classSDict = 0; - m_interfaceSDict = 0; - m_structSDict = 0; - m_exceptionSDict = 0; m_includeList = 0; m_includeDict = 0; m_includedByList = 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_docname = nm; m_dir = 0; - m_visited = FALSE; if (Config_getBool(FULL_PATH_NAMES)) { m_docname.prepend(stripFromPath(m_path.copy())); @@ -256,19 +249,12 @@ FileDefImpl::FileDefImpl(const char *p,const char *nm, /*! destroy the file definition */ FileDefImpl::~FileDefImpl() { - delete m_classSDict; - delete m_interfaceSDict; - delete m_structSDict; - delete m_exceptionSDict; delete m_includeDict; delete m_includeList; delete m_includedByDict; delete m_includedByList; - delete m_namespaceSDict; delete m_srcDefDict; delete m_srcMemberDict; - delete m_usingDirList; - delete m_usingDeclList; delete m_memberGroupSDict; } @@ -292,7 +278,7 @@ void FileDefImpl::setDiskName(const QCString &name) void FileDefImpl::computeAnchors() { MemberList *ml = getMemberList(MemberListType_allMembersList); - if (ml) setAnchors(ml); + if (ml) ml->setAnchors(); } void FileDefImpl::distributeMemberGroupDocumentation() @@ -311,6 +297,7 @@ void FileDefImpl::distributeMemberGroupDocumentation() void FileDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); if (m_memberGroupSDict) { @@ -383,40 +370,31 @@ void FileDefImpl::writeTagFile(FTextStream &tagFile) { case LayoutDocEntry::FileClasses: { - if (m_classSDict) - writeClassesToTagFile(tagFile, m_classSDict); + writeClassesToTagFile(tagFile, m_classes); } break; case LayoutDocEntry::FileInterfaces: { - if (m_interfaceSDict) - writeClassesToTagFile(tagFile, m_interfaceSDict); + writeClassesToTagFile(tagFile, m_interfaces); } break; case LayoutDocEntry::FileStructs: { - if (m_structSDict) - writeClassesToTagFile(tagFile, m_structSDict); + writeClassesToTagFile(tagFile, m_structs); } break; case LayoutDocEntry::FileExceptions: { - if (m_exceptionSDict) - writeClassesToTagFile(tagFile, m_exceptionSDict); + writeClassesToTagFile(tagFile, m_exceptions); } break; case LayoutDocEntry::FileNamespaces: { - if (m_namespaceSDict) + for (const auto *nd : m_namespaces) { - SDict<NamespaceDef>::Iterator ni(*m_namespaceSDict); - NamespaceDef *nd; - for (ni.toFirst();(nd=ni.current());++ni) + if (nd->isLinkableInProject()) { - if (nd->isLinkableInProject()) - { - tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl; - } + tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl; } } } @@ -572,11 +550,9 @@ void FileDefImpl::writeBriefDescription(OutputList &ol) ol.writeSynopsis(); } -void FileDefImpl::writeClassesToTagFile(FTextStream &tagFile, ClassSDict *d) +void FileDefImpl::writeClassesToTagFile(FTextStream &tagFile, const ClassLinkedRefMap &list) { - SDict<ClassDef>::Iterator ci(*d); - ClassDef *cd; - for (ci.toFirst();(cd=ci.current());++ci) + for (const auto &cd : list) { if (cd->isLinkableInProject()) { @@ -722,13 +698,13 @@ void FileDefImpl::writeNamespaceDeclarations(OutputList &ol,const QCString &titl bool const isConstantGroup) { // write list of namespaces - if (m_namespaceSDict) m_namespaceSDict->writeDeclaration(ol,title,isConstantGroup); + m_namespaces.writeDeclaration(ol,title,isConstantGroup); } -void FileDefImpl::writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d) +void FileDefImpl::writeClassDeclarations(OutputList &ol,const QCString &title,const ClassLinkedRefMap &list) { // write list of classes - if (d) d->writeDeclaration(ol,0,title,FALSE); + list.writeDeclaration(ol,0,title,FALSE); } void FileDefImpl::writeInlineClasses(OutputList &ol) @@ -738,7 +714,7 @@ void FileDefImpl::writeInlineClasses(OutputList &ol) bool isEnabled = ol.isEnabled(OutputGenerator::Html); ol.enable(OutputGenerator::Html); - if (m_classSDict) m_classSDict->writeDocumentation(ol,this); + m_classes.writeDocumentation(ol,this); // restore the initial state if needed if (!isEnabled) ol.disable(OutputGenerator::Html); @@ -814,35 +790,35 @@ void FileDefImpl::writeSummaryLinks(OutputList &ol) const SrcLangExt lang=getLanguage(); for (eli.toFirst();(lde=eli.current());++eli) { - if (lde->kind()==LayoutDocEntry::FileClasses && m_classSDict && m_classSDict->declVisible()) + if (lde->kind()==LayoutDocEntry::FileClasses && m_classes.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "nested-classes"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::FileInterfaces && m_interfaceSDict && m_interfaceSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::FileInterfaces && m_interfaces.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "interfaces"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::FileStructs && m_structSDict && m_structSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::FileStructs && m_structs.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "structs"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::FileExceptions && m_exceptionSDict && m_exceptionSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::FileExceptions && m_exceptions.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "exceptions"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::FileNamespaces && m_namespaceSDict && m_namespaceSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::FileNamespaces && m_namespaces.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "namespaces"; @@ -973,25 +949,25 @@ void FileDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::FileClasses: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),m_classSDict); + writeClassDeclarations(ol,ls->title(lang),m_classes); } break; case LayoutDocEntry::FileInterfaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),m_interfaceSDict); + writeClassDeclarations(ol,ls->title(lang),m_interfaces); } break; case LayoutDocEntry::FileStructs: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),m_structSDict); + writeClassDeclarations(ol,ls->title(lang),m_structs); } break; case LayoutDocEntry::FileExceptions: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),m_exceptionSDict); + writeClassDeclarations(ol,ls->title(lang),m_exceptions); } break; case LayoutDocEntry::FileNamespaces: @@ -1121,25 +1097,25 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM { if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable() && !md->isEnumValue()) { - ol.writeString(" <tr><td class=\"navtab\">"); if (md->isLinkableInProject()) { if (md==currentMd) // selected item => highlight { - ol.writeString("<a class=\"qindexHL\" "); + ol.writeString(" <tr><td class=\"navtabHL\">"); } else { - ol.writeString("<a class=\"qindex\" "); + ol.writeString(" <tr><td class=\"navtab\">"); } + ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); + ol.writeString("</td></tr>\n"); } - ol.writeString("</td></tr>\n"); } } } @@ -1149,14 +1125,12 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM } /*! Write a source listing of this file to the output */ -void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) +void FileDefImpl::writeSourceHeader(OutputList &ol) { - static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); - static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); - static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); - static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); - DevNullCodeDocInterface devNullIntf; + bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); + bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); + bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); QCString title = m_docname; if (!m_fileVersion.isEmpty()) { @@ -1206,22 +1180,27 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) ol.endTextLink(); ol.popGeneratorState(); } +} +void FileDefImpl::writeSourceBody(OutputList &ol,ClangTUParser *clangParser) +{ + bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); + DevNullCodeDocInterface devNullIntf; #if USE_LIBCLANG if (Doxygen::clangAssistedParsing && clangParser && (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC)) { - ol.startCodeFragment(); + ol.startCodeFragment("DoxyCode"); clangParser->switchToFile(this); clangParser->writeSources(ol,this); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); } else #endif { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - ol.startCodeFragment(); + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + ol.startCodeFragment("DoxyCode"); bool needs2PassParsing = Doxygen::parseSourcesNeeded && // we need to parse (filtered) sources for cross-references !filterSourceFiles && // but user wants to show sources as-is @@ -1230,13 +1209,13 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) if (needs2PassParsing) { // parse code for cross-references only (see bug707641) - intf.parseCode(devNullIntf,0, + intf->parseCode(devNullIntf,0, fileToString(absFilePath(),TRUE,TRUE), getLanguage(), FALSE,0,this ); } - intf.parseCode(ol,0, + intf->parseCode(ol,0, fileToString(absFilePath(),filterSourceFiles,TRUE), getLanguage(), // lang FALSE, // isExampleBlock @@ -1250,8 +1229,12 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) 0, // searchCtx !needs2PassParsing // collectXRefs ); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); } +} + +void FileDefImpl::writeSourceFooter(OutputList &ol) +{ ol.endContents(); endFileWithNavPath(this,ol); ol.enableAll(); @@ -1271,9 +1254,9 @@ void FileDefImpl::parseSource(ClangTUParser *clangParser) else #endif { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - intf.parseCode( + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + intf->parseCode( devNullIntf,0, fileToString(absFilePath(),filterSourceFiles,TRUE), getLanguage(), @@ -1373,70 +1356,44 @@ void FileDefImpl::insertMember(MemberDef *md) } /*! Adds compound definition \a cd to the list of all compounds of this file */ -void FileDefImpl::insertClass(ClassDef *cd) +void FileDefImpl::insertClass(const ClassDef *cd) { if (cd->isHidden()) return; - ClassSDict *d=0; - ClassSDict **dd=&m_classSDict; + ClassLinkedRefMap &list = m_classes; if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) { if (cd->compoundType()==ClassDef::Interface) { - dd = &m_interfaceSDict; + list = m_interfaces; } else if (cd->compoundType()==ClassDef::Struct) { - dd = &m_structSDict; + list = m_structs; } else if (cd->compoundType()==ClassDef::Exception) { - dd = &m_exceptionSDict; + list = m_exceptions; } } - if (*dd==0) *dd = new ClassSDict(17); - d = *dd; - - if (Config_getBool(SORT_BRIEF_DOCS)) - { - d->inSort(cd->name(),cd); - } - else - { - d->append(cd->name(),cd); - } + list.add(cd->name(),cd); } /*! Adds namespace definition \a nd to the list of all compounds of this file */ -void FileDefImpl::insertNamespace(NamespaceDef *nd) +void FileDefImpl::insertNamespace(const NamespaceDef *nd) { if (nd->isHidden()) return; - if (!nd->name().isEmpty() && - (m_namespaceSDict==0 || m_namespaceSDict->find(nd->name())==0)) - { - if (m_namespaceSDict==0) - { - m_namespaceSDict = new NamespaceSDict; - } - if (Config_getBool(SORT_BRIEF_DOCS)) - { - m_namespaceSDict->inSort(nd->name(),nd); - } - else - { - m_namespaceSDict->append(nd->name(),nd); - } - } + m_namespaces.add(nd->name(),nd); } -const QCString &FileDefImpl::name() const +QCString FileDefImpl::name() const { if (Config_getBool(FULL_PATH_NAMES)) return m_fileName; else - return DefinitionImpl::name(); + return DefinitionMixin::name(); } void FileDefImpl::addSourceRef(int line,Definition *d,MemberDef *md) @@ -1478,33 +1435,19 @@ MemberDef *FileDefImpl::getSourceMember(int lineNr) const void FileDefImpl::addUsingDirective(const NamespaceDef *nd) { - if (m_usingDirList==0) - { - m_usingDirList = new NamespaceSDict; - } - if (m_usingDirList->find(nd->qualifiedName())==0) - { - m_usingDirList->append(nd->qualifiedName(),nd); - } + m_usingDirList.add(nd->qualifiedName(),nd); //printf("%p: FileDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); } -NamespaceSDict *FileDefImpl::getUsedNamespaces() const +LinkedRefMap<const NamespaceDef> FileDefImpl::getUsedNamespaces() const { //printf("%p: FileDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); return m_usingDirList; } -void FileDefImpl::addUsingDeclaration(Definition *d) +void FileDefImpl::addUsingDeclaration(const ClassDef *cd) { - if (m_usingDeclList==0) - { - m_usingDeclList = new SDict<Definition>(17); - } - if (m_usingDeclList->find(d->qualifiedName())==0) - { - m_usingDeclList->append(d->qualifiedName(),d); - } + m_usingDeclList.add(cd->qualifiedName(),cd); } void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported) @@ -1529,10 +1472,10 @@ void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool loca } } -void FileDefImpl::addIncludedUsingDirectives() +void FileDefImpl::addIncludedUsingDirectives(FileDefSet &visitedFiles) { - if (m_visited) return; - m_visited=TRUE; + if (visitedFiles.find(this)!=visitedFiles.end()) return; // file already processed + visitedFiles.insert(this); //printf("( FileDefImpl::addIncludedUsingDirectives for file %s\n",name().data()); if (m_includeList) // file contains #includes @@ -1542,10 +1485,10 @@ void FileDefImpl::addIncludedUsingDirectives() IncludeInfo *ii; for (iii.toFirst();(ii=iii.current());++iii) // foreach #include... { - if (ii->fileDef && !ii->fileDef->isVisited()) // ...that is a known file + if (ii->fileDef) // ...that is a known file { // recurse into this file - ii->fileDef->addIncludedUsingDirectives(); + ii->fileDef->addIncludedUsingDirectives(visitedFiles); } } } @@ -1558,41 +1501,18 @@ void FileDefImpl::addIncludedUsingDirectives() if (ii->fileDef && ii->fileDef!=this) { // add using directives - NamespaceSDict *unl = ii->fileDef->getUsedNamespaces(); - if (unl) + auto unl = ii->fileDef->getUsedNamespaces(); + for (auto it = unl.rbegin(); it!=unl.rend(); ++it) { - NamespaceSDict::Iterator nli(*unl); - NamespaceDef *nd; - for (nli.toLast();(nd=nli.current());--nli) - { - // append each using directive found in a #include file - if (m_usingDirList==0) m_usingDirList = new NamespaceSDict; - //printf("Prepending used namespace %s to the list of file %s\n", - // nd->name().data(),name().data()); - if (m_usingDirList->find(nd->qualifiedName())==0) // not yet added - { - m_usingDirList->prepend(nd->qualifiedName(),nd); - } - } + const auto *nd = *it; + m_usingDirList.prepend(nd->qualifiedName(),nd); } // add using declarations - SDict<Definition> *udl = ii->fileDef->getUsedClasses(); - if (udl) + auto udl = ii->fileDef->getUsedClasses(); + for (auto it = udl.rbegin(); it!=udl.rend(); ++it) { - SDict<Definition>::Iterator udi(*udl); - Definition *d; - for (udi.toLast();(d=udi.current());--udi) - { - //printf("Adding using declaration %s\n",d->name().data()); - if (m_usingDeclList==0) - { - m_usingDeclList = new SDict<Definition>(17); - } - if (m_usingDeclList->find(d->qualifiedName())==0) - { - m_usingDeclList->prepend(d->qualifiedName(),d); - } - } + const auto *cd = *it; + m_usingDeclList.prepend(cd->qualifiedName(),cd); } } } @@ -1919,40 +1839,28 @@ void generateFileTree() void FileDefImpl::combineUsingRelations() { - if (m_visited) return; // already done - m_visited=TRUE; - if (m_usingDirList) + LinkedRefMap<const NamespaceDef> usingDirList = m_usingDirList; + NamespaceDefSet visitedNamespaces; + for (auto &nd : usingDirList) + { + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->combineUsingRelations(visitedNamespaces); + } + } + + for (auto &nd : usingDirList) { - NamespaceSDict::Iterator nli(*m_usingDirList); - NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + // add used namespaces of namespace nd to this namespace + for (const auto &und : nd->getUsedNamespaces()) { - nd->combineUsingRelations(); + addUsingDirective(und); } - for (nli.toFirst();(nd=nli.current());++nli) + // add used classes of namespace nd to this namespace + for (const auto &ucd : nd->getUsedClasses()) { - // add used namespaces of namespace nd to this namespace - if (nd->getUsedNamespaces()) - { - NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); - NamespaceDef *und; - for (unli.toFirst();(und=unli.current());++unli) - { - //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); - addUsingDirective(und); - } - } - // add used classes of namespace nd to this namespace - if (nd->getUsedClasses()) - { - SDict<Definition>::Iterator cli(*nd->getUsedClasses()); - Definition *ucd; - for (cli.toFirst();(ucd=cli.current());++cli) - { - //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); - addUsingDeclaration(ucd); - } - } + addUsingDeclaration(ucd); } } } @@ -1963,7 +1871,8 @@ bool FileDefImpl::isDocumentationFile() const name().right(4)==".txt" || name().right(4)==".dox" || name().right(3)==".md" || - name().right(9)==".markdown"; + name().right(9)==".markdown" || + getLanguageFromFileName(getFileNameExtension(name())) == SrcLangExt_Markdown; } void FileDefImpl::acquireFileVersion() @@ -2054,7 +1963,14 @@ void FileDefImpl::addMemberToList(MemberListType lt,MemberDef *md) { ml->setInFile(TRUE); } - if (ml->listType()&MemberListType_declarationLists) md->setSectionList(this,ml); + if (ml->listType()&MemberListType_declarationLists) + { + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setSectionList(this,ml); + } + } } void FileDefImpl::sortMemberLists() @@ -2077,6 +1993,27 @@ void FileDefImpl::sortMemberLists() } } + if (Config_getBool(SORT_BRIEF_DOCS)) + { + auto classComp = [](const ClassLinkedRefMap::Ptr &c1,const ClassLinkedRefMap::Ptr &c2) + { + return Config_getBool(SORT_BY_SCOPE_NAME) ? + qstricmp(c1->name(), c2->name())<0 : + qstricmp(c1->className(), c2->className())<0; + }; + + std::sort(m_classes.begin(), m_classes.end(), classComp); + std::sort(m_interfaces.begin(),m_interfaces.end(),classComp); + std::sort(m_structs.begin(), m_structs.end(), classComp); + std::sort(m_exceptions.begin(),m_exceptions.end(),classComp); + + auto namespaceComp = [](const NamespaceLinkedRefMap::Ptr &n1,const NamespaceLinkedRefMap::Ptr &n2) + { + return qstricmp(n1->name(),n2->name())<0; + }; + + std::sort(m_namespaces.begin(),m_namespaces.end(),namespaceComp); + } } MemberList *FileDefImpl::getMemberList(MemberListType lt) const @@ -2203,3 +2140,31 @@ int FileDefImpl::numDecMembers() const return ml ? ml->numDecMembers() : 0; } +// --- Cast functions + +FileDef *toFileDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(FileDefImpl)) + { + return static_cast<FileDef*>(d); + } + else + { + return 0; + } +} + +const FileDef *toFileDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(FileDefImpl)) + { + return static_cast<const FileDef*>(d); + } + else + { + return 0; + } +} + diff --git a/src/filedef.h b/src/filedef.h index e4bb549..26e5de5 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -18,6 +18,8 @@ #ifndef FILEDEF_H #define FILEDEF_H +#include <set> + #include "index.h" #include <qlist.h> #include <qintdict.h> @@ -26,23 +28,27 @@ #include "sortdict.h" #include "memberlist.h" #include "containers.h" +#include "classlist.h" class MemberList; class FileDef; class FileList; -class ClassSDict; class ClassDef; class ClassList; class MemberDef; class OutputList; class NamespaceDef; -class NamespaceSDict; +class NamespaceLinkedRefMap; class MemberGroupSDict; class PackageDef; class DirDef; class FTextStream; class ClangTUParser; +// --- Set of files + +using FileDefSet = std::set<const FileDef*>; + /** Class representing the data associated with a \#include statement. */ struct IncludeInfo { @@ -62,7 +68,7 @@ struct IncludeInfo * The member writeDocumentation() can be used to generate the page of * documentation to HTML and LaTeX. */ -class FileDef : virtual public Definition +class FileDef : public DefinitionMutable, public Definition { public: ~FileDef() {} @@ -72,7 +78,7 @@ class FileDef : virtual public Definition virtual DefType definitionType() const = 0; /*! Returns the unique file name (this may include part of the path). */ - virtual const QCString &name() const = 0; + virtual QCString name() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString fileName() const = 0; @@ -116,8 +122,8 @@ class FileDef : virtual public Definition virtual PackageDef *packageDef() const = 0; virtual DirDef *getDirDef() const = 0; - virtual NamespaceSDict *getUsedNamespaces() const = 0; - virtual SDict<Definition> *getUsedClasses() const = 0; + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const = 0; + virtual LinkedRefMap<const ClassDef> getUsedClasses() const = 0; virtual QList<IncludeInfo> *includeFileList() const = 0; virtual QList<IncludeInfo> *includedByFileList() const = 0; virtual void getAllIncludeFilesRecursively(StringVector &incFiles) const = 0; @@ -127,8 +133,8 @@ class FileDef : virtual public Definition /* user defined member groups */ virtual MemberGroupSDict *getMemberGroupSDict() const = 0; - virtual NamespaceSDict *getNamespaceSDict() const = 0; - virtual ClassSDict *getClassSDict() const = 0; + virtual NamespaceLinkedRefMap getNamespaces() const = 0; + virtual ClassLinkedRefMap getClasses() const = 0; virtual QCString title() const = 0; virtual bool hasDetailedDescription() const = 0; @@ -150,20 +156,22 @@ class FileDef : virtual public Definition virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeTagFile(FTextStream &t) = 0; - virtual void writeSource(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void writeSourceHeader(OutputList &ol) = 0; + virtual void writeSourceBody(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void writeSourceFooter(OutputList &ol) = 0; virtual void parseSource(ClangTUParser *clangParser) = 0; virtual void setDiskName(const QCString &name) = 0; virtual void insertMember(MemberDef *md) = 0; - virtual void insertClass(ClassDef *cd) = 0; - virtual void insertNamespace(NamespaceDef *nd) = 0; + virtual void insertClass(const ClassDef *cd) = 0; + virtual void insertNamespace(const NamespaceDef *nd) = 0; virtual void computeAnchors() = 0; virtual void setPackageDef(PackageDef *pd) = 0; virtual void setDirDef(DirDef *dd) = 0; virtual void addUsingDirective(const NamespaceDef *nd) = 0; - virtual void addUsingDeclaration(Definition *def) = 0; + virtual void addUsingDeclaration(const ClassDef *cd) = 0; virtual void combineUsingRelations() = 0; virtual bool generateSourceFile() const = 0; @@ -175,16 +183,21 @@ class FileDef : virtual public Definition virtual void addMembersToMemberGroup() = 0; virtual void distributeMemberGroupDocumentation() = 0; virtual void findSectionsInDocumentation() = 0; - virtual void addIncludedUsingDirectives() = 0; + virtual void addIncludedUsingDirectives(FileDefSet &visitedFiles) = 0; virtual void addListReferences() = 0; - - virtual void setVisited(bool v) = 0; - virtual bool isVisited() const = 0; }; FileDef *createFileDef(const char *p,const char *n,const char *ref=0,const char *dn=0); + +// --- Cast functions + +FileDef *toFileDef(Definition *d); +const FileDef *toFileDef(const Definition *d); + +// ------------------ + /** Class representing a list of FileDef objects. */ class FileList : public QList<FileDef> { diff --git a/src/filename.h b/src/filename.h index c3a0d3e..d236046 100644 --- a/src/filename.h +++ b/src/filename.h @@ -20,6 +20,7 @@ #include <vector> #include "linkedmap.h" +#include "config.h" class FileDef; @@ -38,8 +39,38 @@ class FileName : public std::vector< std::unique_ptr<FileDef> > QCString m_pathName; }; +//! Custom combined key compare and hash functor that uses a lower case string in +//! case CASE_SENSE_NAMES is set to NO. +class FileNameFn +{ + public: + //! used as hash function + std::size_t operator()(const std::string& input) const noexcept + { + return std::hash<std::string>()(searchKey(input)); + } + //! used as equal operator + bool operator() (const std::string &t1, const std::string &t2) const + { + return searchKey(t1) == searchKey(t2); + } + private: + std::string searchKey(std::string input) const + { + std::string key = input; + if (!Config_getBool(CASE_SENSE_NAMES)) + { + // convert key to lower case + std::transform(key.begin(),key.end(),key.begin(), + [](char c){ return (char)std::tolower(c); }); + } + return key; + } +}; + /** Ordered dictionary of FileName objects. */ -class FileNameLinkedMap : public LinkedMap<FileName> +class FileNameLinkedMap : public LinkedMap<FileName,FileNameFn,FileNameFn, + std::unordered_multimap<std::string,FileName*,FileNameFn,FileNameFn> > { }; diff --git a/src/formula.cpp b/src/formula.cpp index ca50c9c..8ba9729 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -148,7 +148,7 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c // store the original directory if (!d.exists()) { - term("Output dir %s does not exist!\n",path); + term("Output directory '%s' does not exist!\n",path); } QCString oldDir = QDir::currentDirPath().utf8(); QCString macroFile = Config_getString(FORMULA_MACROFILE); @@ -167,7 +167,6 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c QCString texName="_formulas.tex"; IntVector formulasToGenerate; QFile f(texName); - bool formulaError=FALSE; if (f.open(IO_WriteOnly)) { FTextStream t(&f); @@ -214,8 +213,9 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c { err("Problems running latex. Check your installation or look " "for typos in _formulas.tex and check _formulas.log!\n"); - formulaError=TRUE; - //return; + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; } Portable::sysTimerStop(); //printf("Running dvips...\n"); @@ -439,12 +439,12 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c if (RM_TMP_FILES) { thisDir.remove("_formulas.dvi"); - if (!formulaError) thisDir.remove("_formulas.log"); // keep file in case of errors + thisDir.remove("_formulas.log"); // keep file in case of errors thisDir.remove("_formulas.aux"); } } // remove the latex file itself - if (RM_TMP_FILES && !formulaError) thisDir.remove("_formulas.tex"); + if (RM_TMP_FILES) 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 diff --git a/src/fortrancode.h b/src/fortrancode.h index 7da6a61..b8cac31 100644 --- a/src/fortrancode.h +++ b/src/fortrancode.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. * @@ -26,13 +26,11 @@ class MemberDef; class QCString; class Definition; -void codeFreeScanner(); - - class FortranCodeParser : public CodeParserInterface { public: - FortranCodeParser(FortranFormat format=FortranFormat_Unknown) : m_format(format) { } + FortranCodeParser(FortranFormat format=FortranFormat_Unknown); + virtual ~FortranCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -51,7 +49,8 @@ class FortranCodeParser : public CodeParserInterface void resetCodeParserState(); private: - FortranFormat m_format; + struct Private; + std::unique_ptr<Private> p; }; class FortranCodeParserFree : public FortranCodeParser diff --git a/src/fortrancode.l b/src/fortrancode.l index 4951001..0ddddd1 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -4,6 +4,7 @@ * * Copyright (C) by Anke Visser * based on the work of Dimitri van Heesch. + * Copyright (C) 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 @@ -25,7 +26,9 @@ **/ %option never-interactive %option case-insensitive +%option reentrant %option prefix="fortrancodeYY" +%option extra-type="struct fortrancodeYY_state *" %option noyy_top_state %top{ #include <stdint.h> @@ -34,7 +37,7 @@ %{ /* - * includes + * includes */ #include <stdio.h> #include <assert.h> @@ -58,6 +61,7 @@ #include "namespacedef.h" #include "tooltip.h" #include "fortrancode.h" +#include "fortranscanner.h" #include "containers.h" const int fixedCommentAfter = 72; @@ -121,219 +125,904 @@ class Scope /*===================================================================*/ /* - * statics + * 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 -static UseSDict *useMembers= new UseSDict; //!< info about used modules -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 g_str=""; //!> contents of fortran string - -static CodeOutputInterface * g_code; - -// TODO: is this still needed? if so, make it work -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_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 -static int *g_hasContLine = NULL; //!< signals whether or not a line has a continuation line (fixed source form) -static bool g_needsTermination; -static const Definition *g_searchCtx; -static bool g_collectXRefs; -static bool g_isFixedForm; - -static bool g_insideBody; //!< inside subprog/program body? => create links -static const char * g_currentFontClass; - -static bool g_exampleBlock; -static QCString g_exampleName; -static QCString g_exampleFile; - -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; - -static char stringStartSymbol; // single or double quote +struct fortrancodeYY_state +{ + QCString docBlock; //!< contents of all lines of a documentation block + QCString currentModule=0; //!< name of the current enclosing module + UseSDict * useMembers= 0; //!< info about used modules + UseEntry * useEntry = 0; //!< current use statement info + QList<Scope> scopeStack; + bool isExternal = false; + QCString str=""; //!> contents of fortran string + + CodeOutputInterface * code = 0; + + const char * inputString = 0; //!< the code fragment as text + 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 contLineNr = 0; //!< current, local, line number for continuation determination + int *hasContLine = 0; //!< signals whether or not a line has a continuation line (fixed source form) + bool needsTermination = false; + const Definition *searchCtx = 0; + bool collectXRefs = false; + bool isFixedForm = false; + + bool insideBody = false; //!< inside subprog/program body? => create links + const char * currentFontClass = 0; + + bool exampleBlock = false; + QCString exampleName; + QCString exampleFile; + + FileDef * sourceFileDef = 0; + Definition * currentDefinition = 0; + MemberDef * currentMemberDef = 0; + bool includeCodeFragment = false; + + char stringStartSymbol = '\0'; // single or double quote // count in variable declaration to filter out // declared from referenced names -static int bracketCount = 0; + int bracketCount = 0; // signal when in type / class /procedure declaration -static int inTypeDecl = 0; + int inTypeDecl = 0; -static bool g_endComment; + bool endComment = false; +}; #if USE_STATE2STRING static const char *stateToString(int state); #endif -static void endFontClass() +static bool getFortranNamespaceDefs(const QCString &mname, + NamespaceDef *&cd); +static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, + ClassDef *&cd, UseSDict *usedict=0); + +//---------------------------------------------------------------------------- + +static void endFontClass(yyscan_t yyscanner); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static void addToSearchIndex(yyscan_t yyscanner,const char *text); +static void startCodeLine(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, + Definition *d,const char *text); +static bool getGenericProcedureLink(yyscan_t yyscanner,const ClassDef *cd, + const char *memberText, + CodeOutputInterface &ol); +static bool getLink(yyscan_t yyscanner,UseSDict *usedict, // dictionary with used modules + const char *memberText, // exact member text + CodeOutputInterface &ol, + const char *text); +static void generateLink(yyscan_t yyscanner,CodeOutputInterface &ol, char *lname); +static int countLines(yyscan_t yyscanner); +static void startScope(yyscan_t yyscanner); +static void endScope(yyscan_t yyscanner); +static void addUse(yyscan_t yyscanner,const QCString &moduleName); +static void addLocalVar(yyscan_t yyscanner,const QCString &varName); +static MemberDef *getFortranDefs(yyscan_t yyscanner,const QCString &memberName, const QCString &moduleName, + UseSDict *usedict=0); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + + +//------------------------------------------------------------------- + +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_countFlowKeywordsMutex; + +/* -----------------------------------------------------------------*/ +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +IDSYM [a-z_A-Z0-9] +ID [a-z_A-Z]+{IDSYM}* +SUBPROG (subroutine|function) +B [ \t] +BS [ \t]* +BS_ [ \t]+ +COMMA {BS},{BS} +ARGS_L0 ("("[^)]*")") +ARGS_L1a [^()]*"("[^)]*")"[^)]* +ARGS_L1 ("("{ARGS_L1a}*")") +ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")" +ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2}) + +NUM_TYPE (complex|integer|logical|real) +LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.) +KIND {ARGS} +CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) +TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE|ENUMERATOR) + +INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" +ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|(NON_)?RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) +ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC) +/* Assume that attribute statements are almost the same as attributes. */ +ATTR_STMT {ATTR_SPEC}|DIMENSION +FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO) +COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON) +IGNORE (CALL) +PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?0 +LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")" + +/* | */ + +%option noyywrap +%option stack +%option caseless +/*%option debug*/ + +%x Start +%x SubCall +%x FuncDef +%x ClassName +%x ClassVar +%x Subprog +%x DocBlock +%x Use +%x UseOnly +%x Import +%x Declaration +%x DeclarationBinding +%x DeclContLine +%x Parameterlist +%x String +%x Subprogend + +%% + /*==================================================================*/ + + /*-------- ignore ------------------------------------------------------------*/ + +<Start>{IGNORE}/{BS}"(" { // do not search keywords, intrinsics... TODO: complete list + codifyLines(yyscanner,yytext); + } + /*-------- inner construct ---------------------------------------------------*/ + +<Start>{COMMANDS}/{BS}[,( \t\n] { // highlight + /* font class is defined e.g. in doxygen.css */ + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>{FLOW}/{BS}[,( \t\n] { + if (yyextra->isFixedForm) + { + if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT; + } + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); + if (mdm) + { + mdm->incrementFlowKeyWordCount(); + } + } + /* font class is defined e.g. in doxygen.css */ + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>{BS}(CASE|CLASS|TYPE){BS_}(IS|DEFAULT) { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>{BS}"end"({BS}{FLOW})/[ \t\n] { // list is a bit long as not all have possible end + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>"implicit"{BS}("none"|{TYPE_SPEC}) { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>^{BS}"namelist"/[//] { // Namelist specification + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + /*-------- use statement -------------------------------------------*/ +<Start>"use"{BS_} { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Use); + } +<Use>"ONLY" { // TODO: rename + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(UseOnly); + } +<Use>{ID} { + QCString tmp = yytext; + tmp = tmp.lower(); + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + + /* append module name to use dict */ + yyextra->useEntry = new UseEntry(); + //yyextra->useEntry->module = yytext; + //yyextra->useMembers->append(yytext, yyextra->useEntry); + //addUse(yytext); + yyextra->useEntry->module = tmp; + yyextra->useMembers->append(tmp, yyextra->useEntry); + addUse(yyscanner,tmp); + } +<Use,UseOnly,Import>{BS},{BS} { codifyLines(yyscanner,yytext); } +<UseOnly,Import>{BS}&{BS}"\n" { codifyLines(yyscanner,yytext); + yyextra->contLineNr++; + YY_FTN_RESET} +<UseOnly>{ID} { + QCString tmp = yytext; + tmp = tmp.lower(); + yyextra->useEntry->onlyNames.append(tmp); + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } +<Use,UseOnly,Import>"\n" { + unput(*yytext); + yy_pop_state(yyscanner); + YY_FTN_RESET + } +<*>"import"{BS}/"\n" | +<*>"import"{BS_} { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Import); + } +<Import>{ID} { + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } +<Import>("ONLY"|"NONE"|"ALL") { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + /*-------- fortran module -----------------------------------------*/ +<Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { // + startScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(ClassName); + if (!qstricmp(yytext,"module")) yyextra->currentModule="module"; + } +<Start>("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n { // + startScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(ClassName); + } +<*>{LANGUAGE_BIND_SPEC} { // + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { // + startScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(ClassName); + } +<ClassName>{ID} { + if (yyextra->currentModule == "module") + { + yyextra->currentModule=yytext; + yyextra->currentModule = yyextra->currentModule.lower(); + } + generateLink(yyscanner,*yyextra->code,yytext); + yy_pop_state(yyscanner); + } +<ClassName>({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable declaration + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<ClassName>\n { // interface may be without name + yy_pop_state(yyscanner); + YY_FTN_REJECT; + } +<Start>^{BS}"end"({BS_}"enum").* { + YY_FTN_REJECT; + } +<Start>^{BS}"end"({BS_}"type").* { + YY_FTN_REJECT; + } +<Start>^{BS}"end"({BS_}"module").* { // just reset yyextra->currentModule, rest is done in following rule + yyextra->currentModule=0; + YY_FTN_REJECT; + } + /*-------- subprog definition -------------------------------------*/ +<Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Subprog); + } +<Subprog>{ID} { // subroutine/function name + DBG_CTX((stderr, "===> start subprogram %s\n", yytext)); + startScope(yyscanner); + generateLink(yyscanner,*yyextra->code,yytext); + } +<Subprog>"result"/{BS}"("[^)]*")" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Subprog>"("[^)]*")" { // ignore rest of line + codifyLines(yyscanner,yytext); + } +<Subprog,Subprogend>"\n" { codifyLines(yyscanner,yytext); + yyextra->contLineNr++; + yy_pop_state(yyscanner); + YY_FTN_RESET + } +<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface")?{BS} { // Fortran subroutine or function ends + //cout << "===> end function " << yytext << endl; + endScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Subprogend); + } +<Subprogend>{ID}/{BS}(\n|!|;) { + generateLink(yyscanner,*yyextra->code,yytext); + yy_pop_state(yyscanner); + } +<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface"){BS}/(\n|!|;) { // Fortran subroutine or function ends + //cout << "===> end function " << yytext << endl; + endScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + /*-------- variable declaration ----------------------------------*/ +<Start>^{BS}"real"/[,:( ] { // real is a bit tricky as it is a data type but also a function. + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Start>{TYPE_SPEC}/[,:( ] { + QCString typ = yytext; + typ = removeRedundantWhiteSpace(typ.lower()); + if (typ.startsWith("real")) YY_FTN_REJECT; + if (typ == "type" || typ == "class" || typ == "procedure") yyextra->inTypeDecl = 1; + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Start>{ATTR_SPEC} { + if (QCString(yytext) == "external") + { + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + yyextra->isExternal = true; + } + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration + if (QCString(yytext) == "external") yyextra->isExternal = true; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Declaration>{ID} { // local var + if (yyextra->isFixedForm && yy_my_start == 1) + { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + else if (yyextra->currentMemberDef && + ((yyextra->currentMemberDef->isFunction() && (yyextra->currentMemberDef->typeString()!=QCString("subroutine") || yyextra->inTypeDecl)) || + yyextra->currentMemberDef->isVariable() || yyextra->currentMemberDef->isEnumValue() + ) + ) + { + generateLink(yyscanner,*yyextra->code, yytext); + } + else + { + yyextra->code->codify(yytext); + addLocalVar(yyscanner,yytext); + } + } +<Declaration>{BS}("=>"|"="){BS} { // Procedure binding + BEGIN(DeclarationBinding); + yyextra->code->codify(yytext); + } +<DeclarationBinding>{ID} { // Type bound procedure link + generateLink(yyscanner,*yyextra->code, yytext); + yy_pop_state(yyscanner); + } +<Declaration>[(] { // start of array or type / class specification + yyextra->bracketCount++; + yyextra->code->codify(yytext); + } + +<Declaration>[)] { // end array specification + yyextra->bracketCount--; + if (!yyextra->bracketCount) yyextra->inTypeDecl = 0; + yyextra->code->codify(yytext); + } + +<Declaration,DeclarationBinding>"&" { // continuation line + yyextra->code->codify(yytext); + if (!yyextra->isFixedForm) + { + yy_push_state(YY_START,yyscanner); + BEGIN(DeclContLine); + } + } +<DeclContLine>"\n" { // declaration not yet finished + yyextra->contLineNr++; + codifyLines(yyscanner,yytext); + yyextra->bracketCount = 0; + yy_pop_state(yyscanner); + YY_FTN_RESET + } +<Declaration,DeclarationBinding>"\n" { // end declaration line (?) + if (yyextra->endComment) + { + yyextra->endComment=FALSE; + } + else + { + codifyLines(yyscanner,yytext); + } + yyextra->bracketCount = 0; + yyextra->contLineNr++; + if (!(yyextra->hasContLine && yyextra->hasContLine[yyextra->contLineNr - 1])) + { + yyextra->isExternal = false; + yy_pop_state(yyscanner); + } + YY_FTN_RESET + } + + /*-------- subprog calls -----------------------------------------*/ + +<Start>"call"{BS_} { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(SubCall); + } +<SubCall>{ID} { // subroutine call + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + yy_pop_state(yyscanner); + } +<Start>{ID}{BS}/"(" { // function call + if (yyextra->isFixedForm && yy_my_start == 6) + { + // fixed form continuation line + YY_FTN_REJECT; + } + else if (QCString(yytext).stripWhiteSpace().lower() == "type") + { + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(QCString(yytext).stripWhiteSpace()); + endFontClass(yyscanner); + yyextra->code->codify(yytext + 4); + } + else + { + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } + } + + /*-------- comments ---------------------------------------------------*/ +<Start,Declaration,DeclarationBinding>\n?{BS}"!>"|"!<" { // start comment line or comment block + if (yytext[0] == '\n') + { + yyextra->contLineNr++; + yy_old_start = 0; + yy_my_start = 1; + 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 + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } +<Declaration,DeclarationBinding>{BS}"!<" { // start comment line or comment block + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } + +<DocBlock>.* { // contents of current comment line + yyextra->docBlock+=yytext; + } +<DocBlock>"\n"{BS}("!>"|"!<"|"!!") { // comment block (next line is also comment line) + yyextra->contLineNr++; + yy_old_start = 0; + yy_my_start = 1; + 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 + yyextra->docBlock+=yytext; + } +<DocBlock>"\n" { // comment block ends at the end of this line + // remove special comment (default config) + yyextra->contLineNr++; + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=((QCString)yyextra->docBlock).contains('\n'); + yyextra->yyLineNr+=1; + nextCodeLine(yyscanner); + yyextra->endComment=TRUE; + } + else // do not remove comment + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + unput(*yytext); + yyextra->contLineNr--; + yy_pop_state(yyscanner); + YY_FTN_RESET + } + +<*>"!"[^><\n].*|"!"$ { // normal comment + if(YY_START == String) YY_FTN_REJECT; // ignore in strings + if (yyextra->isFixedForm && yy_my_start == 6) YY_FTN_REJECT; + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +<*>^[Cc*].* { // normal comment + if(! yyextra->isFixedForm) YY_FTN_REJECT; + + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<*>"assignment"/{BS}"("{BS}"="{BS}")" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<*>"operator"/{BS}"("[^)]*")" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + + /*------ preprocessor --------------------------------------------*/ +<Start>"#".*\n { + if (yyextra->isFixedForm && yy_my_start == 6) YY_FTN_REJECT; + yyextra->contLineNr++; + startFontClass(yyscanner,"preprocessor"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + YY_FTN_RESET + } + /*------ variable references? -------------------------------------*/ + +<Start>"%"{BS}{ID} { // ignore references to elements + yyextra->code->codify(yytext); + } +<Start>{ID} { + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } + /*------ strings --------------------------------------------------*/ +<String>\n { // string with \n inside + yyextra->contLineNr++; + yyextra->str+=yytext; + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->str); + endFontClass(yyscanner); + yyextra->str = ""; + YY_FTN_RESET + } +<String>\"|\' { // string ends with next quote without previous backspace + if(yytext[0]!=yyextra->stringStartSymbol) YY_FTN_REJECT; // single vs double quote + yyextra->str+=yytext; + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->str); + endFontClass(yyscanner); + yy_pop_state(yyscanner); + } +<String>. {yyextra->str+=yytext;} + +<*>\"|\' { /* string starts */ + /* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */ + if (yyextra->isFixedForm && yy_my_start == 6) YY_FTN_REJECT; + yy_push_state(YY_START,yyscanner); + yyextra->stringStartSymbol=yytext[0]; // single or double quote + BEGIN(String); + yyextra->str=yytext; + } + /*-----------------------------------------------------------------------------*/ + +<*>\n { + if (yyextra->endComment) + { + yyextra->endComment=FALSE; + } + else + { + codifyLines(yyscanner,yytext); + // comment cannot extend over the end of a line so should always be terminated at the end of the line. + if (yyextra->currentFontClass && !strcmp(yyextra->currentFontClass,"comment")) endFontClass(yyscanner); + } + yyextra->contLineNr++; + YY_FTN_RESET + } +<*>^{BS}"type"{BS}"=" { yyextra->code->codify(yytext); } + +<*>[\x80-\xFF]* { // keep utf8 characters together... + if (yyextra->isFixedForm && yy_my_start > fixedCommentAfter) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + } + else + { + yyextra->code->codify(yytext); + } + } +<*>. { + if (yyextra->isFixedForm && yy_my_start > fixedCommentAfter) + { + //yy_push_state(YY_START,yyscanner); + //BEGIN(DocBlock); + //yyextra->docBlock=yytext; + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + } + else + { + yyextra->code->codify(yytext); + } + } +<*>{LOG_OPER} { // Fortran logical comparison keywords + yyextra->code->codify(yytext); + } +<*><<EOF>> { + if (YY_START == DocBlock) { + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + } + yyterminate(); + } +%% + +/*@ ---------------------------------------------------------------------------- + */ + +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 inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void endFontClass(yyscan_t yyscanner) { - if (g_currentFontClass) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) { - g_code->endFontClass(); - g_currentFontClass=0; + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; } } -static void startFontClass(const char *s) +static void startFontClass(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // if font class is already set don't stop and start it. // strcmp does not like null pointers as input. - if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s)) + if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s)) { - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } } -static void setCurrentDoc(const QCString &anchor) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - if (g_searchCtx) + if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); } } } -static void addToSearchIndex(const char *text) +static void addToSearchIndex(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - Doxygen::searchIndex->addWord(text,FALSE); + yyextra->code->addWord(text,FALSE); } } -/*! start a new line of code, inserting a line number if g_sourceFileDef +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef * is TRUE. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ -static void startCodeLine() +static void startCodeLine(yyscan_t yyscanner) { - if (g_sourceFileDef) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef) { //QCString lineNumber,lineAnchor; - //lineNumber.sprintf("%05d",g_yyLineNr); - //lineAnchor.sprintf("l%05d",g_yyLineNr); + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->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) + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("startCodeLine %d d=%s\n", yyextra->yyLineNr,d ? d->name().data() : "<null>"); + if (!yyextra->includeCodeFragment && d) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - g_insideBody = FALSE; - g_endComment = FALSE; - g_parmType.resize(0); - g_parmName.resize(0); + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + yyextra->insideBody = FALSE; + yyextra->endComment = FALSE; QCString lineAnchor; - lineAnchor.sprintf("l%05d",g_yyLineNr); - if (g_currentMemberDef) + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) { - g_code->writeLineNumber(g_currentMemberDef->getReference(), - g_currentMemberDef->getOutputFileBase(), - g_currentMemberDef->anchor(),g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { - g_code->writeLineNumber(d->getReference(), - d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - g_code->startCodeLine(g_sourceFileDef); - if (g_currentFontClass) + yyextra->code->startCodeLine(yyextra->sourceFileDef); + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void endFontClass(); -static void endCodeLine() +static void endCodeLine(yyscan_t yyscanner) { - endFontClass(); - g_code->endCodeLine(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); +} + +static void nextCodeLine(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char * fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) + { + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); + } } /*! write a code fragment 'text' that may span multiple lines, inserting * line numbers for each line. */ -static void codifyLines(char *text) +static void codifyLines(yyscan_t yyscanner,const char *text) { - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); - char *p=text,*sp=p; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); + const char *p=text,*sp=p; char c; bool done=FALSE; - const char * tmp_currentFontClass = g_currentFontClass; while (!done) { sp=p; while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; - *(p-1)='\0'; - g_code->codify(sp); - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } - if (tmp_currentFontClass) - { - startFontClass(tmp_currentFontClass); - } + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); + yyextra->code->codify(sp); done=TRUE; } } } -static void codifyLines(QCString str) -{ - char *tmp= (char *) malloc(str.length()+1); - strcpy(tmp, str); - codifyLines(tmp); - free(tmp); -} - /*! 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 * split into multiple links with the same destination, one for each line. */ -static void writeMultiLineCodeLink(CodeOutputInterface &ol, +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, Definition *d,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -351,15 +1040,11 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } + nextCodeLine(yyscanner); } else { @@ -382,7 +1067,7 @@ static bool getFortranNamespaceDefs(const QCString &mname, if (mname.isEmpty()) return FALSE; /* empty name => nothing to link */ // search for module - if ((cd=Doxygen::namespaceSDict->find(mname))) return TRUE; + if ((cd=Doxygen::namespaceLinkedMap->find(mname))) return TRUE; return FALSE; } @@ -396,19 +1081,19 @@ static bool getFortranNamespaceDefs(const QCString &mname, @returns true, if type is found */ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, - ClassDef *&cd, UseSDict *usedict=0) + ClassDef *&cd, UseSDict *usedict) { 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))) + if ((cd=Doxygen::classLinkedMap->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::classLinkedMap->find(moduleName+"::"+tname))) { //cout << "=== type found in local module" << endl; return TRUE; @@ -418,9 +1103,9 @@ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName UseEntry *use; for (UseSDict::Iterator di(*usedict); (use=di.current()); ++di) { - if ((cd= Doxygen::classSDict->find(use->module+"::"+tname))) + if ((cd= Doxygen::classLinkedMap->find(use->module+"::"+tname))) { - //cout << "=== type found in used module" << endl; + //cout << "=== type found in used module" << endl; return TRUE; } } @@ -436,13 +1121,14 @@ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName @param usedict array of data of USE-statement @returns MemberDef pointer, if found, or nullptr otherwise */ -static MemberDef *getFortranDefs(const QCString &memberName, const QCString &moduleName, - UseSDict *usedict=0) +static MemberDef *getFortranDefs(yyscan_t yyscanner,const QCString &memberName, const QCString &moduleName, + UseSDict *usedict) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (memberName.isEmpty()) return nullptr; /* empty name => nothing to link */ // look in local variables - QListIterator<Scope> it(scopeStack); + QListIterator<Scope> it(yyextra->scopeStack); Scope *scope; for (it.toLast();(scope=it.current());--it) { @@ -524,9 +1210,9 @@ static MemberDef *getFortranDefs(const QCString &memberName, const QCString &mod 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, +static bool getGenericProcedureLink(yyscan_t yyscanner,const ClassDef *cd, const char *memberText, - CodeOutputInterface &ol) + CodeOutputInterface &ol) { (void)cd; (void)memberText; @@ -534,31 +1220,33 @@ static bool getGenericProcedureLink(const ClassDef *cd, return FALSE; } -static bool getLink(UseSDict *usedict, // dictionary with used modules +static bool getLink(yyscan_t yyscanner,UseSDict *usedict, // dictionary with used modules const char *memberText, // exact member text - CodeOutputInterface &ol, - const char *text) + CodeOutputInterface &ol, + const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; MemberDef *md=0; QCString memberName= removeRedundantWhiteSpace(memberText); - if ((md=getFortranDefs(memberName, currentModule, usedict)) && md->isLinkable()) + if ((md=getFortranDefs(yyscanner,memberName, yyextra->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 const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { - if (g_currentDefinition && g_currentMemberDef && - md!=g_currentMemberDef && g_insideBody && g_collectXRefs) + if (yyextra->currentDefinition && yyextra->currentMemberDef && + md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } - writeMultiLineCodeLink(ol,md,text ? text : memberText); - addToSearchIndex(text ? text : memberText); + writeMultiLineCodeLink(yyscanner,ol,md,text ? text : memberText); + addToSearchIndex(yyscanner, text ? text : memberText); return TRUE; } } @@ -566,35 +1254,36 @@ static bool getLink(UseSDict *usedict, // dictionary with used modules } -static void generateLink(CodeOutputInterface &ol, char *lname) +static void generateLink(yyscan_t yyscanner,CodeOutputInterface &ol, char *lname) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; ClassDef *cd=0; 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 ( (getFortranTypeDefs(tmp, yyextra->currentModule, cd, yyextra->useMembers)) && cd->isLinkable() ) { if ( (cd->compoundType() == ClassDef::Class) && // was Entry::INTERFACE_SEC) && - (getGenericProcedureLink(cd, tmp, ol)) ) + (getGenericProcedureLink(yyscanner, cd, tmp, ol)) ) { //cout << "=== generic procedure resolved" << endl; } else { // write type or interface link - writeMultiLineCodeLink(ol,cd,tmp); - addToSearchIndex(tmp.data()); + writeMultiLineCodeLink(yyscanner, ol,cd,tmp); + addToSearchIndex(yyscanner, tmp); } } // check for module else if ( (getFortranNamespaceDefs(tmp, nsd)) && nsd->isLinkable() ) { // write module link - writeMultiLineCodeLink(ol,nsd,tmp); - addToSearchIndex(tmp.data()); + writeMultiLineCodeLink(yyscanner,ol,nsd,tmp); + addToSearchIndex(yyscanner,tmp); } // check for function/variable - else if (getLink(useMembers, tmp, ol, tmp)) + else if (getLink(yyscanner,yyextra->useMembers, tmp, ol, tmp)) { //cout << "=== found link for lowercase " << lname << endl; } @@ -602,16 +1291,17 @@ static void generateLink(CodeOutputInterface &ol, char *lname) { // nothing found, just write out the word //startFontClass("charliteral"); //test - codifyLines(tmp); - //endFontClass(); //test - addToSearchIndex(tmp.data()); + codifyLines(yyscanner,tmp); + //endFontClass(yyscanner); //test + addToSearchIndex(yyscanner,tmp); } } /*! counts the number of lines in the input */ -static int countLines() +static int countLines(yyscan_t yyscanner) { - const char *p=g_inputString; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->inputString; char c; int count=1; while ((c=*p)) @@ -619,701 +1309,69 @@ static int countLines() p++ ; if (c=='\n') count++; } - if (p>g_inputString && *(p-1)!='\n') + if (p>yyextra->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; + yyextra->needsTermination=TRUE; } return count; } //---------------------------------------------------------------------------- /** start scope */ -static void startScope() +static void startScope(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr, "===> startScope %s",yytext)); Scope *scope = new Scope; - scopeStack.append(scope); + yyextra->scopeStack.append(scope); } /** end scope */ -static void endScope() +static void endScope(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr,"===> endScope %s",yytext)); - if (scopeStack.isEmpty()) + if (yyextra->scopeStack.isEmpty()) { DBG_CTX((stderr,"WARNING: fortrancode.l: stack empty!\n")); return; } - Scope *scope = scopeStack.getLast(); - scopeStack.removeLast(); + Scope *scope = yyextra->scopeStack.getLast(); + yyextra->scopeStack.removeLast(); for ( QCStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it) { - useMembers->remove(*it); + yyextra->useMembers->remove(*it); } delete scope; } -static void addUse(const QCString &moduleName) +static void addUse(yyscan_t yyscanner,const QCString &moduleName) { - if (!scopeStack.isEmpty()) - scopeStack.getLast()->useNames.append(moduleName); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->scopeStack.isEmpty()) + yyextra->scopeStack.getLast()->useNames.append(moduleName); } -static void addLocalVar(const QCString &varName) +static void addLocalVar(yyscan_t yyscanner,const QCString &varName) { - if (!scopeStack.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->scopeStack.isEmpty()) { std::string lowVarName = varName.lower().str(); - scopeStack.getLast()->localVars.insert(lowVarName); - if (g_isExternal) scopeStack.getLast()->externalVars.insert(lowVarName); + yyextra->scopeStack.getLast()->localVars.insert(lowVarName); + if (yyextra->isExternal) yyextra->scopeStack.getLast()->externalVars.insert(lowVarName); } } -//---------------------------------------------------------------------------- - -/* -----------------------------------------------------------------*/ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static yy_size_t yyread(char *buf,yy_size_t max_size) -{ - yy_size_t c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} - -IDSYM [a-z_A-Z0-9] -ID [a-z_A-Z]+{IDSYM}* -SUBPROG (subroutine|function) -B [ \t] -BS [ \t]* -BS_ [ \t]+ -COMMA {BS},{BS} -ARGS_L0 ("("[^)]*")") -ARGS_L1a [^()]*"("[^)]*")"[^)]* -ARGS_L1 ("("{ARGS_L1a}*")") -ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")" -ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2}) - -NUM_TYPE (complex|integer|logical|real) -LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.) -KIND {ARGS} -CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) -TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE|ENUMERATOR) - -INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" -ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|(NON_)?RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) -ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC) -/* Assume that attribute statements are almost the same as attributes. */ -ATTR_STMT {ATTR_SPEC}|DIMENSION -FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO) -COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON) -IGNORE (CALL) -PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?0 -LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")" - -/* | */ - -%option noyywrap -%option stack -%option caseless -/*%option debug*/ - -%x Start -%x SubCall -%x FuncDef -%x ClassName -%x ClassVar -%x Subprog -%x DocBlock -%x Use -%x UseOnly -%x Import -%x Declaration -%x DeclarationBinding -%x DeclContLine -%x Parameterlist -%x String -%x Subprogend - -%% - /*==================================================================*/ - - /*-------- ignore ------------------------------------------------------------*/ - -<Start>{IGNORE}/{BS}"(" { // do not search keywords, intrinsics... TODO: complete list - codifyLines(yytext); - } - /*-------- inner construct ---------------------------------------------------*/ - -<Start>{COMMANDS}/{BS}[,( \t\n] { // highlight - /* font class is defined e.g. in doxygen.css */ - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Start>{FLOW}/{BS}[,( \t\n] { - if (g_isFixedForm) - { - if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT; - } - if (g_currentMemberDef && g_currentMemberDef->isFunction()) - { - g_currentMemberDef->incrementFlowKeyWordCount(); - } - /* font class is defined e.g. in doxygen.css */ - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } -<Start>{BS}(CASE|CLASS|TYPE){BS_}(IS|DEFAULT) { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } -<Start>{BS}"end"({BS}{FLOW})/[ \t\n] { // list is a bit long as not all have possible end - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } -<Start>"implicit"{BS}("none"|{TYPE_SPEC}) { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } -<Start>^{BS}"namelist"/[//] { // Namelist specification - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } - /*-------- use statement -------------------------------------------*/ -<Start>"use"{BS_} { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Use); - } -<Use>"ONLY" { // TODO: rename - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(UseOnly); - } -<Use>{ID} { - QCString tmp = yytext; - tmp = tmp.lower(); - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - - /* append module name to use dict */ - useEntry = new UseEntry(); - //useEntry->module = yytext; - //useMembers->append(yytext, useEntry); - //addUse(yytext); - 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++; - YY_FTN_RESET} -<UseOnly>{ID} { - QCString tmp = yytext; - tmp = tmp.lower(); - useEntry->onlyNames.append(tmp); - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } -<Use,UseOnly,Import>"\n" { - unput(*yytext); - yy_pop_state();YY_FTN_RESET - } -<*>"import"{BS}/"\n" | -<*>"import"{BS_} { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Import); - } -<Import>{ID} { - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } -<Import>("ONLY"|"NONE"|"ALL") { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } - /*-------- fortran module -----------------------------------------*/ -<Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(ClassName); - if (!qstricmp(yytext,"module")) currentModule="module"; - } -<Start>("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(ClassName); - currentClass="class"; - } -<*>{LANGUAGE_BIND_SPEC} { // - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(ClassName); - currentClass="class"; - } -<ClassName>{ID} { - if (currentModule == "module") - { - currentModule=yytext; - currentModule = currentModule.lower(); - } - generateLink(*g_code,yytext); - yy_pop_state(); - } -<ClassName>({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable declaration - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - } -<ClassName>\n { // interface may be without name - yy_pop_state(); - YY_FTN_REJECT; - } -<Start>^{BS}"end"({BS_}"enum").* { // just reset currentClass, rest is done in following rule - currentClass=0; - YY_FTN_REJECT; - } -<Start>^{BS}"end"({BS_}"type").* { // just reset currentClass, rest is done in following rule - currentClass=0; - YY_FTN_REJECT; - } -<Start>^{BS}"end"({BS_}"module").* { // just reset currentModule, rest is done in following rule - currentModule=0; - YY_FTN_REJECT; - } - /*-------- subprog definition -------------------------------------*/ -<Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Subprog); - } -<Subprog>{ID} { // subroutine/function name - DBG_CTX((stderr, "===> start subprogram %s\n", yytext)); - startScope(); - generateLink(*g_code,yytext); - } -<Subprog>"result"/{BS}"("[^)]*")" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Subprog>"("[^)]*")" { // ignore rest of line - codifyLines(yytext); - } -<Subprog,Subprogend>"\n" { codifyLines(yytext); - g_contLineNr++; - yy_pop_state(); - YY_FTN_RESET - } -<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface")?{BS} { // Fortran subroutine or function ends - //cout << "===> end function " << yytext << endl; - endScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Subprogend); - } -<Subprogend>{ID}/{BS}(\n|!|;) { - generateLink(*g_code,yytext); - yy_pop_state(); - } -<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface"){BS}/(\n|!|;) { // Fortran subroutine or function ends - //cout << "===> end function " << yytext << endl; - endScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } - /*-------- variable declaration ----------------------------------*/ -<Start>^{BS}"real"/[,:( ] { // real is a bit tricky as it is a data type but also a function. - yy_push_state(YY_START); - BEGIN(Declaration); - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Start>{TYPE_SPEC}/[,:( ] { - QCString typ = yytext; - typ = removeRedundantWhiteSpace(typ.lower()); - if (typ.startsWith("real")) YY_FTN_REJECT; - if (typ == "type" || typ == "class" || typ == "procedure") inTypeDecl = 1; - yy_push_state(YY_START); - BEGIN(Declaration); - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Start>{ATTR_SPEC} { - if (QCString(yytext) == "external") - { - yy_push_state(YY_START); - BEGIN(Declaration); - g_isExternal = true; - } - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration - if (QCString(yytext) == "external") g_isExternal = true; - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Declaration>{ID} { // local var - if (g_isFixedForm && yy_my_start == 1) - { - startFontClass("comment"); - g_code->codify(yytext); - endFontClass(); - } - else if (g_currentMemberDef && - ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString()!=QCString("subroutine") || inTypeDecl)) || - g_currentMemberDef->isVariable() || g_currentMemberDef->isEnumValue() - ) - ) - { - generateLink(*g_code, yytext); - } - else - { - g_code->codify(yytext); - addLocalVar(yytext); - } - } -<Declaration>{BS}("=>"|"="){BS} { // Procedure binding - BEGIN(DeclarationBinding); - g_code->codify(yytext); - } -<DeclarationBinding>{ID} { // Type bound procedure link - generateLink(*g_code, yytext); - yy_pop_state(); - } -<Declaration>[(] { // start of array or type / class specification - bracketCount++; - g_code->codify(yytext); - } - -<Declaration>[)] { // end array specification - bracketCount--; - if (!bracketCount) inTypeDecl = 0; - g_code->codify(yytext); - } - -<Declaration,DeclarationBinding>"&" { // continuation line - g_code->codify(yytext); - if (!g_isFixedForm) - { - yy_push_state(YY_START); - BEGIN(DeclContLine); - } - } -<DeclContLine>"\n" { // declaration not yet finished - g_contLineNr++; - codifyLines(yytext); - bracketCount = 0; - yy_pop_state(); - YY_FTN_RESET - } -<Declaration,DeclarationBinding>"\n" { // end declaration line (?) - if (g_endComment) - { - g_endComment=FALSE; - } - else - { - codifyLines(yytext); - } - bracketCount = 0; - g_contLineNr++; - if (!(g_hasContLine && g_hasContLine[g_contLineNr - 1])) - { - g_isExternal = false; - yy_pop_state(); - } - YY_FTN_RESET - } - - /*-------- subprog calls -----------------------------------------*/ - -<Start>"call"{BS_} { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(SubCall); - } -<SubCall>{ID} { // subroutine call - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - yy_pop_state(); - } -<Start>{ID}{BS}/"(" { // function call - if (g_isFixedForm && yy_my_start == 6) - { - // fixed form continuation line - YY_FTN_REJECT; - } - else if (QCString(yytext).stripWhiteSpace().lower() == "type") - { - yy_push_state(YY_START); - BEGIN(Declaration); - startFontClass("keywordtype"); - g_code->codify(QCString(yytext).stripWhiteSpace()); - endFontClass(); - g_code->codify(yytext + 4); - } - else - { - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } - } - - /*-------- comments ---------------------------------------------------*/ -<Start,Declaration,DeclarationBinding>\n?{BS}"!>"|"!<" { // start comment line or comment block - if (yytext[0] == '\n') - { - g_contLineNr++; - yy_old_start = 0; - yy_my_start = 1; - 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 - yy_push_state(YY_START); - BEGIN(DocBlock); - docBlock=yytext; - } -<Declaration,DeclarationBinding>{BS}"!<" { // start comment line or comment block - yy_push_state(YY_START); - BEGIN(DocBlock); - docBlock=yytext; - } - -<DocBlock>.* { // contents of current comment line - docBlock+=yytext; - } -<DocBlock>"\n"{BS}("!>"|"!<"|"!!") { // comment block (next line is also comment line) - g_contLineNr++; - yy_old_start = 0; - yy_my_start = 1; - 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>"\n" { // comment block ends at the end of this line - // remove special comment (default config) - g_contLineNr++; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - g_yyLineNr+=((QCString)docBlock).contains('\n'); - g_yyLineNr+=1; - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } - g_endComment=TRUE; - } - else // do not remove comment - { - startFontClass("comment"); - codifyLines(docBlock); - endFontClass(); - } - unput(*yytext); - g_contLineNr--; - yy_pop_state(); - YY_FTN_RESET - } - -<*>"!"[^><\n].*|"!"$ { // normal comment - if(YY_START == String) YY_FTN_REJECT; // ignore in strings - if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } - -<*>^[Cc*].* { // normal comment - if(! g_isFixedForm) YY_FTN_REJECT; - - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } -<*>"assignment"/{BS}"("{BS}"="{BS}")" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<*>"operator"/{BS}"("[^)]*")" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } - - /*------ preprocessor --------------------------------------------*/ -<Start>"#".*\n { - if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; - g_contLineNr++; - startFontClass("preprocessor"); - codifyLines(yytext); - endFontClass(); - YY_FTN_RESET - } - /*------ variable references? -------------------------------------*/ - -<Start>"%"{BS}{ID} { // ignore references to elements - g_code->codify(yytext); - } -<Start>{ID} { - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } - /*------ strings --------------------------------------------------*/ -<String>\n { // string with \n inside - g_contLineNr++; - g_str+=yytext; - startFontClass("stringliteral"); - codifyLines(g_str); - endFontClass(); - g_str = ""; - YY_FTN_RESET - } -<String>\"|\' { // string ends with next quote without previous backspace - if(yytext[0]!=stringStartSymbol) YY_FTN_REJECT; // single vs double quote - g_str+=yytext; - startFontClass("stringliteral"); - codifyLines(g_str); - endFontClass(); - yy_pop_state(); - } -<String>. {g_str+=yytext;} - -<*>\"|\' { /* string starts */ - /* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */ - if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; - yy_push_state(YY_START); - stringStartSymbol=yytext[0]; // single or double quote - BEGIN(String); - g_str=yytext; - } - /*-----------------------------------------------------------------------------*/ - -<*>\n { - if (g_endComment) - { - g_endComment=FALSE; - } - else - { - codifyLines(yytext); - // comment cannot extend over the end of a line so should always be terminated at the end of the line. - if (g_currentFontClass && !strcmp(g_currentFontClass,"comment")) endFontClass(); - } - g_contLineNr++; - YY_FTN_RESET - } -<*>^{BS}"type"{BS}"=" { g_code->codify(yytext); } - -<*>. { - if (g_isFixedForm && yy_my_start > fixedCommentAfter) - { - //yy_push_state(YY_START); - //BEGIN(DocBlock); - //docBlock=yytext; - startFontClass("comment"); - codifyLines(yytext); - } - else - { - g_code->codify(yytext); - } - } -<*>{LOG_OPER} { // Fortran logical comparison keywords - g_code->codify(yytext); - } -<*><<EOF>> { - if (YY_START == DocBlock) { - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass("comment"); - codifyLines(docBlock); - endFontClass(); - } - } - yyterminate(); - } -%% - -/*@ ---------------------------------------------------------------------------- - */ - /*===================================================================*/ -void resetFortranCodeParserState() {} - -bool recognizeFixedForm(const char* contents, FortranFormat format); /* prototype, implementation in fortranscanner.l */ -const char* prepassFixedForm(const char* contents, int *hasContLine); /* prototype, implementation in fortranscanner.l */ -static void checkContLines(const char *s) +static void checkContLines(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int numLines = 0; int i = 0; const char *p = s; @@ -1325,115 +1383,153 @@ static void checkContLines(const char *s) p++; } - g_hasContLine = (int *) malloc((numLines) * sizeof(int)); + yyextra->hasContLine = (int *) malloc((numLines) * sizeof(int)); for (i = 0; i < numLines; i++) - g_hasContLine[i] = 0; - p = prepassFixedForm(s, g_hasContLine); - g_hasContLine[0] = 0; + yyextra->hasContLine[i] = 0; + p = prepassFixedForm(s, yyextra->hasContLine); + yyextra->hasContLine[0] = 0; } 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, + int startLine,int endLine,bool inlineFragment, + const MemberDef *,bool,const Definition *searchCtx, bool collectXRefs, FortranFormat format) { //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); - if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_isFixedForm = recognizeFixedForm((const char*)s,format); - g_contLineNr = 1; - g_hasContLine = NULL; - if (g_isFixedForm) + return; +} + +//--------------------------------------------------------- + +struct FortranCodeParser::Private +{ + yyscan_t yyscanner; + fortrancodeYY_state state; + FortranFormat format; +}; + +FortranCodeParser::FortranCodeParser(FortranFormat format) : p(std::make_unique<Private>()) +{ + p->format = format; + fortrancodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + fortrancodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); + p->state.useMembers = new UseSDict; +} + +FortranCodeParser::~FortranCodeParser() +{ + delete p->state.useMembers; + fortrancodeYYlex_destroy(p->yyscanner); +} + +void FortranCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + BEGIN( Start ); +} + +void FortranCodeParser::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 + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + //::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, + // fileDef,startLine,endLine,inlineFragment,memberDef, + // showLineNumbers,searchCtx,collectXRefs,m_format); + // 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, + // bool collectXRefs, FortranFormat format) + if (input.isEmpty()) return; + printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->isFixedForm = recognizeFixedForm(input,p->format); + yyextra->contLineNr = 1; + yyextra->hasContLine = NULL; + if (yyextra->isFixedForm) { - checkContLines(g_inputString); + checkContLines(yyscanner,yyextra->inputString); } - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx = searchCtx; - g_collectXRefs = collectXRefs; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + yyextra->searchCtx = searchCtx; + yyextra->collectXRefs = collectXRefs; if (startLine!=-1) - g_yyLineNr = startLine; + yyextra->yyLineNr = startLine; else - g_yyLineNr = 1; + yyextra->yyLineNr = 1; if (endLine!=-1) - g_inputLines = endLine+1; + yyextra->inputLines = endLine+1; else - g_inputLines = g_yyLineNr + countLines() - 1; + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; - if (exBlock && fd==0) + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",exName); + yyextra->sourceFileDef = createFileDef("",exampleName); } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_currentDefinition = 0; - g_currentMemberDef = 0; - if (!g_exampleName.isEmpty()) + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + if (!yyextra->exampleName.isEmpty()) { - g_exampleFile = convertNameToFile(g_exampleName+"-example"); + yyextra->exampleFile = convertNameToFile(yyextra->exampleName+"-example"); } - g_includeCodeFragment = inlineFragment; - startCodeLine(); - g_parmName.resize(0); - g_parmType.resize(0); - fortrancodeYYrestart( fortrancodeYYin ); + yyextra->includeCodeFragment = inlineFragment; + startCodeLine(yyscanner); + fortrancodeYYrestart(0, yyscanner); BEGIN( Start ); - fortrancodeYYlex(); - if (g_needsTermination) + fortrancodeYYlex(yyscanner); + if (yyextra->needsTermination) { - endFontClass(); - g_code->endCodeLine(); + endFontClass(yyscanner); + yyextra->code->endCodeLine(); } - if (exBlock && g_sourceFileDef) + if (isExampleBlock && yyextra->sourceFileDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } - if (g_hasContLine) free(g_hasContLine); - g_hasContLine = NULL; - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - return; -} - -//--------------------------------------------------------- + if (yyextra->hasContLine) free(yyextra->hasContLine); + yyextra->hasContLine = NULL; -void FortranCodeParser::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 - ) -{ - ::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs,m_format); -} + // write the tooltips + TooltipManager::instance().writeTooltips(codeOutIntf); -void FortranCodeParser::resetCodeParserState() -{ - ::resetFortranCodeParserState(); + printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } //--------------------------------------------------------- diff --git a/src/fortranscanner.h b/src/fortranscanner.h index 0e67bb2..0fbba89 100644 --- a/src/fortranscanner.h +++ b/src/fortranscanner.h @@ -53,5 +53,6 @@ class FortranOutlineParserFixed : public FortranOutlineParser FortranOutlineParserFixed() : FortranOutlineParser(FortranFormat_Fixed) { } }; +const char* prepassFixedForm(const char* contents, int *hasContLine); #endif diff --git a/src/fortranscanner.l b/src/fortranscanner.l index cf48a3e..99e1f9a 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -48,6 +48,8 @@ %{ +#include <map> + #include <stdio.h> #include <stdlib.h> #include <assert.h> @@ -202,7 +204,7 @@ struct fortranscannerYY_state //! Accumulated modifiers of current statement, eg variable declaration. SymbolModifiers currentModifiers; //! Holds program scope->symbol name->symbol modifiers. - QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers; + std::map<Entry*,std::map<std::string,SymbolModifiers> > modifiers; int anonCount = 0 ; }; @@ -712,7 +714,7 @@ private { } {ID} { QCString name = yytext; - yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers; yyextra->current->section = Entry::FUNCTION_SEC; yyextra->current->name = name; yyextra->current->fileName = yyextra->fileName; @@ -774,6 +776,7 @@ private { yyterminate(); } yyextra->subrCurrent.pop_back(); + yyextra->vtype = V_IGNORE; yy_pop_state(yyscanner) ; } <BlockData>{ @@ -871,7 +874,7 @@ private { QCString name=yytext; name = name.lower(); /* remember attributes for the symbol */ - yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers; yyextra->argName= name; yyextra->vtype= V_IGNORE; @@ -912,12 +915,12 @@ private { // save, it may be function return type if (parameter) { - yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + yyextra->modifiers[yyextra->current_root][name.lower().str()].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())) + (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower())) { int strt = yyextra->current_root->type.find("function"); QCString lft; @@ -955,11 +958,11 @@ private { 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; + yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->current_root->type; } else { - yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->argType; } } // any accumulated doc for argument should be emptied, @@ -973,7 +976,7 @@ private { QCString name(yyextra->argName); QCString attr("dimension"); attr += yytext; - yyextra->modifiers[yyextra->current_root][name.lower()] |= attr; + yyextra->modifiers[yyextra->current_root][name.lower().str()] |= attr; } <Variable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyextra->colNr-(int)yyleng, yyextra->colNr); // locate !< comment @@ -1147,7 +1150,7 @@ private { <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(); + yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = yyextra->current->name.lower(); if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { @@ -1196,7 +1199,7 @@ private { 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; + yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result; } //cout << "=====> got result " << result << endl; } @@ -1498,49 +1501,6 @@ void truncatePrepass(yyscan_t yyscanner,int index) yyextra->inputStringPrepass.truncate(index); } -// simplified way to know if this is fixed form -bool recognizeFixedForm(const char* contents, FortranFormat format) -{ - int column=0; - bool skipLine=FALSE; - - if (format == FortranFormat_Fixed) return TRUE; - if (format == FortranFormat_Free) return FALSE; - - for(int i=0;;i++) { - column++; - - switch(contents[i]) { - case '\n': - column=0; - skipLine=FALSE; - break; - case ' ': - break; - case '\000': - return FALSE; - case '#': - skipLine=TRUE; - break; - case 'C': - case 'c': - case '*': - if (column==1) return TRUE; - if (skipLine) break; - return FALSE; - case '!': - if (column>1 && column<7) return FALSE; - skipLine=TRUE; - break; - default: - if (skipLine) break; - if (column>=7) return TRUE; - return FALSE; - } - } - return FALSE; -} - /* This function assumes that contents has at least size=length+1 */ static void insertCharacter(char *contents, int length, int pos, char c) { @@ -2061,7 +2021,7 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F /*! Apply yyextra->modifiers stored in \a mdfs to the \a typeName string. */ -static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) +static QCString applyModifiers(QCString typeName, const SymbolModifiers& mdfs) { if (!mdfs.dimension.isNull()) { @@ -2178,14 +2138,14 @@ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) } /*! Apply yyextra->modifiers stored in \a mdfs to the \a arg argument. */ -static void applyModifiers(Argument *arg, SymbolModifiers& mdfs) +static void applyModifiers(Argument *arg, const SymbolModifiers& mdfs) { QCString tmp = arg->type; arg->type = applyModifiers(tmp, mdfs); } /*! Apply yyextra->modifiers stored in \a mdfs to the \a ent entry. */ -static void applyModifiers(Entry *ent, SymbolModifiers& mdfs) +static void applyModifiers(Entry *ent, const SymbolModifiers& mdfs) { QCString tmp = ent->type; ent->type = applyModifiers(tmp, mdfs); @@ -2206,8 +2166,7 @@ static void startScope(yyscan_t yyscanner,Entry *scope) //cout<<"start scope: "<<scope->name<<endl; yyextra->current_root= scope; /* start substructure */ - QMap<QCString,SymbolModifiers> mdfMap; - yyextra->modifiers.insert(scope, mdfMap); + yyextra->modifiers.insert(std::make_pair(scope, std::map<std::string,SymbolModifiers>())); } /*! Ends scope in fortran program: may update subprogram arguments or module variable attributes. @@ -2238,32 +2197,32 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) } // update variables or subprogram arguments with yyextra->modifiers - QMap<QCString,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope]; + std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope]; if (scope->section == Entry::FUNCTION_SEC) { // iterate all symbol yyextra->modifiers of the scope - for (QMap<QCString,SymbolModifiers>::Iterator it=mdfsMap.begin(); it!=mdfsMap.end(); it++) + for (const auto &kv : mdfsMap) { //cout<<it.key()<<": "<<it.data()<<endl; - Argument *arg = findArgument(scope, it.key()); + Argument *arg = findArgument(scope, kv.first); if (arg) { - applyModifiers(arg, it.data()); + applyModifiers(arg, kv.second); } } // find return type for function //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)) + QCString returnName = yyextra->modifiers[yyextra->current_root][scope->name.lower().str()].returnName.lower(); + if (yyextra->modifiers[scope].find(returnName.str())!=yyextra->modifiers[scope].end()) { - scope->type = yyextra->modifiers[scope][returnName].type; // returning type works - applyModifiers(scope, yyextra->modifiers[scope][returnName]); // returning array works + scope->type = yyextra->modifiers[scope][returnName.str()].type; // returning type works + applyModifiers(scope, yyextra->modifiers[scope][returnName.str()]); // returning array works } - } + } if (scope->section == Entry::CLASS_SEC) { // was INTERFACE_SEC if (scope->parent()->section == Entry::FUNCTION_SEC) @@ -2291,7 +2250,7 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) if ((count == 1) && found) { // clear all yyextra->modifiers of the scope - yyextra->modifiers.remove(scope); + yyextra->modifiers.erase(scope); scope->parent()->removeSubEntry(scope); scope = 0; return TRUE; @@ -2307,13 +2266,13 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) continue; //cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<<mdfsMap.count()<<endl; - if (mdfsMap.contains(ce->name.lower())) - applyModifiers(ce.get(), mdfsMap[ce->name.lower()]); + if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end()) + applyModifiers(ce.get(), mdfsMap[ce->name.lower().str()]); } } // clear all yyextra->modifiers of the scope - yyextra->modifiers.remove(scope); + yyextra->modifiers.erase(scope); return TRUE; } @@ -2564,7 +2523,7 @@ static void subrHandleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool b loc_doc.stripWhiteSpace(); // direction as defined with the declaration of the parameter - int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower()].direction; + int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction; // in description [in] is specified if (loc_doc.lower().find(directionParam[SymbolModifiers::IN]) == 0) { @@ -2687,6 +2646,9 @@ static void parseMain(yyscan_t yyscanner, const char *fileName,const char *fileB char *tmpBuf = NULL; initParser(yyscanner); + + if (fileBuf==0 || fileBuf[0]=='\0') return; + yyextra->defaultProtection = Public; yyextra->inputString = fileBuf; yyextra->inputPosition = 0; diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index 6fc14bf..c8edeb2 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -167,7 +167,7 @@ void FTVHelp::finalize() */ void FTVHelp::incContentsDepth() { - //printf("incContentsDepth() indent=%d\n",m_indent); + //printf("%p: incContentsDepth() indent=%d\n",this,m_indent); m_indent++; ASSERT(m_indent<MAX_INDENT); } @@ -178,7 +178,7 @@ void FTVHelp::incContentsDepth() */ void FTVHelp::decContentsDepth() { - //printf("decContentsDepth() indent=%d\n",m_indent); + //printf("%p: decContentsDepth() indent=%d\n",this,m_indent); ASSERT(m_indent>0); if (m_indent>0) { @@ -249,7 +249,7 @@ static QCString node2URL(const FTVNode *n,bool overruleFile=FALSE,bool srcLink=F { if (overruleFile && n->def && n->def->definitionType()==Definition::TypeFile) { - const FileDef *fd = dynamic_cast<const FileDef*>(n->def); + const FileDef *fd = toFileDef(n->def); if (srcLink) { url = fd->getSourceFileBase(); @@ -419,7 +419,7 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in } else if (n->def && n->def->definitionType()==Definition::TypeClass) { - char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def)); + char icon=compoundIcon(toClassDef(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } else @@ -444,9 +444,9 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in { const FileDef *srcRef=0; if (n->def && n->def->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(n->def))->generateSourceFile()) + (toFileDef(n->def))->generateSourceFile()) { - srcRef = dynamic_cast<const FileDef*>(n->def); + srcRef = toFileDef(n->def); } if (srcRef) { @@ -475,7 +475,7 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in } else if (n->def && n->def->definitionType()==Definition::TypeClass) { - char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def)); + char icon=compoundIcon(toClassDef(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } else if (n->def && n->def->definitionType()==Definition::TypeDir) @@ -591,7 +591,7 @@ static bool generateJSTree(NavIndexEntryList &navIndex,FTextStream &t, { if (n->def && n->def->definitionType()==Definition::TypeFile) { - const FileDef *fd = dynamic_cast<const FileDef*>(n->def); + const FileDef *fd = toFileDef(n->def); bool doc,src; doc = fileVisibleInIndex(fd,src); if (doc) diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 9b33356..e0d60bd 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -15,8 +15,12 @@ * */ +#include <algorithm> +#include <vector> + #include <ctype.h> #include <qregexp.h> + #include "groupdef.h" #include "classdef.h" #include "filedef.h" @@ -45,7 +49,7 @@ //--------------------------------------------------------------------------- -class GroupDefImpl : public DefinitionImpl, public GroupDef +class GroupDefImpl : public DefinitionMixin<GroupDef> { public: GroupDefImpl(const char *fileName,int line,const char *name,const char *title,const char *refFileName=0); @@ -54,7 +58,7 @@ 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() ? m_title : DefinitionImpl::name(); } + virtual QCString displayName(bool=TRUE) const { return hasGroupTitle() ? m_title : DefinitionMixin::name(); } virtual const char *groupTitle() const { return m_title; } virtual void setGroupTitle( const char *newtitle ); virtual bool hasGroupTitle( ) const { return m_titleSet; } @@ -72,7 +76,7 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef virtual void writeMemberPages(OutputList &ol); virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; virtual void writeTagFile(FTextStream &); - virtual int numDocMembers() const; + virtual size_t numDocMembers() const; virtual bool isLinkableInProject() const; virtual bool isLinkable() const; virtual bool isASubGroup() const; @@ -97,8 +101,8 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef 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 ClassLinkedRefMap getClasses() const { return m_classes; } + virtual NamespaceLinkedRefMap getNamespaces() const { return m_namespaces; } virtual GroupList * getSubGroups() const { return m_groupList; } virtual PageSDict * getPages() const { return m_pageDict; } virtual const DirList & getDirs() const { return m_dirList; } @@ -136,8 +140,8 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef 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 + ClassLinkedRefMap m_classes; // list of classes in the group + NamespaceLinkedRefMap m_namespaces; // 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 @@ -161,12 +165,10 @@ 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) + const char *refFileName) : DefinitionMixin(df,dl,1,na) { 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) @@ -191,9 +193,7 @@ GroupDefImpl::GroupDefImpl(const char *df,int dl,const char *na,const char *t, GroupDefImpl::~GroupDefImpl() { delete m_fileList; - delete m_classSDict; delete m_groupList; - delete m_namespaceSDict; delete m_pageDict; delete m_exampleDict; delete m_allMemberList; @@ -228,6 +228,7 @@ void GroupDefImpl::distributeMemberGroupDocumentation() void GroupDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; @@ -260,47 +261,12 @@ void GroupDefImpl::addFile(const FileDef *def) bool GroupDefImpl::addClass(const ClassDef *cd) { - static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS); if (cd->isHidden()) return FALSE; updateLanguage(cd); QCString qn = cd->name(); - if (m_classSDict->find(qn)==0) + if (m_classes.find(qn)==0) { - //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs); - if (sortBriefDocs) - { - m_classSDict->inSort(qn,cd); - } - else - { - int i=qn.findRev("::"); - if (i==-1) i=qn.find('.'); - bool found=FALSE; - //printf("i=%d\n",i); - if (i>0) - { - // add nested classes (e.g. A::B, A::C) after their parent (A) in - // order of insertion - QCString scope = qn.left(i); - int j=m_classSDict->findAt(scope); - if (j!=-1) - { - 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); - m_classSDict->insertAt(j,qn,cd); - found=TRUE; - } - } - if (!found) // no insertion point found -> just append - { - m_classSDict->append(qn,cd); - } - } + m_classes.add(qn,cd); return TRUE; } return FALSE; @@ -308,18 +274,14 @@ bool GroupDefImpl::addClass(const ClassDef *cd) bool GroupDefImpl::addNamespace(const NamespaceDef *def) { - static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS); - if (def->isHidden()) return FALSE; - updateLanguage(def); - if (m_namespaceSDict->find(def->name())==0) + if (def->isHidden()) return false; + if (m_namespaces.find(def->name())!=0) { - if (sortBriefDocs) - m_namespaceSDict->inSort(def->name(),def); - else - m_namespaceSDict->append(def->name(),def); - return TRUE; + updateLanguage(def); + m_namespaces.add(def->name(),def); + return true; } - return FALSE; + return false; } void GroupDefImpl::addDir(DirDef *def) @@ -395,13 +357,14 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) sameScope // both are found in the same scope ) { - if (srcMd->getGroupAlias()==0) + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm && srcMd->getGroupAlias()==0) { - md->setGroupAlias(srcMd); + mdm->setGroupAlias(srcMd); } - else if (md!=srcMd->getGroupAlias()) + else if (mdm && md!=srcMd->getGroupAlias()) { - md->setGroupAlias(srcMd->getGroupAlias()); + mdm->setGroupAlias(srcMd->getGroupAlias()); } return FALSE; // member is the same as one that is already added } @@ -648,11 +611,11 @@ void GroupDefImpl::countMembers() } } -int GroupDefImpl::numDocMembers() const +size_t GroupDefImpl::numDocMembers() const { return m_fileList->count()+ - m_classSDict->count()+ - m_namespaceSDict->count()+ + m_classes.size()+ + m_namespaces.size()+ m_groupList->count()+ m_allMemberList->count()+ m_pageDict->count()+ @@ -663,7 +626,7 @@ int GroupDefImpl::numDocMembers() const void GroupDefImpl::computeAnchors() { //printf("GroupDefImpl::computeAnchors()\n"); - setAnchors(m_allMemberList); + m_allMemberList->setAnchors(); } void GroupDefImpl::writeTagFile(FTextStream &tagFile) @@ -681,34 +644,24 @@ void GroupDefImpl::writeTagFile(FTextStream &tagFile) { case LayoutDocEntry::GroupClasses: { - if (m_classSDict) + for (const auto &cd : m_classes) { - SDict<ClassDef>::Iterator ci(*m_classSDict); - ClassDef *cd; - for (ci.toFirst();(cd=ci.current());++ci) + if (cd->isLinkableInProject()) { - if (cd->isLinkableInProject()) - { - tagFile << " <class kind=\"" << cd->compoundTypeString() - << "\">" << convertToXML(cd->name()) << "</class>" << endl; - } + tagFile << " <class kind=\"" << cd->compoundTypeString() + << "\">" << convertToXML(cd->name()) << "</class>" << endl; } } } break; case LayoutDocEntry::GroupNamespaces: { - if (m_namespaceSDict) + for (const auto &nd : m_namespaces) { - SDict<NamespaceDef>::Iterator ni(*m_namespaceSDict); - NamespaceDef *nd; - for (ni.toFirst();(nd=ni.current());++ni) + if (nd->isLinkableInProject()) { - if (nd->isLinkableInProject()) - { - tagFile << " <namespace>" << convertToXML(nd->name()) - << "</namespace>" << endl; - } + tagFile << " <namespace>" << convertToXML(nd->name()) + << "</namespace>" << endl; } } } @@ -811,7 +764,7 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title ) { ol.pushGeneratorState(); - if (m_pageDict->count()!=(uint)numDocMembers()) // not only pages -> classical layout + if (m_pageDict->count()!=numDocMembers()) // not only pages -> classical layout { ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); @@ -888,9 +841,7 @@ void GroupDefImpl::writeBriefDescription(OutputList &ol) ol.writeString(" \n"); ol.enable(OutputGenerator::RTF); - if (Config_getBool(REPEAT_BRIEF) || - !documentation().isEmpty() - ) + if (hasDetailedDescription()) { ol.disableAllBut(OutputGenerator::Html); ol.startTextLink(0,"details"); @@ -961,7 +912,7 @@ void GroupDefImpl::writeFiles(OutputList &ol,const QCString &title) void GroupDefImpl::writeNamespaces(OutputList &ol,const QCString &title) { // write list of namespaces - m_namespaceSDict->writeDeclaration(ol,title); + m_namespaces.writeDeclaration(ol,title); } void GroupDefImpl::writeNestedGroups(OutputList &ol,const QCString &title) @@ -1050,12 +1001,12 @@ void GroupDefImpl::writeDirs(OutputList &ol,const QCString &title) void GroupDefImpl::writeClasses(OutputList &ol,const QCString &title) { // write list of classes - m_classSDict->writeDeclaration(ol,0,title,FALSE); + m_classes.writeDeclaration(ol,0,title,FALSE); } void GroupDefImpl::writeInlineClasses(OutputList &ol) { - m_classSDict->writeDocumentation(ol); + m_classes.writeDocumentation(ol); } void GroupDefImpl::writePageDocumentation(OutputList &ol) @@ -1152,8 +1103,8 @@ void GroupDefImpl::writeSummaryLinks(OutputList &ol) const SrcLangExt lang = getLanguage(); for (eli.toFirst();(lde=eli.current());++eli) { - if ((lde->kind()==LayoutDocEntry::GroupClasses && m_classSDict->declVisible()) || - (lde->kind()==LayoutDocEntry::GroupNamespaces && m_namespaceSDict->declVisible()) || + if ((lde->kind()==LayoutDocEntry::GroupClasses && m_classes.declVisible()) || + (lde->kind()==LayoutDocEntry::GroupNamespaces && m_namespaces.declVisible()) || (lde->kind()==LayoutDocEntry::GroupFiles && m_fileList->count()>0) || (lde->kind()==LayoutDocEntry::GroupNestedGroups && m_groupList->count()>0) || (lde->kind()==LayoutDocEntry::GroupDirs && !m_dirList.empty()) @@ -1399,25 +1350,25 @@ void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *current { if (md->getGroupDef()==this && md->isLinkable() && !md->isEnumValue()) { - ol.writeString(" <tr><td class=\"navtab\">"); if (md->isLinkableInProject()) { if (md==currentMd) // selected item => highlight { - ol.writeString("<a class=\"qindexHL\" "); + ol.writeString(" <tr><td class=\"navtabHL\">"); } else { - ol.writeString("<a class=\"qindex\" "); + ol.writeString(" <tr><td class=\"navtab\">"); } + ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); + ol.writeString("</td></tr>\n"); } - ol.writeString("</td></tr>\n"); } } @@ -1436,9 +1387,10 @@ void addClassToGroups(const Entry *root,ClassDef *cd) GroupDef *gd=0; if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) { - if (gd->addClass(cd)) + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm && gd->addClass(cdm)) { - cd->makePartOfGroup(gd); + cdm->makePartOfGroup(gd); } //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle()); } @@ -1454,7 +1406,14 @@ void addNamespaceToGroups(const Entry *root,NamespaceDef *nd) //printf("group '%s'\n",s->data()); if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) { - if (gd->addNamespace(nd)) nd->makePartOfGroup(gd); + if (gd->addNamespace(nd)) + { + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->makePartOfGroup(gd); + } + } //printf("Namespace %s: in group %s\n",nd->name().data(),s->data()); } } @@ -1594,13 +1553,16 @@ void addMemberToGroups(const Entry *root,MemberDef *md) bool success = fgd->insertMember(md); if (success) { - //printf("insertMember successful\n"); - md->setGroupDef(fgd,pri,root->fileName,root->startLine, - !root->doc.isEmpty()); - ClassDef *cd = md->getClassDefOfAnonymousType(); - if (cd) + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + //printf("insertMember successful\n"); + mdm->setGroupDef(fgd,pri,root->fileName,root->startLine,!root->doc.isEmpty()); + } + ClassDefMutable *cdm = toClassDefMutable(mdm->getClassDefOfAnonymousType()); + if (cdm) { - cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0); + cdm->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0); } } } @@ -1686,6 +1648,67 @@ void GroupDefImpl::addMemberToList(MemberListType lt,MemberDef *md) ml->append(md); } +// performs a partial reordering to group elements together with the same scope +template<class Vec> +static void groupClassesWithSameScope(Vec &vec) +{ + bool done=false; + while (!done) // for each iteration + { + done=true; + for (size_t i=0; i<vec.size(); i++) // go through all items + { + std::string qni = vec[i]->name().str(); + size_t posi = qni.rfind("::"); + if (posi!=std::string::npos) + { + std::string scope = qni.substr(0,posi); + auto it = std::find_if( vec.begin(), vec.end(), + [&](typename Vec::Ptr &cd) + { return cd->name().str()==scope; }); + if (it!=vec.end()) + { + size_t idx = std::distance(vec.begin(),it); + if (i<idx) // parent scope located after child scope + { + // to avoid reordering elements with the same parent + // we skip to the last one with the same scope + size_t k = idx; + while (k<vec.size() && vec[k]->name().str().substr(0,posi)==scope) + { + idx = k; + k++; + } + idx = std::distance(vec.begin(),it); + // swap the items such that i is inserted after idx + for (size_t j=i; j<idx; j++) + { + std::swap(vec[j],vec[j+1]); + } + done=false; + } + else if (idx<i && vec[i-1]->name().str().substr(0,posi)!=scope) + { + // parent scope is found before the item, and the item + // has some other item with a different scope in front of it + // move idx to the end of range with the same scope + while (idx<i && vec[idx]->name().str().substr(0,posi)==scope) + { + idx++; + } + // swap the items such that i is just after idx + for (size_t j=idx; j<i; j++) + { + std::swap(vec[j],vec[j+1]); + } + done=false; + } + } + } + } + } +} + void GroupDefImpl::sortMemberLists() { QListIterator<MemberList> mli(m_memberLists); @@ -1697,6 +1720,26 @@ void GroupDefImpl::sortMemberLists() if (Config_getBool(SORT_BRIEF_DOCS)) { std::sort(m_dirList.begin(), m_dirList.end(), compareDirDefs); + + auto classComp = [](const ClassLinkedRefMap::Ptr &c1,const ClassLinkedRefMap::Ptr &c2) + { + return Config_getBool(SORT_BY_SCOPE_NAME) ? + qstricmp(c1->name(), c2->name())<0 : + qstricmp(c1->className(), c2->className())<0; + }; + std::sort(m_classes.begin(), m_classes.end(), classComp); + + auto namespaceComp = [](const NamespaceLinkedRefMap::Ptr &n1,const NamespaceLinkedRefMap::Ptr &n2) + { + return qstricmp(n1->name(),n2->name())<0; + }; + + std::sort(m_namespaces.begin(),m_namespaces.end(),namespaceComp); + } + else + { + groupClassesWithSameScope(m_classes); + groupClassesWithSameScope(m_namespaces); } } @@ -1770,7 +1813,36 @@ void GroupDefImpl::updateLanguage(const Definition *d) bool GroupDefImpl::hasDetailedDescription() const { static bool repeatBrief = Config_getBool(REPEAT_BRIEF); - return ((!briefDescription().isEmpty() && repeatBrief) || - !documentation().isEmpty()); + return ((!briefDescription().isEmpty() && repeatBrief) || !documentation().isEmpty() || !inbodyDocumentation().isEmpty()) && + (m_pageDict->count()!=numDocMembers()); +} + +// --- Cast functions + +GroupDef *toGroupDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(GroupDefImpl)) + { + return static_cast<GroupDef*>(d); + } + else + { + return 0; + } +} + +const GroupDef *toGroupDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(GroupDefImpl)) + { + return static_cast<const GroupDef*>(d); + } + else + { + return 0; + } } + diff --git a/src/groupdef.h b/src/groupdef.h index 82fa004..0b682c2 100644 --- a/src/groupdef.h +++ b/src/groupdef.h @@ -23,10 +23,12 @@ #include "sortdict.h" #include "definition.h" #include "dirdef.h" +#include "layout.h" class MemberList; class FileList; -class ClassSDict; +class ClassLinkedRefMap; +class NamespaceLinkedRefMap; class FileDef; class ClassDef; class NamespaceDef; @@ -43,7 +45,7 @@ class MemberDef; class FTextStream; /** A model of a group of symbols. */ -class GroupDef : virtual public Definition +class GroupDef : public DefinitionMutable, public Definition { public: ~GroupDef() {} @@ -69,7 +71,7 @@ class GroupDef : virtual public Definition virtual void writeMemberPages(OutputList &ol) = 0; virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; virtual void writeTagFile(FTextStream &) = 0; - virtual int numDocMembers() const = 0; + virtual size_t numDocMembers() const = 0; virtual bool isLinkableInProject() const = 0; virtual bool isLinkable() const = 0; virtual bool isASubGroup() const = 0; @@ -94,8 +96,8 @@ class GroupDef : virtual public Definition virtual MemberGroupSDict *getMemberGroupSDict() const = 0; virtual FileList * getFiles() const = 0; - virtual ClassSDict * getClasses() const = 0; - virtual NamespaceSDict * getNamespaces() const = 0; + virtual ClassLinkedRefMap getClasses() const = 0; + virtual NamespaceLinkedRefMap getNamespaces() const = 0; virtual GroupList * getSubGroups() const = 0; virtual PageSDict * getPages() const = 0; virtual const DirList & getDirs() const = 0; @@ -108,6 +110,14 @@ class GroupDef : virtual public Definition GroupDef *createGroupDef(const char *fileName,int line,const char *name, const char *title,const char *refFileName=0); +// --- Cast functions + +GroupDef *toGroupDef(Definition *d); +const GroupDef *toGroupDef(const Definition *d); + +// ------------------ + + /** A sorted dictionary of GroupDef objects. */ class GroupSDict : public SDict<GroupDef> { diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index ea2dffb..b93a2c4 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.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. * @@ -53,7 +50,7 @@ enum contexts_t INTERDD, // 8 INTERTD // 9 }; -static const char *contexts[10] = +static const char *contexts[10] = { "", // 0 "startli", // 1 "startdd", // 2 @@ -65,10 +62,10 @@ static const char *contexts[10] = "interdd", // 8 "intertd" // 9 }; +static const char *hex="0123456789ABCDEF"; static QCString convertIndexWordToAnchor(const QCString &word) { - static char hex[] = "0123456789abcdef"; static int cnt = 0; QCString result="a"; QCString cntStr; @@ -281,8 +278,8 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl //------------------------------------------------------------------------- HtmlDocVisitor::HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const Definition *ctx) - : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), + const Definition *ctx) + : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_ctx(ctx) { if (ctx) m_langExt=ctx->getDefFileExtension(); @@ -341,7 +338,7 @@ void HtmlDocVisitor::visit(DocEmoji *s) const char *res = EmojiEntityMapper::instance()->unicode(s->index()); if (res) { - m_t << res; + m_t << "<span class=\"emoji\">"<<res<<"</span>"; } else { @@ -439,12 +436,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) if (s->enable()) m_t << "<sup" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sup>"; break; case DocStyleChange::Center: - if (s->enable()) + if (s->enable()) { forceEndParagraph(s); - m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; + m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; } - else + else { m_t << "</center>"; forceStartParagraph(s); @@ -468,12 +465,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) } break; case DocStyleChange::Div: - if (s->enable()) + if (s->enable()) { forceEndParagraph(s); - m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; + m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; } - else + else { m_t << "</div>"; forceStartParagraph(s); @@ -490,7 +487,7 @@ void HtmlDocVisitor::visit(DocStyleChange *s) static void visitPreCaption(FTextStream &t, DocVerbatim *s) { if (s->hasCaption()) - { + { t << "<div class=\"caption\">" << endl; } } @@ -523,11 +520,10 @@ void HtmlDocVisitor::visit(DocVerbatim *s) SrcLangExt langExt = getLanguageFromFileName(lang); switch(s->type()) { - case DocVerbatim::Code: + case DocVerbatim::Code: forceEndParagraph(s); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(lang).parseCode(m_ci, s->context(), s->text(), langExt, @@ -541,14 +537,14 @@ void HtmlDocVisitor::visit(DocVerbatim *s) TRUE, // show line numbers m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(s); break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: forceEndParagraph(s); - m_t << /*PREFRAG_START <<*/ "<pre class=\"fragment\">"; + m_t << "<pre class=\"fragment\">"; filter(s->text()); - m_t << "</pre>" /*<< PREFRAG_END*/; + m_t << "</pre>"; forceStartParagraph(s); break; case DocVerbatim::HtmlOnly: @@ -558,12 +554,12 @@ void HtmlDocVisitor::visit(DocVerbatim *s) if (s->isBlock()) forceStartParagraph(s); } break; - case DocVerbatim::ManOnly: - case DocVerbatim::LatexOnly: - case DocVerbatim::XmlOnly: + case DocVerbatim::ManOnly: + case DocVerbatim::LatexOnly: + case DocVerbatim::XmlOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - /* nothing */ + /* nothing */ break; case DocVerbatim::Dot: @@ -572,8 +568,8 @@ void HtmlDocVisitor::visit(DocVerbatim *s) QCString fileName(4096); forceEndParagraph(s); - fileName.sprintf("%s%d%s", - (Config_getString(HTML_OUTPUT)+"/inline_dotgraph_").data(), + fileName.sprintf("%s%d%s", + (Config_getString(HTML_OUTPUT)+"/inline_dotgraph_").data(), dotindex++, ".dot" ); @@ -606,8 +602,8 @@ void HtmlDocVisitor::visit(DocVerbatim *s) static int mscindex = 1; QCString baseName(4096); - baseName.sprintf("%s%d", - (Config_getString(HTML_OUTPUT)+"/inline_mscgraph_").data(), + baseName.sprintf("%s%d", + (Config_getString(HTML_OUTPUT)+"/inline_mscgraph_").data(), mscindex++ ); QFile file(baseName+".msc"); @@ -671,11 +667,10 @@ void HtmlDocVisitor::visit(DocInclude *inc) SrcLangExt langExt = getLanguageFromFileName(inc->extension()); switch(inc->type()) { - case DocInclude::Include: + case DocInclude::Include: forceEndParagraph(inc); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), inc->text(), langExt, @@ -687,24 +682,23 @@ void HtmlDocVisitor::visit(DocInclude *inc) TRUE, // inlineFragment 0, // memberDef FALSE, // show line numbers - m_ctx // search context + m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); break; case DocInclude::IncWithLines: - { + { forceEndParagraph(inc); - m_t << PREFRAG_START; + m_ci.startCodeFragment("DoxyCode"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), inc->text(), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, // fileDef, -1, // start line -1, // end line @@ -714,7 +708,7 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_ctx // search context ); delete fd; - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); } break; @@ -733,24 +727,23 @@ void HtmlDocVisitor::visit(DocInclude *inc) if (inc->isBlock()) forceStartParagraph(inc); } break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: forceEndParagraph(inc); - m_t << /*PREFRAG_START <<*/ "<pre class=\"fragment\">"; + m_t << "<pre class=\"fragment\">"; filter(inc->text()); - m_t << "</pre>" /*<< PREFRAG_END*/; + m_t << "</pre>"; forceStartParagraph(inc); break; case DocInclude::Snippet: { forceEndParagraph(inc); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), 0, -1, // startLine -1, // endLine @@ -759,23 +752,22 @@ void HtmlDocVisitor::visit(DocInclude *inc) FALSE, // show line number m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); } break; case DocInclude::SnipWithLines: { forceEndParagraph(inc); - m_t << PREFRAG_START; + m_ci.startCodeFragment("DoxyCode"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -785,12 +777,12 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_ctx // search context ); delete fd; - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); } 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; @@ -801,20 +793,20 @@ void HtmlDocVisitor::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()) { forceEndParagraph(op); - if (!m_hide) m_t << PREFRAG_START; + if (!m_hide) m_ci.startCodeFragment("DoxyCode"); pushEnabled(); m_hide=TRUE; } 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()) @@ -822,8 +814,7 @@ void HtmlDocVisitor::visit(DocIncOperator *op) QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode( + getCodeParser(locLangExt).parseCode( m_ci, op->context(), op->text(), @@ -843,10 +834,10 @@ void HtmlDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); - if (!m_hide) m_t << PREFRAG_END; + if (!m_hide) m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(op); } else @@ -859,7 +850,7 @@ void HtmlDocVisitor::visit(DocFormula *f) { if (m_hide) return; bool bDisplay = !f->isInline(); - if (bDisplay) + if (bDisplay) { forceEndParagraph(f); m_t << "<p class=\"formulaDsp\">" << endl; @@ -869,7 +860,7 @@ void HtmlDocVisitor::visit(DocFormula *f) { QCString text = f->text(); bool closeInline = FALSE; - if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && + if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && text.at(text.length()-1)=='$') { closeInline=TRUE; @@ -884,7 +875,7 @@ void HtmlDocVisitor::visit(DocFormula *f) } else { - m_t << "<img class=\"formula" + m_t << "<img class=\"formula" << (bDisplay ? "Dsp" : "Inl"); m_t << "\" alt=\""; filterQuotedCdataAttr(f->text()); @@ -919,7 +910,7 @@ void HtmlDocVisitor::visit(DocFormula *f) void HtmlDocVisitor::visit(DocIndexEntry *e) { QCString anchor = convertIndexWordToAnchor(e->entry()); - if (e->member()) + if (e->member()) { anchor.prepend(e->member()->anchor()+"_"); } @@ -941,7 +932,7 @@ void HtmlDocVisitor::visit(DocSimpleSectSep *) void HtmlDocVisitor::visit(DocCite *cite) { if (m_hide) return; - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { startLink(cite->ref(),cite->file(),cite->relPath(),cite->anchor()); } @@ -950,7 +941,7 @@ void HtmlDocVisitor::visit(DocCite *cite) m_t << "<b>["; } filter(cite->text()); - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { endLink(); } @@ -978,7 +969,7 @@ void HtmlDocVisitor::visitPre(DocAutoList *l) // 1. // a. // i. - // A. + // A. // 1. (repeat)... // m_t << "<ol type=\"" << types[l->depth() % NUM_HTML_LIST_TYPES] << "\""; @@ -1013,20 +1004,20 @@ void HtmlDocVisitor::visitPre(DocAutoListItem *) m_t << "<li>"; } -void HtmlDocVisitor::visitPost(DocAutoListItem *li) +void HtmlDocVisitor::visitPost(DocAutoListItem *li) { if (m_hide) return; m_t << "</li>"; if (!li->isPreformatted()) m_t << "\n"; } -template<class T> +template<class T> bool isFirstChildNode(T *parent, DocNode *node) { return parent->children().getFirst()==node; } -template<class T> +template<class T> bool isLastChildNode(T *parent, DocNode *node) { return parent->children().getLast()==node; @@ -1070,7 +1061,7 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) isLast=FALSE; if (p && p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_ParBlock: { // hierarchy: node N -> para -> parblock -> para @@ -1215,7 +1206,7 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) return t; } -void HtmlDocVisitor::visitPre(DocPara *p) +void HtmlDocVisitor::visitPre(DocPara *p) { if (m_hide) return; @@ -1223,9 +1214,9 @@ void HtmlDocVisitor::visitPre(DocPara *p) // p->parent() ? p->parent()->kind() : -1); bool needsTag = FALSE; - if (p && p->parent()) + if (p && p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_Section: case DocNode::Kind_Internal: @@ -1250,7 +1241,7 @@ void HtmlDocVisitor::visitPre(DocPara *p) } // if the first element of a paragraph is something that should be outside of - // the paragraph (<ul>,<dl>,<table>,..) then that will already started the + // the paragraph (<ul>,<dl>,<table>,..) then that will already started the // paragraph and we don't need to do it here bool paragraphAlreadyStarted = false; uint nodeIndex = 0; @@ -1296,9 +1287,9 @@ void HtmlDocVisitor::visitPost(DocPara *p) // p->parent() ? p->parent()->kind() : -1); bool needsTag = FALSE; - if (p->parent()) + if (p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_Section: case DocNode::Kind_Internal: @@ -1323,7 +1314,7 @@ void HtmlDocVisitor::visitPost(DocPara *p) } // if the last element of a paragraph is something that should be outside of - // the paragraph (<ul>,<dl>,<table>) then that will already have ended the + // the paragraph (<ul>,<dl>,<table>) then that will already have ended the // paragraph and we don't need to do it here int nodeIndex = p->children().count()-1; if (nodeIndex>=0) @@ -1372,21 +1363,21 @@ void HtmlDocVisitor::visitPre(DocSimpleSect *s) m_t << "<dl class=\"section " << s->typeString() << "\"><dt>"; 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; @@ -1454,7 +1445,7 @@ void HtmlDocVisitor::visitPre(DocSimpleListItem *) m_t << "<li>"; } -void HtmlDocVisitor::visitPost(DocSimpleListItem *li) +void HtmlDocVisitor::visitPost(DocSimpleListItem *li) { if (m_hide) return; m_t << "</li>"; @@ -1472,7 +1463,7 @@ void HtmlDocVisitor::visitPre(DocSection *s) m_t << "</h" << s->level() << ">\n"; } -void HtmlDocVisitor::visitPost(DocSection *s) +void HtmlDocVisitor::visitPost(DocSection *s) { forceStartParagraph(s); } @@ -1481,26 +1472,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; forceEndParagraph(s); - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) { - m_t << "<ol" << htmlAttribsToString(s->attribs()); + m_t << "<ol" << htmlAttribsToString(s->attribs()); } - else + else { m_t << "<ul" << htmlAttribsToString(s->attribs()); } m_t << getDirHtmlClassOfNode(getTextDirByConfig(s)) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlList *s) +void HtmlDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) { - m_t << "</ol>"; + m_t << "</ol>"; } else - { + { m_t << "</ul>"; } if (!s->isPreformatted()) m_t << "\n"; @@ -1514,7 +1505,7 @@ void HtmlDocVisitor::visitPre(DocHtmlListItem *i) if (!i->isPreformatted()) m_t << "\n"; } -void HtmlDocVisitor::visitPost(DocHtmlListItem *) +void HtmlDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << "</li>\n"; @@ -1527,7 +1518,7 @@ void HtmlDocVisitor::visitPre(DocHtmlDescList *dl) m_t << "<dl" << htmlAttribsToString(dl->attribs()) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) +void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) { if (m_hide) return; m_t << "</dl>\n"; @@ -1542,7 +1533,7 @@ void HtmlDocVisitor::visitPre(DocHtmlDescTitle *dt) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) +void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "</dt>\n"; @@ -1551,12 +1542,12 @@ void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) void HtmlDocVisitor::visitPre(DocHtmlDescData *dd) { if (m_hide) return; - m_t << "<dd" << htmlAttribsToString(dd->attribs()) + m_t << "<dd" << htmlAttribsToString(dd->attribs()) << getDirHtmlClassOfNode(getTextDirByConfig(dd)) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlDescData *) +void HtmlDocVisitor::visitPost(DocHtmlDescData *) { if (m_hide) return; m_t << "</dd>\n"; @@ -1598,7 +1589,7 @@ void HtmlDocVisitor::visitPre(DocHtmlTable *t) } } -void HtmlDocVisitor::visitPost(DocHtmlTable *t) +void HtmlDocVisitor::visitPost(DocHtmlTable *t) { if (m_hide) return; m_t << "</table>\n"; @@ -1611,7 +1602,7 @@ void HtmlDocVisitor::visitPre(DocHtmlRow *tr) m_t << "<tr" << htmlAttribsToString(tr->attribs()) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlRow *) +void HtmlDocVisitor::visitPost(DocHtmlRow *) { if (m_hide) return; m_t << "</tr>\n"; @@ -1620,17 +1611,17 @@ void HtmlDocVisitor::visitPost(DocHtmlRow *) void HtmlDocVisitor::visitPre(DocHtmlCell *c) { if (m_hide) return; - if (c->isHeading()) + if (c->isHeading()) { - m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; + m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; } - else + else { m_t << "<td" << htmlAttribsToString(c->attribs()) << ">"; } } -void HtmlDocVisitor::visitPost(DocHtmlCell *c) +void HtmlDocVisitor::visitPost(DocHtmlCell *c) { if (m_hide) return; if (c->isHeading()) m_t << "</th>"; else m_t << "</td>"; @@ -1642,7 +1633,7 @@ void HtmlDocVisitor::visitPre(DocHtmlCaption *c) m_t << "<caption" << htmlAttribsToString(c->attribs()) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlCaption *) +void HtmlDocVisitor::visitPost(DocHtmlCaption *) { if (m_hide) return; m_t << "</caption>\n"; @@ -1655,7 +1646,7 @@ void HtmlDocVisitor::visitPre(DocInternal *) //m_t << "<p><b>" << theTranslator->trForInternalUseOnly() << "</b></p>" << endl; } -void HtmlDocVisitor::visitPost(DocInternal *) +void HtmlDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //forceStartParagraph(i); @@ -1676,7 +1667,7 @@ void HtmlDocVisitor::visitPre(DocHRef *href) } } -void HtmlDocVisitor::visitPost(DocHRef *) +void HtmlDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "</a>"; @@ -1686,13 +1677,13 @@ void HtmlDocVisitor::visitPre(DocHtmlHeader *header) { if (m_hide) return; forceEndParagraph(header); - m_t << "<h" << header->level() - << htmlAttribsToString(header->attribs()) + m_t << "<h" << header->level() + << htmlAttribsToString(header->attribs()) << getDirHtmlClassOfNode(getTextDirByConfig(header)) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlHeader *header) +void HtmlDocVisitor::visitPost(DocHtmlHeader *header) { if (m_hide) return; m_t << "</h" << header->level() << ">\n"; @@ -1834,12 +1825,12 @@ void HtmlDocVisitor::visitPre(DocDotFile *df) m_t << "<div class=\"dotgraph\">" << endl; writeDotFile(df->file(),df->relPath(),df->context()); if (df->hasCaption()) - { + { m_t << "<div class=\"caption\">" << endl; } } -void HtmlDocVisitor::visitPost(DocDotFile *df) +void HtmlDocVisitor::visitPost(DocDotFile *df) { if (m_hide) return; if (df->hasCaption()) @@ -1855,11 +1846,11 @@ void HtmlDocVisitor::visitPre(DocMscFile *df) m_t << "<div class=\"mscgraph\">" << endl; writeMscFile(df->file(),df->relPath(),df->context()); if (df->hasCaption()) - { + { m_t << "<div class=\"caption\">" << endl; } } -void HtmlDocVisitor::visitPost(DocMscFile *df) +void HtmlDocVisitor::visitPost(DocMscFile *df) { if (m_hide) return; if (df->hasCaption()) @@ -1895,7 +1886,7 @@ void HtmlDocVisitor::visitPre(DocLink *lnk) startLink(lnk->ref(),lnk->file(),lnk->relPath(),lnk->anchor()); } -void HtmlDocVisitor::visitPost(DocLink *) +void HtmlDocVisitor::visitPost(DocLink *) { if (m_hide) return; endLink(); @@ -1904,7 +1895,7 @@ void HtmlDocVisitor::visitPost(DocLink *) void HtmlDocVisitor::visitPre(DocRef *ref) { if (m_hide) return; - if (!ref->file().isEmpty()) + if (!ref->file().isEmpty()) { // when ref->isSubPage()==TRUE we use ref->file() for HTML and // ref->anchor() for LaTeX/RTF @@ -1913,7 +1904,7 @@ void HtmlDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void HtmlDocVisitor::visitPost(DocRef *ref) +void HtmlDocVisitor::visitPost(DocRef *ref) { if (m_hide) return; if (!ref->file().isEmpty()) endLink(); @@ -1928,7 +1919,7 @@ void HtmlDocVisitor::visitPre(DocSecRefItem *ref) } -void HtmlDocVisitor::visitPost(DocSecRefItem *) +void HtmlDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << "</a></li>\n"; @@ -1942,7 +1933,7 @@ void HtmlDocVisitor::visitPre(DocSecRefList *s) m_t << "<ul class=\"multicol\">" << endl; } -void HtmlDocVisitor::visitPost(DocSecRefList *s) +void HtmlDocVisitor::visitPost(DocSecRefList *s) { if (m_hide) return; m_t << "</ul>" << endl; @@ -1960,7 +1951,7 @@ void HtmlDocVisitor::visitPost(DocSecRefList *s) // } //} // -//void HtmlDocVisitor::visitPost(DocLanguage *l) +//void HtmlDocVisitor::visitPost(DocLanguage *l) //{ // QCString langId = Config_getEnum(OUTPUT_LANGUAGE); // if (l->id().lower()!=langId.lower()) @@ -1977,19 +1968,19 @@ void HtmlDocVisitor::visitPre(DocParamSect *s) QCString heading; switch(s->type()) { - case DocParamSect::Param: - heading=theTranslator->trParameters(); + case DocParamSect::Param: + heading=theTranslator->trParameters(); className="params"; break; - case DocParamSect::RetVal: - heading=theTranslator->trReturnValues(); + case DocParamSect::RetVal: + heading=theTranslator->trReturnValues(); className="retval"; break; - case DocParamSect::Exception: - heading=theTranslator->trExceptions(); + case DocParamSect::Exception: + heading=theTranslator->trExceptions(); className="exception"; break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: heading=theTranslator->trTemplateParameters(); className="tparams"; break; @@ -2052,11 +2043,11 @@ void HtmlDocVisitor::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) { @@ -2076,11 +2067,11 @@ void HtmlDocVisitor::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 << "</td><td>"; @@ -2102,12 +2093,12 @@ void HtmlDocVisitor::visitPre(DocXRefItem *x) bool anonymousEnum = x->file()=="@"; if (!anonymousEnum) { - m_t << "<dl" << getDirHtmlClassOfNode(getTextDirByConfig(x), x->key()) + m_t << "<dl" << getDirHtmlClassOfNode(getTextDirByConfig(x), x->key()) << "><dt><b><a class=\"el\" href=\"" << x->relPath() << addHtmlExtensionIfMissing(x->file()) << "#" << x->anchor() << "\">"; } - else + else { m_t << "<dl class=\"" << x->key() << "\"><dt><b>"; } @@ -2131,7 +2122,7 @@ void HtmlDocVisitor::visitPre(DocInternalRef *ref) startLink(0,ref->file(),ref->relPath(),ref->anchor()); } -void HtmlDocVisitor::visitPost(DocInternalRef *) +void HtmlDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; endLink(); @@ -2180,7 +2171,7 @@ void HtmlDocVisitor::visitPre(DocVhdlFlow *vf) m_t << "<p>"; m_t << "flowchart: " ; // TODO: translate me m_t << "<a href=\""; - m_t << fname.data(); + m_t << fname.data(); m_t << ".svg\">"; m_t << VhdlDocGen::getFlowMember()->name().data(); m_t << "</a>"; @@ -2214,7 +2205,7 @@ void HtmlDocVisitor::visitPost(DocParBlock *) void HtmlDocVisitor::filter(const char *str) -{ +{ if (str==0) return; const char *p=str; char c; @@ -2227,11 +2218,23 @@ void HtmlDocVisitor::filter(const char *str) case '>': m_t << ">"; break; case '&': m_t << "&"; break; case '\\': if ((*p == '(') || (*p == ')')) - m_t << "\\‍" << *p++; - else - m_t << c; - break; - default: m_t << c; + m_t << "\\‍" << *p++; + else + m_t << c; + break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) // non-printable control characters + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_t << c; + } + } + break; } } } @@ -2253,11 +2256,23 @@ void HtmlDocVisitor::filterQuotedCdataAttr(const char* str) case '<': m_t << "<"; break; case '>': m_t << ">"; break; case '\\': if ((*p == '(') || (*p == ')')) - m_t << "\\‍" << *p++; - else - m_t << c; - break; - default: m_t << c; + m_t << "\\‍" << *p++; + else + m_t << c; + break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) // non-printable control characters + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_t << c; + } + } + break; } } } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 7b125af..cd615e4 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -16,8 +16,10 @@ */ #include <stdlib.h> - #include <assert.h> + +#include <mutex> + #include <qdir.h> #include <qregexp.h> #include "message.h" @@ -58,8 +60,7 @@ static QCString g_header; static QCString g_footer; static QCString g_mathjax_code; static QCString g_latex_macro; - -static bool DoxyCodeLineOpen = FALSE; +static const char *hex="0123456789ABCDEF"; // note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this // part will be rendered inside menu.js @@ -87,7 +88,7 @@ static void writeClientSearchBox(FTextStream &t,const char *relPath) // part will be rendered inside menu.js static void writeServerSearchBox(FTextStream &t,const char *relPath,bool highlightSearch) { - static bool externalSearch = Config_getBool(EXTERNAL_SEARCH); + bool externalSearch = Config_getBool(EXTERNAL_SEARCH); t << " <div id=\"MSearchBox\" class=\"MSearchBoxInactive\">\n"; t << " <div class=\"left\">\n"; t << " <form id=\"FSearchBox\" action=\"" << relPath; @@ -422,18 +423,18 @@ static QCString substituteHtmlKeywords(const QCString &str, QCString mathJaxJs; QCString extraCssText; - static QCString projectName = Config_getString(PROJECT_NAME); - static bool timeStamp = Config_getBool(HTML_TIMESTAMP); - static bool treeView = Config_getBool(GENERATE_TREEVIEW); - static bool searchEngine = Config_getBool(SEARCHENGINE); - static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); - static bool mathJax = Config_getBool(USE_MATHJAX); - static QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT); - static bool disableIndex = Config_getBool(DISABLE_INDEX); - static bool hasProjectName = !projectName.isEmpty(); - static bool hasProjectNumber = !Config_getString(PROJECT_NUMBER).isEmpty(); - static bool hasProjectBrief = !Config_getString(PROJECT_BRIEF).isEmpty(); - static bool hasProjectLogo = !Config_getString(PROJECT_LOGO).isEmpty(); + QCString projectName = Config_getString(PROJECT_NAME); + bool timeStamp = Config_getBool(HTML_TIMESTAMP); + bool treeView = Config_getBool(GENERATE_TREEVIEW); + bool searchEngine = Config_getBool(SEARCHENGINE); + bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); + bool mathJax = Config_getBool(USE_MATHJAX); + QCString mathJaxFormat = Config_getEnum(MATHJAX_FORMAT); + bool disableIndex = Config_getBool(DISABLE_INDEX); + bool hasProjectName = !projectName.isEmpty(); + bool hasProjectNumber = !Config_getString(PROJECT_NUMBER).isEmpty(); + bool hasProjectBrief = !Config_getString(PROJECT_BRIEF).isEmpty(); + bool hasProjectLogo = !Config_getString(PROJECT_LOGO).isEmpty(); static bool titleArea = (hasProjectName || hasProjectBrief || hasProjectLogo || (disableIndex && searchEngine)); cssFile = Config_getString(HTML_STYLESHEET); @@ -608,12 +609,11 @@ static QCString substituteHtmlKeywords(const QCString &str, //-------------------------------------------------------------------------- HtmlCodeGenerator::HtmlCodeGenerator() - : m_streamSet(FALSE), m_col(0) { } HtmlCodeGenerator::HtmlCodeGenerator(FTextStream &t,const QCString &relPath) - : m_col(0), m_relPath(relPath) + : m_relPath(relPath) { setTextStream(t); } @@ -631,7 +631,7 @@ void HtmlCodeGenerator::setRelativePath(const QCString &path) void HtmlCodeGenerator::codify(const char *str) { - static int tabSize = Config_getInt(TAB_SIZE); + int tabSize = Config_getInt(TAB_SIZE); if (str && m_streamSet) { const char *p=str; @@ -673,9 +673,21 @@ void HtmlCodeGenerator::codify(const char *str) m_t << "\\"; m_col++; break; - default: p=writeUtf8Char(m_t,p-1); - m_col++; - break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32) + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + m_col++; + } + else + { + p=writeUtf8Char(m_t,p-1); + m_col++; + } + } + break; } } } @@ -699,18 +711,30 @@ void HtmlCodeGenerator::docify(const char *str) case '&': m_t << "&"; break; case '"': m_t << """; break; case '\\': - if (*p=='<') - { 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; - default: m_t << c; + if (*p=='<') + { 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; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_t << c; + } + } + break; } } } @@ -726,10 +750,10 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename, qsnprintf(lineNumber,maxLineNrStr,"%5d",l); qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l); - if (!DoxyCodeLineOpen) + if (!m_lineOpen) { m_t << "<div class=\"line\">"; - DoxyCodeLineOpen = TRUE; + m_lineOpen = TRUE; } m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">"; @@ -868,10 +892,10 @@ void HtmlCodeGenerator::startCodeLine(bool) if (m_streamSet) { m_col=0; - if (!DoxyCodeLineOpen) + if (!m_lineOpen) { m_t << "<div class=\"line\">"; - DoxyCodeLineOpen = TRUE; + m_lineOpen = TRUE; } } } @@ -885,10 +909,10 @@ void HtmlCodeGenerator::endCodeLine() m_t << " "; m_col++; } - if (DoxyCodeLineOpen) + if (m_lineOpen) { m_t << "</div>\n"; - DoxyCodeLineOpen = FALSE; + m_lineOpen = FALSE; } } } @@ -908,13 +932,39 @@ void HtmlCodeGenerator::writeCodeAnchor(const char *anchor) if (m_streamSet) m_t << "<a name=\"" << anchor << "\"></a>"; } +void HtmlCodeGenerator::startCodeFragment(const char *) +{ + if (m_streamSet) m_t << "<div class=\"fragment\">"; +} + +void HtmlCodeGenerator::endCodeFragment(const char *) +{ + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + if (m_streamSet) m_t << "</div><!-- fragment -->"; +} + + //-------------------------------------------------------------------------- -HtmlGenerator::HtmlGenerator() : OutputGenerator() +HtmlGenerator::HtmlGenerator() : OutputGenerator(Config_getString(HTML_OUTPUT)) { - m_dir=Config_getString(HTML_OUTPUT); - m_emptySection=FALSE; - m_sectionCount=0; +} + +HtmlGenerator::HtmlGenerator(const HtmlGenerator &og) : OutputGenerator(og) +{ +} + +HtmlGenerator &HtmlGenerator::operator=(const HtmlGenerator &og) +{ + OutputGenerator::operator=(og); + return *this; +} + +std::unique_ptr<OutputGenerator> HtmlGenerator::clone() const +{ + return std::make_unique<HtmlGenerator>(*this); } HtmlGenerator::~HtmlGenerator() @@ -922,9 +972,10 @@ HtmlGenerator::~HtmlGenerator() //printf("HtmlGenerator::~HtmlGenerator()\n"); } + void HtmlGenerator::init() { - QCString dname=Config_getString(HTML_OUTPUT); + QCString dname = Config_getString(HTML_OUTPUT); QDir d(dname); if (!d.exists() && !d.mkdir(dname)) { @@ -1032,32 +1083,32 @@ void HtmlGenerator::writeTabData() mgr.copyResource("nav_g.png",dname); } -void HtmlGenerator::writeSearchData(const char *dir) +void HtmlGenerator::writeSearchData(const char *dname) { - static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); - //writeImgData(dir,serverBasedSearch ? search_server_data : search_client_data); + bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); + //writeImgData(dname,serverBasedSearch ? search_server_data : search_client_data); ResourceMgr &mgr = ResourceMgr::instance(); - mgr.copyResource("search_l.png",dir); + mgr.copyResource("search_l.png",dname); Doxygen::indexList->addImageFile("search/search_l.png"); - mgr.copyResource("search_m.png",dir); + mgr.copyResource("search_m.png",dname); Doxygen::indexList->addImageFile("search/search_m.png"); - mgr.copyResource("search_r.png",dir); + mgr.copyResource("search_r.png",dname); Doxygen::indexList->addImageFile("search/search_r.png"); if (serverBasedSearch) { - mgr.copyResource("mag.svg",dir); + mgr.copyResource("mag.svg",dname); Doxygen::indexList->addImageFile("search/mag.svg"); } else { - mgr.copyResource("close.svg",dir); + mgr.copyResource("close.svg",dname); Doxygen::indexList->addImageFile("search/close.svg"); - mgr.copyResource("mag_sel.svg",dir); + mgr.copyResource("mag_sel.svg",dname); Doxygen::indexList->addImageFile("search/mag_sel.svg"); } - QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search"; + QCString searchDirName = dname; QFile f(searchDirName+"/search.css"); if (f.open(IO_WriteOnly)) { @@ -1101,8 +1152,10 @@ void HtmlGenerator::writeFooterFile(QFile &file) t << ResourceMgr::instance().getAsString("footer.html"); } +static std::mutex g_indexLock; + void HtmlGenerator::startFile(const char *name,const char *, - const char *title) + const char *title,int id) { //printf("HtmlGenerator::startFile(%s)\n",name); m_relPath = relativePathToRoot(name); @@ -1110,23 +1163,27 @@ void HtmlGenerator::startFile(const char *name,const char *, m_lastTitle=title; startPlainFile(fileName); + m_codeGen.setId(id); m_codeGen.setTextStream(t); m_codeGen.setRelativePath(m_relPath); - Doxygen::indexList->addIndexFile(fileName); + { + std::lock_guard<std::mutex> lock(g_indexLock); + Doxygen::indexList->addIndexFile(fileName); + } m_lastFile = fileName; t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title)),m_relPath); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " << getDoxygenVersion() << " -->" << endl; - //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - static bool searchEngine = Config_getBool(SEARCHENGINE); + //bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + bool searchEngine = Config_getBool(SEARCHENGINE); if (searchEngine /*&& !generateTreeView*/) { 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\", \"" - << m_relPath<< "search\",false,'" << theTranslator->trSearch() << "');\n"; + << m_relPath<< "search\",false,'" << theTranslator->trSearch() << "','" << Doxygen::htmlFileExtension << "');\n"; t << "/* @license-end */\n"; t << "</script>\n"; } @@ -1136,8 +1193,8 @@ void HtmlGenerator::startFile(const char *name,const char *, void HtmlGenerator::writeSearchInfo(FTextStream &t,const QCString &) { - static bool searchEngine = Config_getBool(SEARCHENGINE); - static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); + bool searchEngine = Config_getBool(SEARCHENGINE); + bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); if (searchEngine && !serverBasedSearch) { t << "<!-- window showing the filter options -->\n"; @@ -1165,7 +1222,7 @@ void HtmlGenerator::writeSearchInfo() QCString HtmlGenerator::writeLogoAsString(const char *path) { - static bool timeStamp = Config_getBool(HTML_TIMESTAMP); + bool timeStamp = Config_getBool(HTML_TIMESTAMP); QCString result; if (timeStamp) { @@ -1178,7 +1235,7 @@ QCString HtmlGenerator::writeLogoAsString(const char *path) { result += theTranslator->trGeneratedBy(); } - result += " \n<a href=\"http://www.doxygen.org/index.html\">\n" + result += " \n<a href=\"https://www.doxygen.org/index.html\">\n" "<img class=\"footer\" src=\""; result += path; result += "doxygen.svg\" width=\"104\" height=\"31\" alt=\"doxygen\"/></a> "; @@ -1200,9 +1257,6 @@ void HtmlGenerator::writePageFooter(FTextStream &t,const QCString &lastTitle, void HtmlGenerator::writeFooter(const char *navPath) { - // Currently only tooltips in HTML - TooltipManager::instance()->writeTooltips(m_codeGen); - writePageFooter(t,m_lastTitle,m_relPath,navPath); } @@ -1409,7 +1463,7 @@ void HtmlGenerator::endTextLink() void HtmlGenerator::startHtmlLink(const char *url) { - static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); t << "<a "; if (generateTreeView) t << "target=\"top\" "; t << "href=\""; @@ -1534,7 +1588,7 @@ static void startSectionHeader(FTextStream &t, const QCString &relPath,int sectionCount) { //t << "<!-- startSectionHeader -->"; - static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); + bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); if (dynamicSections) { t << "<div id=\"dynsection-" << sectionCount << "\" " @@ -1559,7 +1613,7 @@ static void endSectionHeader(FTextStream &t) static void startSectionSummary(FTextStream &t,int sectionCount) { //t << "<!-- startSectionSummary -->"; - static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); + bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); if (dynamicSections) { t << "<div id=\"dynsection-" << sectionCount << "-summary\" " @@ -1571,7 +1625,7 @@ static void startSectionSummary(FTextStream &t,int sectionCount) static void endSectionSummary(FTextStream &t) { //t << "<!-- endSectionSummary -->"; - static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); + bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); if (dynamicSections) { t << "</div>" << endl; @@ -1581,7 +1635,7 @@ static void endSectionSummary(FTextStream &t) static void startSectionContent(FTextStream &t,int sectionCount) { //t << "<!-- startSectionContent -->"; - static bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); + bool dynamicSections = Config_getBool(HTML_DYNAMIC_SECTIONS); if (dynamicSections) { t << "<div id=\"dynsection-" << sectionCount << "-content\" " @@ -1617,7 +1671,7 @@ void HtmlGenerator::endClassDiagram(const ClassDiagram &d, startSectionSummary(t,m_sectionCount); endSectionSummary(t); startSectionContent(t,m_sectionCount); - d.writeImage(tt,m_dir,m_relPath,fileName); + d.writeImage(tt,dir(),m_relPath,fileName); if (!result.isEmpty()) { t << " <div class=\"center\">" << endl; @@ -2000,7 +2054,7 @@ void HtmlGenerator::endDotGraph(DotClassGraph &g) endSectionSummary(t); startSectionContent(t,m_sectionCount); - g.writeGraph(t,GOF_BITMAP,EOF_Html,m_dir,m_fileName,m_relPath,TRUE,TRUE,m_sectionCount); + g.writeGraph(t,GOF_BITMAP,EOF_Html,dir(),fileName(),m_relPath,TRUE,TRUE,m_sectionCount); if (generateLegend && !umlLook) { t << "<center><span class=\"legend\">["; @@ -2026,7 +2080,7 @@ void HtmlGenerator::endInclDepGraph(DotInclDepGraph &g) endSectionSummary(t); startSectionContent(t,m_sectionCount); - g.writeGraph(t,GOF_BITMAP,EOF_Html,m_dir,m_fileName,m_relPath,TRUE,m_sectionCount); + g.writeGraph(t,GOF_BITMAP,EOF_Html,dir(),fileName(),m_relPath,TRUE,m_sectionCount); endSectionContent(t); m_sectionCount++; @@ -2044,7 +2098,7 @@ void HtmlGenerator::endGroupCollaboration(DotGroupCollaboration &g) endSectionSummary(t); startSectionContent(t,m_sectionCount); - g.writeGraph(t,GOF_BITMAP,EOF_Html,m_dir,m_fileName,m_relPath,TRUE,m_sectionCount); + g.writeGraph(t,GOF_BITMAP,EOF_Html,dir(),fileName(),m_relPath,TRUE,m_sectionCount); endSectionContent(t); m_sectionCount++; @@ -2062,7 +2116,7 @@ void HtmlGenerator::endCallGraph(DotCallGraph &g) endSectionSummary(t); startSectionContent(t,m_sectionCount); - g.writeGraph(t,GOF_BITMAP,EOF_Html,m_dir,m_fileName,m_relPath,TRUE,m_sectionCount); + g.writeGraph(t,GOF_BITMAP,EOF_Html,dir(),fileName(),m_relPath,TRUE,m_sectionCount); endSectionContent(t); m_sectionCount++; @@ -2080,7 +2134,7 @@ void HtmlGenerator::endDirDepGraph(DotDirDeps &g) endSectionSummary(t); startSectionContent(t,m_sectionCount); - g.writeGraph(t,GOF_BITMAP,EOF_Html,m_dir,m_fileName,m_relPath,TRUE,m_sectionCount); + g.writeGraph(t,GOF_BITMAP,EOF_Html,dir(),fileName(),m_relPath,TRUE,m_sectionCount); endSectionContent(t); m_sectionCount++; @@ -2088,7 +2142,7 @@ void HtmlGenerator::endDirDepGraph(DotDirDeps &g) void HtmlGenerator::writeGraphicalHierarchy(DotGfxHierarchyTable &g) { - g.writeGraph(t,m_dir,m_fileName); + g.writeGraph(t,dir(),fileName()); } void HtmlGenerator::startMemberGroupHeader(bool) @@ -2210,8 +2264,9 @@ void HtmlGenerator::endParamList() t << "</dl>"; } -void HtmlGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void HtmlGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int id) { + m_codeGen.setId(id); HtmlDocVisitor *visitor = new HtmlDocVisitor(t,m_codeGen,ctx); n->accept(visitor); delete visitor; @@ -2275,8 +2330,8 @@ static void endQuickIndexItem(FTextStream &t,const char *l) static bool quickLinkVisible(LayoutNavEntry::Kind kind) { - static bool showFiles = Config_getBool(SHOW_FILES); - static bool showNamespaces = Config_getBool(SHOW_NAMESPACES); + bool showFiles = Config_getBool(SHOW_FILES); + bool showNamespaces = Config_getBool(SHOW_NAMESPACES); switch (kind) { case LayoutNavEntry::MainPage: return TRUE; @@ -2384,8 +2439,8 @@ static void renderQuickLinksAsTabs(FTextStream &t,const QCString &relPath, } if (hlEntry->parent()==LayoutDocManager::instance().rootNavEntry()) // first row is special as it contains the search box { - static bool searchEngine = Config_getBool(SEARCHENGINE); - static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); + bool searchEngine = Config_getBool(SEARCHENGINE); + bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); if (searchEngine) { t << " <li>\n"; @@ -2422,9 +2477,9 @@ static void writeDefaultQuickLinks(FTextStream &t,bool compact, const char *file, const QCString &relPath) { - static bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); - static bool searchEngine = Config_getBool(SEARCHENGINE); - static bool externalSearch = Config_getBool(EXTERNAL_SEARCH); + bool serverBasedSearch = Config_getBool(SERVER_BASED_SEARCH); + bool searchEngine = Config_getBool(SEARCHENGINE); + bool externalSearch = Config_getBool(EXTERNAL_SEARCH); LayoutNavEntry *root = LayoutDocManager::instance().rootNavEntry(); LayoutNavEntry::Kind kind = (LayoutNavEntry::Kind)-1; LayoutNavEntry::Kind altKind = (LayoutNavEntry::Kind)-1; // fall back for the old layout file @@ -2546,7 +2601,7 @@ void HtmlGenerator::endQuickIndices() QCString HtmlGenerator::writeSplitBarAsString(const char *name,const char *relpath) { - static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); QCString result; // write split bar if (generateTreeView) @@ -2613,10 +2668,10 @@ void HtmlGenerator::writeQuickLinks(bool compact,HighlightedItem hli,const char // PHP based search script void HtmlGenerator::writeSearchPage() { - static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - static bool disableIndex = Config_getBool(DISABLE_INDEX); - static QCString projectName = Config_getString(PROJECT_NAME); - static QCString htmlOutput = Config_getString(HTML_OUTPUT); + bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + bool disableIndex = Config_getBool(DISABLE_INDEX); + QCString projectName = Config_getString(PROJECT_NAME); + QCString htmlOutput = Config_getString(HTML_OUTPUT); // OPENSEARCH_PROVIDER { QCString configFileName = htmlOutput+"/search_config.php"; @@ -2661,7 +2716,7 @@ void HtmlGenerator::writeSearchPage() 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\", \"" - << "search\",false,'" << theTranslator->trSearch() << "');\n"; + << "search\",false,'" << theTranslator->trSearch() << "','" << Doxygen::htmlFileExtension << "');\n"; t << "/* @license-end */\n"; t << "</script>\n"; if (!Config_getBool(DISABLE_INDEX)) @@ -2701,8 +2756,9 @@ void HtmlGenerator::writeSearchPage() void HtmlGenerator::writeExternalSearchPage() { - static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - QCString fileName = Config_getString(HTML_OUTPUT)+"/search"+Doxygen::htmlFileExtension; + bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); + QCString dname = Config_getString(HTML_OUTPUT); + QCString fileName = dname+"/search"+Doxygen::htmlFileExtension; QFile f(fileName); if (f.open(IO_WriteOnly)) { @@ -2714,7 +2770,7 @@ void HtmlGenerator::writeExternalSearchPage() 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\", \"" - << "search\",false,'" << theTranslator->trSearch() << "');\n"; + << "search\",false,'" << theTranslator->trSearch() << "','" << Doxygen::htmlFileExtension << "');\n"; t << "/* @license-end */\n"; t << "</script>\n"; if (!Config_getBool(DISABLE_INDEX)) @@ -2752,7 +2808,7 @@ void HtmlGenerator::writeExternalSearchPage() writePageFooter(t,"Search","",""); } - QCString scriptName = Config_getString(HTML_OUTPUT)+"/search/search.js"; + QCString scriptName = dname+"/search/search.js"; QFile sf(scriptName); if (sf.open(IO_WriteOnly)) { @@ -2847,19 +2903,6 @@ void HtmlGenerator::endConstraintList() t << "</div>" << endl; } -void HtmlGenerator::startCodeFragment() -{ - t << PREFRAG_START; -} - -void HtmlGenerator::endCodeFragment() -{ - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << PREFRAG_END; -} - void HtmlGenerator::lineBreak(const char *style) { if (style) diff --git a/src/htmlgen.h b/src/htmlgen.h index a8268da..659a69e 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.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,11 +19,6 @@ #include "outputgen.h" #include "ftextstream.h" -//#define PREFRAG_START "<div class=\"fragment\"><pre class=\"fragment\">" -//#define PREFRAG_END "</pre></div>" -#define PREFRAG_START "<div class=\"fragment\">" -#define PREFRAG_END "</div><!-- fragment -->" - class QFile; class HtmlCodeGenerator : public CodeOutputInterface @@ -33,13 +26,15 @@ class HtmlCodeGenerator : public CodeOutputInterface public: HtmlCodeGenerator(FTextStream &t,const QCString &relPath); HtmlCodeGenerator(); + int id() const { return m_id; } + void setId(int id) { m_id = id; } void setTextStream(FTextStream &t); void setRelativePath(const QCString &path); void codify(const char *text); void writeCodeLink(const char *ref,const char *file, const char *anchor,const char *name, const char *tooltip); - void writeTooltip(const char *id, + void writeTooltip(const char *id, const DocLinkInfo &docInfo, const char *decl, const char *desc, @@ -54,6 +49,8 @@ class HtmlCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *anchor); void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *style); + void endCodeFragment(const char *); private: void _writeCodeLink(const char *className, @@ -61,10 +58,12 @@ class HtmlCodeGenerator : public CodeOutputInterface const char *anchor,const char *name, const char *tooltip); void docify(const char *str); - bool m_streamSet; + bool m_streamSet = false; FTextStream m_t; - int m_col; + int m_col = 0; QCString m_relPath; + bool m_lineOpen = false; + int m_id = 0; }; /** Generator for HTML output */ @@ -72,7 +71,12 @@ class HtmlGenerator : public OutputGenerator { public: HtmlGenerator(); + HtmlGenerator &operator=(const HtmlGenerator &g); + HtmlGenerator(const HtmlGenerator &g); virtual ~HtmlGenerator(); + virtual std::unique_ptr<OutputGenerator> clone() const; + + virtual OutputType type() const { return Html; } static void init(); static void writeStyleSheetFile(QFile &f); static void writeHeaderFile(QFile &f, const char *cssname); @@ -84,18 +88,9 @@ class HtmlGenerator : public OutputGenerator static void writeExternalSearchPage(); static QCString writeLogoAsString(const char *path); static QCString writeSplitBarAsString(const char *name,const char *relpath); - - void enable() - { if (m_genStack->top()) m_active=*m_genStack->top(); else m_active=TRUE; } - void disable() { m_active=FALSE; } - void enableIf(OutputType o) { if (o==Html) enable(); } - void disableIf(OutputType o) { if (o==Html) disable(); } - void disableIfNot(OutputType o) { if (o!=Html) disable(); } - bool isEnabled(OutputType o) { return (o==Html && m_active); } - OutputGenerator *get(OutputType o) { return (o==Html) ? this : 0; } // ---- CodeOutputInterface - void codify(const char *text) + void codify(const char *text) { m_codeGen.codify(text); } void writeCodeLink(const char *ref,const char *file, const char *anchor,const char *name, @@ -111,19 +106,23 @@ class HtmlGenerator : public OutputGenerator { m_codeGen.startCodeLine(hasLineNumbers); } void endCodeLine() { m_codeGen.endCodeLine(); } - void startFontClass(const char *s) + void startFontClass(const char *s) { m_codeGen.startFontClass(s); } - void endFontClass() + void endFontClass() { m_codeGen.endFontClass(); } - void writeCodeAnchor(const char *anchor) + void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment(const char *style) + { m_codeGen.endCodeFragment(style); } // --------------------------- void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); - void writeDoc(DocNode *,const Definition *,const MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *,int id); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int id); void writeFooter(const char *navPath); void endFile(); void clearBuffer(); @@ -139,7 +138,7 @@ class HtmlGenerator : public OutputGenerator void endTitleHead(const char *,const char *); void startTitle() { t << "<div class=\"title\">"; } void endTitle() { t << "</div>"; } - + void startParagraph(const char *classDef); void endParagraph(); void writeString(const char *text); @@ -210,10 +209,8 @@ class HtmlGenerator : public OutputGenerator const char *title,const char *name); void writeRuler() { t << "<hr/>"; } - void writeAnchor(const char *,const char *name) + void writeAnchor(const char *,const char *name) { t << "<a name=\"" << name <<"\" id=\"" << name << "\"></a>"; } - void startCodeFragment(); - void endCodeFragment(); void startEmphasis() { t << "<em>"; } void endEmphasis() { t << "</em>"; } void startBold() { t << "<b>"; } @@ -226,10 +223,10 @@ class HtmlGenerator : public OutputGenerator void endDescForItem() { t << "</dd>\n"; } void lineBreak(const char *style); void writeChar(char c); - void startMemberDoc(const char *clName, const char *memName, - const char *anchor, const char *title, + void startMemberDoc(const char *clName, const char *memName, + const char *anchor, const char *title, int memCount, int memTotal, bool showInline); - void endMemberDoc(bool); + void endMemberDoc(bool); void startDoxyAnchor(const char *fName,const char *manName, const char *anchor,const char *name, const char *args); @@ -294,9 +291,9 @@ class HtmlGenerator : public OutputGenerator void endDirDepGraph(DotDirDeps &g); void writeGraphicalHierarchy(DotGfxHierarchyTable &g); - void startTextBlock(bool) + void startTextBlock(bool) { t << "<div class=\"textblock\">"; } - void endTextBlock(bool) + void endTextBlock(bool) { t << "</div>"; } void lastIndexPage() {} @@ -334,9 +331,6 @@ class HtmlGenerator : public OutputGenerator void writeLabel(const char *l,bool isLast); void endLabels(); - - //static void generateSectionImages(); - private: static void writePageFooter(FTextStream &t,const QCString &,const QCString &,const QCString &); QCString m_lastTitle; @@ -344,11 +338,8 @@ class HtmlGenerator : public OutputGenerator QCString m_relPath; void docify(const char *text,bool inHtmlComment); - HtmlGenerator &operator=(const HtmlGenerator &g); - HtmlGenerator(const HtmlGenerator &g); - - int m_sectionCount; - bool m_emptySection; + int m_sectionCount = 0; + bool m_emptySection = false; HtmlCodeGenerator m_codeGen; }; diff --git a/src/index.cpp b/src/index.cpp index 12f35f2..e68f7eb 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -177,74 +177,41 @@ const int maxItemsBeforeQuickIndex = MAX_ITEMS_BEFORE_QUICK_INDEX; static void startQuickIndexList(OutputList &ol,bool letterTabs=FALSE) { - bool fancyTabs = TRUE; - if (fancyTabs) + if (letterTabs) { - if (letterTabs) - { - ol.writeString(" <div id=\"navrow4\" class=\"tabs3\">\n"); - } - else - { - ol.writeString(" <div id=\"navrow3\" class=\"tabs2\">\n"); - } - ol.writeString(" <ul class=\"tablist\">\n"); + ol.writeString(" <div id=\"navrow4\" class=\"tabs3\">\n"); } else { - ol.writeString(" <div class=\"qindex\">"); + ol.writeString(" <div id=\"navrow3\" class=\"tabs2\">\n"); } + ol.writeString(" <ul class=\"tablist\">\n"); } static void endQuickIndexList(OutputList &ol) { - bool fancyTabs = TRUE; - if (fancyTabs) - { - ol.writeString(" </ul>\n"); - } + ol.writeString(" </ul>\n"); ol.writeString(" </div>\n"); } static void startQuickIndexItem(OutputList &ol,const char *l, bool hl,bool compact,bool &first) { - bool fancyTabs = TRUE; - if (!first && compact && !fancyTabs) ol.writeString(" | "); first=FALSE; - if (fancyTabs) - { - ol.writeString(" <li"); - if (hl) ol.writeString(" class=\"current\""); - ol.writeString("><a "); - } - else - { - if (!compact) ol.writeString("<li>"); - if (hl && compact) - { - ol.writeString("<a class=\"qindexHL\" "); - } - else - { - ol.writeString("<a class=\"qindex\" "); - } - } + ol.writeString(" <li"); + if (hl) ol.writeString(" class=\"current\""); + ol.writeString("><a "); ol.writeString("href=\""); ol.writeString(l); ol.writeString("\">"); - if (fancyTabs) - { - ol.writeString("<span>"); - } + ol.writeString("<span>"); } static void endQuickIndexItem(OutputList &ol) { - bool fancyTabs=TRUE; - if (fancyTabs) ol.writeString("</span>"); + ol.writeString("</span>"); ol.writeString("</a>"); - if (fancyTabs) ol.writeString("</li>\n"); + ol.writeString("</li>\n"); } // don't make this static as it is called from a template function and some @@ -254,7 +221,7 @@ QCString fixSpaces(const QCString &s) return substitute(s," "," "); } -void startTitle(OutputList &ol,const char *fileName,const Definition *def) +void startTitle(OutputList &ol,const char *fileName,const DefinitionMutable *def) { ol.startHeaderSection(); if (def) def->writeSummaryLinks(ol); @@ -307,7 +274,6 @@ void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents, ol.writeFooter(navPath); // write the footer ol.popGeneratorState(); ol.endFile(); - TooltipManager::instance()->clearTooltips(); // Only clear after the last is written } void endFileWithNavPath(const Definition *d,OutputList &ol) @@ -326,6 +292,66 @@ void endFileWithNavPath(const Definition *d,OutputList &ol) } //---------------------------------------------------------------------- + +static bool memberVisibleInIndex(const MemberDef *md) +{ + bool isAnonymous = md->isAnonymous(); + bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); + bool extractStatic = Config_getBool(EXTRACT_STATIC); + return (!isAnonymous && + (!hideUndocMembers || md->hasDocumentation()) && + (!md->isStatic() || extractStatic) + ); +} + +static void writeMemberToIndex(const Definition *def,const MemberDef *md,bool addToIndex) +{ + bool isAnonymous = md->isAnonymous(); + bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); + const MemberList *enumList = md->enumFieldList(); + bool isDir = enumList!=0 && md->isEnumerate(); + if (md->getOuterScope()==def || md->getOuterScope()==Doxygen::globalScope) + { + Doxygen::indexList->addContentsItem(isDir, + md->name(),md->getReference(),md->getOutputFileBase(),md->anchor(),FALSE,addToIndex); + } + else // inherited member + { + Doxygen::indexList->addContentsItem(isDir, + md->name(),def->getReference(),def->getOutputFileBase(),md->anchor(),FALSE,addToIndex); + } + if (isDir) + { + if (!isAnonymous) + { + Doxygen::indexList->incContentsDepth(); + } + MemberListIterator emli(*enumList); + MemberDef *emd; + for (emli.toFirst();(emd=emli.current());++emli) + { + if (!hideUndocMembers || emd->hasDocumentation()) + { + if (emd->getOuterScope()==def || emd->getOuterScope()==Doxygen::globalScope) + { + Doxygen::indexList->addContentsItem(FALSE, + emd->name(),emd->getReference(),emd->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); + } + else // inherited member + { + Doxygen::indexList->addContentsItem(FALSE, + emd->name(),def->getReference(),def->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); + } + } + } + if (!isAnonymous) + { + Doxygen::indexList->decContentsDepth(); + } + } +} + +//---------------------------------------------------------------------- template<class T> void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, const QCString &name,const QCString &anchor, @@ -338,15 +364,9 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, addToIndex, def); int numClasses=0; - ClassSDict *classes = def->getClassSDict(); - if (classes) + for (const auto &cd : def->getClasses()) { - ClassDef *cd; - ClassSDict::Iterator it(*classes); - for (;(cd=it.current());++it) - { - if (cd->isLinkable()) numClasses++; - } + if (cd->isLinkable()) numClasses++; } //printf("addMembersToIndex(def=%s hasMembers=%d numClasses=%d)\n",def->name().data(),hasMembers,numClasses); if (hasMembers || numClasses>0) @@ -366,55 +386,9 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, MemberDef *md; for (mi.toFirst();(md=mi.current());++mi) { - const MemberList *enumList = md->enumFieldList(); - bool isDir = enumList!=0 && md->isEnumerate(); - bool isAnonymous = md->isAnonymous(); - static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); - static bool extractStatic = Config_getBool(EXTRACT_STATIC); - if (!isAnonymous && - (!hideUndocMembers || md->hasDocumentation()) && - (!md->isStatic() || extractStatic) - ) + if (memberVisibleInIndex(md)) { - if (md->getOuterScope()==def || md->getOuterScope()==Doxygen::globalScope) - { - Doxygen::indexList->addContentsItem(isDir, - md->name(),md->getReference(),md->getOutputFileBase(),md->anchor(),FALSE,addToIndex); - } - else // inherited member - { - Doxygen::indexList->addContentsItem(isDir, - md->name(),def->getReference(),def->getOutputFileBase(),md->anchor(),FALSE,addToIndex); - } - } - if (isDir) - { - if (!isAnonymous) - { - Doxygen::indexList->incContentsDepth(); - } - MemberListIterator emli(*enumList); - MemberDef *emd; - for (emli.toFirst();(emd=emli.current());++emli) - { - if (!hideUndocMembers || emd->hasDocumentation()) - { - if (emd->getOuterScope()==def || emd->getOuterScope()==Doxygen::globalScope) - { - Doxygen::indexList->addContentsItem(FALSE, - emd->name(),emd->getReference(),emd->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); - } - else // inherited member - { - Doxygen::indexList->addContentsItem(FALSE, - emd->name(),def->getReference(),def->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); - } - } - } - if (!isAnonymous) - { - Doxygen::indexList->decContentsDepth(); - } + writeMemberToIndex(def,md,addToIndex); } } } @@ -424,20 +398,15 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, lde->kind()==LayoutDocEntry::ClassNestedClasses ) { - if (classes) + for (const auto &cd : def->getClasses()) { - ClassDef *cd; - ClassSDict::Iterator it(*classes); - for (;(cd=it.current());++it) + if (cd->isLinkable() && (cd->partOfGroups()==0 || def->definitionType()==Definition::TypeGroup)) { - if (cd->isLinkable() && (cd->partOfGroups()==0 || def->definitionType()==Definition::TypeGroup)) - { - static bool inlineSimpleStructs = Config_getBool(INLINE_SIMPLE_STRUCTS); - bool isNestedClass = def->definitionType()==Definition::TypeClass; - addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(FALSE),cd->anchor(), - addToIndex && (isNestedClass || (cd->isSimple() && inlineSimpleStructs)), - preventSeparateIndex || cd->isEmbeddedInOuterScope()); - } + static bool inlineSimpleStructs = Config_getBool(INLINE_SIMPLE_STRUCTS); + bool isNestedClass = def->definitionType()==Definition::TypeClass; + addMembersToIndex(cd,LayoutDocManager::Class,cd->displayName(FALSE),cd->anchor(), + addToIndex && (isNestedClass || (cd->isSimple() && inlineSimpleStructs)), + preventSeparateIndex || cd->isEmbeddedInOuterScope()); } } } @@ -451,14 +420,13 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, //---------------------------------------------------------------------------- /*! Generates HTML Help tree of classes */ -static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSuper,int level,FTVHelp* ftv,bool addToIndex) +static void writeClassTreeToOutput(OutputList &ol,const BaseClassList &bcl,int level,FTVHelp* ftv,bool addToIndex,ClassDefSet &visitedClasses) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); + if (bcl.empty()) return; bool started=FALSE; - for ( ; bcli.current() ; ++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcli.current()->classDef; + ClassDef *cd=bcd.classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -491,7 +459,8 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe } ol.startIndexListItem(); //printf("Passed...\n"); - bool hasChildren = !cd->isVisited() && !hideSuper && classHasVisibleChildren(cd); + bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() && + classHasVisibleChildren(cd); //printf("tree4: Has children %s: %d\n",cd->name().data(),hasChildren); if (cd->isLinkable()) { @@ -513,7 +482,7 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe { if (cd->getLanguage()==SrcLangExt_VHDL) { - ftv->addContentsItem(hasChildren,bcli.current()->usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); + ftv->addContentsItem(hasChildren,bcd.usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); } else { @@ -538,15 +507,14 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe if (hasChildren) { //printf("Class %s at %p visited=%d\n",cd->name().data(),cd,cd->visited); - bool wasVisited=cd->isVisited(); - cd->setVisited(TRUE); + visitedClasses.insert(cd); if (cd->getLanguage()==SrcLangExt_VHDL) { - writeClassTree(ol,cd->baseClasses(),wasVisited,level+1,ftv,addToIndex); + writeClassTreeToOutput(ol,cd->baseClasses(),level+1,ftv,addToIndex,visitedClasses); } else { - writeClassTree(ol,cd->subClasses(),wasVisited,level+1,ftv,addToIndex); + writeClassTreeToOutput(ol,cd->subClasses(),level+1,ftv,addToIndex,visitedClasses); } } ol.endIndexListItem(); @@ -731,7 +699,7 @@ static void writeDirTreeNode(OutputList &ol, DirDef *dd, int level, FTVHelp* ftv else if (src) { Doxygen::indexList->addContentsItem( - FALSE, convertToHtml(fd->name(),TRUE), 0, + FALSE, fd->name(), 0, fd->getSourceFileBase(), 0, FALSE, TRUE, fd); } } @@ -801,7 +769,7 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) else if (src) { Doxygen::indexList->addContentsItem( - FALSE, convertToHtml(fd->name(),TRUE), 0, + FALSE, fd->name(), 0, fd->getSourceFileBase(), 0, FALSE, TRUE, fd.get()); } } @@ -819,13 +787,11 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) //---------------------------------------------------------------------------- -static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FTVHelp* ftv,bool addToIndex, - ClassDef::CompoundType ct) +static void writeClassTreeForList(OutputList &ol,const ClassLinkedMap &cl,bool &started,FTVHelp* ftv,bool addToIndex, + ClassDef::CompoundType ct,ClassDefSet &visitedClasses) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - ClassSDict::Iterator cli(*cl); - ClassDef *cd; - for (;(cd=cli.current());++cli) + for (const auto &cd : cl) { //printf("class %s hasVisibleRoot=%d isVisibleInHierarchy=%d\n", // cd->name().data(), @@ -864,7 +830,8 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT started=TRUE; } ol.startIndexListItem(); - bool hasChildren = !cd->isVisited() && classHasVisibleChildren(cd); + bool hasChildren = visitedClasses.find(cd.get())==visitedClasses.end() && + classHasVisibleChildren(cd.get()); //printf("list: Has children %s: %d\n",cd->name().data(),hasChildren); if (cd->isLinkable()) { @@ -886,7 +853,7 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT } if (ftv) { - ftv->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); + ftv->addContentsItem(hasChildren,cd->displayName(),cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd.get()); } } else @@ -900,18 +867,18 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT } if (ftv) { - ftv->addContentsItem(hasChildren,cd->displayName(),0,0,0,FALSE,FALSE,cd); + ftv->addContentsItem(hasChildren,cd->displayName(),0,0,0,FALSE,FALSE,cd.get()); } } if (cd->getLanguage()==SrcLangExt_VHDL && hasChildren) { - writeClassTree(ol,cd->baseClasses(),cd->isVisited(),1,ftv,addToIndex); - cd->setVisited(TRUE); + writeClassTreeToOutput(ol,cd->baseClasses(),1,ftv,addToIndex,visitedClasses); + visitedClasses.insert(cd.get()); } else if (hasChildren) { - writeClassTree(ol,cd->subClasses(),cd->isVisited(),1,ftv,addToIndex); - cd->setVisited(TRUE); + writeClassTreeToOutput(ol,cd->subClasses(),1,ftv,addToIndex,visitedClasses); + visitedClasses.insert(cd.get()); } ol.endIndexListItem(); } @@ -921,16 +888,15 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex,ClassDef::CompoundType ct) { - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); + ClassDefSet visitedClasses; if (ftv) { ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); } bool started=FALSE; - writeClassTreeForList(ol,Doxygen::classSDict,started,ftv,addToIndex,ct); - writeClassTreeForList(ol,Doxygen::hiddenClasses,started,ftv,addToIndex,ct); + writeClassTreeForList(ol,*Doxygen::classLinkedMap,started,ftv,addToIndex,ct,visitedClasses); + writeClassTreeForList(ol,*Doxygen::hiddenClassLinkedMap,started,ftv,addToIndex,ct,visitedClasses); if (started) { endIndexHierarchy(ol,0); @@ -947,13 +913,11 @@ static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex,Cla //---------------------------------------------------------------------------- -static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType ct) +static int countClassesInTreeList(const ClassLinkedMap &cl, ClassDef::CompoundType ct) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); int count=0; - ClassSDict::Iterator cli(cl); - ClassDef *cd; - for (;(cd=cli.current());++cli) + for (const auto &cd : cl) { if (sliceOpt && cd->compoundType() != ct) { @@ -963,7 +927,7 @@ static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType c { if (cd->isVisibleInHierarchy()) // should it be visible { - if (cd->subClasses()) // should have sub classes + if (!cd->subClasses().empty()) // should have sub classes { count++; } @@ -976,10 +940,8 @@ static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType c static int countClassHierarchy(ClassDef::CompoundType ct) { int count=0; - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); - count+=countClassesInTreeList(*Doxygen::classSDict, ct); - count+=countClassesInTreeList(*Doxygen::hiddenClasses, ct); + count+=countClassesInTreeList(*Doxygen::classLinkedMap, ct); + count+=countClassesInTreeList(*Doxygen::hiddenClassLinkedMap, ct); return count; } @@ -1544,9 +1506,7 @@ static void writeFileIndex(OutputList &ol) static int countNamespaces() { int count=0; - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for (;(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { if (nd->isLinkableInProject()) count++; } @@ -1554,75 +1514,124 @@ static int countNamespaces() } //---------------------------------------------------------------------------- +template<typename Ptr> const ClassDef *get_pointer(const Ptr &p); +template<> const ClassDef *get_pointer(const ClassLinkedMap::Ptr &p) { return p.get(); } +template<> const ClassDef *get_pointer(const ClassLinkedRefMap::Ptr &p) { return p; } -void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct) +template<class ListType> +static void writeClassTree(const ListType &cl,FTVHelp *ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - if (clDict) + for (const auto &cdi : cl) { - ClassSDict::Iterator cli(*clDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) + const ClassDef *cd = get_pointer(cdi); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm && cd->getLanguage()==SrcLangExt_VHDL) { - if (cd->getLanguage()==SrcLangExt_VHDL) + if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || + (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS + )// no architecture { - if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || - (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS - )// no architecture - { - continue; - } - if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS) + continue; + } + if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS) + { + QCString n=cd->name(); + cdm->setClassName(n.data()); + } + } + + if (sliceOpt && cd->compoundType() != ct) + { + continue; + } + + if (!globalOnly || + cd->getOuterScope()==0 || + cd->getOuterScope()==Doxygen::globalScope + ) + { + int count=0; + for (const auto &ccd : cd->getClasses()) + { + if (ccd->isLinkableInProject() && ccd->templateMaster()==0) { - QCString n=cd->name(); - cd->setClassName(n.data()); + count++; } } - - if (sliceOpt && cd->compoundType() != ct) + if (classVisibleInIndex(cd) && cd->templateMaster()==0) { - continue; + ftv->addContentsItem(count>0,cd->displayName(FALSE),cd->getReference(), + cd->getOutputFileBase(),cd->anchor(),FALSE,TRUE,cd); + if ((cd->getOuterScope()==0 || + cd->getOuterScope()->definitionType()!=Definition::TypeClass + ) + ) + { + addMembersToIndex(cd,LayoutDocManager::Class, + cd->displayName(FALSE), + cd->anchor(), + addToIndex && cd->partOfGroups()==0 && !cd->isSimple()); + } + if (count>0) + { + ftv->incContentsDepth(); + writeClassTree(cd->getClasses(),ftv,addToIndex,FALSE,ct); + ftv->decContentsDepth(); + } } + } + } +} - if (!globalOnly || - cd->getOuterScope()==0 || - cd->getOuterScope()==Doxygen::globalScope - ) +static int countVisibleMembers(const NamespaceDef *nd) +{ + int count=0; + QListIterator<LayoutDocEntry> eli(LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDef) + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + MemberList *ml = nd->getMemberList(lmd->type); + if (ml) { - int count=0; - if (cd->getClassSDict()) + MemberListIterator mi(*ml); + MemberDef *md; + for (mi.toFirst();(md=mi.current());++mi) { - ClassSDict::Iterator ccit(*cd->getClassSDict()); - ClassDef *ccd; - for (;(ccd=ccit.current());++ccit) + if (memberVisibleInIndex(md)) { - if (ccd->isLinkableInProject() && ccd->templateMaster()==0) - { - count++; - } + count++; } } - if (classVisibleInIndex(cd) && cd->templateMaster()==0) + } + } + } + return count; +} + +static void writeNamespaceMembers(const NamespaceDef *nd,bool addToIndex) +{ + QListIterator<LayoutDocEntry> eli(LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDef) + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + MemberList *ml = nd->getMemberList(lmd->type); + if (ml) + { + MemberListIterator mi(*ml); + MemberDef *md; + for (mi.toFirst();(md=mi.current());++mi) { - ftv->addContentsItem(count>0,cd->displayName(FALSE),cd->getReference(), - cd->getOutputFileBase(),cd->anchor(),FALSE,TRUE,cd); - if (addToIndex && - /*cd->partOfGroups()==0 &&*/ - (cd->getOuterScope()==0 || - cd->getOuterScope()->definitionType()!=Definition::TypeClass - ) - ) + //printf(" member %s visible=%d\n",md->name().data(),memberVisibleInIndex(md)); + if (memberVisibleInIndex(md)) { - addMembersToIndex(cd,LayoutDocManager::Class, - cd->displayName(FALSE), - cd->anchor(), - cd->partOfGroups()==0 && !cd->isSimple()); - } - if (count>0) - { - ftv->incContentsDepth(); - writeClassTree(cd->getClassSDict(),ftv,addToIndex,FALSE,ct); - ftv->decContentsDepth(); + writeMemberToIndex(nd,md,addToIndex); } } } @@ -1630,81 +1639,178 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO } } -static void writeNamespaceTree(const NamespaceSDict *nsDict,FTVHelp *ftv, - bool rootOnly,bool showClasses,bool addToIndex,ClassDef::CompoundType ct) +static void writeNamespaceTree(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv, + bool rootOnly,bool addToIndex); + +static void writeNamespaceTreeElement(const NamespaceDef *nd,FTVHelp *ftv, + bool rootOnly,bool addToIndex) +{ + if (!nd->isAnonymous() && + (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) + { + + bool hasChildren = namespaceHasNestedNamespace(nd) || + namespaceHasNestedClass(nd,false,ClassDef::Class); + bool isLinkable = nd->isLinkableInProject(); + int visibleMembers = countVisibleMembers(nd); + + //printf("namespace %s hasChildren=%d visibleMembers=%d\n",nd->name().data(),hasChildren,visibleMembers); + + QCString ref; + QCString file; + if (isLinkable) + { + ref = nd->getReference(); + file = nd->getOutputFileBase(); + if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK + { + file=file.replace(0,qstrlen("namespace"),"class"); + } + } + + bool isDir = hasChildren || visibleMembers>0; + if ((isLinkable) || isDir) + { + ftv->addContentsItem(hasChildren,nd->localName(),ref,file,0,FALSE,TRUE,nd); + + if (addToIndex) + { + Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(), + hasChildren && !file.isEmpty(),addToIndex); + } + if (addToIndex && isDir) + { + Doxygen::indexList->incContentsDepth(); + } + + //printf("*** writeNamespaceTree count=%d addToIndex=%d false=%d classCount=%d\n", + // count,addToIndex,false,classCount); + if (isDir) + { + ftv->incContentsDepth(); + writeNamespaceTree(nd->getNamespaces(),ftv,FALSE,addToIndex); + writeClassTree(nd->getClasses(),ftv,FALSE,FALSE,ClassDef::Class); + writeNamespaceMembers(nd,addToIndex); + ftv->decContentsDepth(); + } + if (addToIndex && isDir) + { + Doxygen::indexList->decContentsDepth(); + } + } + } +} + +static void writeNamespaceTree(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv, + bool rootOnly,bool addToIndex) +{ + for (const auto &nd : nsLinkedMap) + { + writeNamespaceTreeElement(nd,ftv,rootOnly,addToIndex); + } +} + +static void writeNamespaceTree(const NamespaceLinkedMap &nsLinkedMap,FTVHelp *ftv, + bool rootOnly,bool addToIndex) +{ + for (const auto &nd : nsLinkedMap) + { + writeNamespaceTreeElement(nd.get(),ftv,rootOnly,addToIndex); + } +} + +static void writeClassTreeInsideNamespace(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv, + bool rootOnly,bool addToIndex,ClassDef::CompoundType ct); + +static void writeClassTreeInsideNamespaceElement(const NamespaceDef *nd,FTVHelp *ftv, + bool rootOnly,bool addToIndex,ClassDef::CompoundType ct) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - if (nsDict) + if (!nd->isAnonymous() && + (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) { - NamespaceSDict::Iterator nli(*nsDict); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + bool isDir = namespaceHasNestedClass(nd,sliceOpt,ct); + bool isLinkable = nd->isLinkableInProject(); + + //printf("namespace %s isDir=%d\n",nd->name().data(),isDir); + + QCString ref; + QCString file; + if (isLinkable) { - if (!nd->isAnonymous() && - (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) + ref = nd->getReference(); + file = nd->getOutputFileBase(); + if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK { + file=file.replace(0,qstrlen("namespace"),"class"); + } + } - bool hasChildren = namespaceHasVisibleChild(nd,showClasses,sliceOpt,ct); - bool isLinkable = nd->isLinkableInProject(); + if (isDir) + { + ftv->addContentsItem(isDir,nd->localName(),ref,file,0,FALSE,TRUE,nd); - QCString ref; - QCString file; - if (isLinkable) + if (addToIndex) + { + // the namespace entry is already shown under the namespace list so don't + // add it to the nav index and don't create a separate index file for it otherwise + // it will overwrite the one written for the namespace list. + Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(), + false, // separateIndex + false // addToNavIndex + ); + } + if (addToIndex) + { + Doxygen::indexList->incContentsDepth(); + } + + ftv->incContentsDepth(); + writeClassTreeInsideNamespace(nd->getNamespaces(),ftv,FALSE,addToIndex,ct); + ClassLinkedRefMap d = nd->getClasses(); + if (sliceOpt) + { + if (ct == ClassDef::Interface) { - ref = nd->getReference(); - file = nd->getOutputFileBase(); - if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK - { - file=file.replace(0,qstrlen("namespace"),"class"); - } + d = nd->getInterfaces(); } - - if ((isLinkable && !showClasses) || hasChildren) + else if (ct == ClassDef::Struct) { - ftv->addContentsItem(hasChildren,nd->localName(),ref,file,0,FALSE,TRUE,nd); - - if (addToIndex) - { - Doxygen::indexList->addContentsItem(hasChildren,nd->localName(),ref,file,QCString(), - hasChildren && !file.isEmpty(),addToIndex); - } - - //printf("*** writeNamespaceTree count=%d addToIndex=%d showClasses=%d classCount=%d\n", - // count,addToIndex,showClasses,classCount); - if (hasChildren) - { - if (addToIndex) Doxygen::indexList->incContentsDepth(); - ftv->incContentsDepth(); - writeNamespaceTree(nd->getNamespaceSDict(),ftv,FALSE,showClasses,addToIndex,ct); - if (showClasses) - { - ClassSDict *d = nd->getClassSDict(); - if (sliceOpt) - { - if (ct == ClassDef::Interface) - { - d = nd->getInterfaceSDict(); - } - else if (ct == ClassDef::Struct) - { - d = nd->getStructSDict(); - } - else if (ct == ClassDef::Exception) - { - d = nd->getExceptionSDict(); - } - } - writeClassTree(d,ftv,addToIndex,FALSE,ct); - } - ftv->decContentsDepth(); - if (addToIndex) Doxygen::indexList->decContentsDepth(); - } + d = nd->getStructs(); + } + else if (ct == ClassDef::Exception) + { + d = nd->getExceptions(); } } + writeClassTree(d,ftv,addToIndex,FALSE,ct); + ftv->decContentsDepth(); + + if (addToIndex) + { + Doxygen::indexList->decContentsDepth(); + } } } } +static void writeClassTreeInsideNamespace(const NamespaceLinkedRefMap &nsLinkedMap,FTVHelp *ftv, + bool rootOnly,bool addToIndex,ClassDef::CompoundType ct) +{ + for (const auto &nd : nsLinkedMap) + { + writeClassTreeInsideNamespaceElement(nd,ftv,rootOnly,addToIndex,ct); + } +} + +static void writeClassTreeInsideNamespace(const NamespaceLinkedMap &nsLinkedMap,FTVHelp *ftv, + bool rootOnly,bool addToIndex,ClassDef::CompoundType ct) +{ + for (const auto &nd : nsLinkedMap) + { + writeClassTreeInsideNamespaceElement(nd.get(),ftv,rootOnly,addToIndex,ct); + } +} static void writeNamespaceIndex(OutputList &ol) { @@ -1733,9 +1839,7 @@ static void writeNamespaceIndex(OutputList &ol) ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { if (nd->isLinkableInProject()) { @@ -1763,7 +1867,7 @@ static void writeNamespaceIndex(OutputList &ol) //ol.docify(" ("); ol.generateDoc( nd->briefFile(),nd->briefLine(), - nd,0, + nd.get(),0, nd->briefDescription(TRUE), FALSE, // index words FALSE, // isExample @@ -1795,7 +1899,7 @@ static void writeNamespaceIndex(OutputList &ol) Doxygen::indexList->incContentsDepth(); } FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,FALSE,addToIndex,ClassDef::Class); + writeNamespaceTree(*Doxygen::namespaceLinkedMap,ftv,TRUE,addToIndex); QGString outStr; FTextStream t(&outStr); ftv->generateTreeViewInline(t); @@ -1821,9 +1925,7 @@ static int countAnnotatedClasses(int *cp, ClassDef::CompoundType ct) static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); int count=0; int countPrinted=0; - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (sliceOpt && cd->compoundType() != ct) { @@ -1851,10 +1953,7 @@ static void writeAnnotatedClassList(OutputList &ol,ClassDef::CompoundType ct) static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->getLanguage()==SrcLangExt_VHDL && ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || @@ -1898,7 +1997,7 @@ static void writeAnnotatedClassList(OutputList &ol,ClassDef::CompoundType ct) { ol.generateDoc( cd->briefFile(),cd->briefLine(), - cd,0, + cd.get(),0, cd->briefDescription(TRUE), FALSE, // indexWords FALSE, // isExample @@ -1930,6 +2029,29 @@ static QCString letterToString(uint letter) return QString(QChar(letter)).utf8(); } +static QCString letterToLabel(const char *startLetter) +{ + const char *p = startLetter; + if (startLetter==0 || *startLetter==0) return ""; + char c = *p; + QCString result; + if (isId1(c)) + { + result+=c; + } + else + { + result="0x"; + const char hex[]="0123456789abcdef"; + while ((c=*p++)) + { + result+=hex[((unsigned char)c)>>4]; + result+=hex[((unsigned char)c)&0xf]; + } + } + return result; +} + static QCString letterToLabel(uint startLetter) { char s[11]; // max 0x12345678 + '\0' @@ -1967,87 +2089,31 @@ static QCString letterToLabel(uint startLetter) return s; } -//---------------------------------------------------------------------------- -/** Special class list where sorting takes IGNORE_PREFIX into account. */ -class PrefixIgnoreClassList : public ClassList -{ - public: - typedef const ClassDef ElementType; - PrefixIgnoreClassList(uint letter) : m_letter(letter) {} - uint letter() const { return m_letter; } - private: - virtual int compareValue(const ClassDef *c1, const ClassDef *c2) const - { - QCString n1 = c1->className(); - QCString n2 = c2->className(); - return qstricmp (n1.data()+getPrefixIndex(n1), n2.data()+getPrefixIndex(n2)); - } - uint m_letter; -}; +//---------------------------------------------------------------------------- /** Class representing a cell in the alphabetical class index. */ class AlphaIndexTableCell { public: - AlphaIndexTableCell(int row,int col,uint letter,const ClassDef *cd) : + AlphaIndexTableCell(int row,int col,const std::string &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>"); + { } 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; } + std::string letter() const { return m_letter; } + int row() const { return m_row; } + int column() const { return m_col; } private: - uint m_letter; + std::string m_letter; const ClassDef *m_class; int m_row; int m_col; }; -/** Class representing a row in the alphabetical class index. */ -class AlphaIndexTableRows : public QList<AlphaIndexTableCell> -{ - public: - AlphaIndexTableRows() { setAutoDelete(TRUE); } -}; - -/** Iterator for the cells in a row of the alphabetical class index. */ -class AlphaIndexTableRowsIterator : public QListIterator<AlphaIndexTableCell> -{ - public: - AlphaIndexTableRowsIterator(const AlphaIndexTableRows &list_) : - QListIterator<AlphaIndexTableCell>(list_) {} -}; - -/** Class representing the columns in the alphabetical class index. */ -class AlphaIndexTableColumns : public QList<AlphaIndexTableRows> -{ - public: - AlphaIndexTableColumns() { setAutoDelete(TRUE); } -}; - -class UsedIndexLetters : public SIntDict<uint> -{ - public: - UsedIndexLetters() : SIntDict<uint>(257) { setAutoDelete(TRUE); } - void add(uint letter) - { - uint *v = find(letter); - if (v==0) - { - append(letter,new uint(letter)); - } - } - private: - int compareValues( const uint *p1, const uint *p2) const - { - return (int)*p1 - (int)*p2; // subtracting is done by int not uint. - } -}; +using UsedIndexLetters = std::set<std::string>; // write an alphabetical index of all class with a header for each letter static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct, int annotatedCount) @@ -2058,11 +2124,7 @@ static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct UsedIndexLetters indexLettersUsed; // first count the number of headers - ClassSDict::Iterator cli(*Doxygen::classSDict); - const ClassDef *cd; - uint startLetter=0; - int headerItems=0; - for (;(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (sliceOpt && cd->compoundType() != ct) continue; @@ -2073,50 +2135,36 @@ static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct int index = getPrefixIndex(cd->className()); //printf("name=%s index=%d %d\n",cd->className().data(),index,cd->protection()); - startLetter=getUtf8CodeToLower(cd->className(),index); - indexLettersUsed.add(startLetter); + char charStr[MAX_UTF8_CHAR_SIZE]; + if (getUtf8Char(cd->className().data()+index,charStr,CaseModifier::ToUpper)>0) + // get the first UTF8 character (after the part that should be ignored) + { + indexLettersUsed.insert(charStr); + } } } - indexLettersUsed.sort(); // write quick link index (row of letters) QCString alphaLinks = "<div class=\"qindex\">"; - SIntDict<uint>::Iterator it(indexLettersUsed); - uint *pLetter; - for (it.toFirst();(pLetter=it.current());++it) - { - if (headerItems) alphaLinks += " | "; - headerItems++; - QCString li = letterToLabel(*pLetter); - QCString ls = letterToString(*pLetter); + bool first=true; + for (const auto &letter : indexLettersUsed) + { + if (!first) alphaLinks += " | "; + first=false; + QCString li = letterToLabel(letter.c_str()); alphaLinks += (QCString)"<a class=\"qindex\" href=\"#letter_" + li + "\">" + - ls + "</a>"; + letter + "</a>"; } alphaLinks += "</div>\n"; ol.writeString(alphaLinks); - - // the number of columns in the table - const int columns = Config_getInt(COLS_IN_ALPHA_INDEX); - - int i,j; - int totalItems = headerItems*2 + annotatedCount; // number of items in the table (headers span 2 items) - int rows = (totalItems + columns - 1)/columns; // number of rows in the table - - //printf("headerItems=%d totalItems=%d columns=%d rows=%d itemsInLastRow=%d\n", - // headerItems,totalItems,columns,rows,itemsInLastRow); - - // Keep a list of classes for each starting letter - LetterToIndexMap<PrefixIgnoreClassList> classesByLetter; - AlphaIndexTableColumns tableColumns; + std::map<std::string, std::vector<const ClassDef*> > classesByLetter; // fill the columns with the class list (row elements in each column, // expect for the columns with number >= itemsInLastRow, which get one // item less. - //int icount=0; - startLetter=0; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (sliceOpt && cd->compoundType() != ct) continue; @@ -2126,185 +2174,100 @@ static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct if (cd->isLinkableInProject() && cd->templateMaster()==0) { int index = getPrefixIndex(cd->className()); - startLetter=getUtf8CodeToLower(cd->className(),index); - // Do some sorting again, since the classes are sorted by name with - // prefix, which should be ignored really. - if (cd->getLanguage()==SrcLangExt_VHDL) + char charStr[MAX_UTF8_CHAR_SIZE]; + if (getUtf8Char(cd->className().data()+index,charStr,CaseModifier::ToUpper)>0) + // get the first UTF8 character (after the part that should be ignored) { - if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS )// no architecture + auto it = classesByLetter.find(charStr); + if (it!=classesByLetter.end()) // add class to the existing list { - classesByLetter.append(startLetter,cd); + it->second.push_back(cd.get()); + } + else // new entry + { + classesByLetter.insert( + std::make_pair(std::string(charStr), + std::vector<const ClassDef*>({ cd.get() }))); } - } - else - { - classesByLetter.append(startLetter,cd); } } } - #define NEXT_ROW() \ - do \ - { \ - if (row>maxRows) maxRows=row; \ - if (row>=rows && col<columns) \ - { \ - col++; \ - row=0; \ - tableRows = new AlphaIndexTableRows; \ - tableColumns.append(tableRows); \ - } \ - } \ - while(0) \ - - AlphaIndexTableRows *tableRows = new AlphaIndexTableRows; - tableColumns.append(tableRows); - int col=0,row=0,maxRows=0; - PrefixIgnoreClassList *cl; - SIntDict<PrefixIgnoreClassList>::Iterator lit(classesByLetter); - for (lit.toFirst();(cl=lit.current());++lit) + // sort the class lists per letter while ignoring the prefix + for (auto &kv : classesByLetter) { - uint l = cl->letter(); - // add special header cell - tableRows->append(new AlphaIndexTableCell(row,col,l,(ClassDef*)0x8)); - row++; - tableRows->append(new AlphaIndexTableCell(row,col,0,(ClassDef*)0x8)); - row++; - ClassListIterator cit(*cl); - cit.toFirst(); - cd = cit.current(); - ++cit; - tableRows->append(new AlphaIndexTableCell(row,col,0,cd)); - row++; - NEXT_ROW(); - for (;(cd=cit.current()); ++cit) - { - // add normal cell - tableRows->append(new AlphaIndexTableCell(row,col,0,cd)); - row++; - NEXT_ROW(); - } - } - - // create row iterators for each column - AlphaIndexTableRowsIterator **colIterators = new AlphaIndexTableRowsIterator*[columns]; - for (i=0;i<columns;i++) - { - if (i<(int)tableColumns.count()) - { - colIterators[i] = new AlphaIndexTableRowsIterator(*tableColumns.at(i)); - } - else // empty column - { - colIterators[i] = 0; - } + std::sort(kv.second.begin(), kv.second.end(), + [](const auto &c1,const auto &c2) + { + QCString n1 = c1->className(); + QCString n2 = c2->className(); + return qstricmp(n1.data()+getPrefixIndex(n1), n2.data()+getPrefixIndex(n2))<0; + }); } - ol.writeString("<table class=\"classindex\">\n"); // generate table - for (i=0;i<=maxRows;i++) // foreach table row - { - //printf("writing row %d\n",i); - //ol.nextTableRow(); - ol.writeString("<tr>"); - // the last column may contain less items then the others - //int colsInRow = (i<rows-1) ? columns : itemsInLastRow; - //printf("row [%d]\n",i); - bool cellCont = false; - for (j=0;j<columns;j++) // foreach table column - { - if (colIterators[j]) + if (!classesByLetter.empty()) + { + ol.writeString("<div class=\"classindex\">\n"); + int counter=0; + for (const auto &cl : classesByLetter) + { + QCString parity = (counter++%2)==0 ? "even" : "odd"; + ol.writeString("<dl class=\"classindex " + parity + "\">\n"); + + // write character heading + ol.writeString("<dt class=\"alphachar\">"); + QCString s = letterToLabel(cl.first.c_str()); + ol.writeString("<a name=\"letter_"); + ol.writeString(s); + ol.writeString("\">"); + ol.writeString(cl.first.c_str()); + ol.writeString("</a>"); + ol.writeString("</dt>\n"); + + // write class links + for (const auto &cd : cl.second) { - AlphaIndexTableCell *cell = colIterators[j]->current(); - if (cell) + ol.writeString("<dd>"); + QCString namesp,cname; + extractNamespaceName(cd->name(),cname,namesp); + QCString nsDispName; + SrcLangExt lang = cd->getLanguage(); + QCString sep = getLanguageSpecificSeparator(lang); + if (sep!="::") { - if (cell->row()==i) - { - if (cell->letter()!=0) - { - cellCont = true; - QCString s = letterToLabel(cell->letter()); - ol.writeString("<td rowspan=\"2\" valign=\"bottom\">"); - ol.writeString("<a name=\"letter_"); - ol.writeString(s); - ol.writeString("\"></a>"); - ol.writeString("<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">" - "<tr>" - "<td><div class=\"ah\">  "); - ol.writeString(letterToString(cell->letter())); - ol.writeString( "  </div>" - "</td>" - "</tr>" - "</table>\n"); - } - else if (cell->classDef()!=(ClassDef*)0x8) - { - cellCont = true; - cd = cell->classDef(); - ol.writeString("<td valign=\"top\">"); - QCString namesp,cname; - //if (cd->getNamespaceDef()) namesp=cd->getNamespaceDef()->displayName(); - //QCString cname=cd->className(); - extractNamespaceName(cd->name(),cname,namesp); - QCString nsDispName; - SrcLangExt lang = cd->getLanguage(); - QCString sep = getLanguageSpecificSeparator(lang); - if (sep!="::") - { - nsDispName=substitute(namesp,"::",sep); - cname=substitute(cname,"::",sep); - } - else - { - nsDispName=namesp; - } - - ol.writeObjectLink(cd->getReference(), - cd->getOutputFileBase(),cd->anchor(),cname); - if (!namesp.isEmpty()) - { - ol.docify(" ("); - NamespaceDef *nd = getResolvedNamespace(namesp); - if (nd && nd->isLinkable()) - { - ol.writeObjectLink(nd->getReference(), - nd->getOutputFileBase(),0,nsDispName); - } - else - { - ol.docify(nsDispName); - } - ol.docify(")"); - } - ol.writeNonBreakableSpace(3); - } - ++(*colIterators[j]); - if (cell->letter()!=0 || cell->classDef()!=(ClassDef*)0x8) - { - ol.writeString("</td>\n"); - } - } + nsDispName=substitute(namesp,"::",sep); + cname=substitute(cname,"::",sep); } else { - cellCont = true; - ol.writeString("<td></td>"); + nsDispName=namesp; } - } - } - if (!cellCont) ol.writeString("<td></td>"); // we need at least one cell in case of xhtml - ol.writeString("</tr>\n"); - } - ol.writeString("</table>\n"); - ol.writeString(alphaLinks); + ol.writeObjectLink(cd->getReference(), + cd->getOutputFileBase(),cd->anchor(),cname); + if (!namesp.isEmpty()) + { + ol.writeString(" ("); + NamespaceDef *nd = getResolvedNamespace(namesp); + if (nd && nd->isLinkable()) + { + ol.writeObjectLink(nd->getReference(), + nd->getOutputFileBase(),0,nsDispName); + } + else + { + ol.docify(nsDispName); + } + ol.writeString(")"); + } + ol.writeString("</dd>"); + } - // release the temporary memory - for (i=0;i<columns;i++) - { - delete colIterators[i]; + ol.writeString("</dl>\n"); + } + ol.writeString("</div>\n"); } - delete[] colIterators; } //---------------------------------------------------------------------------- @@ -2425,26 +2388,50 @@ static void writeAlphabeticalExceptionIndex(OutputList &ol) //---------------------------------------------------------------------------- -static void writeAnnotatedIndex(OutputList &ol) +struct AnnotatedIndexContext +{ + AnnotatedIndexContext(int numAnno,int numPrint, + LayoutNavEntry::Kind lk,LayoutNavEntry::Kind fk, + const QCString &title,const QCString &intro, + ClassDef::CompoundType ct, + const QCString &fn, + HighlightedItem hi) : + numAnnotated(numAnno), numPrinted(numPrint), + listKind(lk), fallbackKind(fk), + listDefaultTitleText(title), listDefaultIntroText(intro), + compoundType(ct),fileBaseName(fn), + hiItem(hi) { } + + const int numAnnotated; + const int numPrinted; + const LayoutNavEntry::Kind listKind; + const LayoutNavEntry::Kind fallbackKind; + const QCString listDefaultTitleText; + const QCString listDefaultIntroText; + const ClassDef::CompoundType compoundType; + const QCString fileBaseName; + const HighlightedItem hiItem; +}; + +static void writeAnnotatedIndexGeneric(OutputList &ol,const AnnotatedIndexContext ctx) { //printf("writeAnnotatedIndex: count=%d printed=%d\n", // annotatedClasses,annotatedClassesPrinted); - if (annotatedClasses==0) return; + if (ctx.numAnnotated==0) return; ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); - if (annotatedClassesPrinted==0) + if (ctx.numPrinted==0) { ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::RTF); } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Classes); // fall back - QCString title = lne ? lne->title() : theTranslator->trCompoundList(); + LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(ctx.listKind); + if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(ctx.fallbackKind); // fall back + QCString title = lne ? lne->title() : ctx.listDefaultTitleText; bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotated",0,title,HLI_AnnotatedClasses); + startFile(ol,ctx.fileBaseName,0,title,ctx.hiItem); startTitle(ol,0); ol.parseText(title); @@ -2453,7 +2440,7 @@ static void writeAnnotatedIndex(OutputList &ol) ol.startContents(); ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trCompoundListDescription()); + ol.parseText(lne ? lne->intro() : ctx.listDefaultIntroText); ol.endTextBlock(); // --------------- @@ -2463,7 +2450,7 @@ static void writeAnnotatedIndex(OutputList &ol) ol.disable(OutputGenerator::Html); Doxygen::indexList->disable(); - writeAnnotatedClassList(ol, ClassDef::Class); + writeAnnotatedClassList(ol, ctx.compoundType); Doxygen::indexList->enable(); ol.popGeneratorState(); @@ -2477,17 +2464,16 @@ static void writeAnnotatedIndex(OutputList &ol) { if (addToIndex) { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotated",0,TRUE,TRUE); + Doxygen::indexList->addContentsItem(TRUE,title,0,ctx.fileBaseName,0,TRUE,TRUE); Doxygen::indexList->incContentsDepth(); } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Class); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Class); + FTVHelp ftv(false); + writeClassTreeInsideNamespace(*Doxygen::namespaceLinkedMap,&ftv,TRUE,addToIndex,ctx.compoundType); + writeClassTree(*Doxygen::classLinkedMap,&ftv,addToIndex,TRUE,ctx.compoundType); QGString outStr; FTextStream t(&outStr); - ftv->generateTreeViewInline(t); + ftv.generateTreeViewInline(t); ol.writeString(outStr); - delete ftv; if (addToIndex) { Doxygen::indexList->decContentsDepth(); @@ -2503,233 +2489,58 @@ static void writeAnnotatedIndex(OutputList &ol) //---------------------------------------------------------------------------- -static void writeAnnotatedInterfaceIndex(OutputList &ol) +static void writeAnnotatedIndex(OutputList &ol) { - //printf("writeAnnotatedInterfaceIndex: count=%d printed=%d\n", - // annotatedInterfaces,annotatedInterfacesPrinted); - if (annotatedInterfaces==0) return; + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedClasses,annotatedClassesPrinted, + LayoutNavEntry::ClassList,LayoutNavEntry::Classes, + theTranslator->trCompoundList(),theTranslator->trCompoundListDescription(), + ClassDef::Class, + "annotated", + HLI_AnnotatedClasses)); - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - if (annotatedInterfacesPrinted==0) - { - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Interfaces); // fall back - QCString title = lne ? lne->title() : theTranslator->trInterfaceList(); - bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotatedinterfaces",0,title,HLI_AnnotatedInterfaces); - - startTitle(ol,0); - ol.parseText(title); - endTitle(ol,0,0); - - ol.startContents(); - - ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trInterfaceListDescription()); - ol.endTextBlock(); - - // --------------- - // Linear interface index for Latex/RTF - // --------------- - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - Doxygen::indexList->disable(); - - writeAnnotatedClassList(ol, ClassDef::Interface); - - Doxygen::indexList->enable(); - ol.popGeneratorState(); - - // --------------- - // Hierarchical interface index for HTML - // --------------- - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); +} - { - if (addToIndex) - { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedinterfaces",0,TRUE,TRUE); - Doxygen::indexList->incContentsDepth(); - } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Interface); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Interface); - QGString outStr; - FTextStream t(&outStr); - ftv->generateTreeViewInline(t); - ol.writeString(outStr); - delete ftv; - if (addToIndex) - { - Doxygen::indexList->decContentsDepth(); - } - } +//---------------------------------------------------------------------------- - ol.popGeneratorState(); - // ------ +static void writeAnnotatedInterfaceIndex(OutputList &ol) +{ + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedInterfaces,annotatedInterfacesPrinted, + LayoutNavEntry::InterfaceList,LayoutNavEntry::Interfaces, + theTranslator->trInterfaceList(),theTranslator->trInterfaceListDescription(), + ClassDef::Interface, + "annotatedinterfaces", + HLI_AnnotatedInterfaces)); - endFile(ol); // contains ol.endContents() - ol.popGeneratorState(); } //---------------------------------------------------------------------------- static void writeAnnotatedStructIndex(OutputList &ol) { - //printf("writeAnnotatedStructIndex: count=%d printed=%d\n", - // annotatedStructs,annotatedStructsPrinted); - if (annotatedStructs==0) return; - - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - if (annotatedStructsPrinted==0) - { - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::StructList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Structs); // fall back - QCString title = lne ? lne->title() : theTranslator->trStructList(); - bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotatedstructs",0,title,HLI_AnnotatedStructs); - - startTitle(ol,0); - ol.parseText(title); - endTitle(ol,0,0); - - ol.startContents(); - - ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trStructListDescription()); - ol.endTextBlock(); - - // --------------- - // Linear struct index for Latex/RTF - // --------------- - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - Doxygen::indexList->disable(); - - writeAnnotatedClassList(ol, ClassDef::Struct); - - Doxygen::indexList->enable(); - ol.popGeneratorState(); - - // --------------- - // Hierarchical struct index for HTML - // --------------- - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - - { - if (addToIndex) - { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedstructs",0,TRUE,TRUE); - Doxygen::indexList->incContentsDepth(); - } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Struct); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Struct); - QGString outStr; - FTextStream t(&outStr); - ftv->generateTreeViewInline(t); - ol.writeString(outStr); - delete ftv; - if (addToIndex) - { - Doxygen::indexList->decContentsDepth(); - } - } + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedStructs,annotatedStructsPrinted, + LayoutNavEntry::StructList,LayoutNavEntry::Structs, + theTranslator->trStructList(),theTranslator->trStructListDescription(), + ClassDef::Struct, + "annotatedstructs", + HLI_AnnotatedStructs)); - ol.popGeneratorState(); - // ------ - - endFile(ol); // contains ol.endContents() - ol.popGeneratorState(); } //---------------------------------------------------------------------------- static void writeAnnotatedExceptionIndex(OutputList &ol) { - //printf("writeAnnotatedExceptionIndex: count=%d printed=%d\n", - // annotatedExceptions,annotatedExceptionsPrinted); - if (annotatedExceptions==0) return; - - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - if (annotatedExceptionsPrinted==0) - { - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Exceptions); // fall back - QCString title = lne ? lne->title() : theTranslator->trExceptionList(); - bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotatedexceptions",0,title,HLI_AnnotatedExceptions); - - startTitle(ol,0); - ol.parseText(title); - endTitle(ol,0,0); - - ol.startContents(); - - ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trExceptionListDescription()); - ol.endTextBlock(); - - // --------------- - // Linear interface index for Latex/RTF - // --------------- - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - Doxygen::indexList->disable(); - - writeAnnotatedClassList(ol, ClassDef::Exception); + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedExceptions,annotatedExceptionsPrinted, + LayoutNavEntry::ExceptionList,LayoutNavEntry::Exceptions, + theTranslator->trExceptionList(),theTranslator->trExceptionListDescription(), + ClassDef::Exception, + "annotatedexceptions", + HLI_AnnotatedExceptions)); - Doxygen::indexList->enable(); - ol.popGeneratorState(); - - // --------------- - // Hierarchical interface index for HTML - // --------------- - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - - { - if (addToIndex) - { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedexceptions",0,TRUE,TRUE); - Doxygen::indexList->incContentsDepth(); - } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Exception); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Exception); - QGString outStr; - FTextStream t(&outStr); - ftv->generateTreeViewInline(t); - ol.writeString(outStr); - delete ftv; - if (addToIndex) - { - Doxygen::indexList->decContentsDepth(); - } - } - - ol.popGeneratorState(); - // ------ - - endFile(ol); // contains ol.endContents() - ol.popGeneratorState(); } //---------------------------------------------------------------------------- @@ -2777,7 +2588,7 @@ static void writeNamespaceLinkForMember(OutputList &ol,MemberDef *md,const char static void writeMemberList(OutputList &ol,bool useSections,int page, const LetterToIndexMap<MemberIndexList> &memberLists, - DefinitionIntf::DefType type) + Definition::DefType type) { int index = (int)type; ASSERT(index<3); @@ -3977,7 +3788,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* // write group info bool hasSubGroups = gd->getSubGroups()->count()>0; bool hasSubPages = gd->getPages()->count()>0; - int numSubItems = 0; + size_t numSubItems = 0; if (1 /*Config_getBool(TOC_EXPAND)*/) { QListIterator<MemberList> mli(gd->getMemberLists()); @@ -3989,10 +3800,10 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* numSubItems += ml->count(); } } - numSubItems += gd->getNamespaces()->count(); - numSubItems += gd->getClasses()->count(); + numSubItems += gd->getNamespaces().size(); + numSubItems += gd->getClasses().size(); numSubItems += gd->getFiles()->count(); - numSubItems += static_cast<int>(gd->getDirs().size()); + numSubItems += gd->getDirs().size(); numSubItems += gd->getPages()->count(); } @@ -4070,9 +3881,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* } else if (lde->kind()==LayoutDocEntry::GroupClasses && addToIndex) { - ClassSDict::Iterator it(*gd->getClasses()); - ClassDef *cd; - for (;(cd=it.current());++it) + for (const auto &cd : gd->getClasses()) { //bool nestedClassInSameGroup = // cd->getOuterScope() && cd->getOuterScope()->definitionType()==Definition::TypeClass && @@ -4097,9 +3906,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* } else if (lde->kind()==LayoutDocEntry::GroupNamespaces && addToIndex) { - NamespaceSDict::Iterator it(*gd->getNamespaces()); - NamespaceDef *nd; - for (;(nd=it.current());++it) + for (const auto &nd : gd->getNamespaces()) { if (nd->isVisible()) { @@ -4125,7 +3932,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* } else if (lde->kind()==LayoutDocEntry::GroupDirs && addToIndex) { - for (const auto dd : gd->getDirs()) + for (const auto &dd : gd->getDirs()) { if (dd->isVisible()) { @@ -4147,7 +3954,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* bool hasSections = pd->hasSections(); Doxygen::indexList->addContentsItem( hasSubPages || hasSections, - convertToHtml(pd->title(),TRUE), + pd->title(), gd->getReference(), gd->getOutputFileBase(), si ? si->label().data() : 0, @@ -4499,7 +4306,7 @@ static void writeIndex(OutputList &ol) { ol.startHeaderSection(); ol.startTitleHead(0); - ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->docLine(), + ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->getStartBodyLine(), Doxygen::mainPage,0,Doxygen::mainPage->title(),TRUE,FALSE, 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); headerWritten = TRUE; diff --git a/src/index.h b/src/index.h index f571375..6cca60d 100644 --- a/src/index.h +++ b/src/index.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 <qcstring.h> class Definition; +class DefinitionMutable; class MemberDef; class OutputList; class FTextStream; @@ -36,7 +37,7 @@ class IndexIntf virtual void finalize() = 0; virtual void incContentsDepth() = 0; virtual void decContentsDepth() = 0; - virtual void addContentsItem(bool isDir, const char *name, const char *ref, + virtual void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor, bool separateIndex, bool addToNavIndex,const Definition *def) = 0; virtual void addIndexItem(const Definition *context,const MemberDef *md, @@ -73,7 +74,7 @@ class IndexList : public IndexIntf /** Creates a list of indexes */ IndexList() { m_intfs.setAutoDelete(TRUE); m_enabled=TRUE; } /** Add an index generator to the list */ - void addIndex(IndexIntf *intf) + void addIndex(IndexIntf *intf) { m_intfs.append(intf); } void disable() { m_enabled = FALSE; } @@ -83,25 +84,25 @@ class IndexList : public IndexIntf { return m_enabled; } // IndexIntf implementation - void initialize() + void initialize() { foreach(&IndexIntf::initialize); } - void finalize() + void finalize() { foreach(&IndexIntf::finalize); } void incContentsDepth() { if (m_enabled) foreach(&IndexIntf::incContentsDepth); } void decContentsDepth() { if (m_enabled) foreach(&IndexIntf::decContentsDepth); } - void addContentsItem(bool isDir, const char *name, const char *ref, + void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor,bool separateIndex=FALSE,bool addToNavIndex=FALSE, const Definition *def=0) { if (m_enabled) foreach(&IndexIntf::addContentsItem,isDir,name,ref,file,anchor,separateIndex,addToNavIndex,def); } void addIndexItem(const Definition *context,const MemberDef *md,const char *sectionAnchor=0,const char *title=0) { if (m_enabled) foreach(&IndexIntf::addIndexItem,context,md,sectionAnchor,title); } - void addIndexFile(const char *name) + void addIndexFile(const char *name) { if (m_enabled) foreach(&IndexIntf::addIndexFile,name); } - void addImageFile(const char *name) + void addImageFile(const char *name) { if (m_enabled) foreach(&IndexIntf::addImageFile,name); } - void addStyleSheetFile(const char *name) + void addStyleSheetFile(const char *name) { if (m_enabled) foreach(&IndexIntf::addStyleSheetFile,name); } private: @@ -244,7 +245,7 @@ extern int documentedDirs; extern int documentedHtmlFiles; extern int documentedPages; -void startTitle(OutputList &ol,const char *fileName,const Definition *def=0); +void startTitle(OutputList &ol,const char *fileName,const DefinitionMutable *def=0); void endTitle(OutputList &ol,const char *fileName,const char *name); void startFile(OutputList &ol,const char *name,const char *manName, const char *title,HighlightedItem hli=HLI_None, diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 19f01b0..fbb6530 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -175,7 +175,7 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s) } -LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, +LatexDocVisitor::LatexDocVisitor(FTextStream &t,LatexCodeGenerator &ci, 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), @@ -351,13 +351,10 @@ void LatexDocVisitor::visit(DocVerbatim *s) { case DocVerbatim::Code: { - m_t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCode}\n"; + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); + m_ci.endCodeFragment("DoxyCode"); } break; case DocVerbatim::Verbatim: @@ -461,44 +458,40 @@ void LatexDocVisitor::visit(DocInclude *inc) { case DocInclude::IncWithLines: { - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - QFileInfo cfi( inc->file() ); - FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile(), - fd, // fileDef, - -1, // start line - -1, // end line - FALSE, // inline fragment - 0, // memberDef - TRUE // show line numbers - ); - delete fd; - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + m_ci.startCodeFragment("DoxyCodeInclude"); + QFileInfo cfi( inc->file() ); + FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile(), + fd, // fileDef, + -1, // start line + -1, // end line + FALSE, // inline fragment + 0, // memberDef + TRUE // show line numbers + ); + delete fd; + m_ci.endCodeFragment("DoxyCodeInclude"); } break; case DocInclude::Include: - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(),langExt,inc->isExample(), - inc->exampleFile(), - 0, // fileDef - -1, // startLine - -1, // endLine - TRUE, // inlineFragment - 0, // memberDef - FALSE - ); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}\n"; + { + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(),langExt,inc->isExample(), + inc->exampleFile(), + 0, // fileDef + -1, // startLine + -1, // endLine + TRUE, // inlineFragment + 0, // memberDef + FALSE + ); + m_ci.endCodeFragment("DoxyCodeInclude"); + } break; case DocInclude::DontInclude: case DocInclude::DontIncWithLines: @@ -518,43 +511,37 @@ void LatexDocVisitor::visit(DocInclude *inc) break; case DocInclude::Snippet: { - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile() - ); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile() + ); + m_ci.endCodeFragment("DoxyCodeInclude"); } break; case DocInclude::SnipWithLines: { - QFileInfo cfi( inc->file() ); - FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile(), - fd, - lineBlock(inc->text(),inc->blockId()), - -1, // endLine - FALSE, // inlineFragment - 0, // memberDef - TRUE // show line number - ); - delete fd; - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + QFileInfo cfi( inc->file() ); + FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile(), + fd, + lineBlock(inc->text(),inc->blockId()), + -1, // endLine + FALSE, // inlineFragment + 0, // memberDef + TRUE // show line number + ); + delete fd; + m_ci.endCodeFragment("DoxyCodeInclude"); } break; case DocInclude::SnippetDoc: @@ -571,8 +558,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) // op->type(),op->isFirst(),op->isLast(),op->text().data()); if (op->isFirst()) { - if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); + if (!m_hide) m_ci.startCodeFragment("DoxyCodeInclude"); pushEnabled(); m_hide = TRUE; } @@ -591,16 +577,15 @@ void LatexDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, - op->isExample(),op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, + op->isExample(),op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); @@ -609,8 +594,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) if (op->isLast()) { popEnabled(); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - if (!m_hide) m_t << "\n\\end{DoxyCodeInclude}\n"; + if (!m_hide) m_ci.endCodeFragment("DoxyCodeInclude"); } else { @@ -1504,7 +1488,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) if (m_hide) return; bool hasInOutSpecs = s->hasInOutSpecifier(); bool hasTypeSpecs = s->hasTypeSpecifier(); - incUsedTableLevels(); + m_ci.incUsedTableLevel(); switch(s->type()) { case DocParamSect::Param: @@ -1535,7 +1519,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) void LatexDocVisitor::visitPost(DocParamSect *s) { if (m_hide) return; - decUsedTableLevels(); + m_ci.decUsedTableLevel(); switch(s->type()) { case DocParamSect::Param: @@ -1754,7 +1738,13 @@ void LatexDocVisitor::visitPost(DocParBlock *) void LatexDocVisitor::filter(const char *str) { - filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem); + filterLatexString(m_t,str, + m_insideTabbing, + m_insidePre, + m_insideItem, + m_ci.usedTableLevel()>0, // insideTable + false // keepSpaces + ); } void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable) diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index 71fb5be..003d780 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.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. * @@ -25,19 +25,19 @@ #include <qlist.h> class FTextStream; -class CodeOutputInterface; +class LatexCodeGenerator; /*! @brief Concrete visitor implementation for LaTeX output. */ class LatexDocVisitor : public DocVisitor { public: - LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, + LatexDocVisitor(FTextStream &t,LatexCodeGenerator &ci, const char *langExt,bool insideTabbing); - + //-------------------------------------- // visitor functions for leaf nodes //-------------------------------------- - + void visit(DocWord *); void visit(DocLinkedWord *); void visit(DocWhiteSpace *); @@ -59,7 +59,7 @@ class LatexDocVisitor : public DocVisitor //-------------------------------------- // visitor functions for compound nodes //-------------------------------------- - + void visitPre(DocAutoList *); void visitPost(DocAutoList *); void visitPre(DocAutoListItem *); @@ -141,7 +141,7 @@ class LatexDocVisitor : public DocVisitor struct ActiveRowSpan { - ActiveRowSpan(DocHtmlCell *c,int rs,int cs,int col) + ActiveRowSpan(DocHtmlCell *c,int rs,int cs,int col) : cell(c), rowSpan(rs), colSpan(cs), column(col) {} DocHtmlCell *cell; int rowSpan; @@ -152,9 +152,9 @@ class LatexDocVisitor : public DocVisitor typedef QList<ActiveRowSpan> RowSpanList; //-------------------------------------- - // helper functions + // helper functions //-------------------------------------- - + void filter(const char *str); void startLink(const QCString &ref,const QCString &file, const QCString &anchor,bool refToTable=FALSE); @@ -184,7 +184,7 @@ class LatexDocVisitor : public DocVisitor //-------------------------------------- FTextStream &m_t; - CodeOutputInterface &m_ci; + LatexCodeGenerator &m_ci; bool m_insidePre; bool m_insideItem; bool m_hide; @@ -195,7 +195,7 @@ class LatexDocVisitor : public DocVisitor struct TableState { - TableState() : numCols(0), currentColumn(0), inRowSpan(FALSE), + TableState() : numCols(0), currentColumn(0), inRowSpan(FALSE), inColSpan(FALSE), firstRow(FALSE) { rowSpans.setAutoDelete(TRUE); } RowSpanList rowSpans; diff --git a/src/latexgen.cpp b/src/latexgen.cpp index cb42863..bfde4d1 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -44,18 +44,14 @@ #include "resourcemgr.h" #include "portable.h" -static bool DoxyCodeOpen = FALSE; -static bool DoxyCodeLineOpen = FALSE; -//------------------------------- - LatexCodeGenerator::LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFileName) - : m_relPath(relPath), m_sourceFileName(sourceFileName), m_col(0) + : m_relPath(relPath), m_sourceFileName(sourceFileName) { m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); setTextStream(t); } -LatexCodeGenerator::LatexCodeGenerator() : m_streamSet(FALSE), m_col(0) +LatexCodeGenerator::LatexCodeGenerator() { m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); } @@ -84,9 +80,9 @@ void LatexCodeGenerator::codify(const char *str) signed char c; //char cs[5]; int spacesToNextTabStop; - static int tabSize = Config_getInt(TAB_SIZE); - static signed char *result = NULL; - static int lresult = 0; + int tabSize = Config_getInt(TAB_SIZE); + static THREAD_LOCAL signed char *result = NULL; + static THREAD_LOCAL int lresult = 0; int i; while ((c=*p)) { @@ -108,7 +104,9 @@ void LatexCodeGenerator::codify(const char *str) m_col+=spacesToNextTabStop; p++; break; - case '\n': (usedTableLevels()>0 && !DoxyCodeOpen) ? m_t << "\\newline\n" : m_t << '\n'; m_col=0; p++; + case '\n': m_t << '\n'; + m_col=0; + p++; break; default: i=0; @@ -149,14 +147,13 @@ void LatexCodeGenerator::codify(const char *str) COPYCHAR(); } result[i]=0; // add terminator - //if (m_prettyCode) - //{ - filterLatexString(m_t,(const char *)result,FALSE,TRUE); - //} - //else - //{ - // t << result; - //} + filterLatexString(m_t,(const char *)result, + false, // insideTabbing + true, // insidePre + false, // insideItem + m_usedTableLevel>0, // insideTable + false // keepSpaces + ); break; } } @@ -168,8 +165,8 @@ void LatexCodeGenerator::writeCodeLink(const char *ref,const char *f, const char *anchor,const char *name, const char *) { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool usePDFLatex = Config_getBool(USE_PDFLATEX); int l = qstrlen(name); if (!ref && usePDFLatex && pdfHyperlinks) { @@ -190,12 +187,12 @@ void LatexCodeGenerator::writeCodeLink(const char *ref,const char *f, void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l) { - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - if (!DoxyCodeLineOpen) + bool usePDFLatex = Config_getBool(USE_PDFLATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + if (!m_doxyCodeLineOpen) { m_t << "\\DoxyCodeLine{"; - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = TRUE; } if (m_prettyCode) { @@ -231,19 +228,19 @@ void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,co void LatexCodeGenerator::startCodeLine(bool) { m_col=0; - if (!DoxyCodeLineOpen) + if (!m_doxyCodeLineOpen) { m_t << "\\DoxyCodeLine{"; - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = TRUE; } } void LatexCodeGenerator::endCodeLine() { - if (DoxyCodeLineOpen) + if (m_doxyCodeLineOpen) { m_t << "}"; - DoxyCodeLineOpen = FALSE; + m_doxyCodeLineOpen = FALSE; } codify("\n"); } @@ -258,23 +255,40 @@ void LatexCodeGenerator::endFontClass() m_t << "}"; } -void LatexCodeGenerator::setDoxyCodeOpen(bool val) +void LatexCodeGenerator::startCodeFragment(const char *style) { - DoxyCodeOpen = val; + m_t << "\n\\begin{" << style << "}{" << m_usedTableLevel << "}\n"; +} + +void LatexCodeGenerator::endCodeFragment(const char *style) +{ + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + m_t << "\\end{" << style << "}\n"; } + //------------------------------- -LatexGenerator::LatexGenerator() : OutputGenerator() +LatexGenerator::LatexGenerator() : OutputGenerator(Config_getString(LATEX_OUTPUT)) { - m_dir=Config_getString(LATEX_OUTPUT); //printf("LatexGenerator::LatexGenerator() m_insideTabbing=FALSE\n"); - m_insideTabbing=FALSE; - m_firstDescItem=TRUE; - m_disableLinks=FALSE; - m_indent=0; - templateMemberItem = FALSE; - m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); +} + +LatexGenerator::LatexGenerator(const LatexGenerator &og) : OutputGenerator(og) +{ +} + +LatexGenerator &LatexGenerator::operator=(const LatexGenerator &og) +{ + OutputGenerator::operator=(og); + return *this; +} + +std::unique_ptr<OutputGenerator> LatexGenerator::clone() const +{ + return std::make_unique<LatexGenerator>(*this); } LatexGenerator::~LatexGenerator() @@ -284,8 +298,7 @@ LatexGenerator::~LatexGenerator() static void writeLatexMakefile() { bool generateBib = !CitationManager::instance().isEmpty(); - QCString dir=Config_getString(LATEX_OUTPUT); - QCString fileName=dir+"/Makefile"; + QCString fileName=Config_getString(LATEX_OUTPUT)+"/Makefile"; QFile file(fileName); if (!file.open(IO_WriteOnly)) { @@ -463,12 +476,11 @@ static void writeMakeBat() void LatexGenerator::init() { - - QCString dir=Config_getString(LATEX_OUTPUT); - QDir d(dir); - if (!d.exists() && !d.mkdir(dir)) + QCString dname = Config_getString(LATEX_OUTPUT); + QDir d(dname); + if (!d.exists() && !d.mkdir(dname)) { - term("Could not create output directory %s\n",dir.data()); + term("Could not create output directory %s\n",dname.data()); } writeLatexMakefile(); @@ -509,7 +521,6 @@ static void writeDefaultHeaderPart1(FTextStream &t) // Load required packages t << "% Packages required by doxygen\n" "\\usepackage{fixltx2e}\n" // for \textsubscript - "\\usepackage{calc}\n" "\\usepackage{doxygen}\n"; const StringVector &extraLatexStyles = Config_getList(LATEX_EXTRA_STYLESHEET); for (const auto &extraStyle : extraLatexStyles) @@ -535,13 +546,10 @@ static void writeDefaultHeaderPart1(FTextStream &t) t << "\\usepackage{graphicx}\n" "\\usepackage[utf8]{inputenc}\n" "\\usepackage{makeidx}\n" - "\\usepackage{multicol}\n" - "\\usepackage{multirow}\n" "\\PassOptionsToPackage{warn}{textcomp}\n" "\\usepackage{textcomp}\n" "\\usepackage[nointegrals]{wasysym}\n" - "\\usepackage[table]{xcolor}\n" - "\\usepackage{ifpdf,ifxetex}\n" + "\\usepackage{ifxetex}\n" "\n"; // Language support @@ -565,8 +573,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) { t << font; } - t << "\\usepackage{amssymb}\n" - "\\usepackage{sectsty}\n" + t << "\\usepackage{sectsty}\n" "\\allsectionsfont{%\n" " \\fontseries{bc}\\selectfont%\n" " \\color{darkgray}%\n" @@ -634,7 +641,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) // Headers & footers QGString genString; QCString generatedBy; - static bool timeStamp = Config_getBool(LATEX_TIMESTAMP); + bool timeStamp = Config_getBool(LATEX_TIMESTAMP); FTextStream tg(&genString); if (timeStamp) { @@ -644,23 +651,34 @@ static void writeDefaultHeaderPart1(FTextStream &t) { generatedBy = theTranslator->trGeneratedBy(); } - filterLatexString(tg, generatedBy, FALSE,FALSE,FALSE); + filterLatexString(tg, generatedBy, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); t << "% Headers & footers\n" "\\usepackage{fancyhdr}\n" "\\pagestyle{fancyplain}\n" - "\\fancyhead[LE]{\\fancyplain{}{\\bfseries\\thepage}}\n" - "\\fancyhead[CE]{\\fancyplain{}{}}\n" - "\\fancyhead[RE]{\\fancyplain{}{\\bfseries\\leftmark}}\n" - "\\fancyhead[LO]{\\fancyplain{}{\\bfseries\\rightmark}}\n" - "\\fancyhead[CO]{\\fancyplain{}{}}\n" - "\\fancyhead[RO]{\\fancyplain{}{\\bfseries\\thepage}}\n" - "\\fancyfoot[LE]{\\fancyplain{}{}}\n" - "\\fancyfoot[CE]{\\fancyplain{}{}}\n" - "\\fancyfoot[RE]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n" - "\\fancyfoot[LO]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n" - "\\fancyfoot[CO]{\\fancyplain{}{}}\n" - "\\fancyfoot[RO]{\\fancyplain{}{}}\n" - "\\renewcommand{\\footrulewidth}{0.4pt}\n"; + "\\renewcommand{\\footrulewidth}{0.4pt}\n" + "%\n" + "\\fancypagestyle{fancyplain}{\n" + "\\fancyhf{}\n" + "\\fancyhead[LE, RO]{\\bfseries\\thepage}\n" + "\\fancyhead[LO]{\\bfseries\\rightmark}\n" + "\\fancyhead[RE]{\\bfseries\\leftmark}\n" + "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n" + "}\n" + "%\n" + "\\fancypagestyle{plain}{\n" + "\\fancyhf{}\n" + "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n" + "\\renewcommand{\\headrulewidth}{0pt}}\n" + "%\n" + "\\pagestyle{fancyplain}\n" + "%\n"; + if (!Config_getBool(COMPACT_LATEX)) { t << "\\renewcommand{\\chaptermark}[1]{%\n" @@ -698,11 +716,10 @@ static void writeDefaultHeaderPart1(FTextStream &t) QCString macroFile = Config_getString(FORMULA_MACROFILE); if (!macroFile.isEmpty()) { - QCString dir=Config_getString(LATEX_OUTPUT); QFileInfo fi(macroFile); macroFile=fi.absFilePath().utf8(); QCString stripMacroFile = fi.fileName().data(); - copyFile(macroFile,dir + "/" + stripMacroFile); + copyFile(macroFile,Config_getString(LATEX_OUTPUT) + "/" + stripMacroFile); t << "\\input{" << stripMacroFile << "}" << endl; } @@ -752,7 +769,8 @@ static void writeDefaultHeaderPart1(FTextStream &t) // End of preamble, now comes the document contents t << "%===== C O N T E N T S =====\n" "\n" - "\\begin{document}\n"; + "\\begin{document}\n" + "\\raggedbottom\n"; QCString documentPre = theTranslator->latexDocumentPre(); if (!documentPre.isEmpty()) { @@ -884,7 +902,7 @@ void LatexGenerator::writeStyleSheetFile(QFile &f) writeDefaultStyleSheet(t); } -void LatexGenerator::startFile(const char *name,const char *,const char *) +void LatexGenerator::startFile(const char *name,const char *,const char *,int) { #if 0 setEncoding(Config_getString(LATEX_OUTPUT_ENCODING)); @@ -982,14 +1000,13 @@ void LatexGenerator::startIndexSection(IndexSections is) { GroupSDict::Iterator gli(*Doxygen::groupSDict); GroupDef *gd; - bool found=FALSE; - for (gli.toFirst();(gd=gli.current()) && !found;++gli) + for (gli.toFirst();(gd=gli.current());++gli) { if (!gd->isReference()) { if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; t << "{"; //Module Documentation}\n"; - found=TRUE; + break; } } } @@ -998,49 +1015,43 @@ void LatexGenerator::startIndexSection(IndexSections is) { SDict<DirDef>::Iterator dli(*Doxygen::directories); DirDef *dd; - bool found=FALSE; - for (dli.toFirst();(dd=dli.current()) && !found;++dli) + for (dli.toFirst();(dd=dli.current());++dli) { if (dd->isLinkableInProject()) { if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; t << "{"; //Module Documentation}\n"; - found=TRUE; + break; } } } break; case isNamespaceDocumentation: { - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - bool found=FALSE; - for (nli.toFirst();(nd=nli.current()) && !found;++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; t << "{"; // Namespace Documentation}\n": - found=TRUE; + break; } } } break; case isClassDocumentation: { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - bool found=FALSE; - for (cli.toFirst();(cd=cli.current()) && !found;++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; t << "{"; //Compound Documentation}\n"; - found=TRUE; + break; } } } @@ -1087,10 +1098,10 @@ void LatexGenerator::startIndexSection(IndexSections is) void LatexGenerator::endIndexSection(IndexSections is) { - //static bool compactLatex = Config_getBool(COMPACT_LATEX); - static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); - static QCString latexHeader = Config_getString(LATEX_HEADER); - static QCString latexFooter = Config_getString(LATEX_FOOTER); + //bool compactLatex = Config_getBool(COMPACT_LATEX); + bool sourceBrowser = Config_getBool(SOURCE_BROWSER); + QCString latexHeader = Config_getString(LATEX_HEADER); + QCString latexFooter = Config_getString(LATEX_FOOTER); switch (is) { case isTitlePageStart: @@ -1181,55 +1192,38 @@ void LatexGenerator::endIndexSection(IndexSections is) break; case isNamespaceDocumentation: { - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; bool found=FALSE; - for (nli.toFirst();(nd=nli.current()) && !found;++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { - t << "}\n\\input{" << nd->getOutputFileBase() << "}\n"; - found=TRUE; - } - } - while ((nd=nli.current())) - { - if (nd->isLinkableInProject()) - { - //if (compactLatex) t << "\\input"; else t << "\\include"; - t << "\\input"; - t << "{" << nd->getOutputFileBase() << "}\n"; + if (!found) + { + t << "}\n"; + found=true; + } + t << "\\input{" << nd->getOutputFileBase() << "}\n"; } - ++nli; } } break; case isClassDocumentation: { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; bool found=FALSE; - for (cli.toFirst();(cd=cli.current()) && !found;++cli) - { - if (cd->isLinkableInProject() && - cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() - ) - { - t << "}\n\\input{" << cd->getOutputFileBase() << "}\n"; - found=TRUE; - } - } - for (;(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { - //if (compactLatex) t << "\\input"; else t << "\\include"; - t << "\\input"; - t << "{" << cd->getOutputFileBase() << "}\n"; + if (!found) + { + t << "}\n"; // end doxysection or chapter title + found=TRUE; + } + t << "\\input{" << cd->getOutputFileBase() << "}\n"; } } } @@ -1245,24 +1239,14 @@ void LatexGenerator::endIndexSection(IndexSections is) { if (isFirst) { - t << "}\n\\input{" << fd->getOutputFileBase() << "}\n"; - if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) - { - //t << "\\include{" << fd->getSourceFileBase() << "}\n"; - t << "\\input{" << fd->getSourceFileBase() << "}\n"; - } - isFirst=FALSE; + t << "}\n"; // end doxysection or chapter title } - else + isFirst=FALSE; + t << "\\input{" << fd->getOutputFileBase() << "}\n"; + if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) { - //if (compactLatex) t << "\\input" ; else t << "\\include"; - t << "\\input" ; - t << "{" << fd->getOutputFileBase() << "}\n"; - if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) - { - //t << "\\include{" << fd->getSourceFileBase() << "}\n"; - t << "\\input{" << fd->getSourceFileBase() << "}\n"; - } + //t << "\\include{" << fd->getSourceFileBase() << "}\n"; + t << "\\input{" << fd->getSourceFileBase() << "}\n"; } } } @@ -1476,7 +1460,7 @@ void LatexGenerator::endIndexValue(const char *name,bool /*hasBrief*/) void LatexGenerator::startTextLink(const char *f,const char *anchor) { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); if (!m_disableLinks && pdfHyperlinks) { t << "\\mbox{\\hyperlink{"; @@ -1492,7 +1476,7 @@ void LatexGenerator::startTextLink(const char *f,const char *anchor) void LatexGenerator::endTextLink() { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); if (!m_disableLinks && pdfHyperlinks) { t << "}"; @@ -1503,7 +1487,7 @@ void LatexGenerator::endTextLink() void LatexGenerator::writeObjectLink(const char *ref, const char *f, const char *anchor, const char *text) { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); if (!m_disableLinks && !ref && pdfHyperlinks) { t << "\\mbox{\\hyperlink{"; @@ -1538,8 +1522,8 @@ void LatexGenerator::endPageRef(const char *clname, const char *anchor) void LatexGenerator::startTitleHead(const char *fileName) { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool usePDFLatex = Config_getBool(USE_PDFLATEX); if (usePDFLatex && pdfHyperlinks && fileName) { t << "\\hypertarget{" << stripPath(fileName) << "}{}"; @@ -1669,8 +1653,8 @@ void LatexGenerator::startMemberDoc(const char *clname, t << "}" << endl; } static const char *levelLab[] = { "doxysubsubsection","doxyparagraph","doxysubparagraph", "doxysubparagraph" }; - static bool compactLatex = Config_getBool(COMPACT_LATEX); - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool compactLatex = Config_getBool(COMPACT_LATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); int level=0; if (showInline) level+=2; if (compactLatex) level++; @@ -1706,8 +1690,8 @@ void LatexGenerator::startDoxyAnchor(const char *fName,const char *, const char *anchor, const char *, const char *) { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool usePDFLatex = Config_getBool(USE_PDFLATEX); t << "\\mbox{"; if (usePDFLatex && pdfHyperlinks) { @@ -1730,8 +1714,8 @@ void LatexGenerator::writeAnchor(const char *fName,const char *name) { //printf("LatexGenerator::writeAnchor(%s,%s)\n",fName,name); t << "\\label{" << stripPath(name) << "}" << endl; - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool usePDFLatex = Config_getBool(USE_PDFLATEX); if (usePDFLatex && pdfHyperlinks) { if (fName) @@ -1775,8 +1759,8 @@ void LatexGenerator::addIndexItem(const char *s1,const char *s2) void LatexGenerator::startSection(const char *lab,const char *,SectionType type) { - static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); + bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); + bool usePDFLatex = Config_getBool(USE_PDFLATEX); if (usePDFLatex && pdfHyperlinks) { t << "\\hypertarget{" << stripPath(lab) << "}{}"; @@ -1818,7 +1802,13 @@ void LatexGenerator::endSection(const char *lab,SectionType) void LatexGenerator::docify(const char *str) { - filterLatexString(t,str,m_insideTabbing,FALSE,FALSE); + filterLatexString(t,str, + m_insideTabbing, // insideTabbing + false, // insidePre + false, // insideItem + m_codeGen.usedTableLevel()>0, // insideTable + false // keepSpaces + ); } void LatexGenerator::writeChar(char c) @@ -1838,7 +1828,7 @@ void LatexGenerator::startClassDiagram() void LatexGenerator::endClassDiagram(const ClassDiagram &d, const char *fileName,const char *) { - d.writeFigure(t,m_dir,fileName); + d.writeFigure(t,dir(),fileName); } @@ -1955,13 +1945,13 @@ void LatexGenerator::writeNonBreakableSpace(int) void LatexGenerator::startDescTable(const char *title) { - incUsedTableLevels(); + m_codeGen.incUsedTableLevel(); t << "\\begin{DoxyEnumFields}{" << title << "}" << endl; } void LatexGenerator::endDescTable() { - decUsedTableLevels(); + m_codeGen.decUsedTableLevel(); t << "\\end{DoxyEnumFields}" << endl; } @@ -2067,7 +2057,7 @@ void LatexGenerator::startDotGraph() void LatexGenerator::endDotGraph(DotClassGraph &g) { - g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); + g.writeGraph(t,GOF_EPS,EOF_LaTeX,dir(),fileName(),m_relPath); } void LatexGenerator::startInclDepGraph() @@ -2076,7 +2066,7 @@ void LatexGenerator::startInclDepGraph() void LatexGenerator::endInclDepGraph(DotInclDepGraph &g) { - g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); + g.writeGraph(t,GOF_EPS,EOF_LaTeX,dir(),fileName(),m_relPath); } void LatexGenerator::startGroupCollaboration() @@ -2085,7 +2075,7 @@ void LatexGenerator::startGroupCollaboration() void LatexGenerator::endGroupCollaboration(DotGroupCollaboration &g) { - g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); + g.writeGraph(t,GOF_EPS,EOF_LaTeX,dir(),fileName(),m_relPath); } void LatexGenerator::startCallGraph() @@ -2094,7 +2084,7 @@ void LatexGenerator::startCallGraph() void LatexGenerator::endCallGraph(DotCallGraph &g) { - g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); + g.writeGraph(t,GOF_EPS,EOF_LaTeX,dir(),fileName(),m_relPath); } void LatexGenerator::startDirDepGraph() @@ -2103,7 +2093,7 @@ void LatexGenerator::startDirDepGraph() void LatexGenerator::endDirDepGraph(DotDirDeps &g) { - g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),m_fileName,m_relPath); + g.writeGraph(t,GOF_EPS,EOF_LaTeX,dir(),fileName(),m_relPath); } void LatexGenerator::startDescription() @@ -2206,10 +2196,10 @@ void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket) t << " "; } -void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int) { LatexDocVisitor *visitor = - new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); + new LatexDocVisitor(t,m_codeGen,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); n->accept(visitor); delete visitor; } @@ -2255,21 +2245,6 @@ void LatexGenerator::endConstraintList() t << "\\end{Desc}" << endl; } -void LatexGenerator::startCodeFragment() -{ - t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; - DoxyCodeOpen = TRUE; -} - -void LatexGenerator::endCodeFragment() -{ - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << "\\end{DoxyCode}\n"; - DoxyCodeOpen = FALSE; -} - void LatexGenerator::startInlineHeader() { if (Config_getBool(COMPACT_LATEX)) @@ -2301,7 +2276,7 @@ void LatexGenerator::lineBreak(const char *) void LatexGenerator::startMemberDocSimple(bool isEnum) { - incUsedTableLevels(); + m_codeGen.incUsedTableLevel(); if (isEnum) { t << "\\begin{DoxyEnumFields}{"; @@ -2317,7 +2292,7 @@ void LatexGenerator::startMemberDocSimple(bool isEnum) void LatexGenerator::endMemberDocSimple(bool isEnum) { - decUsedTableLevels(); + m_codeGen.decUsedTableLevel(); if (isEnum) { t << "\\end{DoxyEnumFields}" << endl; diff --git a/src/latexgen.h b/src/latexgen.h index 2c32388..6be5de7 100644 --- a/src/latexgen.h +++ b/src/latexgen.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. * @@ -18,6 +18,7 @@ #ifndef LATEXGEN_H #define LATEXGEN_H +#include "config.h" #include "outputgen.h" class QFile; @@ -51,7 +52,13 @@ class LatexCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} - static void setDoxyCodeOpen(bool val); + void startCodeFragment(const char *style); + void endCodeFragment(const char *style); + + // extra methods not part of CodeOutputInterface + void incUsedTableLevel() { m_usedTableLevel++; } + void decUsedTableLevel() { m_usedTableLevel--; } + int usedTableLevel() const { return m_usedTableLevel; } private: void _writeCodeLink(const char *className, @@ -59,12 +66,14 @@ class LatexCodeGenerator : public CodeOutputInterface const char *anchor,const char *name, const char *tooltip); void docify(const char *str); - bool m_streamSet; + bool m_streamSet = false; FTextStream m_t; QCString m_relPath; QCString m_sourceFileName; - int m_col; - bool m_prettyCode; + int m_col = 0; + bool m_prettyCode = false; + bool m_doxyCodeLineOpen = false; + int m_usedTableLevel = 0; }; /** Generator for LaTeX output. */ @@ -72,23 +81,17 @@ class LatexGenerator : public OutputGenerator { public: LatexGenerator(); - ~LatexGenerator(); + LatexGenerator(const LatexGenerator &); + LatexGenerator &operator=(const LatexGenerator &); + virtual ~LatexGenerator(); + virtual std::unique_ptr<OutputGenerator> clone() const; + static void init(); static void writeStyleSheetFile(QFile &f); static void writeHeaderFile(QFile &f); static void writeFooterFile(QFile &f); - //OutputGenerator *copy(); - //OutputGenerator *clone() { return new LatexGenerator(*this); } - //void append(const OutputGenerator *o); - void enable() - { if (m_genStack->top()) m_active=*m_genStack->top(); else m_active=TRUE; } - void disable() { m_active=FALSE; } - void enableIf(OutputType o) { if (o==Latex) enable(); } - void disableIf(OutputType o) { if (o==Latex) disable(); } - void disableIfNot(OutputType o) { if (o!=Latex) disable(); } - bool isEnabled(OutputType o) { return (o==Latex && m_active); } - OutputGenerator *get(OutputType o) { return (o==Latex) ? this : 0; } + virtual OutputType type() const { return Latex; } // --- CodeOutputInterface void codify(const char *text) @@ -113,17 +116,21 @@ class LatexGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment(const char *style) + { m_codeGen.endCodeFragment(style); } // --------------------------- - void writeDoc(DocNode *,const Definition *ctx,const MemberDef *); + void writeDoc(DocNode *,const Definition *ctx,const MemberDef *,int id); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int id); void writeSearchInfo() {} void writeFooter(const char *) {} void endFile(); void clearBuffer(); - + void startIndexSection(IndexSections); void endIndexSection(IndexSections); void writePageLink(const char *,bool); @@ -167,7 +174,7 @@ class LatexGenerator : public OutputGenerator void endItemListItem() {} void startMemberSections() {} - void endMemberSections() {} + void endMemberSections() {} void startHeaderSection() {} void endHeaderSection() {} void startMemberHeader(const char *,int); @@ -193,14 +200,12 @@ class LatexGenerator : public OutputGenerator void endMemberGroupDocs(); void startMemberGroup(); void endMemberGroup(bool); - + void insertMemberAlign(bool) {} void insertMemberAlignLeft(int,bool){} void writeRuler() { t << endl << endl; } void writeAnchor(const char *fileName,const char *name); - void startCodeFragment(); - void endCodeFragment(); void startEmphasis() { t << "{\\em "; } void endEmphasis() { t << "}"; } void startBold() { t << "{\\bfseries "; } @@ -216,7 +221,7 @@ class LatexGenerator : public OutputGenerator void endDoxyAnchor(const char *,const char *); void writeChar(char c); void writeLatexSpacing() { t << "\\hspace{0.3cm}"; } - void writeStartAnnoItem(const char *type,const char *file, + void writeStartAnnoItem(const char *type,const char *file, const char *path,const char *name); void writeEndAnnoItem(const char *name); void startSubsection() { t << "\\subsection*{"; } @@ -229,7 +234,7 @@ class LatexGenerator : public OutputGenerator void endSmall() { t << "\\normalsize "; } void startMemberDescription(const char *,const char *,bool); void endMemberDescription(); - void startMemberDeclaration() {} + void startMemberDeclaration() {} void endMemberDeclaration(const char *,const char *) {} void writeInheritedSectionTitle(const char *,const char *,const char *, const char *,const char *,const char *) {} @@ -326,15 +331,13 @@ class LatexGenerator : public OutputGenerator private: - LatexGenerator(const LatexGenerator &); - LatexGenerator &operator=(const LatexGenerator &); - bool m_insideTabbing; - bool m_firstDescItem; - bool m_disableLinks; + bool m_insideTabbing = false; + bool m_firstDescItem = true; + bool m_disableLinks = false; QCString m_relPath; - int m_indent; - bool templateMemberItem; - bool m_prettyCode; + int m_indent = 0; + bool templateMemberItem = false; + bool m_prettyCode = Config_getBool(LATEX_SOURCE_CODE); LatexCodeGenerator m_codeGen; }; diff --git a/src/layout.cpp b/src/layout.cpp index fd31803..5cac7e1 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -16,6 +16,10 @@ * */ +#include <assert.h> +#include <qfile.h> +#include <qfileinfo.h> + #include "layout.h" #include "message.h" #include "language.h" @@ -24,38 +28,57 @@ #include "doxygen.h" #include "version.h" #include "config.h" +#include "xml.h" +#include "resourcemgr.h" -#include <assert.h> -#include <qxml.h> -#include <qfile.h> -#include <qstring.h> -#include <qfileinfo.h> -#include <qtextstream.h> - -static const char layout_default[] = -#include "layout_default.xml.h" -; +inline QCString compileOptions(const QCString &def) +{ + return def; +} -#define ADD_OPTION(langId,text) "|"+QCString().setNum(langId)+"="+text +inline QCString compileOptions(const QCString &def,SrcLangExt langId1,const QCString &value1) +{ + return compileOptions(def)+"|"+QCString().setNum(langId1)+"="+value1; +} -#define COMPILE_FOR_1_OPTION(def,langId1,text1) \ - def+ADD_OPTION(langId1,text1) +inline QCString compileOptions(const QCString &def,SrcLangExt langId1,const QCString &value1, + SrcLangExt langId2,const QCString &value2) +{ + return compileOptions(def,langId1,value1)+ + "|"+QCString().setNum(langId2)+"="+value2; +} -#define COMPILE_FOR_2_OPTIONS(def,langId1,text1,langId2,text2) \ - COMPILE_FOR_1_OPTION(def,langId1,text1)+ADD_OPTION(langId2,text2) +inline QCString compileOptions(const QCString &def,SrcLangExt langId1,const QCString &value1, + SrcLangExt langId2,const QCString &value2, + SrcLangExt langId3,const QCString &value3) +{ + return compileOptions(def,langId1,value1,langId2,value2)+ + "|"+QCString().setNum(langId3)+"="+value3; +} -#define COMPILE_FOR_3_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3) \ - COMPILE_FOR_2_OPTIONS(def,langId1,text1,langId2,text2)+ADD_OPTION(langId3,text3) +inline QCString compileOptions(const QCString &def,SrcLangExt langId1,const QCString &value1, + SrcLangExt langId2,const QCString &value2, + SrcLangExt langId3,const QCString &value3, + SrcLangExt langId4,const QCString &value4) +{ + return compileOptions(def,langId1,value1,langId2,value2,langId3,value3)+ + "|"+QCString().setNum(langId4)+"="+value4; +} -#define COMPILE_FOR_4_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3,langId4,text4) \ - COMPILE_FOR_3_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3)+ADD_OPTION(langId4,text4) +inline QCString compileOptions(const QCString &def,SrcLangExt langId1,const QCString &value1, + SrcLangExt langId2,const QCString &value2, + SrcLangExt langId3,const QCString &value3, + SrcLangExt langId4,const QCString &value4, + SrcLangExt langId5,const QCString &value5) +{ + return compileOptions(def,langId1,value1,langId2,value2,langId3,value3,langId4,value4)+ + "|"+QCString().setNum(langId5)+"="+value5; +} -#define COMPILE_FOR_5_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3,langId4,text4,langId5,text5) \ - COMPILE_FOR_4_OPTIONS(def,langId1,text1,langId2,text2,langId3,text3,langId4,text4)+ADD_OPTION(langId5,text5) -static bool elemIsVisible(const QXmlAttributes &attrib,bool defVal=TRUE) +static bool elemIsVisible(const XMLHandlers::Attributes &attrib,bool defVal=TRUE) { - QCString visible = attrib.value("visible").utf8(); + QCString visible = XMLHandlers::value(attrib,"visible"); if (visible.isEmpty()) return defVal; if (visible.at(0)=='$' && visible.length()>1) { @@ -96,6 +119,8 @@ LayoutNavEntry *LayoutNavEntry::find(LayoutNavEntry::Kind kind, return result; } + + QCString LayoutNavEntry::url() const { QCString url = baseFile().stripWhiteSpace(); @@ -132,762 +157,28 @@ QCString LayoutNavEntry::url() const //--------------------------------------------------------------------------------- -class LayoutParser : public QXmlDefaultHandler +class LayoutParser { - private: - class StartElementHandler - { - typedef void (LayoutParser::*Handler)(const QXmlAttributes &attrib); - public: - StartElementHandler(LayoutParser *parent, Handler h) - : m_parent(parent), m_handler(h) {} - virtual ~StartElementHandler() {} - virtual void operator()(const QXmlAttributes &attrib) - { - (m_parent->*m_handler)(attrib); - } - protected: - StartElementHandler() : m_parent(0), m_handler(0) {} - private: - LayoutParser *m_parent; - Handler m_handler; - }; - - class StartElementHandlerKind : public StartElementHandler - { - typedef void (LayoutParser::*Handler)(LayoutDocEntry::Kind kind, - const QXmlAttributes &attrib); - public: - 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); - } - private: - LayoutParser *m_parent; - LayoutDocEntry::Kind m_kind; - Handler m_handler; - }; - - class StartElementHandlerSection : public StartElementHandler - { - typedef void (LayoutParser::*Handler)(LayoutDocEntry::Kind kind, - const QXmlAttributes &attrib, - const QCString &title); - public: - StartElementHandlerSection(LayoutParser *parent, LayoutDocEntry::Kind k,Handler h, - 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); - } - private: - LayoutParser *m_parent; - LayoutDocEntry::Kind m_kind; - Handler m_handler; - QCString m_title; - }; - - class StartElementHandlerMember : public StartElementHandler - { - typedef void (LayoutParser::*Handler)(const QXmlAttributes &attrib, - MemberListType type, - const QCString &title, - const QCString &subtitle); - public: - 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); - } - private: - LayoutParser *m_parent; - Handler m_handler; - MemberListType m_type; - QCString m_title; - QCString m_subscript; - }; - - class StartElementHandlerNavEntry : public StartElementHandler - { - typedef void (LayoutParser::*Handler)(LayoutNavEntry::Kind kind, - const QXmlAttributes &attrib, - const QCString &title); - public: - StartElementHandlerNavEntry(LayoutParser *parent, - 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); - } - private: - LayoutParser *m_parent; - LayoutNavEntry::Kind m_kind; - Handler m_handler; - QCString m_title; - }; - - class EndElementHandler - { - typedef void (LayoutParser::*Handler)(); - public: - EndElementHandler(LayoutParser *parent, Handler h) : m_parent(parent), m_handler(h) {} - void operator()() { (m_parent->*m_handler)(); } - private: - LayoutParser *m_parent; - Handler m_handler; - }; - - public: static LayoutParser &instance() { static LayoutParser *theInstance = new LayoutParser; return *theInstance; } - void init() + + // =========== XMLHandler events + void setDocumentLocator(const XMLLocator *locator) + { + m_locator = locator; + } + void error( const std::string &fileName,int lineNr,const std::string &msg) { - m_sHandler.setAutoDelete(TRUE); - m_eHandler.setAutoDelete(TRUE); - m_part = -1; // invalid - m_rootNav = 0; - - //bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); - //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", - new StartElementHandler(this,&LayoutParser::startLayout)); - m_eHandler.insert("doxygenlayout", - new EndElementHandler(this,&LayoutParser::endLayout)); - - // class layout handlers - m_sHandler.insert("navindex", - new StartElementHandler(this,&LayoutParser::startNavIndex)); - m_sHandler.insert("navindex/tab", - new StartElementHandler(this,&LayoutParser::startNavEntry)); - m_eHandler.insert("navindex/tab", - new EndElementHandler(this,&LayoutParser::endNavEntry)); - m_eHandler.insert("navindex", - new EndElementHandler(this,&LayoutParser::endNavIndex)); - - // class layout handlers - m_sHandler.insert("class", - new StartElementHandler(this,&LayoutParser::startClass)); - m_sHandler.insert("class/briefdescription", - new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/detaileddescription", - new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, - theTranslator->trDetailedDescription())); - m_sHandler.insert("class/authorsection", - new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/includes", - new StartElementHandlerKind(this,LayoutDocEntry::ClassIncludes,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/inheritancegraph", - new StartElementHandlerKind(this,LayoutDocEntry::ClassInheritanceGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/collaborationgraph", - new StartElementHandlerKind(this,LayoutDocEntry::ClassCollaborationGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/allmemberslink", - new StartElementHandlerKind(this,LayoutDocEntry::ClassAllMembersLink,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/usedfiles", - new StartElementHandlerKind(this,LayoutDocEntry::ClassUsedFiles,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/memberdecl", - new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("class/memberdecl/membergroups", - new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("class/memberdecl/nestedclasses", - new StartElementHandlerSection(this,LayoutDocEntry::ClassNestedClasses,&LayoutParser::startSectionEntry, - COMPILE_FOR_2_OPTIONS( - theTranslator->trCompounds(), - SrcLangExt_VHDL,theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), - SrcLangExt_Fortran,theTranslator->trDataTypes() - ))); - m_sHandler.insert("class/memberdecl/services", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_services,theTranslator->trServices())); - m_sHandler.insert("class/memberdecl/interfaces", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_interfaces,theTranslator->trInterfaces())); - m_sHandler.insert("class/memberdecl/publictypes", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pubTypes,theTranslator->trPublicTypes())); - m_sHandler.insert("class/memberdecl/publicslots", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_pubStaticMethods, - COMPILE_FOR_1_OPTION( - theTranslator->trStaticPublicMembers(), - SrcLangExt_ObjC,theTranslator->trClassMethods() - ))); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_proStaticMethods,theTranslator->trStaticProtectedMembers())); - m_sHandler.insert("class/memberdecl/protectedattributes", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_related,theTranslator->trRelatedFunctions(), - theTranslator->trRelatedSubscript())); - m_eHandler.insert("class/memberdecl", - new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("class/memberdef", - new StartElementHandler(this,&LayoutParser::startMemberDef)); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_typedefMembers,theTranslator->trMemberTypedefDocumentation())); - m_sHandler.insert("class/memberdef/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_enumMembers,theTranslator->trMemberEnumerationDocumentation())); - m_sHandler.insert("class/memberdef/services", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_serviceMembers,theTranslator->trInterfaces())); - m_sHandler.insert("class/memberdef/interfaces", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_interfaceMembers,theTranslator->trInterfaces())); - m_sHandler.insert("class/memberdef/constructors", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_constructors,theTranslator->trConstructorDocumentation())); - m_sHandler.insert("class/memberdef/functions", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_functionMembers, - COMPILE_FOR_3_OPTIONS( - theTranslator->trMemberFunctionDocumentation(), - SrcLangExt_ObjC,theTranslator->trMethodDocumentation(), - SrcLangExt_Fortran,theTranslator->trMemberFunctionDocumentationFortran(), - SrcLangExt_Slice,theTranslator->trOperationDocumentation() - ))); - m_sHandler.insert("class/memberdef/related", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_relatedMembers,theTranslator->trRelatedFunctionDocumentation())); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_propertyMembers,theTranslator->trPropertyDocumentation())); - m_sHandler.insert("class/memberdef/events", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_eventMembers,theTranslator->trEventDocumentation())); - m_eHandler.insert("class/memberdef", - new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("class", - new EndElementHandler(this,&LayoutParser::endClass)); - - - // namespace layout handlers - m_sHandler.insert("namespace", - new StartElementHandler(this,&LayoutParser::startNamespace)); - m_sHandler.insert("namespace/briefdescription", - new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("namespace/detaileddescription", - new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, - theTranslator->trDetailedDescription())); - m_sHandler.insert("namespace/authorsection", - new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("namespace/memberdecl", - new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("namespace/memberdecl/nestednamespaces", - new StartElementHandlerSection(this,LayoutDocEntry::NamespaceNestedNamespaces,&LayoutParser::startSectionEntry, - COMPILE_FOR_5_OPTIONS( - theTranslator->trNamespaces(), - SrcLangExt_Java,theTranslator->trPackages(), - SrcLangExt_VHDL,theTranslator->trPackages(), - SrcLangExt_IDL,theTranslator->trModules(), - SrcLangExt_Fortran,theTranslator->trModules(), - SrcLangExt_Slice,(sliceOpt ? - theTranslator->trModules() : - theTranslator->trNamespaces())))); - m_sHandler.insert("namespace/memberdecl/constantgroups", - new StartElementHandlerSection(this,LayoutDocEntry::NamespaceNestedConstantGroups,&LayoutParser::startSectionEntry, - theTranslator->trConstantGroups())); - m_sHandler.insert("namespace/memberdecl/interfaces", - new StartElementHandlerSection(this,LayoutDocEntry::NamespaceInterfaces,&LayoutParser::startSectionEntry, - theTranslator->trSliceInterfaces())); - 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", - new StartElementHandlerSection(this,LayoutDocEntry::NamespaceStructs,&LayoutParser::startSectionEntry, - theTranslator->trStructs())); - m_sHandler.insert("namespace/memberdecl/exceptions", - new StartElementHandlerSection(this,LayoutDocEntry::NamespaceExceptions,&LayoutParser::startSectionEntry, - theTranslator->trExceptions())); - m_sHandler.insert("namespace/memberdecl/membergroups", - new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("namespace/memberdecl/typedefs", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decTypedefMembers,theTranslator->trTypedefs())); - m_sHandler.insert("namespace/memberdecl/sequences", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decSequenceMembers,theTranslator->trSequences())); - m_sHandler.insert("namespace/memberdecl/dictionaries", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decDictionaryMembers,theTranslator->trDictionaries())); - m_sHandler.insert("namespace/memberdecl/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decEnumMembers,theTranslator->trEnumerations())); - m_sHandler.insert("namespace/memberdecl/functions", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decFuncMembers, - COMPILE_FOR_2_OPTIONS( - theTranslator->trFunctions(), - SrcLangExt_Fortran,theTranslator->trSubprograms(), - SrcLangExt_VHDL,theTranslator->trFunctionAndProc() - ))); - m_sHandler.insert("namespace/memberdecl/variables", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decVarMembers, - sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables())); - m_eHandler.insert("namespace/memberdecl", - new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("namespace/memberdef", - new StartElementHandler(this,&LayoutParser::startMemberDef)); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation())); - m_sHandler.insert("namespace/memberdef/sequences", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation())); - m_sHandler.insert("namespace/memberdef/dictionaries", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docDictionaryMembers, - theTranslator->trDictionaryDocumentation())); - m_sHandler.insert("namespace/memberdef/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation())); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docVarMembers, - sliceOpt ? theTranslator->trConstantDocumentation() : - theTranslator->trVariableDocumentation())); - m_eHandler.insert("namespace/memberdef", - new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("namespace", - new EndElementHandler(this,&LayoutParser::endNamespace)); - - // file layout handlers - m_sHandler.insert("file", - new StartElementHandler(this,&LayoutParser::startFile)); - m_sHandler.insert("file/briefdescription", - new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/detaileddescription", - new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, - theTranslator->trDetailedDescription())); - m_sHandler.insert("file/authorsection", - new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/includes", - new StartElementHandlerKind(this,LayoutDocEntry::FileIncludes,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/includegraph", - new StartElementHandlerKind(this,LayoutDocEntry::FileIncludeGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/includedbygraph", - new StartElementHandlerKind(this,LayoutDocEntry::FileIncludedByGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/sourcelink", - new StartElementHandlerKind(this,LayoutDocEntry::FileSourceLink,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/memberdecl/membergroups", - new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("file/memberdecl", - new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("file/memberdecl/interfaces", - new StartElementHandlerSection(this,LayoutDocEntry::FileInterfaces,&LayoutParser::startSectionEntry, - theTranslator->trSliceInterfaces())); - 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", - new StartElementHandlerSection(this,LayoutDocEntry::FileStructs,&LayoutParser::startSectionEntry, - theTranslator->trStructs())); - m_sHandler.insert("file/memberdecl/exceptions", - new StartElementHandlerSection(this,LayoutDocEntry::FileExceptions,&LayoutParser::startSectionEntry, - theTranslator->trExceptions())); - m_sHandler.insert("file/memberdecl/namespaces", - new StartElementHandlerSection(this,LayoutDocEntry::FileNamespaces,&LayoutParser::startSectionEntry, - COMPILE_FOR_4_OPTIONS( - theTranslator->trNamespaces(), - SrcLangExt_Java,theTranslator->trPackages(), - SrcLangExt_IDL,theTranslator->trModules(), - SrcLangExt_Fortran,theTranslator->trModules(), - SrcLangExt_Slice,theTranslator->trModules() - ))); - m_sHandler.insert("file/memberdecl/constantgroups", - new StartElementHandlerSection(this,LayoutDocEntry::FileConstantGroups,&LayoutParser::startSectionEntry, - theTranslator->trConstantGroups())); - m_sHandler.insert("file/memberdecl/defines", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decDefineMembers,theTranslator->trDefines())); - m_sHandler.insert("file/memberdecl/typedefs", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decTypedefMembers,theTranslator->trTypedefs())); - m_sHandler.insert("file/memberdecl/sequences", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decSequenceMembers,theTranslator->trSequences())); - m_sHandler.insert("file/memberdecl/dictionaries", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decDictionaryMembers,theTranslator->trDictionaries())); - m_sHandler.insert("file/memberdecl/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decEnumMembers,theTranslator->trEnumerations())); - m_sHandler.insert("file/memberdecl/functions", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decFuncMembers, - COMPILE_FOR_2_OPTIONS( - theTranslator->trFunctions(), - SrcLangExt_Fortran,theTranslator->trSubprograms(), - SrcLangExt_VHDL,theTranslator->trFunctionAndProc() - ))); - m_sHandler.insert("file/memberdecl/variables", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decVarMembers, - sliceOpt ? theTranslator->trConstants() : theTranslator->trVariables())); - - m_eHandler.insert("file/memberdecl", - new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("file/memberdef", - new StartElementHandler(this,&LayoutParser::startMemberDef)); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docDefineMembers,theTranslator->trDefineDocumentation())); - m_sHandler.insert("file/memberdef/typedefs", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation())); - m_sHandler.insert("file/memberdef/sequences", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation())); - m_sHandler.insert("file/memberdef/dictionaries", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docDictionaryMembers, - theTranslator->trDictionaryDocumentation())); - m_sHandler.insert("file/memberdef/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docEnumMembers, - theTranslator->trEnumerationTypeDocumentation())); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docVarMembers,theTranslator->trVariableDocumentation())); - m_eHandler.insert("file/memberdef", - new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("file", - new EndElementHandler(this,&LayoutParser::endFile)); - - // group layout handlers - m_sHandler.insert("group", - new StartElementHandler(this,&LayoutParser::startGroup)); - m_sHandler.insert("group/briefdescription", - new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/detaileddescription", - new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, - theTranslator->trDetailedDescription())); - m_sHandler.insert("group/authorsection", - new StartElementHandlerKind(this,LayoutDocEntry::AuthorSection,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/groupgraph", - new StartElementHandlerKind(this,LayoutDocEntry::GroupGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/memberdecl/membergroups", - new StartElementHandlerKind(this,LayoutDocEntry::MemberGroups,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("group/memberdecl", - new StartElementHandler(this,&LayoutParser::startMemberDecl)); - 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", - 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", - new StartElementHandlerSection(this,LayoutDocEntry::GroupDirs,&LayoutParser::startSectionEntry, - theTranslator->trDirectories() - )); - m_sHandler.insert("group/memberdecl/nestedgroups", - new StartElementHandlerSection(this,LayoutDocEntry::GroupNestedGroups,&LayoutParser::startSectionEntry, - theTranslator->trModules() - )); - m_sHandler.insert("group/memberdecl/files", - new StartElementHandlerSection(this,LayoutDocEntry::GroupFiles,&LayoutParser::startSectionEntry, - theTranslator->trFile(TRUE,FALSE) - )); - - m_sHandler.insert("group/memberdecl/defines", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decDefineMembers,theTranslator->trDefines())); - m_sHandler.insert("group/memberdecl/typedefs", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decTypedefMembers,theTranslator->trTypedefs())); - m_sHandler.insert("group/memberdecl/sequences", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decSequenceMembers,theTranslator->trSequences())); - m_sHandler.insert("group/memberdecl/dictionaries", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decDictionaryMembers,theTranslator->trDictionaries())); - m_sHandler.insert("group/memberdecl/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decEnumMembers,theTranslator->trEnumerations())); - m_sHandler.insert("group/memberdecl/enumvalues", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decEnumValMembers,theTranslator->trEnumerationValues())); - m_sHandler.insert("group/memberdecl/functions", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decFuncMembers, - COMPILE_FOR_2_OPTIONS( - theTranslator->trFunctions(), - SrcLangExt_Fortran,theTranslator->trSubprograms(), - SrcLangExt_VHDL,theTranslator->trFunctionAndProc() - ))); - m_sHandler.insert("group/memberdecl/variables", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decVarMembers,theTranslator->trVariables())); - m_sHandler.insert("group/memberdecl/signals", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decSignalMembers,theTranslator->trSignals())); - m_sHandler.insert("group/memberdecl/publicslots", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decPubSlotMembers,theTranslator->trPublicSlots())); - m_sHandler.insert("group/memberdecl/protectedslots", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decProSlotMembers,theTranslator->trProtectedSlots())); - m_sHandler.insert("group/memberdecl/privateslots", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decPriSlotMembers,theTranslator->trPrivateSlots())); - m_sHandler.insert("group/memberdecl/events", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decEventMembers,theTranslator->trEvents())); - m_sHandler.insert("group/memberdecl/properties", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decPropMembers,theTranslator->trProperties())); - m_sHandler.insert("group/memberdecl/friends", - new StartElementHandlerMember(this,&LayoutParser::startMemberDeclEntry, - MemberListType_decFriendMembers,theTranslator->trFriends())); - m_eHandler.insert("group/memberdecl", - new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_sHandler.insert("group/memberdef", - new StartElementHandler(this,&LayoutParser::startMemberDef)); - m_sHandler.insert("group/memberdef/pagedocs", - new StartElementHandlerKind(this,LayoutDocEntry::GroupPageDocs,&LayoutParser::startSimpleEntry)); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docDefineMembers,theTranslator->trDefineDocumentation())); - m_sHandler.insert("group/memberdef/typedefs", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docTypedefMembers,theTranslator->trTypedefDocumentation())); - m_sHandler.insert("group/memberdef/sequences", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docSequenceMembers,theTranslator->trSequenceDocumentation())); - m_sHandler.insert("group/memberdef/dictionaries", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docDictionaryMembers, - theTranslator->trDictionaryDocumentation())); - m_sHandler.insert("group/memberdef/enums", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docEnumMembers,theTranslator->trEnumerationTypeDocumentation())); - m_sHandler.insert("group/memberdef/enumvalues", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docEnumValMembers,theTranslator->trEnumerationValueDocumentation())); - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docVarMembers,theTranslator->trVariableDocumentation())); - m_sHandler.insert("group/memberdef/signals", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - 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", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docProSlotMembers,theTranslator->trProtectedSlots())); - m_sHandler.insert("group/memberdef/privateslots", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docPriSlotMembers,theTranslator->trPrivateSlots())); - m_sHandler.insert("group/memberdef/events", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docEventMembers,theTranslator->trEvents())); - m_sHandler.insert("group/memberdef/properties", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docPropMembers,theTranslator->trProperties())); - m_sHandler.insert("group/memberdef/friends", - new StartElementHandlerMember(this,&LayoutParser::startMemberDefEntry, - MemberListType_docFriendMembers,theTranslator->trFriends())); - m_eHandler.insert("group/memberdef", - new EndElementHandler(this,&LayoutParser::endMemberDef)); - m_eHandler.insert("group", - new EndElementHandler(this,&LayoutParser::endGroup)); - - // directory layout handlers - m_sHandler.insert("directory", - new StartElementHandler(this,&LayoutParser::startDirectory)); - m_sHandler.insert("directory/briefdescription", - new StartElementHandlerKind(this,LayoutDocEntry::BriefDesc,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("directory/detaileddescription", - new StartElementHandlerSection(this,LayoutDocEntry::DetailedDesc,&LayoutParser::startSectionEntry, - theTranslator->trDetailedDescription())); - m_sHandler.insert("directory/directorygraph", - new StartElementHandlerKind(this,LayoutDocEntry::DirGraph,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("directory/memberdecl", - new StartElementHandler(this,&LayoutParser::startMemberDecl)); - m_sHandler.insert("directory/memberdecl/dirs", - new StartElementHandlerKind(this,LayoutDocEntry::DirSubDirs,&LayoutParser::startSimpleEntry)); - m_sHandler.insert("directory/memberdecl/files", - new StartElementHandlerKind(this,LayoutDocEntry::DirFiles,&LayoutParser::startSimpleEntry)); - m_eHandler.insert("directory/memberdecl", - new EndElementHandler(this,&LayoutParser::endMemberDecl)); - m_eHandler.insert("directory", - new EndElementHandler(this,&LayoutParser::endDirectory)); + ::warn(fileName.c_str(),lineNr,"%s",msg.c_str()); } + void startElement( const std::string &name, const XMLHandlers::Attributes& attrib ); + void endElement( const std::string &name ); - void startSimpleEntry(LayoutDocEntry::Kind k,const QXmlAttributes &attrib) + void startSimpleEntry(LayoutDocEntry::Kind k,const XMLHandlers::Attributes &attrib) { bool isVisible = elemIsVisible(attrib); if (m_part!=-1 && isVisible) @@ -897,11 +188,13 @@ class LayoutParser : public QXmlDefaultHandler } } - void startSectionEntry(LayoutDocEntry::Kind k,const QXmlAttributes &attrib, + // ============ Specific callbacks + + void startSectionEntry(LayoutDocEntry::Kind k,const XMLHandlers::Attributes &attrib, const QCString &title) { bool isVisible = elemIsVisible(attrib); - QCString userTitle = attrib.value("title").utf8(); + QCString userTitle = XMLHandlers::value(attrib,"title"); //printf("startSectionEntry: title='%s' userTitle='%s'\n", // title.data(),userTitle.data()); if (userTitle.isEmpty()) userTitle = title; @@ -913,13 +206,13 @@ class LayoutParser : public QXmlDefaultHandler } - void startMemberDeclEntry(const QXmlAttributes &attrib,MemberListType type, + void startMemberDeclEntry(const XMLHandlers::Attributes &attrib,MemberListType type, const QCString &title,const QCString &subscript) { - //QCString visible = convertToQCString(attrib.value("visible")); + //QCString visible = convertToQCString(XMLHandlers::value(attrib,"visible")); //bool isVisible = visible.isEmpty() || (visible!="no" && visible!="0"); - QCString userTitle = attrib.value("title").utf8(); - QCString userSubscript = attrib.value("subtitle").utf8(); + QCString userTitle = XMLHandlers::value(attrib,"title"); + QCString userSubscript = XMLHandlers::value(attrib,"subtitle"); if (userTitle.isEmpty()) userTitle = title; if (userSubscript.isEmpty()) userSubscript = subscript; //printf("memberdecl: %s\n",userTitle.data()); @@ -930,10 +223,10 @@ class LayoutParser : public QXmlDefaultHandler } } - void startMemberDefEntry(const QXmlAttributes &attrib,MemberListType type, + void startMemberDefEntry(const XMLHandlers::Attributes &attrib,MemberListType type, const QCString &title,const QCString &) { - QCString userTitle = attrib.value("title").utf8(); + QCString userTitle = XMLHandlers::value(attrib,"title"); if (userTitle.isEmpty()) userTitle = title; //printf("memberdef: %s\n",userTitle.data()); if (m_part!=-1 /*&& isVisible*/) @@ -943,15 +236,11 @@ class LayoutParser : public QXmlDefaultHandler } } - void startLayout(const QXmlAttributes &) - { - } - - void endLayout() + void startLayout(const XMLHandlers::Attributes &) { } - void startNavIndex(const QXmlAttributes &) + void startNavIndex(const XMLHandlers::Attributes &) { m_scope="navindex/"; m_rootNav = LayoutDocManager::instance().rootNavEntry(); @@ -970,7 +259,7 @@ class LayoutParser : public QXmlDefaultHandler } } - void startNavEntry(const QXmlAttributes &attrib) + void startNavEntry(const XMLHandlers::Attributes &attrib) { static bool javaOpt = Config_getBool(OPTIMIZE_OUTPUT_JAVA); static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); @@ -1203,7 +492,7 @@ class LayoutParser : public QXmlDefaultHandler LayoutNavEntry::Kind kind; // find type in the table int i=0; - QString type = attrib.value("type"); + QCString type = XMLHandlers::value(attrib,"type"); while (mapping[i].typeStr) { if (mapping[i].typeStr==type) @@ -1215,19 +504,20 @@ class LayoutParser : public QXmlDefaultHandler } if (mapping[i].typeStr==0) { + std::string fileName = m_locator->fileName(); if (type.isEmpty()) { - err("an entry tag within a navindex has no type attribute! Check your layout file!\n"); + ::warn(fileName.c_str(),m_locator->lineNr(),"an entry tag within a navindex has no type attribute! Check your layout file!\n"); } else { - err("the type '%s' is not supported for the entry tag within a navindex! Check your layout file!\n",type.data()); + ::warn(fileName.c_str(),m_locator->lineNr(),"the type '%s' is not supported for the entry tag within a navindex! Check your layout file!\n",type.data()); } m_invalidEntry=TRUE; return; } QCString baseFile = mapping[i].baseFile; - QCString title = attrib.value("title").utf8(); + QCString title = XMLHandlers::value(attrib,"title"); bool isVisible = elemIsVisible(attrib); if (title.isEmpty()) // use default title { @@ -1238,12 +528,12 @@ class LayoutParser : public QXmlDefaultHandler // this is mainly done to get compatible naming with older versions. } } - QCString intro = attrib.value("intro").utf8(); + QCString intro = XMLHandlers::value(attrib,"intro"); if (intro.isEmpty()) // use default intro text { intro = mapping[i].intro; } - QCString url = attrib.value("url").utf8(); + QCString url = XMLHandlers::value(attrib,"url"); if (mapping[i].kind==LayoutNavEntry::User && !url.isEmpty()) { baseFile=url; @@ -1270,7 +560,7 @@ class LayoutParser : public QXmlDefaultHandler m_invalidEntry=FALSE; } - void startClass(const QXmlAttributes &) + void startClass(const XMLHandlers::Attributes &) { LayoutDocManager::instance().clear(LayoutDocManager::Class); m_scope="class/"; @@ -1283,7 +573,7 @@ class LayoutParser : public QXmlDefaultHandler m_part = -1; } - void startNamespace(const QXmlAttributes &) + void startNamespace(const XMLHandlers::Attributes &) { LayoutDocManager::instance().clear(LayoutDocManager::Namespace); m_scope="namespace/"; @@ -1296,7 +586,7 @@ class LayoutParser : public QXmlDefaultHandler m_part = -1; } - void startFile(const QXmlAttributes &) + void startFile(const XMLHandlers::Attributes &) { LayoutDocManager::instance().clear(LayoutDocManager::File); m_scope="file/"; @@ -1309,7 +599,7 @@ class LayoutParser : public QXmlDefaultHandler m_part = -1; } - void startGroup(const QXmlAttributes &) + void startGroup(const XMLHandlers::Attributes &) { LayoutDocManager::instance().clear(LayoutDocManager::Group); m_scope="group/"; @@ -1322,7 +612,7 @@ class LayoutParser : public QXmlDefaultHandler m_part = -1; } - void startDirectory(const QXmlAttributes &) + void startDirectory(const XMLHandlers::Attributes &) { LayoutDocManager::instance().clear(LayoutDocManager::Directory); m_scope="directory/"; @@ -1335,7 +625,7 @@ class LayoutParser : public QXmlDefaultHandler m_part = -1; } - void startMemberDef(const QXmlAttributes &) + void startMemberDef(const XMLHandlers::Attributes &) { m_scope+="memberdef/"; if (m_part!=-1) @@ -1359,7 +649,7 @@ class LayoutParser : public QXmlDefaultHandler } } - void startMemberDecl(const QXmlAttributes &) + void startMemberDecl(const XMLHandlers::Attributes &) { m_scope+="memberdecl/"; if (m_part!=-1) @@ -1383,95 +673,811 @@ class LayoutParser : public QXmlDefaultHandler } } - // reimplemented from QXmlDefaultHandler - bool startElement( const QString&, const QString&, - const QString& name, const QXmlAttributes& attrib ) - { - //printf("startElement [%s]::[%s]\n",m_scope.data(),name.data()); - StartElementHandler *handler = m_sHandler[m_scope+name.utf8()]; - if (handler) - { - (*handler)(attrib); - } - else - { - err("Unexpected start tag '%s' found in scope='%s'!\n", - name.data(),m_scope.data()); - } - return TRUE; - } - bool endElement( const QString&, const QString&, const QString& name ) - { - //printf("endElement [%s]::[%s]\n",m_scope.data(),name.data()); - EndElementHandler *handler; - if (!m_scope.isEmpty() && m_scope.right(name.length()+1)==name.utf8()+"/") - { // element ends current scope - handler = m_eHandler[m_scope.left(m_scope.length()-1)]; - } - else // continue with current scope - { - handler = m_eHandler[m_scope+name.utf8()]; - } - if (handler) - { - (*handler)(); - } - return TRUE; - } - bool startDocument() - { - return TRUE; - } private: - LayoutParser() : m_sHandler(163), m_eHandler(17) { } + LayoutParser() { } ~LayoutParser() { delete m_rootNav; } - QDict<StartElementHandler> m_sHandler; - QDict<EndElementHandler> m_eHandler; QCString m_scope; - int m_part = 0; + int m_part = -1; LayoutNavEntry *m_rootNav = 0; bool m_invalidEntry = false; static int m_userGroupCount; + const XMLLocator *m_locator = nullptr; }; -int LayoutParser::m_userGroupCount=0; - //--------------------------------------------------------------------------------- -class LayoutErrorHandler : public QXmlErrorHandler +struct ElementCallbacks { - public: - LayoutErrorHandler(const char *fn) : fileName(fn) {} - bool warning( const QXmlParseException &exception ) - { - warn_uncond("at line %d column %d of %s: %s\n", - exception.lineNumber(),exception.columnNumber(),fileName.data(), - exception.message().data()); - return FALSE; - } - bool error( const QXmlParseException &exception ) - { - err("at line %d column %d of %s: %s\n", - exception.lineNumber(),exception.columnNumber(),fileName.data(), - exception.message().data()); - return FALSE; - } - bool fatalError( const QXmlParseException &exception ) - { - err("fatal: at line %d column %d of %s: %s\n", - exception.lineNumber(),exception.columnNumber(),fileName.data(), - exception.message().data()); - return FALSE; - } - QString errorString() { return ""; } + using StartCallback = std::function<void(LayoutParser&,const XMLHandlers::Attributes&)>; + using EndCallback = std::function<void(LayoutParser&)>; + + StartCallback startCb; + EndCallback endCb; +}; + +static ElementCallbacks::StartCallback startCb(void (LayoutParser::*fn)(const XMLHandlers::Attributes &)) +{ + return [fn](LayoutParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(attr); }; +} + +static ElementCallbacks::StartCallback startCb(void (LayoutParser::*fn)(LayoutDocEntry::Kind,const XMLHandlers::Attributes &),LayoutDocEntry::Kind kind) +{ + return [fn,kind](LayoutParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(kind,attr); }; +} + +static ElementCallbacks::StartCallback startCb(void (LayoutParser::*fn)(LayoutDocEntry::Kind,const XMLHandlers::Attributes &,const QCString &), + LayoutDocEntry::Kind kind, + std::function<QCString()> title + ) +{ + return [fn,kind,title](LayoutParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(kind,attr,title()); }; +} + +static ElementCallbacks::StartCallback startCb(void (LayoutParser::*fn)(const XMLHandlers::Attributes &,MemberListType,const QCString &,const QCString &), + MemberListType type, + std::function<QCString()> title + ) +{ + return [fn,type,title](LayoutParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(attr,type,title(),QCString()); }; +} + +static ElementCallbacks::StartCallback startCb(void (LayoutParser::*fn)(const XMLHandlers::Attributes &,MemberListType,const QCString &,const QCString &), + MemberListType type, + std::function<QCString()> title, + std::function<QCString()> subtitle + ) +{ + return [fn,type,title,subtitle](LayoutParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(attr,type,title(),subtitle()); }; +} + + +static ElementCallbacks::EndCallback endCb(void (LayoutParser::*fn)()) +{ + return [fn](LayoutParser &parser) { (parser.*fn)(); }; +} + +static ElementCallbacks::EndCallback endCb() +{ + return [](LayoutParser &){}; +} + +static const std::map< std::string, ElementCallbacks > g_elementHandlers = +{ + // path/name + { "doxygenlayout", { startCb(&LayoutParser::startLayout), + endCb() + } }, + { "navindex", { startCb(&LayoutParser::startNavIndex), + endCb(&LayoutParser::endNavIndex) + } }, + { "navindex/tab", { startCb(&LayoutParser::startNavEntry), + endCb(&LayoutParser::endNavEntry) + } }, + + // class layout handlers + { "class", { startCb(&LayoutParser::startClass), + endCb(&LayoutParser::endClass) + } }, + { "class/briefdescription", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::BriefDesc), + endCb() + } }, + { "class/detaileddescription", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::DetailedDesc, + [](){ return compileOptions(theTranslator->trDetailedDescription()); }), + endCb() + } }, + { "class/authorsection", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::AuthorSection), + endCb() + } }, + { "class/includes", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::ClassIncludes), + endCb() + } }, + { "class/inheritancegraph", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::ClassInheritanceGraph), + endCb() + } }, + { "class/collaborationgraph", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::ClassCollaborationGraph), + endCb() + } }, + { "class/allmemberslink", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::ClassAllMembersLink), + endCb() + } }, + { "class/usedfiles", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::ClassUsedFiles), + endCb() + } }, + { "class/memberdecl", { startCb(&LayoutParser::startMemberDecl), + endCb(&LayoutParser::endMemberDecl) + } }, + { "class/memberdecl/membergroups", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::MemberGroups), + endCb() + } }, + { "class/memberdecl/nestedclasses", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::ClassNestedClasses, + []() { return compileOptions(/*default*/ theTranslator->trCompounds(), + SrcLangExt_VHDL, theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), + SrcLangExt_Fortran,theTranslator->trDataTypes()); }), + endCb() + } }, + { "class/memberdecl/services", { startCb(&LayoutParser::startMemberDeclEntry,MemberListType_services, + []() { return compileOptions(theTranslator->trServices()); }), + endCb() + } }, + { "class/memberdecl/interfaces", { startCb(&LayoutParser::startMemberDeclEntry,MemberListType_interfaces, + []() { return compileOptions(theTranslator->trInterfaces()); }), + endCb() + } }, + { "class/memberdecl/publictypes", { startCb(&LayoutParser::startMemberDeclEntry,MemberListType_pubTypes, + []() { return compileOptions(theTranslator->trPublicTypes()); }), + endCb() + } }, + { "class/memberdecl/publicslots", { startCb(&LayoutParser::startMemberDeclEntry,MemberListType_pubSlots, + []() { return compileOptions(theTranslator->trPublicSlots()); }), + endCb() + } }, + { "class/memberdecl/signals", { startCb(&LayoutParser::startMemberDeclEntry,MemberListType_signals, + []() { return compileOptions(theTranslator->trSignals()); }), + endCb() + } }, + { "class/memberdecl/publicmethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pubMethods, + []() { return compileOptions(/* default */ theTranslator->trPublicMembers(), + SrcLangExt_ObjC, theTranslator->trInstanceMethods(), + SrcLangExt_Slice,theTranslator->trOperations()); }), + endCb() + } }, + { "class/memberdecl/publicstaticmethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pubStaticMethods, + []() { return compileOptions(/* default */ theTranslator->trStaticPublicMembers(), + SrcLangExt_ObjC, theTranslator->trClassMethods()); }), + endCb() + } }, + { "class/memberdecl/publicattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pubAttribs, + []() { return compileOptions(/* default */ theTranslator->trPublicAttribs(), + SrcLangExt_Slice,theTranslator->trDataMembers()); }), + endCb() + } }, + { "class/memberdecl/publicstaticattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pubStaticAttribs, + []() { return compileOptions(theTranslator->trStaticPublicAttribs()); }), + endCb() + } }, + { "class/memberdecl/protectedtypes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_proTypes, + []() { return compileOptions(theTranslator->trProtectedTypes()); }), + endCb() + } }, + { "class/memberdecl/protectedslots", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_proSlots, + []() { return compileOptions(theTranslator->trProtectedSlots()); }), + endCb() + } }, + { "class/memberdecl/protectedmethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_proMethods, + []() { return compileOptions(theTranslator->trProtectedMembers()); }), + endCb() + } }, + { "class/memberdecl/protectedstaticmethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_proStaticMethods, + []() { return compileOptions(theTranslator->trStaticProtectedMembers()); }), + endCb() + } }, + { "class/memberdecl/protectedattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_proAttribs, + []() { return compileOptions(theTranslator->trProtectedAttribs()); }), + endCb() + } }, + { "class/memberdecl/protectedstaticattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_proStaticAttribs, + []() { return compileOptions(theTranslator->trStaticProtectedAttribs()); }), + endCb() + } }, + { "class/memberdecl/packagetypes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pacTypes, + []() { return compileOptions(theTranslator->trPackageTypes()); }), + endCb() + } }, + { "class/memberdecl/packagemethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pacMethods, + []() { return compileOptions(theTranslator->trPackageMembers()); }), + endCb() + } }, + { "class/memberdecl/packagestaticmethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pacStaticMethods, + []() { return compileOptions(theTranslator->trStaticPackageMembers()); }), + endCb() + } }, + { "class/memberdecl/packageattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pacAttribs, + []() { return compileOptions(theTranslator->trPackageAttribs()); }), + endCb() + } }, + { "class/memberdecl/packagestaticattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_pacStaticAttribs, + []() { return compileOptions(theTranslator->trStaticPackageAttribs()); }), + endCb() + } }, + { "class/memberdecl/properties", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_properties, + []() { return compileOptions(theTranslator->trProperties()); }), + endCb() + } }, + { "class/memberdecl/events", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_events, + []() { return compileOptions(theTranslator->trEvents()); }), + endCb() + } }, + { "class/memberdecl/privatetypes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_priTypes, + []() { return compileOptions(theTranslator->trPrivateTypes()); }), + endCb() + } }, + { "class/memberdecl/privateslots", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_priSlots, + []() { return compileOptions(theTranslator->trPrivateSlots()); }), + endCb() + } }, + { "class/memberdecl/privatemethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_priMethods, + []() { return compileOptions(theTranslator->trPrivateMembers()); }), + endCb() + } }, + { "class/memberdecl/privatestaticmethods", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_priStaticMethods, + []() { return compileOptions(theTranslator->trStaticPrivateMembers()); }), + endCb() + } }, + { "class/memberdecl/privateattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_priAttribs, + []() { return compileOptions(theTranslator->trPrivateAttribs()); }), + endCb() + } }, + { "class/memberdecl/privatestaticattributes", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_priStaticAttribs, + []() { return compileOptions(theTranslator->trStaticPrivateAttribs()); }), + endCb() + } }, + { "class/memberdecl/friends", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_friends, + []() { return compileOptions(theTranslator->trFriends()); }), + endCb() + } }, + { "class/memberdecl/related", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_related, + []() { return compileOptions(theTranslator->trRelatedFunctions()); }, + []() { return compileOptions(theTranslator->trRelatedSubscript()); }), + endCb() + } }, + { "class/memberdef", { startCb(&LayoutParser::startMemberDef), + endCb(&LayoutParser::endMemberDef) + } }, + { "class/memberdef/inlineclasses", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::ClassInlineClasses, + []() { return compileOptions(/* default */ theTranslator->trClassDocumentation(), + SrcLangExt_Fortran,theTranslator->trTypeDocumentation()); }), + endCb() + } }, + { "class/memberdef/typedefs", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_typedefMembers, + []() { return compileOptions(theTranslator->trMemberTypedefDocumentation()); }), + endCb() + } }, + { "class/memberdef/enums", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_enumMembers, + []() { return compileOptions(theTranslator->trMemberEnumerationDocumentation()); }), + endCb() + } }, + { "class/memberdef/services", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_serviceMembers, + []() { return compileOptions(theTranslator->trInterfaces()); }), + endCb() + } }, + { "class/memberdef/interfaces", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_interfaceMembers, + []() { return compileOptions(theTranslator->trInterfaces()); }), + endCb() + } }, + { "class/memberdef/constructors", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_constructors, + []() { return compileOptions(theTranslator->trConstructorDocumentation()); }), + endCb() + } }, + { "class/memberdef/functions", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_functionMembers, + []() { return compileOptions(/* default */ theTranslator->trMemberFunctionDocumentation(), SrcLangExt_ObjC, theTranslator->trMethodDocumentation(), + SrcLangExt_Fortran,theTranslator->trMemberFunctionDocumentationFortran(), + SrcLangExt_Slice, theTranslator->trOperationDocumentation()); }), + endCb() + } }, + { "class/memberdef/related", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_relatedMembers, + []() { return compileOptions(theTranslator->trRelatedFunctionDocumentation()); }), + endCb() + } }, + { "class/memberdef/variables", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_variableMembers, + []() { return compileOptions(/* default */ theTranslator->trMemberDataDocumentation(), + SrcLangExt_Slice, theTranslator->trDataMemberDocumentation()); }), + endCb() + } }, + { "class/memberdef/properties", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_propertyMembers, + []() { return compileOptions(theTranslator->trPropertyDocumentation()); }), + endCb() + } }, + { "class/memberdef/events", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_eventMembers, + []() { return compileOptions(theTranslator->trEventDocumentation()); }), + endCb() + } }, + + // namespace layout handlers + { "namespace", { startCb(&LayoutParser::startNamespace), + endCb(&LayoutParser::endNamespace) + } }, + + { "namespace/briefdescription", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::BriefDesc), + endCb() + } }, + { "namespace/detaileddescription", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::DetailedDesc, + []() { return compileOptions(theTranslator->trDetailedDescription()); }), + endCb() + } }, + { "namespace/authorsection", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::AuthorSection), + endCb() + } }, + { "namespace/memberdecl", { startCb(&LayoutParser::startMemberDecl), + endCb(&LayoutParser::endMemberDecl) + } }, + { "namespace/memberdecl/nestednamespaces", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::NamespaceNestedNamespaces, + []() { return compileOptions(/* default */ theTranslator->trNamespaces(), + SrcLangExt_Java, theTranslator->trPackages(), + SrcLangExt_VHDL, theTranslator->trPackages(), + SrcLangExt_IDL, theTranslator->trModules(), + SrcLangExt_Fortran,theTranslator->trModules(), + SrcLangExt_Slice,(Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? + theTranslator->trModules() : + theTranslator->trNamespaces())); }), + endCb() + } }, + { "namespace/memberdecl/constantgroups", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::NamespaceNestedConstantGroups, + []() { return compileOptions(theTranslator->trConstantGroups()); }), + endCb() + } }, + { "namespace/memberdecl/interfaces", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::NamespaceInterfaces, + []() { return compileOptions(theTranslator->trSliceInterfaces()); }), + endCb() + } }, + { "namespace/memberdecl/classes", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::NamespaceClasses, + []() { return compileOptions(/* default */ theTranslator->trCompounds(), + SrcLangExt_VHDL, theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), + SrcLangExt_Fortran,theTranslator->trDataTypes()); }), + endCb() + } }, + { "namespace/memberdecl/structs", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::NamespaceStructs, + []() { return compileOptions(theTranslator->trStructs()); }), + endCb() + } }, + { "namespace/memberdecl/exceptions", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::NamespaceExceptions, + []() { return compileOptions(theTranslator->trExceptions()); }), + endCb() + } }, + { "namespace/memberdecl/membergroups", { startCb(&LayoutParser::startSimpleEntry,LayoutDocEntry::MemberGroups), + endCb() + } }, + { "namespace/memberdecl/typedefs", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decTypedefMembers, + []() { return compileOptions(theTranslator->trTypedefs()); }), + endCb() + } }, + { "namespace/memberdecl/sequences", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decSequenceMembers, + []() { return compileOptions(theTranslator->trSequences()); }), + endCb() + } }, + { "namespace/memberdecl/dictionaries", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decDictionaryMembers, + []() { return compileOptions(theTranslator->trDictionaries()); }), + endCb() + } }, + { "namespace/memberdecl/enums", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decEnumMembers, + []() { return compileOptions(theTranslator->trEnumerations()); }), + endCb() + } }, + { "namespace/memberdecl/functions", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decFuncMembers, + []() { return compileOptions(/* default */ theTranslator->trFunctions(), + SrcLangExt_Fortran,theTranslator->trSubprograms(), + SrcLangExt_VHDL, theTranslator->trFunctionAndProc()); }), + endCb() + } }, + { "namespace/memberdecl/variables", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decVarMembers, + []() { return compileOptions(Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? + theTranslator->trConstants() : + theTranslator->trVariables()); }), + endCb() + } }, + { "namespace/memberdef", { startCb(&LayoutParser::startMemberDef), + endCb(&LayoutParser::endMemberDef) + } }, + { "namespace/memberdef/inlineclasses", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::NamespaceInlineClasses, + []() { return compileOptions(/* default */ theTranslator->trClassDocumentation(), + SrcLangExt_Fortran,theTranslator->trTypeDocumentation()); }), + endCb() + } }, + { "namespace/memberdef/typedefs", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docTypedefMembers, + []() { return compileOptions(theTranslator->trTypedefDocumentation()); }), + endCb() + } }, + { "namespace/memberdef/sequences", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docSequenceMembers, + []() { return compileOptions(theTranslator->trSequenceDocumentation()); }), + endCb() + } }, + { "namespace/memberdef/dictionaries", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docDictionaryMembers, + []() { return compileOptions(theTranslator->trDictionaryDocumentation()); }), + endCb() + } }, + { "namespace/memberdef/enums", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docEnumMembers, + []() { return compileOptions(theTranslator->trEnumerationTypeDocumentation()); }), + endCb() + } }, + { "namespace/memberdef/functions", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docFuncMembers, + []() { return compileOptions(/* default */ theTranslator->trFunctionDocumentation(), + SrcLangExt_Fortran,theTranslator->trSubprogramDocumentation()); }), + endCb() + } }, + { "namespace/memberdef/variables", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docVarMembers, + []() { return compileOptions(Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? + theTranslator->trConstantDocumentation() : + theTranslator->trVariableDocumentation()); }), + endCb() + } }, + + // file layout handlers + { "file", { startCb(&LayoutParser::startFile), + endCb(&LayoutParser::endFile) + } }, + + { "file/briefdescription", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::BriefDesc), + endCb() + } }, + { "file/detaileddescription", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::DetailedDesc, + []() { return compileOptions(theTranslator->trDetailedDescription()); }), + endCb() + } }, + { "file/authorsection", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::AuthorSection), + endCb() + } }, + { "file/includes", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::FileIncludes), + endCb() + } }, + { "file/includegraph", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::FileIncludeGraph), + endCb() + } }, + { "file/includedbygraph", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::FileIncludedByGraph), + endCb() + } }, + { "file/sourcelink", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::FileSourceLink), + endCb() + } }, + { "file/memberdecl/membergroups", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::MemberGroups), + endCb() + } }, + { "file/memberdecl", { startCb(&LayoutParser::startMemberDecl), + endCb(&LayoutParser::endMemberDecl) + } }, + + { "file/memberdecl/interfaces", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileInterfaces, + []() { return compileOptions(theTranslator->trSliceInterfaces()); }), + endCb() + } }, + { "file/memberdecl/classes", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileClasses, + []() { return compileOptions(/* default */ theTranslator->trCompounds(), + SrcLangExt_VHDL, theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), + SrcLangExt_Fortran,theTranslator->trDataTypes()); }), + endCb() + } }, + { "file/memberdecl/structs", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileStructs, + []() { return compileOptions(theTranslator->trStructs()); }), + endCb() + } }, + { "file/memberdecl/exceptions", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileExceptions, + []() { return compileOptions(theTranslator->trExceptions()); }), + endCb() + } }, + { "file/memberdecl/namespaces", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileNamespaces, + []() { return compileOptions(/* default */ theTranslator->trNamespaces(), + SrcLangExt_Java, theTranslator->trPackages(), + SrcLangExt_IDL, theTranslator->trModules(), + SrcLangExt_Fortran,theTranslator->trModules(), + SrcLangExt_Slice, theTranslator->trModules()); }), + endCb() + } }, + { "file/memberdecl/constantgroups", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileConstantGroups, + []() { return compileOptions(theTranslator->trConstantGroups()); }), + endCb() + } }, + { "file/memberdecl/defines", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decDefineMembers, + []() { return compileOptions(theTranslator->trDefines()); }), + endCb() + } }, + { "file/memberdecl/typedefs", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decTypedefMembers, + []() { return compileOptions(theTranslator->trTypedefs()); }), + endCb() + } }, + { "file/memberdecl/sequences", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decSequenceMembers, + []() { return compileOptions(theTranslator->trSequences()); }), + endCb() + } }, + { "file/memberdecl/dictionaries", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decDictionaryMembers, + []() { return compileOptions(theTranslator->trDictionaries()); }), + endCb() + } }, + { "file/memberdecl/enums", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decEnumMembers, + []() { return compileOptions(theTranslator->trEnumerations()); }), + endCb() + } }, + { "file/memberdecl/functions", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decFuncMembers, + []() { return compileOptions(/* default */ theTranslator->trFunctions(), + SrcLangExt_Fortran,theTranslator->trSubprograms(), + SrcLangExt_VHDL, theTranslator->trFunctionAndProc()); }), + endCb() + } }, + { "file/memberdecl/variables", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decVarMembers, + []() { return compileOptions(Config_getBool(OPTIMIZE_OUTPUT_SLICE) ? + theTranslator->trConstants() : + theTranslator->trVariables()); }), + endCb() + } }, + { "file/memberdef", { startCb(&LayoutParser::startMemberDef), + endCb(&LayoutParser::endMemberDef) + } }, + + { "file/memberdef/inlineclasses", { startCb(&LayoutParser::startSectionEntry,LayoutDocEntry::FileInlineClasses, + []() { return compileOptions(/* default */ theTranslator->trClassDocumentation(), + SrcLangExt_Fortran, theTranslator->trTypeDocumentation()); }), + endCb() + } }, + { "file/memberdef/defines", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docDefineMembers, + []() { return compileOptions(theTranslator->trDefineDocumentation()); }), + endCb() + } }, + { "file/memberdef/typedefs", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docTypedefMembers, + []() { return compileOptions(theTranslator->trTypedefDocumentation()); }), + endCb() + } }, + { "file/memberdef/sequences", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docSequenceMembers, + []() { return compileOptions(theTranslator->trSequenceDocumentation()); }), + endCb() + } }, + { "file/memberdef/dictionaries", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docDictionaryMembers, + []() { return compileOptions(theTranslator->trDictionaryDocumentation()); }), + endCb() + } }, + { "file/memberdef/enums", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docEnumMembers, + []() { return compileOptions(theTranslator->trEnumerationTypeDocumentation()); }), + endCb() + } }, + { "file/memberdef/functions", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docFuncMembers, + []() { return compileOptions(/* default */ theTranslator->trFunctionDocumentation(), + SrcLangExt_Fortran, theTranslator->trSubprogramDocumentation()); }), + endCb() + } }, + { "file/memberdef/variables", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docVarMembers, + []() { return compileOptions(theTranslator->trVariableDocumentation()); }), + endCb() + } }, + + // group layout handlers + { "group", { startCb(&LayoutParser::startGroup), + endCb(&LayoutParser::endGroup) + } }, + { "group/briefdescription", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::BriefDesc), + endCb() + } }, + { "group/detaileddescription", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::DetailedDesc, + []() { return compileOptions(theTranslator->trDetailedDescription()); }), + endCb() + } }, + { "group/authorsection", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::AuthorSection), + endCb() + } }, + { "group/groupgraph", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::GroupGraph), + endCb() + } }, + { "group/memberdecl/membergroups", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::MemberGroups), + endCb() + } }, + + { "group/memberdecl", { startCb(&LayoutParser::startMemberDecl), + endCb(&LayoutParser::endMemberDecl) + } }, + + { "group/memberdecl/classes", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupClasses, + []() { return compileOptions(/* default */ theTranslator->trCompounds(), + SrcLangExt_VHDL, theTranslator->trVhdlType(VhdlDocGen::ENTITY,FALSE), + SrcLangExt_Fortran, theTranslator->trDataTypes()); }), + endCb() + } }, + { "group/memberdecl/namespaces", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupNamespaces, + []() { return compileOptions(/* default */ theTranslator->trNamespaces(), + SrcLangExt_Java, theTranslator->trPackages(), + SrcLangExt_Fortran, theTranslator->trModules()); }), + endCb() + } }, + { "group/memberdecl/dirs", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupDirs, + []() { return compileOptions(theTranslator->trDirectories()); }), + endCb() + } }, + { "group/memberdecl/nestedgroups", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupNestedGroups, + []() { return compileOptions(theTranslator->trModules()); }), + endCb() + } }, + { "group/memberdecl/files", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupFiles, + []() { return compileOptions(theTranslator->trFile(TRUE,FALSE)); }), + endCb() + } }, + { "group/memberdecl/defines", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decDefineMembers, + []() { return compileOptions(theTranslator->trDefines()); }), + endCb() + } }, + { "group/memberdecl/typedefs", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decTypedefMembers, + []() { return compileOptions(theTranslator->trTypedefs()); }), + endCb() + } }, + { "group/memberdecl/sequences", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decSequenceMembers, + []() { return compileOptions(theTranslator->trSequences()); }), + endCb() + } }, + { "group/memberdecl/dictionaries", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decDictionaryMembers, + []() { return compileOptions(theTranslator->trDictionaries()); }), + endCb() + } }, + { "group/memberdecl/enums", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decEnumMembers, + []() { return compileOptions(theTranslator->trEnumerations()); }), + endCb() + } }, + { "group/memberdecl/enumvalues", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decEnumValMembers, + []() { return compileOptions(theTranslator->trEnumerationValues()); }), + endCb() + } }, + { "group/memberdecl/functions", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decFuncMembers, + []() { return compileOptions(/* default */ theTranslator->trFunctions(), + SrcLangExt_Fortran,theTranslator->trSubprograms(), + SrcLangExt_VHDL, theTranslator->trFunctionAndProc()); }), + endCb() + } }, + { "group/memberdecl/variables", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decVarMembers, + []() { return compileOptions(theTranslator->trVariables()); }), + endCb() + } }, + { "group/memberdecl/signals", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decSignalMembers, + []() { return compileOptions(theTranslator->trSignals()); }), + endCb() + } }, + { "group/memberdecl/publicslots", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decPubSlotMembers, + []() { return compileOptions(theTranslator->trPublicSlots()); }), + endCb() + } }, + { "group/memberdecl/protectedslots", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decProSlotMembers, + []() { return compileOptions(theTranslator->trProtectedSlots()); }), + endCb() + } }, + { "group/memberdecl/privateslots", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decPriSlotMembers, + []() { return compileOptions(theTranslator->trPrivateSlots()); }), + endCb() + } }, + { "group/memberdecl/events", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decEventMembers, + []() { return compileOptions(theTranslator->trEvents()); }), + endCb() + } }, + { "group/memberdecl/properties", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decPropMembers, + []() { return compileOptions(theTranslator->trProperties()); }), + endCb() + } }, + { "group/memberdecl/friends", { startCb(&LayoutParser::startMemberDeclEntry, MemberListType_decFriendMembers, + []() { return compileOptions(theTranslator->trFriends()); }), + endCb() + } }, + { "group/memberdef", { startCb(&LayoutParser::startMemberDef), + endCb(&LayoutParser::endMemberDef) + } }, + + { "group/memberdef/pagedocs", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::GroupPageDocs), + endCb() + } }, + { "group/memberdef/inlineclasses", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::GroupInlineClasses, + []() { return compileOptions(/* default */ theTranslator->trClassDocumentation(), + SrcLangExt_Fortran,theTranslator->trTypeDocumentation()); }), + endCb() + } }, + { "group/memberdef/defines", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docDefineMembers, + []() { return compileOptions(theTranslator->trDefineDocumentation()); }), + endCb() + } }, + { "group/memberdef/typedefs", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docTypedefMembers, + []() { return compileOptions(theTranslator->trTypedefDocumentation()); }), + endCb() + } }, + { "group/memberdef/sequences", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docSequenceMembers, + []() { return compileOptions(theTranslator->trSequenceDocumentation()); }), + endCb() + } }, + { "group/memberdef/dictionaries", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docDictionaryMembers, + []() { return compileOptions(theTranslator->trDictionaryDocumentation()); }), + endCb() + } }, + { "group/memberdef/enums", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docEnumMembers, + []() { return compileOptions(theTranslator->trEnumerationTypeDocumentation()); }), + endCb() + } }, + { "group/memberdef/enumvalues", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docEnumValMembers, + []() { return compileOptions(theTranslator->trEnumerationValueDocumentation()); }), + endCb() + } }, + { "group/memberdef/functions", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docFuncMembers, + []() { return compileOptions(/* default */ theTranslator->trFunctionDocumentation(), + SrcLangExt_Fortran,theTranslator->trSubprogramDocumentation()); }), + endCb() + } }, + { "group/memberdef/variables", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docVarMembers, + []() { return compileOptions(theTranslator->trVariableDocumentation()); }), + endCb() + } }, + { "group/memberdef/signals", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docSignalMembers, + []() { return compileOptions(theTranslator->trSignals()); }), + endCb() + } }, + { "group/memberdef/publicslots", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docPubSlotMembers, + []() { return compileOptions(theTranslator->trPublicSlots()); }), + endCb() + } }, + { "group/memberdef/protectedslots", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docProSlotMembers, + []() { return compileOptions(theTranslator->trProtectedSlots()); }), + endCb() + } }, + { "group/memberdef/privateslots", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docPriSlotMembers, + []() { return compileOptions(theTranslator->trPrivateSlots()); }), + endCb() + } }, + { "group/memberdef/events", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docEventMembers, + []() { return compileOptions(theTranslator->trEvents()); }), + endCb() + } }, + { "group/memberdef/properties", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docPropMembers, + []() { return compileOptions(theTranslator->trProperties()); }), + endCb() + } }, { "group/memberdef/friends", { startCb(&LayoutParser::startMemberDefEntry, MemberListType_docFriendMembers, + []() { return compileOptions(theTranslator->trFriends()); }), + endCb() + } }, + + // directory layout handlers + { "directory", { startCb(&LayoutParser::startDirectory), + endCb(&LayoutParser::endDirectory) + } }, + + { "directory/briefdescription", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::BriefDesc), + endCb() + } }, + { "directory/detaileddescription", { startCb(&LayoutParser::startSectionEntry, LayoutDocEntry::DetailedDesc, + []() { return compileOptions(theTranslator->trDetailedDescription()); }), + endCb() + } }, + { "directory/directorygraph", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::DirGraph), + endCb() + } }, + { "directory/memberdecl", { startCb(&LayoutParser::startMemberDecl), + endCb(&LayoutParser::endMemberDecl) + } }, + + { "directory/memberdecl/dirs", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::DirSubDirs), + endCb() + } }, + { "directory/memberdecl/files", { startCb(&LayoutParser::startSimpleEntry, LayoutDocEntry::DirFiles), + endCb() + } }, - private: - QString errorMsg; - QString fileName; }; +void LayoutParser::startElement( const std::string &name, const XMLHandlers::Attributes& attrib ) +{ + //printf("startElement [%s]::[%s]\n",m_scope.data(),name.data()); + auto it = g_elementHandlers.find(m_scope.str()+name); + if (it!=g_elementHandlers.end()) + { + it->second.startCb(*this,attrib); + } + else + { + std::string fileName = m_locator->fileName(); + ::warn(fileName.c_str(),m_locator->lineNr(),"Unexpected start tag '%s' found in scope='%s'!\n", + name.data(),m_scope.data()); + } +} + +void LayoutParser::endElement( const std::string &name ) +{ + //printf("endElement [%s]::[%s]\n",m_scope.data(),name.data()); + auto it=g_elementHandlers.end(); + + if (!m_scope.isEmpty() && m_scope.right(static_cast<uint>(name.length())+1)==name+"/") + { // element ends current scope + it = g_elementHandlers.find(m_scope.left(m_scope.length()-1).str()); + } + else // continue with current scope + { + it = g_elementHandlers.find(m_scope.str()+name); + } + if (it!=g_elementHandlers.end()) + { + it->second.endCb(*this); + } +} + +//--------------------------------------------------------------------------------- + +int LayoutParser::m_userGroupCount=0; + //--------------------------------------------------------------------------------- class LayoutDocManager::Private @@ -1481,35 +1487,33 @@ class LayoutDocManager::Private LayoutNavEntry *rootNav; }; -LayoutDocManager::LayoutDocManager() +LayoutDocManager::LayoutDocManager() : d(std::make_unique<Private>()) { - d = new Private; int i; for (i=0;i<LayoutDocManager::NrParts;i++) { d->docEntries[i].setAutoDelete(TRUE); } d->rootNav = new LayoutNavEntry; - LayoutParser::instance().init(); } void LayoutDocManager::init() { - // parse the default layout - LayoutErrorHandler errorHandler( "layout_default.xml" ); - QXmlInputSource source; - source.setData( layout_default ); - QXmlSimpleReader reader; - reader.setContentHandler( &LayoutParser::instance() ); - reader.setErrorHandler( &errorHandler ); - reader.parse( source ); + LayoutParser &layoutParser = LayoutParser::instance(); + XMLHandlers handlers; + handlers.startElement = [&layoutParser](const std::string &name,const XMLHandlers::Attributes &attrs) { layoutParser.startElement(name,attrs); }; + handlers.endElement = [&layoutParser](const std::string &name) { layoutParser.endElement(name); }; + handlers.error = [&layoutParser](const std::string &fileName,int lineNr,const std::string &msg) { layoutParser.error(fileName,lineNr,msg); }; + XMLParser parser(handlers); + layoutParser.setDocumentLocator(&parser); + QCString layout_default = ResourceMgr::instance().getAsString("layout_default.xml"); + parser.parse("layout_default.xml",layout_default); } LayoutDocManager::~LayoutDocManager() { delete d->rootNav; - delete d; } LayoutDocManager & LayoutDocManager::instance() @@ -1540,13 +1544,14 @@ void LayoutDocManager::clear(LayoutDocManager::LayoutPart p) void LayoutDocManager::parse(const char *fileName) { - LayoutErrorHandler errorHandler(fileName); - QXmlInputSource source; - source.setData(fileToString(fileName)); - QXmlSimpleReader reader; - reader.setContentHandler( &LayoutParser::instance() ); - reader.setErrorHandler( &errorHandler ); - reader.parse( source ); + LayoutParser &layoutParser = LayoutParser::instance(); + XMLHandlers handlers; + handlers.startElement = [&layoutParser](const std::string &name,const XMLHandlers::Attributes &attrs) { layoutParser.startElement(name,attrs); }; + handlers.endElement = [&layoutParser](const std::string &name) { layoutParser.endElement(name); }; + handlers.error = [&layoutParser](const std::string &fn,int lineNr,const std::string &msg) { layoutParser.error(fn,lineNr,msg); }; + XMLParser parser(handlers); + layoutParser.setDocumentLocator(&parser); + parser.parse(fileName,fileToString(fileName)); } //--------------------------------------------------------------------------------- @@ -1560,8 +1565,8 @@ void writeDefaultLayoutFile(const char *fileName) err("Failed to open file %s for writing!\n",fileName); return; } - QTextStream t(&f); - t.setEncoding(QTextStream::UnicodeUTF8); + FTextStream t(&f); + QCString layout_default = ResourceMgr::instance().getAsString("layout_default.xml"); t << substitute(layout_default,"$doxygenversion",getDoxygenVersion()); } diff --git a/src/layout.h b/src/layout.h index b1facf5..68d5c6e 100644 --- a/src/layout.h +++ b/src/layout.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. * @@ -19,6 +19,7 @@ #ifndef LAYOUT_H #define LAYOUT_H +#include <memory> #include <qlist.h> #include "types.h" @@ -30,14 +31,14 @@ class QTextStream; struct LayoutDocEntry { virtual ~LayoutDocEntry() {} - enum Kind { + enum Kind { // Generic items for all pages MemberGroups, MemberDeclStart, MemberDeclEnd, MemberDecl, MemberDefStart, MemberDefEnd, MemberDef, BriefDesc, DetailedDesc, AuthorSection, - + // Class specific items ClassIncludes, ClassInlineClasses, ClassInheritanceGraph, ClassNestedClasses, @@ -51,7 +52,7 @@ struct LayoutDocEntry // File specific items FileClasses, FileInterfaces, FileStructs, FileExceptions, FileConstantGroups, FileNamespaces, - FileIncludes, FileIncludeGraph, + FileIncludes, FileIncludeGraph, FileIncludedByGraph, FileSourceLink, FileInlineClasses, @@ -90,7 +91,7 @@ private: struct LayoutDocEntryMemberDecl: public LayoutDocEntry { LayoutDocEntryMemberDecl(MemberListType tp, - const QCString &tl,const QCString &ss) + const QCString &tl,const QCString &ss) : type(tp), m_title(tl), m_subscript(ss) {} Kind kind() const { return MemberDecl; } @@ -105,7 +106,7 @@ private: /** @brief Represents of a member definition list with configurable title. */ struct LayoutDocEntryMemberDef: public LayoutDocEntry { - LayoutDocEntryMemberDef(MemberListType tp,const QCString &tl) + LayoutDocEntryMemberDef(MemberListType tp,const QCString &tl) : type(tp), m_title(tl) {} Kind kind() const { return MemberDef; } @@ -116,44 +117,44 @@ private: }; /** @brief Base class for the layout of a navigation item at the top of the HTML pages. */ -struct LayoutNavEntry +struct LayoutNavEntry { public: - enum Kind { - None = -1, - MainPage, + enum Kind { + None = -1, + MainPage, Pages, - Modules, - Namespaces, + Modules, + Namespaces, NamespaceList, NamespaceMembers, Classes, - ClassList, - ClassIndex, - ClassHierarchy, + ClassList, + ClassIndex, + ClassHierarchy, ClassMembers, Interfaces, - InterfaceList, - InterfaceIndex, - InterfaceHierarchy, + InterfaceList, + InterfaceIndex, + InterfaceHierarchy, Structs, - StructList, - StructIndex, + StructList, + StructIndex, Exceptions, - ExceptionList, - ExceptionIndex, - ExceptionHierarchy, - Files, + ExceptionList, + ExceptionIndex, + ExceptionHierarchy, + Files, FileList, FileGlobals, Examples, User, UserGroup }; - LayoutNavEntry(LayoutNavEntry *parent,Kind k,bool vs,const QCString &bf, - const QCString &tl,const QCString &intro,bool prepend=FALSE) + LayoutNavEntry(LayoutNavEntry *parent,Kind k,bool vs,const QCString &bf, + const QCString &tl,const QCString &intro,bool prepend=FALSE) : m_parent(parent), m_kind(k), m_visible(vs), m_baseFile(bf), m_title(tl), m_intro(intro) - { m_children.setAutoDelete(TRUE); + { m_children.setAutoDelete(TRUE); if (parent) { if (prepend) parent->prependChild(this); else parent->addChild(this); } } LayoutNavEntry *parent() const { return m_parent; } @@ -208,7 +209,7 @@ class LayoutDocManager void clear(LayoutPart p); LayoutDocManager(); ~LayoutDocManager(); - Private *d; + std::unique_ptr<Private> d; friend class LayoutParser; }; diff --git a/src/linkedmap.h b/src/linkedmap.h index 84dcf26..f09b6d8 100644 --- a/src/linkedmap.h +++ b/src/linkedmap.h @@ -21,26 +21,30 @@ #include <memory> #include <string> #include <algorithm> +#include <cctype> -//! @brief Container class representing a vector of objects with unique keys. +//! @brief Container class representing a vector of objects with 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> +template<class T, class Hash = std::hash<std::string>, + class KeyEqual = std::equal_to<std::string>, + class Map = std::unordered_map<std::string,T*,Hash,KeyEqual > > 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; + using reverse_iterator = typename Vec::reverse_iterator; + using const_reverse_iterator = typename Vec::const_reverse_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 + const T *find(const char *key_) const { - std::string key = k ? std::string(k) : std::string(); + std::string key(key_ ? key_ : ""); auto it = m_lookup.find(key); return it!=m_lookup.end() ? it->second : nullptr; } @@ -51,7 +55,7 @@ class LinkedMap 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. + //! Adds a new object to the ordered vector 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> @@ -60,8 +64,8 @@ class LinkedMap 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)...); + std::string key(k ? k : ""); + Ptr ptr = std::make_unique<T>(key.c_str(),std::forward<Args>(args)...); result = ptr.get(); m_lookup.insert({key,result}); m_entries.push_back(std::move(ptr)); @@ -69,11 +73,46 @@ class LinkedMap return result; } + //! Adds an existing object to the ordered vector (unless another object was already + //! added under the same key). Ownership is transferred. + //! 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. + T *add(const char *k, Ptr &&ptr) + { + T *result = find(k); + if (result==nullptr) + { + std::string key(k ? k : ""); + result = ptr.get(); + m_lookup.insert({key,result}); + m_entries.push_back(std::move(ptr)); + } + return result; + } + + //! Prepends a new object to the ordered vector 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 *prepend(const char *k, Args&&... args) + { + T *result = find(k); + if (result==nullptr) + { + std::string key(k ? k : ""); + Ptr ptr = std::make_unique<T>(key.c_str(),std::forward<Args>(args)...); + result = ptr.get(); + m_lookup.insert({key,result}); + m_entries.push_front(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) + //! Returns true if the object was deleted or false it is was not found. + bool del(const char *key_) { - std::string key = k ? std::string(k) : std::string(); + std::string key(key_ ? key_ : ""); auto it = m_lookup.find(key); if (it!=m_lookup.end()) { @@ -88,12 +127,18 @@ class LinkedMap 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(); } + Ptr &operator[](size_t pos) { return m_entries[pos]; } + const Ptr &operator[](size_t pos) const { return m_entries[pos]; } + 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(); } + reverse_iterator rbegin() { return m_entries.rbegin(); } + reverse_iterator rend() { return m_entries.rend(); } + const_reverse_iterator rbegin() const { return m_entries.crbegin(); } + const_reverse_iterator rend() const { return m_entries.crend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } void clear() { @@ -102,30 +147,33 @@ class LinkedMap } private: + Map m_lookup; Vec m_entries; }; -#if 0 // not yet used -//! @brief Container class representing a vector of objects with unique keys. +//! @brief Container class representing a vector of objects with 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> +template<class T, class Hash = std::hash<std::string>, + class KeyEqual = std::equal_to<std::string>, + class Map = std::unordered_map<std::string,T*,Hash,KeyEqual > > 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; + using reverse_iterator = typename Vec::reverse_iterator; + using const_reverse_iterator = typename Vec::const_reverse_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 + const T *find(const char *key_) const { - std::string key = k ? std::string(k) : std::string(); + std::string key(key_ ? key_ : ""); auto it = m_lookup.find(key); return it!=m_lookup.end() ? it->second : nullptr; } @@ -136,14 +184,14 @@ class LinkedRefMap 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 + //! Adds an object reference to the ordered vector if it was not added already. + //! Return true if the reference 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(); + std::string key(k ? k : ""); m_lookup.insert({key,obj}); m_entries.push_back(obj); return true; @@ -154,12 +202,55 @@ class LinkedRefMap } } - 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(); } + //! Prepends an object reference to the ordered vector if it was not added already. + //! Return true if the reference was added, and false if an object with the same key + //! was already added before + bool prepend(const char *k, T* obj) + { + if (find(k)==nullptr) // new element + { + std::string key(k ? k : ""); + m_lookup.insert({key,obj}); + m_entries.insert(m_entries.begin(),obj); + return true; + } + else // already existing, don't add + { + return false; + } + } + + //! Removes an object from the container and deletes it. + //! Returns true if the object was deleted or false it is was not found. + bool del(const char *key_) + { + std::string key(key_ ? key_ : ""); + 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; + } + + Ptr &operator[](size_t pos) { return m_entries[pos]; } + const Ptr &operator[](size_t pos) const { return m_entries[pos]; } + 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(); } + reverse_iterator rbegin() { return m_entries.rbegin(); } + reverse_iterator rend() { return m_entries.rend(); } + const_reverse_iterator rbegin() const { return m_entries.crbegin(); } + const_reverse_iterator rend() const { return m_entries.crend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } void clear() { @@ -171,7 +262,6 @@ class LinkedRefMap Map m_lookup; Vec m_entries; }; -#endif #endif diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index fef857e..875cd14 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.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 "mandocvisitor.h" #include "docparser.h" @@ -33,7 +30,7 @@ #include "emoji.h" ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const char *langExt) + const char *langExt) : DocVisitor(DocVisitor_Man), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_firstCol(FALSE), m_indent(0), m_langExt(langExt) { @@ -205,8 +202,7 @@ void ManDocVisitor::visit(DocVerbatim *s) if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(), + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(), langExt, s->isExample(),s->exampleFile()); if (!m_firstCol) m_t << endl; @@ -214,7 +210,7 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP" << endl; m_firstCol=TRUE; break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; @@ -224,18 +220,18 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP" << endl; m_firstCol=TRUE; break; - case DocVerbatim::ManOnly: - m_t << s->text(); + case DocVerbatim::ManOnly: + m_t << s->text(); break; - case DocVerbatim::HtmlOnly: - case DocVerbatim::XmlOnly: - case DocVerbatim::LatexOnly: + case DocVerbatim::HtmlOnly: + case DocVerbatim::XmlOnly: + case DocVerbatim::LatexOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - case DocVerbatim::Dot: - case DocVerbatim::Msc: - case DocVerbatim::PlantUML: - /* nothing */ + case DocVerbatim::Dot: + case DocVerbatim::Msc: + case DocVerbatim::PlantUML: + /* nothing */ break; } } @@ -252,14 +248,13 @@ void ManDocVisitor::visit(DocInclude *inc) switch(inc->type()) { case DocInclude::IncWithLines: - { + { if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -278,12 +273,11 @@ void ManDocVisitor::visit(DocInclude *inc) m_firstCol=TRUE; } break; - case DocInclude::Include: + case DocInclude::Include: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -311,7 +305,7 @@ void ManDocVisitor::visit(DocInclude *inc) case DocInclude::ManInclude: m_t << inc->text(); break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; @@ -325,8 +319,7 @@ void ManDocVisitor::visit(DocInclude *inc) if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -345,13 +338,12 @@ void ManDocVisitor::visit(DocInclude *inc) m_t << ".nf" << endl; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -366,8 +358,8 @@ void ManDocVisitor::visit(DocInclude *inc) m_firstCol=TRUE; } 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; @@ -381,7 +373,7 @@ void ManDocVisitor::visit(DocIncOperator *op) SrcLangExt langExt = getLanguageFromFileName(locLangExt); //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) { @@ -392,10 +384,10 @@ void ManDocVisitor::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()) @@ -404,8 +396,7 @@ void ManDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef op->line(), // startLine @@ -419,7 +410,7 @@ void ManDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); if (!m_hide) @@ -484,7 +475,7 @@ void ManDocVisitor::visitPre(DocAutoListItem *li) QCString ws; ws.fill(' ',m_indent-2); if (!m_firstCol) m_t << endl; - m_t << ".IP \"" << ws; + m_t << ".IP \"" << ws; if (((DocAutoList *)li->parent())->isEnumList()) { m_t << li->itemNumber() << ".\" " << m_indent+2; @@ -497,14 +488,14 @@ void ManDocVisitor::visitPre(DocAutoListItem *li) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocAutoListItem *) +void ManDocVisitor::visitPost(DocAutoListItem *) { if (m_hide) return; m_t << endl; m_firstCol=TRUE; } -void ManDocVisitor::visitPre(DocPara *) +void ManDocVisitor::visitPre(DocPara *) { } @@ -515,7 +506,7 @@ void ManDocVisitor::visitPost(DocPara *p) !(p->parent() && // and for parameter sections p->parent()->kind()==DocNode::Kind_ParamSect ) - ) + ) { if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; @@ -535,28 +526,28 @@ void ManDocVisitor::visitPre(DocSimpleSect *s) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } m_t << "\\fB"; 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; @@ -630,7 +621,7 @@ void ManDocVisitor::visitPre(DocSimpleListItem *) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSimpleListItem *) +void ManDocVisitor::visitPost(DocSimpleListItem *) { if (m_hide) return; m_t << endl; @@ -649,7 +640,7 @@ void ManDocVisitor::visitPre(DocSection *s) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSection *) +void ManDocVisitor::visitPost(DocSection *) { } @@ -661,7 +652,7 @@ void ManDocVisitor::visitPre(DocHtmlList *) m_t << ".PD 0" << endl; } -void ManDocVisitor::visitPost(DocHtmlList *) +void ManDocVisitor::visitPost(DocHtmlList *) { if (m_hide) return; m_indent-=2; @@ -675,7 +666,7 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) QCString ws; ws.fill(' ',m_indent-2); if (!m_firstCol) m_t << endl; - m_t << ".IP \"" << ws; + m_t << ".IP \"" << ws; if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered) { m_t << li->itemNumber() << ".\" " << m_indent+2; @@ -688,7 +679,7 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocHtmlListItem *) +void ManDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << endl; @@ -703,7 +694,7 @@ void ManDocVisitor::visitPost(DocHtmlListItem *) // m_insidePre=TRUE; //} // -//void ManDocVisitor::visitPost(DocHtmlPre *) +//void ManDocVisitor::visitPost(DocHtmlPre *) //{ // m_insidePre=FALSE; // if (!m_firstCol) m_t << endl; @@ -716,7 +707,7 @@ void ManDocVisitor::visitPre(DocHtmlDescList *) { } -void ManDocVisitor::visitPost(DocHtmlDescList *) +void ManDocVisitor::visitPost(DocHtmlDescList *) { if (m_hide) return; if (!m_firstCol) m_t << endl; @@ -732,7 +723,7 @@ void ManDocVisitor::visitPre(DocHtmlDescTitle *) m_firstCol=FALSE; } -void ManDocVisitor::visitPost(DocHtmlDescTitle *) +void ManDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "\\fP\" 1c" << endl; @@ -743,7 +734,7 @@ void ManDocVisitor::visitPre(DocHtmlDescData *) { } -void ManDocVisitor::visitPost(DocHtmlDescData *) +void ManDocVisitor::visitPost(DocHtmlDescData *) { } @@ -751,7 +742,7 @@ void ManDocVisitor::visitPre(DocHtmlTable *) { } -void ManDocVisitor::visitPost(DocHtmlTable *) +void ManDocVisitor::visitPost(DocHtmlTable *) { } @@ -759,7 +750,7 @@ void ManDocVisitor::visitPre(DocHtmlCaption *) { } -void ManDocVisitor::visitPost(DocHtmlCaption *) +void ManDocVisitor::visitPost(DocHtmlCaption *) { } @@ -767,7 +758,7 @@ void ManDocVisitor::visitPre(DocHtmlRow *) { } -void ManDocVisitor::visitPost(DocHtmlRow *) +void ManDocVisitor::visitPost(DocHtmlRow *) { } @@ -775,7 +766,7 @@ void ManDocVisitor::visitPre(DocHtmlCell *) { } -void ManDocVisitor::visitPost(DocHtmlCell *) +void ManDocVisitor::visitPost(DocHtmlCell *) { } @@ -788,7 +779,7 @@ void ManDocVisitor::visitPre(DocInternal *) //m_t << ".RS 4" << endl; } -void ManDocVisitor::visitPost(DocInternal *) +void ManDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //if (!m_firstCol) m_t << endl; @@ -803,7 +794,7 @@ void ManDocVisitor::visitPre(DocHRef *) m_t << "\\fC"; } -void ManDocVisitor::visitPost(DocHRef *) +void ManDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "\\fP"; @@ -817,7 +808,7 @@ void ManDocVisitor::visitPre(DocHtmlHeader *header) m_t << " \""; } -void ManDocVisitor::visitPost(DocHtmlHeader *header) +void ManDocVisitor::visitPost(DocHtmlHeader *header) { if (m_hide) return; m_t << "\"" << endl; @@ -829,7 +820,7 @@ void ManDocVisitor::visitPre(DocImage *) { } -void ManDocVisitor::visitPost(DocImage *) +void ManDocVisitor::visitPost(DocImage *) { } @@ -837,14 +828,14 @@ void ManDocVisitor::visitPre(DocDotFile *) { } -void ManDocVisitor::visitPost(DocDotFile *) +void ManDocVisitor::visitPost(DocDotFile *) { } void ManDocVisitor::visitPre(DocMscFile *) { } -void ManDocVisitor::visitPost(DocMscFile *) +void ManDocVisitor::visitPost(DocMscFile *) { } @@ -862,7 +853,7 @@ void ManDocVisitor::visitPre(DocLink *) m_t << "\\fB"; } -void ManDocVisitor::visitPost(DocLink *) +void ManDocVisitor::visitPost(DocLink *) { if (m_hide) return; m_t << "\\fP"; @@ -875,7 +866,7 @@ void ManDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void ManDocVisitor::visitPost(DocRef *) +void ManDocVisitor::visitPost(DocRef *) { if (m_hide) return; m_t << "\\fP"; @@ -891,7 +882,7 @@ void ManDocVisitor::visitPre(DocSecRefItem *) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSecRefItem *) +void ManDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << endl; @@ -904,7 +895,7 @@ void ManDocVisitor::visitPre(DocSecRefList *) m_indent+=2; } -void ManDocVisitor::visitPost(DocSecRefList *) +void ManDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; m_indent-=2; @@ -916,20 +907,20 @@ void ManDocVisitor::visitPre(DocParamSect *s) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } m_t << "\\fB"; 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); @@ -961,11 +952,11 @@ void ManDocVisitor::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 << "\\fP "; @@ -986,7 +977,7 @@ void ManDocVisitor::visitPre(DocXRefItem *x) if (m_hide) return; if (x->title().isEmpty()) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } @@ -1012,7 +1003,7 @@ void ManDocVisitor::visitPre(DocInternalRef *) m_t << "\\fB"; } -void ManDocVisitor::visitPost(DocInternalRef *) +void ManDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; m_t << "\\fP"; @@ -1030,7 +1021,7 @@ void ManDocVisitor::visitPre(DocHtmlBlockQuote *) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } @@ -1064,12 +1055,12 @@ void ManDocVisitor::visitPost(DocParBlock *) void ManDocVisitor::filter(const char *str) -{ +{ if (str) { const char *p=str; char c=0; - while ((c=*p++)) + while ((c=*p++)) { switch(c) { diff --git a/src/mangen.cpp b/src/mangen.cpp index 1faa296..e58aa6e 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -74,15 +74,23 @@ static QCString getSubdir() return dir; } -ManGenerator::ManGenerator() : OutputGenerator() +ManGenerator::ManGenerator() : OutputGenerator(Config_getString(MAN_OUTPUT)+"/"+getSubdir()) { - m_dir=Config_getString(MAN_OUTPUT) + "/" + getSubdir(); - m_firstCol=TRUE; - m_paragraph=TRUE; - m_col=0; - m_upperCase=FALSE; - m_insideTabbing=FALSE; - m_inHeader=FALSE; +} + +ManGenerator::ManGenerator(const ManGenerator &og) : OutputGenerator(og) +{ +} + +ManGenerator &ManGenerator::operator=(const ManGenerator &og) +{ + OutputGenerator::operator=(og); + return *this; +} + +std::unique_ptr<OutputGenerator> ManGenerator::clone() const +{ + return std::make_unique<ManGenerator>(*this); } ManGenerator::~ManGenerator() @@ -147,7 +155,7 @@ static QCString buildFileName(const char *name) return fileName; } -void ManGenerator::startFile(const char *,const char *manName,const char *) +void ManGenerator::startFile(const char *,const char *manName,const char *,int) { startPlainFile( buildFileName( manName ) ); m_firstCol=TRUE; @@ -383,7 +391,7 @@ void ManGenerator::endItemListItem() { } -void ManGenerator::startCodeFragment() +void ManGenerator::startCodeFragment(const char *) { newParagraph(); t << ".nf" << endl; @@ -391,7 +399,7 @@ void ManGenerator::startCodeFragment() m_paragraph=FALSE; } -void ManGenerator::endCodeFragment() +void ManGenerator::endCodeFragment(const char *) { if (!m_firstCol) t << endl; t << ".fi" << endl; @@ -428,7 +436,7 @@ void ManGenerator::startDoxyAnchor(const char *,const char *manName, // name,baseName.data(),buildFileName(baseName).data()); // - remove dangerous characters and append suffix, then add dir prefix - QCString fileName=m_dir+"/"+buildFileName( baseName ); + QCString fileName=dir()+"/"+buildFileName( baseName ); QFile linkfile( fileName ); // - only create file if it doesn't exist already if ( !linkfile.open( IO_ReadOnly ) ) @@ -688,7 +696,7 @@ void ManGenerator::endParamList() { } -void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int) { ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); diff --git a/src/mangen.h b/src/mangen.h index a3a2a33..052c5ee 100644 --- a/src/mangen.h +++ b/src/mangen.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,24 +27,17 @@ class ManGenerator : public OutputGenerator { public: ManGenerator(); - ~ManGenerator(); - - //OutputGenerator *copy() { return new ManGenerator; } - //OutputGenerator *clone() { return new ManGenerator(*this); } - //void append(const OutputGenerator *o); - void enable() - { if (m_genStack->top()) m_active=*m_genStack->top(); else m_active=TRUE; } - void disable() { m_active=FALSE; } - void enableIf(OutputType o) { if (o==Man) enable(); } - void disableIf(OutputType o) { if (o==Man) disable(); } - void disableIfNot(OutputType o) { if (o!=Man) disable(); } - bool isEnabled(OutputType o) { return (o==Man && m_active); } - OutputGenerator *get(OutputType o) { return (o==Man) ? this : 0; } + ManGenerator(const ManGenerator &g); + ManGenerator &operator=(const ManGenerator &g); + virtual ~ManGenerator(); + virtual std::unique_ptr<OutputGenerator> clone() const; + + OutputType type() const { return Man; } - void writeDoc(DocNode *,const Definition *,const MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *,int); static void init(); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int); void writeSearchInfo() {} void writeFooter(const char *) {} void endFile(); @@ -60,7 +53,7 @@ class ManGenerator : public OutputGenerator void endTitleHead(const char *,const char *); void startTitle(); void endTitle(); - + void newParagraph(); void startParagraph(const char *classDef); void endParagraph(); @@ -68,11 +61,11 @@ class ManGenerator : public OutputGenerator void startIndexListItem() {} void endIndexListItem() {} void startIndexList() {} - void endIndexList() { newParagraph(); } + void endIndexList() { newParagraph(); } void startIndexKey() {} - void endIndexKey() {} + void endIndexKey() {} void startIndexValue(bool) {} - void endIndexValue(const char *,bool) {} + void endIndexValue(const char *,bool) {} void startItemList() {} void endItemList() { newParagraph(); } void startIndexItem(const char *ref,const char *file); @@ -130,8 +123,8 @@ class ManGenerator : public OutputGenerator void writeRuler() {} void writeAnchor(const char *,const char *) {} - void startCodeFragment(); - void endCodeFragment(); + void startCodeFragment(const char *); + void endCodeFragment(const char *); void writeLineNumber(const char *,const char *,const char *,int l) { t << l << " "; m_col=0; } void startCodeLine(bool) {} void endCodeLine() { codify("\n"); m_col=0; } @@ -163,7 +156,7 @@ class ManGenerator : public OutputGenerator void endSmall() {} void startMemberDescription(const char *,const char *,bool) { t << "\n.RI \""; m_firstCol=FALSE; } void endMemberDescription() { t << "\""; m_firstCol=FALSE; } - void startMemberDeclaration() {} + void startMemberDeclaration() {} void endMemberDeclaration(const char *,const char *) {} void writeInheritedSectionTitle(const char *,const char *,const char *, const char *,const char *,const char *) {} @@ -196,7 +189,7 @@ class ManGenerator : public OutputGenerator void startContents() {} void endContents() {} void writeNonBreakableSpace(int n) { int i; for (i=0;i<n;i++) t << " "; } - + void startDescTable(const char *t); void endDescTable(); void startDescTableRow() {} @@ -214,7 +207,7 @@ class ManGenerator : public OutputGenerator void endGroupCollaboration(DotGroupCollaboration &) {} void startCallGraph() {} void endCallGraph(DotCallGraph &) {} - void startDirDepGraph() {} + void startDirDepGraph() {} void endDirDepGraph(DotDirDeps &) {} void writeGraphicalHierarchy(DotGfxHierarchyTable &) {} @@ -264,15 +257,13 @@ class ManGenerator : public OutputGenerator void addWord(const char *,bool) {} private: - bool m_firstCol; - bool m_paragraph; - int m_col; - bool m_upperCase; - bool m_insideTabbing; - bool m_inHeader; + bool m_firstCol = true; + bool m_paragraph = true; + int m_col = 0; + bool m_upperCase = false; + bool m_insideTabbing = false; + bool m_inHeader = false; - ManGenerator(const ManGenerator &g); - ManGenerator &operator=(const ManGenerator &g); }; #endif diff --git a/src/markdown.cpp b/src/markdown.cpp index 00c0723..340ac99 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -59,7 +59,7 @@ #ifdef ENABLE_TRACING #define IOSTREAM stdout #define DATA_BUFSIZE 20 -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) #define PRETTY_FUNC __FUNCSIG__ #else #define PRETTY_FUNC __PRETTY_FUNCTION__ @@ -784,7 +784,11 @@ void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle, m_out.addStr(title); m_out.addStr("\""); } - m_out.addStr("\n"); + else + { + m_out.addStr(" ");// so the line break will not be part of the image name + } + m_out.addStr("\\ilinebr"); } int Markdown::processLink(const char *data,int,int size) @@ -808,6 +812,7 @@ int Markdown::processLink(const char *data,int,int size) } contentStart=i; int level=1; + int nlTotal=0; int nl=0; // find the matching ] while (i<size) @@ -831,6 +836,8 @@ int Markdown::processLink(const char *data,int,int size) } i++; } + nlTotal += nl; + nl = 0; if (i>=size) return 0; // premature end of comment -> no link contentEnd=i; convertStringFragment(content,data+contentStart,contentEnd-contentStart); @@ -843,9 +850,12 @@ int Markdown::processLink(const char *data,int,int size) if (i<size && data[i]=='\n') // one newline allowed here { i++; + nl++; // skip more whitespace while (i<size && data[i]==' ') i++; } + nlTotal += nl; + nl = 0; bool explicitTitle=FALSE; if (i<size && data[i]=='(') // inline link @@ -854,7 +864,6 @@ int Markdown::processLink(const char *data,int,int size) while (i<size && data[i]==' ') i++; if (i<size && data[i]=='<') i++; linkStart=i; - nl=0; int braceCount=1; while (i<size && data[i]!='\'' && data[i]!='"' && braceCount>0) { @@ -876,6 +885,8 @@ int Markdown::processLink(const char *data,int,int size) i++; } } + nlTotal += nl; + nl = 0; if (i>=size || data[i]=='\n') return 0; convertStringFragment(link,data+linkStart,i-linkStart); link = link.stripWhiteSpace(); @@ -985,6 +996,8 @@ int Markdown::processLink(const char *data,int,int size) { return 0; } + nlTotal += nl; + nl = 0; if (isToc) // special case for [TOC] { int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS); @@ -1037,7 +1050,11 @@ int Markdown::processLink(const char *data,int,int size) if (!(Portable::isAbsolutePath(link) || isURL(link))) { QFileInfo forg(link); - if (!(forg.exists() && forg.isReadable())) + if (forg.exists() && forg.isReadable()) + { + link = forg.absFilePath().data(); + } + else if (!(forg.exists() && forg.isReadable())) { QFileInfo fi(m_fileName); QCString mdFile = m_fileName.left(m_fileName.length()-fi.fileName().length()) + link; @@ -1066,6 +1083,7 @@ int Markdown::processLink(const char *data,int,int size) m_out.addStr("<a href=\""); m_out.addStr(link); m_out.addStr("\""); + for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n"); if (!title.isEmpty()) { m_out.addStr(" title=\""); @@ -1631,7 +1649,7 @@ static bool isFencedCodeBlock(const char *data,int size,int refIndent, { if (data[i]==tildaChar) { - end=i-1; + end=i; int endTildes=0; while (i<size && data[i]==tildaChar) endTildes++,i++; while (i<size && data[i]==' ') i++; @@ -1675,7 +1693,12 @@ static bool isCodeBlock(const char *data,int offset,int size,int &indent) // search back 3 lines and remember the start of lines -1 and -2 while (i>0 && nl<3) { - if (data[i-offset-1]=='\n') nl_pos[nl++]=i-offset; + int j = i-offset-1; + int nl_size = isNewline(data+j); + if (nl_size>0) + { + nl_pos[nl++]=j+nl_size; + } i--; } @@ -1699,8 +1722,8 @@ 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); + //printf(">isCodeBlock local_indent %d>=%d+%d=%d\n", + // indent0,indent,codeBlockIndent,indent0>=indent+codeBlockIndent); // if the difference is >4 spaces -> code block return indent0>=indent+codeBlockIndent; } @@ -1923,16 +1946,16 @@ int Markdown::writeTableBlock(const char *data,int size) { if (row % 2) { - m_out.addStr("<tr class=\"markdownTableRowOdd\">"); + m_out.addStr("\n<tr class=\"markdownTableRowOdd\">"); } else { - m_out.addStr("<tr class=\"markdownTableRowEven\">"); + m_out.addStr("\n<tr class=\"markdownTableRowEven\">"); } } else { - m_out.addStr(" <tr class=\"markdownTableHead\">"); + m_out.addStr("\n <tr class=\"markdownTableHead\">"); } for (int c = 0; c < columns; c++) { @@ -1986,11 +2009,11 @@ int Markdown::writeTableBlock(const char *data,int size) } // need at least one space on either side of the cell text in // order for doxygen to do other formatting - m_out.addStr("> " + cellText + "\\ilinebr </" + cellTag + ">"); + m_out.addStr("> " + cellText + " \\ilinebr </" + cellTag + ">"); } cellTag = "td"; cellClass = "class=\"markdownTableBody"; - m_out.addStr(" </tr>\n"); + m_out.addStr(" </tr>"); } m_out.addStr("</table>\n"); @@ -2023,7 +2046,7 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) QCString id; if (isHRuler(data,size)) { - m_out.addStr("\n<hr>\n"); + m_out.addStr("<hr>\n"); } else if ((level=isAtxHeader(data,size,header,id,TRUE))) { @@ -2050,7 +2073,7 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) { if (!id.isEmpty()) { - m_out.addStr("\\anchor "+id+"\n"); + m_out.addStr("\\anchor "+id+"\\ilinebr "); } hTag.sprintf("h%d",level); m_out.addStr("<"+hTag+">"); @@ -2058,13 +2081,17 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) m_out.addStr("</"+hTag+">\n"); } } - else // nothing interesting -> just output the line + else if (size>0) // nothing interesting -> just output the line { - m_out.addStr(data,size); + int tmpSize = size; + if (data[size-1] == '\n') tmpSize--; + m_out.addStr(data,tmpSize); + if (hasLineBreak(data,size)) { - m_out.addStr("<br>\n"); + m_out.addStr("<br>"); } + if (tmpSize != size) m_out.addChar('\n'); } } @@ -2100,14 +2127,14 @@ int Markdown::writeBlockQuote(const char *data,int size) { for (l=curLevel;l<level;l++) { - m_out.addStr("<blockquote>\n"); + m_out.addStr("<blockquote>"); } } else if (level<curLevel) // quote level decreased => add end markers { for (l=level;l<curLevel;l++) { - m_out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>"); } } curLevel=level; @@ -2120,7 +2147,7 @@ int Markdown::writeBlockQuote(const char *data,int size) // end of comment within blockquote => add end markers for (l=0;l<curLevel;l++) { - m_out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>"); } return i; } @@ -2130,6 +2157,7 @@ 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()); + // no need for \ilinebr here as the previous line was empty and was skipped m_out.addStr("@verbatim\n"); int emptyLines=0; while (i<size) @@ -2164,7 +2192,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent) break; } } - m_out.addStr("@endverbatim\n"); + m_out.addStr("@endverbatim\\ilinebr "); while (emptyLines>0) // write skipped empty lines { // add empty line @@ -2263,8 +2291,7 @@ void Markdown::writeFencedCodeBlock(const char *data,const char *lng, m_out.addStr("{"+lang+"}"); } addStrEscapeUtf8Nbsp(data+blockStart,blockEnd-blockStart); - m_out.addStr("\n"); - m_out.addStr("@endcode\n"); + m_out.addStr("@endcode"); } QCString Markdown::processQuotations(const QCString &s,int refIndent) @@ -2491,18 +2518,20 @@ static bool isExplicitPage(const QCString &docs) return FALSE; } -QCString Markdown::extractPageTitle(QCString &docs,QCString &id) +QCString Markdown::extractPageTitle(QCString &docs,QCString &id, int &prepend) { TRACE(docs.data()); - int ln=0; // first first non-empty line + prepend = 0; QCString title; - const char *data = docs.data(); int i=0; int size=docs.size(); + QCString docs_org(docs); + const char *data = docs_org.data(); + docs = ""; while (i<size && (data[i]==' ' || data[i]=='\n')) { - if (data[i]=='\n') ln++; + if (data[i]=='\n') prepend++; i++; } if (i>=size) return ""; @@ -2512,16 +2541,13 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id) // first line from i..end1 if (end1<size) { - ln++; // second line form end1..end2 int end2=end1+1; while (end2<size && data[end2-1]!='\n') end2++; if (isHeaderline(data+end1,size-end1,FALSE)) { convertStringFragment(title,data+i,end1-i-1); - QCString lns; - lns.fill('\n',ln); - docs=lns+docs.mid(end2); + docs+="\n\n"+docs_org.mid(end2); id = extractTitleId(title, 0); //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data()); return title; @@ -2529,10 +2555,12 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id) } if (i<end1 && isAtxHeader(data+i,end1-i,title,id,FALSE)>0) { - docs=docs.mid(end1); + docs+="\n"; + docs+=docs_org.mid(end1); } else { + docs=docs_org; id = extractTitleId(title, 0); } //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data()); @@ -2661,7 +2689,15 @@ QCString markdownFileNameToId(const QCString &fileName) QCString baseFn = stripFromPath(QFileInfo(fileName).absFilePath().utf8()); int i = baseFn.findRev('.'); if (i!=-1) baseFn = baseFn.left(i); - QCString baseName = substitute(substitute(substitute(baseFn," ","_"),"/","_"),":","_"); + QCString baseName = baseFn; + char *p = baseName.rawData(); + char c; + while ((c=*p)) + { + if (!isId(c)) *p='_'; // escape characters that do not yield an identifier by underscores + p++; + } + //printf("markdownFileNameToId(%s)=md_%s\n",qPrint(fileName),qPrint(baseName)); return "md_"+baseName; } @@ -2686,6 +2722,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, ClangTUParser* /*clangParser*/) { std::shared_ptr<Entry> current = std::make_shared<Entry>(); + int prepend = 0; // number of empty lines in front current->lang = SrcLangExt_Markdown; current->fileName = fileName; current->docFile = fileName; @@ -2693,7 +2730,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, QCString docs = fileBuf; QCString id; Markdown markdown(fileName,1,0); - QCString title=markdown.extractPageTitle(docs,id).stripWhiteSpace(); + QCString title=markdown.extractPageTitle(docs,id,prepend).stripWhiteSpace(); if (id.startsWith("autotoc_md")) id = ""; int indentLevel=title.isEmpty() ? 0 : -1; markdown.setIndentLevel(indentLevel); @@ -2710,24 +2747,26 @@ void MarkdownOutlineParser::parseInput(const char *fileName, QFileInfo(mdfileAsMainPage).absFilePath()) // file reference with path ) { - docs.prepend("@anchor " + id + "\n"); - docs.prepend("@mainpage "+title+"\n"); + docs.prepend("@anchor " + id + "\\ilinebr "); + docs.prepend("@mainpage "+title+"\\ilinebr "); } else if (id=="mainpage" || id=="index") { if (title.isEmpty()) title = titleFn; - docs.prepend("@anchor " + id + "\n"); - docs.prepend("@mainpage "+title+"\n"); + docs.prepend("@anchor " + id + "\\ilinebr "); + docs.prepend("@mainpage "+title+"\\ilinebr "); } else { - if (title.isEmpty()) title = titleFn; - if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\n"); - docs.prepend("@page "+id+" "+title+"\n"); + if (title.isEmpty()) {title = titleFn;prepend=0;} + if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\\ilinebr "); + docs.prepend("@page "+id+" "+title+"\\ilinebr "); } + for (int i = 0; i < prepend; i++) docs.prepend("\n"); } int lineNr=1; + p->commentScanner.enterFile(fileName,lineNr); Protection prot=Public; bool needsEntry = FALSE; int position=0; @@ -2759,6 +2798,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, { root->moveToSubEntryAndKeep(current); } + p->commentScanner.leaveFile(fileName,lineNr); } void MarkdownOutlineParser::parsePrototype(const char *text) diff --git a/src/markdown.h b/src/markdown.h index 1210967..dd4ff73 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -34,7 +34,7 @@ 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); + QCString extractPageTitle(QCString &docs,QCString &id,int &prepend); void setIndentLevel(int level) { m_indentLevel = level; } private: diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 464dbd0..ecc07d7 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -47,7 +47,7 @@ //----------------------------------------------------------------------------- -class MemberDefImpl : public DefinitionImpl, public MemberDef +class MemberDefImpl : public DefinitionMixin<MemberDefMutable> { public: MemberDefImpl(const char *defFileName,int defLine,int defColumn, @@ -76,15 +76,11 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual int initializerLines() const; virtual uint64 getMemberSpecifiers() const; virtual const MemberList *getSectionList(const Definition *) const; - virtual QCString displayDefinition() const; + virtual QCString displayDefinition() const; virtual const ClassDef *getClassDef() const; - virtual ClassDef *getClassDef(); virtual const FileDef *getFileDef() const; - virtual FileDef *getFileDef(); virtual const NamespaceDef* getNamespaceDef() const; - virtual NamespaceDef* getNamespaceDef(); virtual const GroupDef *getGroupDef() const; - virtual GroupDef *getGroupDef(); virtual ClassDef *accessorClass() const; virtual const char *getReadAccessor() const; virtual const char *getWriteAccessor() const; @@ -242,7 +238,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual int getDeclColumn() const; virtual void setMemberType(MemberType t); virtual void setDefinition(const char *d); - virtual void setFileDef(FileDef *fd); + virtual void setFileDef(const FileDef *fd); virtual void setAnchor(); virtual void setProtection(Protection p); virtual void setMemberSpecifiers(uint64 s); @@ -250,9 +246,9 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setInitializer(const char *i); virtual void setBitfields(const char *s); virtual void setMaxInitLines(int lines); - virtual void setMemberClass(ClassDef *cd); + virtual void setMemberClass(const ClassDef *cd); virtual void setSectionList(const Definition *container,MemberList *sl); - virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, + virtual void setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0); virtual void setReadAccessor(const char *r); @@ -281,7 +277,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setTypeConstraints(const ArgumentList &al); virtual void setType(const char *t); virtual void setAccessorType(ClassDef *cd,const char *t); - virtual void setNamespace(NamespaceDef *nd); + virtual void setNamespace(const NamespaceDef *nd); virtual void setMemberGroup(MemberGroup *grp); virtual void setMemberGroupId(int id); virtual void makeImplementationDetail(); @@ -323,13 +319,14 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void warnIfUndocumented() const; virtual void warnIfUndocumentedParams() const; virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const; - virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, + virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs, 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, bool onlyText=FALSE) const; virtual void addToSearchIndex() const; + virtual void resolveUnnamedParameters(const MemberDef *md); private: void _computeLinkableInProject(); @@ -360,10 +357,10 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef IMPL *m_impl; uchar m_isLinkableCached; // 0 = not cached, 1=FALSE, 2=TRUE uchar m_isConstructorCached; // 0 = not cached, 1=FALSE, 2=TRUE - uchar m_isDestructorCached; // 0 = not cached, 1=FALSE, 2=TRUE + uchar m_isDestructorCached; // 1 = not cached, 1=FALSE, 2=TRUE }; -MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, +MemberDefMutable *createMemberDef(const char *defFileName,int defLine,int defColumn, const char *type,const char *name,const char *args, const char *excp,Protection prot,Specifier virt,bool stat, Relationship related,MemberType t,const ArgumentList &tal, @@ -375,15 +372,15 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, //----------------------------------------------------------------------------- -class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef +class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef> { public: MemberDefAliasImpl(const Definition *newScope,const MemberDef *md) - : DefinitionAliasImpl(newScope,md), m_memberGroup(0) {} - virtual ~MemberDefAliasImpl() {} + : DefinitionAliasMixin(newScope,md), m_memberGroup(0) { init(); } + virtual ~MemberDefAliasImpl() { deinit(); } virtual DefType definitionType() const { return TypeMember; } - const MemberDef *getMdAlias() const { return dynamic_cast<const MemberDef*>(getAlias()); } + const MemberDef *getMdAlias() const { return toMemberDef(getAlias()); } virtual MemberDef *resolveAlias() { return const_cast<MemberDef*>(getMdAlias()); } virtual const MemberDef *resolveAlias() const { return getMdAlias(); } @@ -392,6 +389,8 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef } virtual void moveTo(Definition *) {} + virtual QCString name() const + { return getMdAlias()->name(); } virtual QCString getOutputFileBase() const { return getMdAlias()->getOutputFileBase(); } virtual QCString getReference() const @@ -428,7 +427,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { return getMdAlias()->getFileDef(); } virtual const NamespaceDef* getNamespaceDef() const { return getMdAlias()->getNamespaceDef(); } - virtual ClassDef *accessorClass() const + virtual const ClassDef *accessorClass() const { return getMdAlias()->accessorClass(); } virtual const char *getReadAccessor() const { return getMdAlias()->getReadAccessor(); } @@ -737,95 +736,13 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef virtual int getDeclColumn() const { return getMdAlias()->getDeclColumn(); } - // non-const getters should not be called - virtual ClassDef *getClassDef() - { err("non-const getClassDef() called on aliased member. Please report as a bug.\n"); return 0; } - virtual FileDef *getFileDef() - { err("non-const getFileDef() called on aliased member. Please report as a bug.\n"); return 0; } - virtual NamespaceDef* getNamespaceDef() - { err("non-const getNamespaceDef() called on aliased member. Please report as a bug.\n"); return 0; } - virtual GroupDef *getGroupDef() - { err("non-const getGroupDef() called on aliased member. Please report as a bug.\n"); return 0; } - virtual ArgumentList &argumentList() - { err("non-const argumentList() called on aliased member. Please report as bug.\n"); - static ArgumentList dummy; return dummy; - } - - virtual void setEnumBaseType(const QCString &type) {} - virtual void setMemberType(MemberType t) {} - virtual void setDefinition(const char *d) {} - virtual void setFileDef(FileDef *fd) {} - virtual void setAnchor() {} - virtual void setProtection(Protection p) {} - virtual void setMemberSpecifiers(uint64 s) {} - virtual void mergeMemberSpecifiers(uint64 s) {} - virtual void setInitializer(const char *i) {} - virtual void setBitfields(const char *s) {} - virtual void setMaxInitLines(int lines) {} - virtual void setMemberClass(ClassDef *cd) {} - 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) {} - virtual void setReadAccessor(const char *r) {} - virtual void setWriteAccessor(const char *w) {} - virtual void setTemplateSpecialization(bool b) {} - virtual void makeRelated() {} - virtual void makeForeign() {} - virtual void setInheritsDocsFrom(MemberDef *md) {} - virtual void setTagInfo(const TagInfo *i) {} - virtual void setArgsString(const char *as) {} - virtual void setReimplements(MemberDef *md) {} - virtual void insertReimplementedBy(MemberDef *md) {} - virtual void setRelatedAlso(ClassDef *cd) {} - virtual void insertEnumField(MemberDef *md) {} - virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE) {} - virtual void setEnumClassScope(ClassDef *cd) {} - virtual void setDocumentedEnumValues(bool value) {} - virtual void setAnonymousEnumType(const MemberDef *md) {} - virtual bool addExample(const char *anchor,const char *name,const char *file) { return FALSE; } - 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 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) {} - virtual void setNamespace(NamespaceDef *nd) {} + virtual void warnIfUndocumented() const {} + virtual void warnIfUndocumentedParams() const {} + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const {} virtual void setMemberGroup(MemberGroup *grp) { m_memberGroup = grp; } - virtual void setMemberGroupId(int id) {} - virtual void makeImplementationDetail() {} - virtual void setFromAnonymousScope(bool b) const {} - virtual void setFromAnonymousMember(MemberDef *m) {} - virtual void enableCallGraph(bool e) {} - virtual void enableCallerGraph(bool e) {} - virtual void enableReferencedByRelation(bool e) {} - virtual void enableReferencesRelation(bool e) {} - virtual void setTemplateMaster(MemberDef *mt) {} - virtual void addListReference(Definition *d) {} - virtual void setDocsForDefinition(bool b) {} - virtual void setGroupAlias(const MemberDef *md) {} - virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) {} - virtual void invalidateTypedefValCache() {} - virtual void invalidateCachedArgumentTypes() {} - virtual void setMemberDefinition(MemberDef *md) {} - virtual void setMemberDeclaration(MemberDef *md) {} - virtual void setAnonymousUsed() const {} - virtual void copyArgumentNames(MemberDef *bmd) {} - virtual void setCategory(ClassDef *) {} - virtual void setCategoryRelation(MemberDef *) {} - 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 *inbodyFile,int inbodyLine) {} - virtual void setHidden(bool b) {} - virtual void addToSearchIndex() const {} - virtual void findSectionsInDocumentation() {} - virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, + virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs, const std::unique_ptr<ArgumentList> &actualArgs) const { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); } - virtual void incrementFlowKeyWordCount() {} virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, @@ -838,18 +755,6 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { getMdAlias()->writeEnumDeclaration(typeDecl,cd,nd,fd,gd); } - virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol, - const char *scopeName,const Definition *container, - bool inGroup,bool showEnumValues=FALSE,bool - showInline=FALSE) const {} - virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const {} - virtual void writeLink(OutputList &ol, - const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - bool onlyText=FALSE) const {} - virtual void writeTagFile(FTextStream &) const {} - virtual void warnIfUndocumented() const {} - virtual void warnIfUndocumentedParams() const {} - virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const {} private: MemberGroup *m_memberGroup; // group's member definition }; @@ -857,7 +762,9 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd) { - return new MemberDefAliasImpl(newScope,aliasMd); + MemberDef *amd = new MemberDefAliasImpl(newScope,aliasMd); + //printf("amd: name=%s displayName=%s\n",amd->name().data(),amd->displayName().data()); + return amd; } //----------------------------------------------------------------------------- @@ -938,7 +845,7 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me const ArgumentList &defArgList=(md->isDocsForDefinition()) ? md->argumentList() : md->declArgumentList(); //printf("writeDefArgumentList '%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition()); - if (!defArgList.hasParameters() || md->isProperty()) + if (!defArgList.hasParameters() || md->isProperty() || md->isTypedef()) { return FALSE; // member has no function like argument list } @@ -985,7 +892,7 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me } else if (scope->definitionType()==Definition::TypeClass) { - cName=tempArgListToString((dynamic_cast<const ClassDef*>(scope))->templateArguments(), + cName=tempArgListToString((toClassDef(scope))->templateArguments(), scope->getLanguage()); //printf("2. cName=%s\n",cName.data()); } @@ -1275,9 +1182,9 @@ class MemberDefImpl::IMPL const ArgumentList &al,const char *meta ); - ClassDef *classDef = 0; // member of or related to - FileDef *fileDef = 0; // member of file definition - NamespaceDef *nspace = 0; // the namespace this member is in. + const ClassDef *classDef = 0; // member of or related to + const FileDef *fileDef = 0; // member of file definition + const NamespaceDef *nspace = 0; // the namespace this member is in. MemberDef *enumScope = 0; // the enclosing scope, if this is an enum field bool livesInsideEnum = false; @@ -1338,7 +1245,7 @@ class MemberDefImpl::IMPL const MemberDef *groupAlias = 0; // Member containing the definition int grpId = 0; // group id MemberGroup *memberGroup = 0; // group's member definition - GroupDef *group = 0; // group in which this member is in + const GroupDef *group = 0; // group in which this member is in Grouping::GroupPri_t grouppri; // priority of this definition QCString groupFileName; // file where this grouping was defined int groupStartLine = 0; // line " " " " " @@ -1529,7 +1436,7 @@ MemberDefImpl::MemberDefImpl(const char *df,int dl,int dc, const char *t,const char *na,const char *a,const char *e, Protection p,Specifier v,bool s,Relationship r,MemberType mt, const ArgumentList &tal,const ArgumentList &al,const char *meta - ) : DefinitionImpl(df,dl,dc,removeRedundantWhiteSpace(na)) + ) : DefinitionMixin(df,dl,dc,removeRedundantWhiteSpace(na)) { //printf("MemberDefImpl::MemberDef(%s)\n",na); m_impl = new MemberDefImpl::IMPL; @@ -1539,7 +1446,7 @@ MemberDefImpl::MemberDefImpl(const char *df,int dl,int dc, m_isDestructorCached = 0; } -MemberDefImpl::MemberDefImpl(const MemberDefImpl &md) : DefinitionImpl(md) +MemberDefImpl::MemberDefImpl(const MemberDefImpl &md) : DefinitionMixin(md) { m_impl = new MemberDefImpl::IMPL; m_isLinkableCached = 0; @@ -1609,15 +1516,15 @@ void MemberDefImpl::moveTo(Definition *scope) setOuterScope(scope); if (scope->definitionType()==Definition::TypeClass) { - m_impl->classDef = dynamic_cast<ClassDef*>(scope); + m_impl->classDef = toClassDef(scope); } else if (scope->definitionType()==Definition::TypeFile) { - m_impl->fileDef = dynamic_cast<FileDef*>(scope); + m_impl->fileDef = toFileDef(scope); } else if (scope->definitionType()==Definition::TypeNamespace) { - m_impl->nspace = dynamic_cast<NamespaceDef*>(scope); + m_impl->nspace = toNamespaceDef(scope); } m_isLinkableCached = 0; m_isConstructorCached = 0; @@ -1641,7 +1548,11 @@ void MemberDefImpl::insertReimplementedBy(MemberDef *md) { if (m_impl->templateMaster) { - m_impl->templateMaster->insertReimplementedBy(md); + MemberDefMutable *mdm = toMemberDefMutable(m_impl->templateMaster); + if (mdm) + { + mdm->insertReimplementedBy(md); + } } if (m_impl->redefinedBy==0) m_impl->redefinedBy = new MemberList(MemberListType_redefinedBy); if (m_impl->redefinedBy->findRef(md)==-1) @@ -1779,7 +1690,7 @@ QCString MemberDefImpl::getOutputFileBase() const QCString MemberDefImpl::getReference() const { - QCString ref = DefinitionImpl::getReference(); + QCString ref = DefinitionMixin::getReference(); if (!ref.isEmpty()) { return ref; @@ -1914,25 +1825,25 @@ void MemberDefImpl::_computeLinkableInProject() void MemberDefImpl::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace) { - DefinitionImpl::setDocumentation(d,docFile,docLine,stripWhiteSpace); + DefinitionMixin::setDocumentation(d,docFile,docLine,stripWhiteSpace); m_isLinkableCached = 0; } void MemberDefImpl::setBriefDescription(const char *b,const char *briefFile,int briefLine) { - DefinitionImpl::setBriefDescription(b,briefFile,briefLine); + DefinitionMixin::setBriefDescription(b,briefFile,briefLine); m_isLinkableCached = 0; } void MemberDefImpl::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine) { - DefinitionImpl::setInbodyDocumentation(d,inbodyFile,inbodyLine); + DefinitionMixin::setInbodyDocumentation(d,inbodyFile,inbodyLine); m_isLinkableCached = 0; } void MemberDefImpl::setHidden(bool b) { - DefinitionImpl::setHidden(b); + DefinitionMixin::setHidden(b); m_isLinkableCached = 0; } @@ -1977,10 +1888,10 @@ void MemberDefImpl::writeLink(OutputList &ol, const NamespaceDef *nspace = getNamespaceDef(); if (!hideScopeNames) { - if (m_impl->enumScope && m_impl->livesInsideEnum) - { - n.prepend(m_impl->enumScope->displayName()+sep); - } + //if (m_impl->enumScope && m_impl->livesInsideEnum) + //{ + // n.prepend(m_impl->enumScope->displayName()+sep); + //} if (classDef && gd && !isRelated()) { n.prepend(classDef->displayName()+sep); @@ -2227,7 +2138,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, QCString cfname = getOutputFileBase(); // search for the last anonymous scope in the member type - ClassDef *annoClassDef=getClassDefOfAnonymousType(); + ClassDefMutable *annoClassDef=toClassDefMutable(getClassDefOfAnonymousType()); ol.startMemberDeclaration(); @@ -2405,6 +2316,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL); static bool extractStatic = Config_getBool(EXTRACT_STATIC); + MemberDefMutable *annMemb = toMemberDefMutable(m_impl->annMemb); //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d hasDocumentation=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable(),hasDocumentation()); if (!name().isEmpty() && // name valid (hasDocumentation() || isReference()) && // has docs @@ -2412,16 +2324,15 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, !(isStatic() && getClassDef()==0 && !extractStatic) // hidden due to static-ness ) { - if (m_impl->annMemb) + if (annMemb) { //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor()); - m_impl->annMemb->writeLink(ol, - m_impl->annMemb->getClassDef(), - m_impl->annMemb->getNamespaceDef(), - m_impl->annMemb->getFileDef(), - m_impl->annMemb->getGroupDef() - ); - m_impl->annMemb->setAnonymousUsed(); + annMemb->writeLink(ol, + annMemb->getClassDef(), + annMemb->getNamespaceDef(), + annMemb->getFileDef(), + annMemb->getGroupDef()); + annMemb->setAnonymousUsed(); setAnonymousUsed(); } else @@ -2442,9 +2353,9 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, // there is a brief member description and brief member // descriptions are enabled or there is no detailed description. { - if (m_impl->annMemb) + if (annMemb) { - m_impl->annMemb->setAnonymousUsed(); + annMemb->setAnonymousUsed(); setAnonymousUsed(); } const ClassDef *rcd = cd; @@ -3335,7 +3246,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, if (getClassDef()) { scopeName=getClassDef()->displayName(); scopedContainer=getClassDef(); } else if (getNamespaceDef()) { scopeName=getNamespaceDef()->displayName(); scopedContainer=getNamespaceDef(); } else if (getFileDef()) { scopeName=getFileDef()->displayName(); scopedContainer=getFileDef(); } - ciname = (dynamic_cast<const GroupDef *>(container))->groupTitle(); + ciname = (toGroupDef(container))->groupTitle(); } else if (container->definitionType()==TypeFile && getNamespaceDef() && getNamespaceDef()->isLinkable()) { // member is in a namespace, but is written as part of the file documentation @@ -3433,7 +3344,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { //printf("Anonymous compound '%s'\n",cname.data()); ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); - ol.startMemberDoc(ciname,name(),memAnchor,name(),memCount,memTotal,showInline); + ol.startMemberDoc(ciname,name(),memAnchor,"",memCount,memTotal,showInline); // search for the last anonymous compound name in the definition int si=ldef.find(' '),pi,ei=i+l; if (si==-1) si=0; @@ -3681,12 +3592,12 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, else ol.parseText(theTranslator->trInitialValue()); ol.endBold(); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - ol.startCodeFragment(); - intf.parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + ol.startCodeFragment("DoxyCode"); + intf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), -1,-1,TRUE,this,FALSE,this); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); } QCString brief = briefDescription(); @@ -3904,7 +3815,7 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *conta //printf("===> %s::anonymous: %s\n",name().data(),cd?cd->name().data():"<none>"); if (container && container->definitionType()==Definition::TypeClass && - !(dynamic_cast<const ClassDef*>(container))->isJavaEnum()) + !(toClassDef(container))->isJavaEnum()) { ol.startInlineMemberType(); ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); @@ -4050,6 +3961,18 @@ void MemberDefImpl::warnIfUndocumented() const warnIfUndocumentedParams(); } } +static QCString stripTrailingReturn(const QCString trailRet) +{ + QCString ret = trailRet; + + ret = ret.stripWhiteSpace(); + if (ret.startsWith("->")) + { + ret = ret.mid(2).stripWhiteSpace(); + return ret; + } + return trailRet; +} void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const { @@ -4058,7 +3981,17 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn 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 (!isVoidReturn && returnType == "auto") + { + const ArgumentList &defArgList=isDocsForDefinition() ? argumentList() : declArgumentList(); + if (!defArgList.trailingReturnType().isEmpty()) + { + QCString strippedTrailingReturn = stripTrailingReturn(defArgList.trailingReturnType()); + isVoidReturn = (strippedTrailingReturn=="void") || (strippedTrailingReturn.right(5)==" void"); + } + } if (!m_impl->hasDocumentedParams && hasParamCommand) { @@ -4186,7 +4119,7 @@ bool MemberDefImpl::isDeleted() const bool MemberDefImpl::hasDocumentation() const { - return DefinitionImpl::hasDocumentation() || + return DefinitionMixin::hasDocumentation() || (m_impl->mtype==MemberType_Enumeration && m_impl->docEnumValues) || // has enum values (m_impl->defArgList.hasDocumentation()); // has doc arguments } @@ -4194,7 +4127,7 @@ bool MemberDefImpl::hasDocumentation() const #if 0 bool MemberDefImpl::hasUserDocumentation() const { - bool hasDocs = DefinitionImpl::hasUserDocumentation(); + bool hasDocs = DefinitionMixin::hasUserDocumentation(); return hasDocs; } #endif @@ -4272,7 +4205,7 @@ void MemberDefImpl::setAnchor() m_impl->anc = "a"+sigStr; } -void MemberDefImpl::setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, +void MemberDefImpl::setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine, bool hasDocs,MemberDef *member) { @@ -4292,38 +4225,36 @@ void MemberDefImpl::setEnumScope(MemberDef *md,bool livesInsideEnum) m_impl->livesInsideEnum=livesInsideEnum; if (md->getGroupDef()) { - m_impl->group=md->getGroupDef(); - m_impl->grouppri=md->getGroupPri(); - m_impl->groupFileName=md->getGroupFileName(); - m_impl->groupStartLine=md->getGroupStartLine(); - m_impl->groupHasDocs=md->getGroupHasDocs(); + m_impl->group = const_cast<GroupDef*>(md->getGroupDef()); + m_impl->grouppri = md->getGroupPri(); + m_impl->groupFileName = md->getGroupFileName(); + m_impl->groupStartLine = md->getGroupStartLine(); + m_impl->groupHasDocs = md->getGroupHasDocs(); m_isLinkableCached = 0; } } -void MemberDefImpl::setMemberClass(ClassDef *cd) +void MemberDefImpl::setMemberClass(const ClassDef *cd) { m_impl->classDef=cd; m_isLinkableCached = 0; m_isConstructorCached = 0; - setOuterScope(cd); + setOuterScope(const_cast<ClassDef*>(cd)); } -void MemberDefImpl::setNamespace(NamespaceDef *nd) +void MemberDefImpl::setNamespace(const NamespaceDef *nd) { m_impl->nspace=nd; - setOuterScope(nd); + setOuterScope(const_cast<NamespaceDef*>(nd)); } -MemberDef *MemberDefImpl::createTemplateInstanceMember( +MemberDefMutable *MemberDefImpl::createTemplateInstanceMember( const ArgumentList &formalArgs,const std::unique_ptr<ArgumentList> &actualArgs) const { //printf(" Member %s %s %s\n",typeString(),name().data(),argsString()); - std::unique_ptr<ArgumentList> actualArgList; + std::unique_ptr<ArgumentList> actualArgList = std::make_unique<ArgumentList>(m_impl->defArgList); if (!m_impl->defArgList.empty()) { - actualArgList = std::make_unique<ArgumentList>(m_impl->defArgList); - // replace formal arguments with actuals for (Argument &arg : *actualArgList) { @@ -4332,10 +4263,6 @@ MemberDef *MemberDefImpl::createTemplateInstanceMember( actualArgList->setTrailingReturnType( substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs)); } - else - { - actualArgList = std::make_unique<ArgumentList>(); - } QCString methodName=name(); if (methodName.left(9)=="operator ") // conversion operator @@ -4343,7 +4270,7 @@ MemberDef *MemberDefImpl::createTemplateInstanceMember( methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs); } - MemberDef *imd = createMemberDef( + MemberDefMutable *imd = createMemberDef( getDefFileName(),getDefLine(),getDefColumn(), substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs), methodName, @@ -4417,7 +4344,7 @@ void MemberDefImpl::addListReference(Definition *) QCString memName = name(); Definition *pd=getOuterScope(); QCString pdName = pd->definitionType()==Definition::TypeClass ? - (dynamic_cast<ClassDef*>(pd))->displayName() : pd->name(); + (toClassDef(pd))->displayName() : pd->name(); QCString sep = getLanguageSpecificSeparator(lang,TRUE); QCString memArgs; if (!isRelated() @@ -4712,12 +4639,17 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, if (fmdl) { MemberListIterator mli(*fmdl); - MemberDef *fmd=mli.current(); + MemberDefMutable *fmd=toMemberDefMutable(mli.current()); bool fmdVisible = fmd ? fmd->isBriefSectionVisible() : TRUE; + bool first=true; while (fmd) { if (fmdVisible) { + if (!first) + { + typeDecl.writeString(", "); + } /* in html we start a new line after a number of items */ if (numVisibleEnumValues>enumValuesPerLine && (enumMemCount%enumValuesPerLine)==0 @@ -4752,15 +4684,12 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, typeDecl.writeString(" "); typeDecl.parseText(fmd->initializer()); } + first=false; } bool prevVisible = fmdVisible; ++mli; - fmd=mli.current(); - if (fmd && (fmdVisible=fmd->isBriefSectionVisible())) - { - typeDecl.writeString(", "); - } + fmd=toMemberDefMutable(mli.current()); if (prevVisible) { typeDecl.disable(OutputGenerator::Man); @@ -4814,6 +4743,7 @@ ClassDef *MemberDefImpl::accessorClass() const void MemberDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); } @@ -4894,7 +4824,7 @@ QCString MemberDefImpl::qualifiedName() const } else { - return DefinitionImpl::qualifiedName(); + return DefinitionMixin::qualifiedName(); } } @@ -4981,31 +4911,16 @@ const ClassDef *MemberDefImpl::getClassDef() const return m_impl->classDef; } -ClassDef *MemberDefImpl::getClassDef() -{ - return m_impl->classDef; -} - const FileDef *MemberDefImpl::getFileDef() const { return m_impl->fileDef; } -FileDef *MemberDefImpl::getFileDef() -{ - return m_impl->fileDef; -} - const NamespaceDef* MemberDefImpl::getNamespaceDef() const { return m_impl->nspace; } -NamespaceDef* MemberDefImpl::getNamespaceDef() -{ - return m_impl->nspace; -} - const char *MemberDefImpl::getReadAccessor() const { return m_impl->read; @@ -5021,11 +4936,6 @@ const GroupDef *MemberDefImpl::getGroupDef() const return m_impl->group; } -GroupDef *MemberDefImpl::getGroupDef() -{ - return m_impl->group; -} - Grouping::GroupPri_t MemberDefImpl::getGroupPri() const { return m_impl->grouppri; @@ -5463,6 +5373,54 @@ const ArgumentList &MemberDefImpl::declArgumentList() const return m_impl->declArgList; } +void MemberDefImpl::resolveUnnamedParameters(const MemberDef *md) +{ + ArgumentList &decAl = m_impl->declArgList; + ArgumentList &defAl = m_impl->defArgList; + const ArgumentList &decAlSrc = md->declArgumentList(); + const ArgumentList &defAlSrc = md->argumentList(); + auto decSrc = decAlSrc.begin(), defSrc = defAlSrc.begin(); + for (auto decIt = decAl.begin(), defIt = defAl.begin(); + decIt != decAl.end() && defIt != defAl.end() && decSrc != decAlSrc.end() && defSrc != defAlSrc.end(); + ++decIt, ++defIt, ++decSrc, ++defSrc++) + { + Argument &decA = *decIt; + Argument &defA = *defIt; + const Argument &decAS = *decSrc; + const Argument &defAS = *defSrc; + if (decA.name.isEmpty()) + { + if (!defA.name.isEmpty()) + { + decA.name = defA.name; + } + else if (!decAS.name.isEmpty()) + { + decA.name = decAS.name; + } + else if (!defAS.name.isEmpty()) + { + decA.name = defAS.name; + } + } + if (defA.name.isEmpty()) + { + if (!decA.name.isEmpty()) + { + defA.name = decA.name; + } + else if (!decAS.name.isEmpty()) + { + defA.name = decAS.name; + } + else if (!defAS.name.isEmpty()) + { + defA.name = defAS.name; + } + } + } +} + const ArgumentList &MemberDefImpl::templateArguments() const { return m_impl->tArgList; @@ -5593,7 +5551,7 @@ void MemberDefImpl::setDefinition(const char *d) m_impl->def=d; } -void MemberDefImpl::setFileDef(FileDef *fd) +void MemberDefImpl::setFileDef(const FileDef *fd) { m_impl->fileDef=fd; m_isLinkableCached = 0; @@ -5883,7 +5841,7 @@ int MemberDefImpl::numberOfFlowKeyWords() const QCString MemberDefImpl::displayName(bool) const { - return DefinitionImpl::name(); + return DefinitionMixin::name(); } void MemberDefImpl::addToSearchIndex() const @@ -5929,10 +5887,21 @@ static void transferArgumentDocumentation(ArgumentList &decAl,ArgumentList &defA { defA.docs = decA.docs; } + if (Config_getBool(RESOLVE_UNNAMED_PARAMS)) + { + if (decA.name.isEmpty() && !defA.name.isEmpty()) + { + decA.name = defA.name; + } + else if (defA.name.isEmpty() && !decA.name.isEmpty()) + { + defA.name = decA.name; + } + } } } -void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) +void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *mdef) { //printf("mdec=%s isPrototype()=%d\n",mdec->name().data(),mdec->isPrototype()); if ( @@ -5944,12 +5913,10 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) // mdef, mdef ? mdef->name().data() : "", // mdec, mdec ? mdec->name().data() : ""); - const MemberDef *cmdec = const_cast<const MemberDef*>(mdec); - 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, + ArgumentList &mdefAl = const_cast<ArgumentList&>(mdef->argumentList()); + ArgumentList &mdecAl = const_cast<ArgumentList&>(mdec->argumentList()); + if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, + mdec->getOuterScope(),mdec->getFileDef(),&mdecAl, TRUE ) ) /* match found */ @@ -5960,6 +5927,11 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) // mdec->getFileDef()->name().data(),mdec->documentation().data() // ); + if (Config_getBool(RESOLVE_UNNAMED_PARAMS)) + { + mdec->resolveUnnamedParameters(mdef); + } + // first merge argument documentation transferArgumentDocumentation(mdecAl,mdefAl); @@ -6021,7 +5993,6 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers()); mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers()); - // copy group info. if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0) { @@ -6072,7 +6043,7 @@ QCString MemberDefImpl::briefDescription(bool abbr) const } else { - return DefinitionImpl::briefDescription(abbr); + return DefinitionMixin::briefDescription(abbr); } } @@ -6084,7 +6055,7 @@ QCString MemberDefImpl::documentation() const } else { - return DefinitionImpl::documentation(); + return DefinitionMixin::documentation(); } } @@ -6128,7 +6099,114 @@ bool MemberDefImpl::isRelatedOrFriend() const bool MemberDefImpl::isReference() const { - return DefinitionImpl::isReference() || + return DefinitionMixin::isReference() || (m_impl->templateMaster && m_impl->templateMaster->isReference()); } +//------------------------------------------------------------------------------- +// Helpers + +void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst) +{ + if (src==0 || dst==0) return; + //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()) && + src->showInCallGraph() + ) + { + dst->addSourceReferencedBy(src); + MemberDefMutable *mdDef = toMemberDefMutable(dst->memberDefinition()); + if (mdDef) + { + mdDef->addSourceReferencedBy(src); + } + MemberDefMutable *mdDecl = toMemberDefMutable(dst->memberDeclaration()); + if (mdDecl) + { + mdDecl->addSourceReferencedBy(src); + } + } + if ((src->hasReferencesRelation() || src->hasCallGraph()) && + src->showInCallGraph() + ) + { + src->addSourceReferences(dst); + MemberDefMutable *mdDef = toMemberDefMutable(src->memberDefinition()); + if (mdDef) + { + mdDef->addSourceReferences(dst); + } + MemberDefMutable *mdDecl = toMemberDefMutable(src->memberDeclaration()); + if (mdDecl) + { + mdDecl->addSourceReferences(dst); + } + } +} + +// --- Cast functions +// +MemberDef *toMemberDef(Definition *d) +{ + if (d && (typeid(*d)==typeid(MemberDefImpl) || typeid(*d)==typeid(MemberDefAliasImpl))) + { + return static_cast<MemberDef*>(d); + } + else + { + return 0; + } +} + +MemberDef *toMemberDef(DefinitionMutable *md) +{ + Definition *d = toDefinition(md); + if (d && typeid(*d)==typeid(MemberDefImpl)) + { + return static_cast<MemberDef*>(d); + } + else + { + return 0; + } +} + +const MemberDef *toMemberDef(const Definition *d) +{ + if (d && (typeid(*d)==typeid(MemberDefImpl) || typeid(*d)==typeid(MemberDefAliasImpl))) + { + return static_cast<const MemberDef*>(d); + } + else + { + return 0; + } +} + +MemberDefMutable *toMemberDefMutable(Definition *d) +{ + if (d && typeid(*d)==typeid(MemberDefImpl)) + { + return static_cast<MemberDefMutable*>(d); + } + else + { + return 0; + } +} + +MemberDefMutable *toMemberDefMutable(const Definition *d) +{ + if (d && typeid(*d)==typeid(MemberDefImpl)) + { + return const_cast<MemberDefMutable*>(static_cast<const MemberDefMutable*>(d)); + } + else + { + return 0; + } +} + + + diff --git a/src/memberdef.h b/src/memberdef.h index f15c31e..11d403c 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -27,8 +27,8 @@ #include "types.h" #include "definition.h" #include "arguments.h" +#include "classdef.h" -class ClassDef; class NamespaceDef; class GroupDef; class FileDef; @@ -40,9 +40,10 @@ class GroupDef; class QTextStream; class QStrList; struct TagInfo; +class MemberDefMutable; /** A model of a class/file/namespace member symbol. */ -class MemberDef : virtual public Definition +class MemberDef : public Definition { public: virtual ~MemberDef() {} @@ -54,6 +55,8 @@ class MemberDef : virtual public Definition virtual MemberDef *resolveAlias() = 0; virtual const MemberDef *resolveAlias() const = 0; + ClassDefMutable *getClassDefMutable() const; + //----------------------------------------------------------------------------------- // ---- getters ----- //----------------------------------------------------------------------------------- @@ -77,25 +80,17 @@ class MemberDef : virtual public Definition virtual QCString displayDefinition() const = 0; // scope query members - virtual const ClassDef *getClassDef() const = 0; - virtual ClassDef *getClassDef() = 0; - virtual const FileDef *getFileDef() const = 0; - virtual FileDef *getFileDef() = 0; - + virtual const ClassDef *getClassDef() const = 0; virtual const NamespaceDef* getNamespaceDef() const = 0; - virtual NamespaceDef* getNamespaceDef() = 0; - - virtual const GroupDef *getGroupDef() const = 0; - virtual GroupDef *getGroupDef() = 0; - - virtual ClassDef *accessorClass() const = 0; + virtual const ClassDef *accessorClass() const = 0; // grabbing the property read/write accessor names virtual const char *getReadAccessor() const = 0; virtual const char *getWriteAccessor() const = 0; // querying the grouping definition + virtual const GroupDef *getGroupDef() const = 0; virtual Grouping::GroupPri_t getGroupPri() const = 0; virtual const char *getGroupFileName() const = 0; virtual int getGroupStartLine() const = 0; @@ -216,7 +211,6 @@ class MemberDef : virtual public Definition virtual bool isDocsForDefinition() const = 0; virtual const MemberDef *getEnumScope() const = 0; virtual const MemberList *enumFieldList() const = 0; - virtual void setEnumBaseType(const QCString &type) = 0; virtual QCString enumBaseType() const = 0; virtual bool hasExamples() const = 0; @@ -225,7 +219,6 @@ class MemberDef : virtual public Definition // argument related members virtual const ArgumentList &argumentList() const = 0; - virtual ArgumentList &argumentList() = 0; virtual const ArgumentList &declArgumentList() const = 0; virtual const ArgumentList &templateArguments() const = 0; virtual const ArgumentLists &definitionTemplateParameterLists() const = 0; @@ -280,15 +273,33 @@ class MemberDef : virtual public Definition virtual int getDeclLine() const = 0; virtual int getDeclColumn() const = 0; + virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs, + const std::unique_ptr<ArgumentList> &actualArgs) const = 0; + virtual void writeDeclaration(OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const = 0; + virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd, + const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0; + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0; + virtual void warnIfUndocumented() const = 0; + virtual void warnIfUndocumentedParams() const = 0; + + // TODO: this is not a getter, should be passed at construction + virtual void setMemberGroup(MemberGroup *grp) = 0; +}; + +class MemberDefMutable : public DefinitionMutable, public MemberDef +{ + public: + //----------------------------------------------------------------------------------- // ---- setters ----- //----------------------------------------------------------------------------------- - // set functions virtual void setMemberType(MemberType t) = 0; virtual void setDefinition(const char *d) = 0; - virtual void setFileDef(FileDef *fd) = 0; + virtual void setFileDef(const FileDef *fd) = 0; virtual void setAnchor() = 0; virtual void setProtection(Protection p) = 0; virtual void setMemberSpecifiers(uint64 s) = 0; @@ -296,9 +307,9 @@ class MemberDef : virtual public Definition virtual void setInitializer(const char *i) = 0; virtual void setBitfields(const char *s) = 0; virtual void setMaxInitLines(int lines) = 0; - virtual void setMemberClass(ClassDef *cd) = 0; + virtual void setMemberClass(const ClassDef *cd) = 0; virtual void setSectionList(const Definition *container,MemberList *sl) = 0; - virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, + virtual void setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0) = 0; virtual void setReadAccessor(const char *r) = 0; @@ -311,6 +322,7 @@ class MemberDef : virtual public Definition virtual void setTagInfo(const TagInfo *i) = 0; virtual void setArgsString(const char *as) = 0; virtual void incrementFlowKeyWordCount() = 0; + virtual void setEnumBaseType(const QCString &type) = 0; // relation to other members virtual void setReimplements(MemberDef *md) = 0; @@ -336,16 +348,16 @@ class MemberDef : virtual public Definition // argument related members virtual void moveArgumentList(std::unique_ptr<ArgumentList> al) = 0; virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al) = 0; + virtual void resolveUnnamedParameters(const MemberDef *md) = 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; // namespace related members - virtual void setNamespace(NamespaceDef *nd) = 0; + virtual void setNamespace(const NamespaceDef *nd) = 0; // member group related members - virtual void setMemberGroup(MemberGroup *grp) = 0; virtual void setMemberGroupId(int id) = 0; virtual void makeImplementationDetail() = 0; @@ -387,8 +399,6 @@ class MemberDef : virtual public Definition // --- actions ---- //----------------------------------------------------------------------------------- - virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, - const std::unique_ptr<ArgumentList> &actualArgs) const = 0; virtual void findSectionsInDocumentation() = 0; virtual void addToSearchIndex() const = 0; @@ -396,32 +406,40 @@ class MemberDef : virtual public Definition // --- write output ---- //----------------------------------------------------------------------------------- - virtual void writeDeclaration(OutputList &ol, - const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, - bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const = 0; virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol, const char *scopeName,const Definition *container, bool inGroup,bool showEnumValues=FALSE,bool showInline=FALSE) const = 0; virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const = 0; - virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd, - const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0; virtual void writeTagFile(FTextStream &) const = 0; virtual void writeLink(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool onlyText=FALSE) const = 0; // write helpers - virtual void warnIfUndocumented() const = 0; - virtual void warnIfUndocumentedParams() const = 0; - virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0; virtual void setAnonymousUsed() const = 0; virtual void setFromAnonymousScope(bool b) const = 0; }; +inline ClassDefMutable *MemberDef::getClassDefMutable() const +{ + return toClassDefMutable(getClassDef()); +} + +// --- Cast functions + +MemberDef *toMemberDef(Definition *d); +MemberDef *toMemberDef(DefinitionMutable *d); +const MemberDef *toMemberDef(const Definition *d); +MemberDefMutable *toMemberDefMutable(Definition *d); +MemberDefMutable *toMemberDefMutable(const Definition *d); + +//------------------------------------------------------------------------ + + /** Factory method to create a new instance of a MemberDef */ -MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, +MemberDefMutable *createMemberDef(const char *defFileName,int defLine,int defColumn, const char *type,const char *name,const char *args, const char *excp,Protection prot,Specifier virt,bool stat, Relationship related,MemberType t,const ArgumentList &tal, @@ -429,6 +447,7 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd); -void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef); +void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *mdef); +void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst); #endif diff --git a/src/membergroup.cpp b/src/membergroup.cpp index e229835..bd3bf0c 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -71,10 +71,14 @@ void MemberGroup::insertMember(MemberDef *md) GroupDef *gd; if (firstMd && !firstMd->isAlias() && (gd=const_cast<GroupDef*>(firstMd->getGroupDef()))) { - md->setGroupDef(gd, firstMd->getGroupPri(), - firstMd->getGroupFileName(), - firstMd->getGroupStartLine(), - firstMd->getGroupHasDocs()); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setGroupDef(gd, firstMd->getGroupPri(), + firstMd->getGroupFileName(), + firstMd->getGroupStartLine(), + firstMd->getGroupHasDocs()); + } gd->insertMember(md); } } @@ -82,7 +86,7 @@ void MemberGroup::insertMember(MemberDef *md) void MemberGroup::setAnchors() { - ::setAnchors(memberList); + memberList->setAnchors(); } void MemberGroup::writeDeclarations(OutputList &ol, @@ -112,7 +116,7 @@ void MemberGroup::writeDocumentation(OutputList &ol,const char *scopeName, } void MemberGroup::writeDocumentationPage(OutputList &ol,const char *scopeName, - const Definition *container) const + const DefinitionMutable *container) const { memberList->writeDocumentationPage(ol,scopeName,container); } @@ -217,12 +221,13 @@ void MemberGroup::distributeMemberGroupDocumentation() if (md) // distribute docs of md to other members of the list { //printf("Member %s has documentation!\n",md->name().data()); - MemberDef *omd; - for (li.toFirst();(omd=li.current());++li) + MemberDef *iomd; + for (li.toFirst();(iomd=li.current());++li) { - if (md!=omd && omd->documentation().isEmpty() && - omd->briefDescription().isEmpty() && - omd->inbodyDocumentation().isEmpty() + MemberDefMutable *omd = toMemberDefMutable(iomd); + if (omd && md!=omd && omd->documentation().isEmpty() && + omd->briefDescription().isEmpty() && + omd->inbodyDocumentation().isEmpty() ) { //printf("Copying documentation to member %s\n",omd->name().data()); diff --git a/src/membergroup.h b/src/membergroup.h index c10e421..e1dae25 100644 --- a/src/membergroup.h +++ b/src/membergroup.h @@ -35,6 +35,7 @@ class FileDef; class GroupDef; class OutputList; class Definition; +class DefinitionMutable; class FTextStream; class RefItem; @@ -59,7 +60,7 @@ class MemberGroup void writeDocumentation(OutputList &ol,const char *scopeName, const Definition *container,bool showEnumValues,bool showInline) const; void writeDocumentationPage(OutputList &ol,const char *scopeName, - const Definition *container) const; + const DefinitionMutable *container) const; void writeTagFile(FTextStream &); void addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd, MemberListType lt, diff --git a/src/memberlist.cpp b/src/memberlist.cpp index b8e5e89..bbc6e5d 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -63,7 +63,7 @@ MemberList::~MemberList() delete memberGroupList; } -static int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) +int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) { bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST); if (sortConstructorsFirst) @@ -334,10 +334,14 @@ void MemberList::setAnonymousEnumType() MemberDef *vmd; for ( ; (vmd=vmli.current()) ; ++vmli) { - QCString vtype=vmd->typeString(); - if ((vtype.find(name))!=-1) + MemberDefMutable *vmdm = toMemberDefMutable(vmd); + if (vmdm) { - vmd->setAnonymousEnumType(md); + QCString vtype=vmd->typeString(); + if ((vtype.find(name))!=-1) + { + vmdm->setAnonymousEnumType(md); + } } } } @@ -504,6 +508,10 @@ void MemberList::writePlainDeclarations(OutputList &ol, ol.writeString("local "); } ol.writeString("enum "); + if (md->isStrong()) + { + ol.writeString("class "); + } ol.insertMemberAlign(); md->writeEnumDeclaration(ol,cd,nd,fd,gd); if (!detailsLinkable) @@ -576,7 +584,8 @@ void MemberList::writePlainDeclarations(OutputList &ol, { if (md->fromAnonymousScope() && !md->anonymousDeclShown()) { - md->setFromAnonymousScope(FALSE); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) mdm->setFromAnonymousScope(FALSE); //printf("anonymous compound members\n"); if (md->isBriefSectionVisible()) { @@ -587,7 +596,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, } md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup); } - md->setFromAnonymousScope(TRUE); + if (mdm) mdm->setFromAnonymousScope(TRUE); } } } @@ -747,9 +756,13 @@ void MemberList::writeDeclarations(OutputList &ol, } if (inheritedFrom && cd) { - // also add members that of this list type, that are grouped together - // in a separate list in class 'inheritedFrom' - cd->addGroupedInheritedMembers(ol,m_listType,inheritedFrom,inheritId); + const ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + // also add members that of this list type, that are grouped together + // in a separate list in class 'inheritedFrom' + cdm->addGroupedInheritedMembers(ol,m_listType,inheritedFrom,inheritId); + } } //printf("----- end writeDeclaration() ----\n"); } @@ -812,9 +825,13 @@ void MemberList::writeDocumentation(OutputList &ol, { uint overloadCount = *overloadTotalDict.find(md->name()); uint *pCount = overloadCountDict.find(md->name()); - md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container, - m_inGroup,showEnumValues,showInline); - (*pCount)++; + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container, + m_inGroup,showEnumValues,showInline); + (*pCount)++; + } } } if (memberGroupList) @@ -840,21 +857,25 @@ void MemberList::writeSimpleDocumentation(OutputList &ol, const ClassDef *cd = 0; if (container && container->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<const ClassDef*>(container); + cd = toClassDef(container); } ol.startMemberDocSimple(cd && cd->isJavaEnum()); MemberListIterator mli(*this); const MemberDef *md; for ( ; (md=mli.current()) ; ++mli) { - md->writeMemberDocSimple(ol,container); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->writeMemberDocSimple(ol,container); + } } ol.endMemberDocSimple(cd && cd->isJavaEnum()); } // separate member pages void MemberList::writeDocumentationPage(OutputList &ol, - const char *scopeName, const Definition *container) const + const char *scopeName, const DefinitionMutable *container) const { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); @@ -864,9 +885,11 @@ void MemberList::writeDocumentationPage(OutputList &ol, overloadTotalDict.setAutoDelete(TRUE); overloadCountDict.setAutoDelete(TRUE); MemberListIterator mli(*this); - const MemberDef *md; - for (mli.toFirst() ; (md=mli.current()) ; ++mli) + const MemberDef *imd; + for (mli.toFirst() ; (imd=mli.current()) ; ++mli) { + MemberDefMutable *md = toMemberDefMutable(imd); + if (md->isDetailedSectionLinkable()) { uint *pCount = overloadTotalDict.find(md->name()); @@ -882,8 +905,10 @@ void MemberList::writeDocumentationPage(OutputList &ol, } } - for ( mli.toFirst() ; (md=mli.current()) ; ++mli) + for ( mli.toFirst() ; (imd=mli.current()) ; ++mli) { + Definition *container_d = toDefinition(const_cast<DefinitionMutable*>(container)); + MemberDefMutable *md = toMemberDefMutable(imd); if (md->isDetailedSectionLinkable()) { uint overloadCount = *overloadTotalDict.find(md->name()); @@ -900,10 +925,11 @@ void MemberList::writeDocumentationPage(OutputList &ol, if (generateTreeView) { - md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,m_inGroup); + md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container_d,m_inGroup); (*pCount)++; + ol.endContents(); - endFileWithNavPath(container,ol); + endFileWithNavPath(container_d,ol); } else { @@ -916,7 +942,7 @@ void MemberList::writeDocumentationPage(OutputList &ol, ol.writeString(" </td>\n"); ol.writeString(" <td valign=\"top\" class=\"mempage\">\n"); - md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,m_inGroup); + md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container_d,m_inGroup); (*pCount)++; ol.writeString(" </td>\n"); @@ -952,10 +978,11 @@ void MemberList::addMemberGroup(MemberGroup *mg) void MemberList::addListReferences(Definition *def) { MemberListIterator mli(*this); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) + MemberDef *imd; + for ( ; (imd=mli.current()) ; ++mli) { - if (!md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)) + MemberDefMutable *md = toMemberDefMutable(imd); + if (md && !md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)) { md->addListReference(def); const MemberList *enumFields = md->enumFieldList(); @@ -966,8 +993,12 @@ void MemberList::addListReferences(Definition *def) MemberDef *vmd; for ( ; (vmd=vmli.current()) ; ++vmli) { - //printf(" adding %s\n",vmd->name().data()); - vmd->addListReference(def); + MemberDefMutable *vmdm = toMemberDefMutable(vmd); + if (vmdm) + { + //printf(" adding %s\n",vmd->name().data()); + vmdm->addListReference(def); + } } } } @@ -986,10 +1017,14 @@ void MemberList::addListReferences(Definition *def) void MemberList::findSectionsInDocumentation(const Definition *d) { MemberListIterator mli(*this); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) + MemberDef *imd; + for ( ; (imd=mli.current()) ; ++mli) { - md->findSectionsInDocumentation(); + MemberDefMutable *md = toMemberDefMutable(imd); + if (md) + { + md->findSectionsInDocumentation(); + } } if (memberGroupList) { @@ -1059,7 +1094,7 @@ QCString MemberList::listTypeAsString(MemberListType type) case MemberListType_decFriendMembers: return "friend-members"; case MemberListType_decPropMembers: return "prop-members"; case MemberListType_enumFields: return "enum-fields"; - case MemberListType_memberGroup: return "member-group"; + case MemberListType_memberGroup: break; default: break; } return ""; @@ -1068,25 +1103,33 @@ QCString MemberList::listTypeAsString(MemberListType type) void MemberList::writeTagFile(FTextStream &tagFile) { MemberListIterator mli(*this); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) + MemberDef *imd; + for ( ; (imd=mli.current()) ; ++mli) { - if (md->getLanguage()!=SrcLangExt_VHDL) + MemberDefMutable *md = toMemberDefMutable(imd); + if (md) { - md->writeTagFile(tagFile); - if (md->memberType()==MemberType_Enumeration && md->enumFieldList() && !md->isStrong()) + if (md->getLanguage()!=SrcLangExt_VHDL) { - MemberListIterator vmli(*md->enumFieldList()); - MemberDef *vmd; - for ( ; (vmd=vmli.current()) ; ++vmli) + md->writeTagFile(tagFile); + if (md->memberType()==MemberType_Enumeration && md->enumFieldList() && !md->isStrong()) { - vmd->writeTagFile(tagFile); + MemberListIterator vmli(*md->enumFieldList()); + MemberDef *ivmd; + for ( ; (ivmd=vmli.current()) ; ++vmli) + { + MemberDefMutable *vmd = toMemberDefMutable(ivmd); + if (vmd) + { + vmd->writeTagFile(tagFile); + } + } } } - } - else - { - VhdlDocGen::writeTagFile(md,tagFile); + else + { + VhdlDocGen::writeTagFile(md,tagFile); + } } } if (memberGroupList) @@ -1100,6 +1143,24 @@ void MemberList::writeTagFile(FTextStream &tagFile) } } +// compute the HTML anchors for a list of members +void MemberList::setAnchors() +{ + //int count=0; + MemberListIterator mli(*this); + MemberDef *md; + for (;(md=mli.current());++mli) + { + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm && !md->isReference()) + { + mdm->setAnchor(); + } + } +} + + + //-------------------------------------------------------------------------- int MemberSDict::compareValues(const MemberDef *c1, const MemberDef *c2) const diff --git a/src/memberlist.h b/src/memberlist.h index 4038453..e62655b 100644 --- a/src/memberlist.h +++ b/src/memberlist.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. * @@ -81,7 +79,7 @@ class MemberList : private QList<MemberDef> bool showEnumValues=FALSE,bool showInline=FALSE) const; void writeSimpleDocumentation(OutputList &ol,const Definition *container) const; void writeDocumentationPage(OutputList &ol, - const char *scopeName, const Definition *container) const; + const char *scopeName, const DefinitionMutable *container) const; void writeTagFile(FTextStream &); bool declVisible() const; void addMemberGroup(MemberGroup *mg); @@ -92,6 +90,7 @@ class MemberList : private QList<MemberDef> void setNeedsSorting(bool b); MemberGroupList *getMemberGroupList() const { return memberGroupList; } void setAnonymousEnumType(); + void setAnchors(); private: int compareValues(const MemberDef *item1,const MemberDef *item2) const; @@ -105,7 +104,7 @@ class MemberList : private QList<MemberDef> int m_dictCnt; int m_protoCnt; int m_defCnt; - int m_friendCnt; + int m_friendCnt; */ int m_numDecMembers; // number of members in the brief part of the memberlist int m_numDecEnumValues; @@ -145,5 +144,6 @@ class MemberSDict : public SDict<MemberDef> int compareValues(const MemberDef *item1,const MemberDef *item2) const; }; +int genericCompareMembers(const MemberDef *c1,const MemberDef *c2); #endif diff --git a/src/message.cpp b/src/message.cpp index 984a00f..95a7553 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -34,6 +34,14 @@ static const char *error_str = "error: "; static FILE *warnFile = stderr; +enum warn_as_error +{ + WARN_NO, + WARN_YES, + FAIL_ON_WARNINGS, +}; +static warn_as_error warnBehavior = WARN_NO; +static bool warnStat = false; static std::mutex g_mutex; @@ -99,7 +107,11 @@ void initWarningFormat() warnFile = stderr; } - if (Config_getBool(WARN_AS_ERROR)) + QCString warnStr = Config_getEnum(WARN_AS_ERROR).upper(); + if (warnStr =="NO") warnBehavior=WARN_NO; + else if (warnStr =="YES") warnBehavior=WARN_YES; + else if (warnStr =="FAIL_ON_WARNINGS") warnBehavior=FAIL_ON_WARNINGS; + if (warnBehavior == WARN_YES) { warning_str = error_str; } @@ -129,7 +141,6 @@ static void format_warn(const char *file,int line,const char *text) QCString textSubst = text; QCString versionSubst; // substitute markers by actual values - bool warnAsError = Config_getBool(WARN_AS_ERROR); QCString msgText = substitute( substitute( @@ -144,7 +155,7 @@ static void format_warn(const char *file,int line,const char *text) ), "$text",textSubst ); - if (warnAsError) + if (warnBehavior == WARN_YES) { msgText += " (warning treated as error, aborting now)"; } @@ -155,22 +166,23 @@ static void format_warn(const char *file,int line,const char *text) // print resulting message fwrite(msgText.data(),1,msgText.length(),warnFile); } - if (warnAsError) + if (warnBehavior == WARN_YES) { exit(1); } + warnStat = true; } -static void handle_warn_as_error(void) +static void handle_warn_as_error() { - static bool warnAsError = Config_getBool(WARN_AS_ERROR); - if (warnAsError) + if (warnBehavior == WARN_YES) { 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); } + warnStat = true; } static void do_warn(bool enabled, const char *file, int line, const char *prefix, const char *fmt, va_list args) @@ -279,6 +291,12 @@ void term(const char *fmt, ...) exit(1); } +void warn_flush() +{ + fflush(warnFile); +} + + void printlex(int dbg, bool enter, const char *lexName, const char *fileName) { const char *enter_txt = "entering"; @@ -306,3 +324,11 @@ void printlex(int dbg, bool enter, const char *lexName, const char *fileName) Debug::print(Debug::Lex,0,"%s lexical analyzer: %s\n",enter_txt_uc, qPrint(lexName)); } } + +extern void finishWarnExit() +{ + if (warnStat && warnBehavior == FAIL_ON_WARNINGS) + { + exit(1); + } +} diff --git a/src/message.h b/src/message.h index e84344b..af49632 100644 --- a/src/message.h +++ b/src/message.h @@ -35,6 +35,8 @@ 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(); +void warn_flush(); +extern void finishWarnExit(); extern void printlex(int dbg, bool enter, const char *lexName, const char *fileName); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 88eea5d..11597bc 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -34,8 +34,21 @@ #include "membername.h" //------------------------------------------------------------------ +static QCString makeDisplayName(const NamespaceDef *nd,bool includeScope) +{ + QCString result=includeScope ? nd->name() : nd->localName(); + SrcLangExt lang = nd->getLanguage(); + QCString sep = getLanguageSpecificSeparator(lang); + if (sep!="::") + { + result = substitute(result,"::",sep); + } + //printf("makeDisplayName() %s->%s lang=%d\n",name().data(),result.data(),lang); + return result; +} +//------------------------------------------------------------------ -class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef +class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable> { public: NamespaceDefImpl(const char *defFileName,int defLine,int defColumn, @@ -58,10 +71,10 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual void countMembers(); virtual int numDocMembers() const; virtual void addUsingDirective(const NamespaceDef *nd); - virtual const NamespaceSDict *getUsedNamespaces() const; - virtual void addUsingDeclaration(const Definition *def); - virtual const SDict<Definition> *getUsedClasses() const { return usingDeclList; } - virtual void combineUsingRelations(); + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const { return m_usingDirList; } + virtual void addUsingDeclaration(const ClassDef *cd); + virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return m_usingDeclList; } + virtual void combineUsingRelations(NamespaceDefSet &visitedNamespace); virtual QCString displayName(bool=TRUE) const; virtual QCString localName() const; virtual void setInline(bool isInline) { m_inline = isInline; } @@ -76,7 +89,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual void distributeMemberGroupDocumentation(); virtual void findSectionsInDocumentation(); virtual void sortMemberLists(); - virtual Definition *findInnerCompound(const char *name) const; + virtual const Definition *findInnerCompound(const char *name) const; virtual void addInnerCompound(const Definition *d); virtual void addListReferences(); virtual void setFileName(const QCString &fn); @@ -85,21 +98,18 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual const QList<MemberList> &getMemberLists() const { return m_memberLists; } virtual MemberDef *getMemberByName(const QCString &) const; virtual MemberGroupSDict *getMemberGroupSDict() const { return memberGroupSDict; } - virtual ClassSDict *getClassSDict() const { return classSDict; } - virtual ClassSDict *getInterfaceSDict() const { return interfaceSDict; } - virtual ClassSDict *getStructSDict() const { return structSDict; } - virtual ClassSDict *getExceptionSDict() const { return exceptionSDict; } - virtual const NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; } + virtual ClassLinkedRefMap getClasses() const { return classes; } + virtual ClassLinkedRefMap getInterfaces() const { return interfaces; } + virtual ClassLinkedRefMap getStructs() const { return structs; } + virtual ClassLinkedRefMap getExceptions() const { return exceptions; } + virtual NamespaceLinkedRefMap getNamespaces() const { return namespaces; } virtual QCString title() const; virtual QCString compoundTypeString() const; virtual void setMetaData(const QCString &m); - void setVisited(bool v) { m_visited = v; } - bool isVisited() const { return m_visited; } private: - bool m_visited; MemberList *createMemberList(MemberListType lt); void addMemberToList(MemberListType lt,MemberDef *md); void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title); @@ -108,7 +118,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef void writeBriefDescription(OutputList &ol); void startMemberDeclarations(OutputList &ol); void endMemberDeclarations(OutputList &ol); - void writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d); + void writeClassDeclarations(OutputList &ol,const QCString &title,const ClassLinkedRefMap &d); void writeInlineClasses(OutputList &ol); void writeMemberGroups(OutputList &ol); void writeAuthorSection(OutputList &ol); @@ -116,7 +126,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef void endMemberDocumentation(OutputList &ol); void writeSummaryLinks(OutputList &ol) const; void addNamespaceAttributes(OutputList &ol); - void writeClassesToTagFile(FTextStream &,ClassSDict *d); + void writeClassesToTagFile(FTextStream &,const ClassLinkedRefMap &d); void writeNamespaceDeclarations(OutputList &ol,const QCString &title, bool isConstantGroup=false); @@ -124,18 +134,18 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef QCString fileName; FileList files; - NamespaceSDict *usingDirList = 0; - SDict<Definition> *usingDeclList = 0; + LinkedRefMap<const NamespaceDef> m_usingDirList; + LinkedRefMap<const ClassDef> m_usingDeclList; SDict<Definition> *m_innerCompounds = 0; MemberSDict *m_allMembersDict = 0; QList<MemberList> m_memberLists; MemberGroupSDict *memberGroupSDict = 0; - ClassSDict *classSDict = 0; - ClassSDict *interfaceSDict = 0; - ClassSDict *structSDict = 0; - ClassSDict *exceptionSDict = 0; - NamespaceSDict *namespaceSDict = 0; + ClassLinkedRefMap classes; + ClassLinkedRefMap interfaces; + ClassLinkedRefMap structs; + ClassLinkedRefMap exceptions; + NamespaceLinkedRefMap namespaces; bool m_subGrouping = false; enum { NAMESPACE, MODULE, CONSTANT_GROUP, LIBRARY } m_type; bool m_isPublished = false; @@ -143,7 +153,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef bool m_inline = false; }; -NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColumn, +NamespaceDefMutable *createNamespaceDef(const char *defFileName,int defLine,int defColumn, const char *name,const char *ref, const char *refFile,const char*type, bool isPublished) @@ -153,14 +163,15 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu //------------------------------------------------------------------ -class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef +class NamespaceDefAliasImpl : public DefinitionAliasMixin<NamespaceDef> { public: - NamespaceDefAliasImpl(const Definition *newScope,const NamespaceDef *nd) : DefinitionAliasImpl(newScope,nd) {} - virtual ~NamespaceDefAliasImpl() {} + NamespaceDefAliasImpl(const Definition *newScope,const NamespaceDef *nd) + : DefinitionAliasMixin(newScope,nd) { init(); } + virtual ~NamespaceDefAliasImpl() { deinit(); } virtual DefType definitionType() const { return TypeNamespace; } - const NamespaceDef *getNSAlias() const { return dynamic_cast<const NamespaceDef*>(getAlias()); } + const NamespaceDef *getNSAlias() const { return toNamespaceDef(getAlias()); } // ---- getters virtual QCString getOutputFileBase() const @@ -169,18 +180,14 @@ class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef { return getNSAlias()->anchor(); } virtual int numDocMembers() const { return getNSAlias()->numDocMembers(); } - virtual void addUsingDirective(const NamespaceDef *nd) {} - virtual const NamespaceSDict *getUsedNamespaces() const + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const { return getNSAlias()->getUsedNamespaces(); } - virtual void addUsingDeclaration(const Definition *def) {} - virtual const SDict<Definition> *getUsedClasses() const + virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return getNSAlias()->getUsedClasses(); } - virtual void combineUsingRelations() {} virtual QCString displayName(bool b=TRUE) const - { return getNSAlias()->displayName(b); } + { return makeDisplayName(this,b); } virtual QCString localName() const { return getNSAlias()->localName(); } - virtual void setInline(bool isInline) { } virtual bool isConstantGroup() const { return getNSAlias()->isConstantGroup(); } virtual bool isModule() const @@ -195,7 +202,7 @@ class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef { return getNSAlias()->isLinkable(); } virtual bool hasDetailedDescription() const { return getNSAlias()->hasDetailedDescription(); } - virtual Definition *findInnerCompound(const char *name) const + virtual const Definition *findInnerCompound(const char *name) const { return getNSAlias()->findInnerCompound(name); } virtual bool subGrouping() const { return getNSAlias()->subGrouping(); } @@ -207,51 +214,29 @@ class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef { return getNSAlias()->getMemberByName(name); } virtual MemberGroupSDict *getMemberGroupSDict() const { return getNSAlias()->getMemberGroupSDict(); } - virtual ClassSDict *getClassSDict() const - { return getNSAlias()->getClassSDict(); } - virtual ClassSDict *getInterfaceSDict() const - { return getNSAlias()->getInterfaceSDict(); } - virtual ClassSDict *getStructSDict() const - { return getNSAlias()->getStructSDict(); } - virtual ClassSDict *getExceptionSDict() const - { return getNSAlias()->getExceptionSDict(); } - virtual const NamespaceSDict *getNamespaceSDict() const - { return getNSAlias()->getNamespaceSDict(); } + virtual ClassLinkedRefMap getClasses() const + { return getNSAlias()->getClasses(); } + virtual ClassLinkedRefMap getInterfaces() const + { return getNSAlias()->getInterfaces(); } + virtual ClassLinkedRefMap getStructs() const + { return getNSAlias()->getStructs(); } + virtual ClassLinkedRefMap getExceptions() const + { return getNSAlias()->getExceptions(); } + virtual NamespaceLinkedRefMap getNamespaces() const + { return getNSAlias()->getNamespaces(); } virtual QCString title() const { return getNSAlias()->title(); } virtual QCString compoundTypeString() const { return getNSAlias()->compoundTypeString(); } - - // --- setters/actions - virtual void setMetaData(const QCString &m) {} - virtual void insertUsedFile(FileDef *fd) { } - virtual void writeDocumentation(OutputList &ol) {} - virtual void writeMemberPages(OutputList &ol) {} - virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const {} - virtual void writeTagFile(FTextStream &) {} - virtual void insertClass(const ClassDef *cd) {} - virtual void insertNamespace(const NamespaceDef *nd) {} - virtual void insertMember(MemberDef *md) {} - virtual void computeAnchors() {} - virtual void countMembers() {} - virtual void addMembersToMemberGroup() {} - virtual void distributeMemberGroupDocumentation() {} - virtual void findSectionsInDocumentation() {} - virtual void sortMemberLists() {} - virtual void addInnerCompound(const Definition *d) {} - virtual void addListReferences() {} - virtual void setFileName(const QCString &fn) {} - - void setVisited(bool v) { m_visited = v; } - bool isVisited() const { return m_visited; } - - private: - bool m_visited = false; }; NamespaceDef *createNamespaceDefAlias(const Definition *newScope,const NamespaceDef *nd) { - return new NamespaceDefAliasImpl(newScope,nd); + NamespaceDef *alnd = new NamespaceDefAliasImpl(newScope,nd); + //printf("alnd name=%s localName=%s qualifiedName=%s displayName()=%s\n", + // alnd->name().data(),alnd->localName().data(),alnd->qualifiedName().data(), + // alnd->displayName().data()); + return alnd; } //------------------------------------------------------------------ @@ -260,7 +245,7 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, const char *name,const char *lref, const char *fName, const char*type, bool isPublished) : - DefinitionImpl(df,dl,dc,name) + DefinitionMixin(df,dl,dc,name) ,m_isPublished(isPublished) { if (fName) @@ -278,19 +263,11 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, { setFileName(name); } - classSDict = new ClassSDict(17); - interfaceSDict = new ClassSDict(17); - structSDict = new ClassSDict(17); - exceptionSDict = new ClassSDict(17); - namespaceSDict = new NamespaceSDict(17); m_innerCompounds = new SDict<Definition>(17); - usingDirList = 0; - usingDeclList = 0; m_allMembersDict = 0; setReference(lref); memberGroupSDict = new MemberGroupSDict; memberGroupSDict->setAutoDelete(TRUE); - m_visited=FALSE; m_inline=FALSE; m_subGrouping=Config_getBool(SUBGROUPING); if (type && !strcmp("module", type)) @@ -313,14 +290,7 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, NamespaceDefImpl::~NamespaceDefImpl() { - delete classSDict; - delete interfaceSDict; - delete structSDict; - delete exceptionSDict; - delete namespaceSDict; delete m_innerCompounds; - delete usingDirList; - delete usingDeclList; delete memberGroupSDict; delete m_allMembersDict; } @@ -349,6 +319,7 @@ void NamespaceDefImpl::distributeMemberGroupDocumentation() void NamespaceDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; @@ -384,56 +355,40 @@ void NamespaceDefImpl::addInnerCompound(const Definition *d) m_innerCompounds->append(d->localName(),d); if (d->definitionType()==Definition::TypeNamespace) { - insertNamespace(dynamic_cast<const NamespaceDef *>(d)); + insertNamespace(toNamespaceDef(d)); } else if (d->definitionType()==Definition::TypeClass) { - insertClass(dynamic_cast<const ClassDef *>(d)); + insertClass(toClassDef(d)); } } void NamespaceDefImpl::insertClass(const ClassDef *cd) { - ClassSDict *d = classSDict; + ClassLinkedRefMap &d = classes; if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) { if (cd->compoundType()==ClassDef::Interface) { - d = interfaceSDict; + d = interfaces; } else if (cd->compoundType()==ClassDef::Struct) { - d = structSDict; + d = structs; } else if (cd->compoundType()==ClassDef::Exception) { - d = exceptionSDict; + d = exceptions; } } - if (d->find(cd->name())==0) - { - if (Config_getBool(SORT_BRIEF_DOCS)) - { - d->inSort(cd->name(),cd); - } - else - { - d->append(cd->name(),cd); - } - } + d.add(cd->name(),cd); } void NamespaceDefImpl::insertNamespace(const NamespaceDef *nd) { - if (namespaceSDict->find(nd->name())==0) - { - if (Config_getBool(SORT_MEMBER_DOCS)) - namespaceSDict->inSort(nd->name(),nd); - else - namespaceSDict->append(nd->name(),nd); - } + namespaces.add(nd->name(),nd); } @@ -470,6 +425,7 @@ void NamespaceDefImpl::insertMember(MemberDef *md) //printf("%s::insertMember(%s) isInline=%d hasDocs=%d\n",qPrint(name()),qPrint(md->name()), // isInline(),hasDocumentation()); if (md->isHidden()) return; + MemberDefMutable *mdm = toMemberDefMutable(md); // if this is an inline namespace that is not documented, then insert the // member in the parent scope instead @@ -480,16 +436,25 @@ void NamespaceDefImpl::insertMember(MemberDef *md) { if (outerScope->definitionType()==Definition::TypeNamespace) { - NamespaceDef *nd = dynamic_cast<NamespaceDef*>(outerScope); - nd->insertMember(md); - md->setNamespace(nd); + NamespaceDefMutable *nd = toNamespaceDefMutable(outerScope); + if (nd) + { + nd->insertMember(md); + if (mdm) + { + mdm->setNamespace(nd); + } + } } else if (outerScope->definitionType()==Definition::TypeFile) { - FileDef *fd = dynamic_cast<FileDef*>(outerScope); + FileDef *fd = toFileDef(outerScope); fd->insertMember(md); - md->setFileDef(fd); - md->setOuterScope(fd); + if (mdm) + { + mdm->setFileDef(fd); + mdm->setOuterScope(fd); + } } } } @@ -559,12 +524,16 @@ void NamespaceDefImpl::insertMember(MemberDef *md) if (outerScope->definitionType()==Definition::TypeNamespace) { aliasMd.reset(createMemberDefAlias(outerScope,md)); - dynamic_cast<NamespaceDef*>(outerScope)->insertMember(aliasMd.get()); + NamespaceDefMutable *ndm = toNamespaceDefMutable(outerScope); + if (ndm) + { + ndm->insertMember(aliasMd.get()); + } } else if (outerScope->definitionType()==Definition::TypeFile) { aliasMd.reset(createMemberDefAlias(outerScope,md)); - dynamic_cast<FileDef*>(outerScope)->insertMember(aliasMd.get()); + toFileDef(outerScope)->insertMember(aliasMd.get()); } if (aliasMd) { @@ -581,7 +550,7 @@ void NamespaceDefImpl::insertMember(MemberDef *md) void NamespaceDefImpl::computeAnchors() { MemberList *allMemberList = getMemberList(MemberListType_allMembersList); - if (allMemberList) setAnchors(allMemberList); + if (allMemberList) allMemberList->setAnchors(); } bool NamespaceDefImpl::hasDetailedDescription() const @@ -610,42 +579,33 @@ void NamespaceDefImpl::writeTagFile(FTextStream &tagFile) { case LayoutDocEntry::NamespaceNestedNamespaces: { - if (namespaceSDict) + for (const auto &nd : namespaces) { - SDict<NamespaceDef>::Iterator ni(*namespaceSDict); - NamespaceDef *nd; - for (ni.toFirst();(nd=ni.current());++ni) + if (nd->isLinkableInProject()) { - if (nd->isLinkableInProject()) - { - tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl; - } + tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl; } } } break; case LayoutDocEntry::NamespaceClasses: { - if (classSDict) - writeClassesToTagFile(tagFile, classSDict); + writeClassesToTagFile(tagFile, classes); } break; case LayoutDocEntry::NamespaceInterfaces: { - if (interfaceSDict) - writeClassesToTagFile(tagFile, interfaceSDict); + writeClassesToTagFile(tagFile, interfaces); } break; case LayoutDocEntry::NamespaceStructs: { - if (structSDict) - writeClassesToTagFile(tagFile, structSDict); + writeClassesToTagFile(tagFile, structs); } break; case LayoutDocEntry::NamespaceExceptions: { - if (exceptionSDict) - writeClassesToTagFile(tagFile, exceptionSDict); + writeClassesToTagFile(tagFile, exceptions); } break; case LayoutDocEntry::MemberDecl: @@ -810,20 +770,20 @@ void NamespaceDefImpl::endMemberDocumentation(OutputList &ol) } } -void NamespaceDefImpl::writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d) +void NamespaceDefImpl::writeClassDeclarations(OutputList &ol,const QCString &title,const ClassLinkedRefMap &d) { - if (d) d->writeDeclaration(ol,0,title,TRUE); + d.writeDeclaration(ol,0,title,TRUE); } void NamespaceDefImpl::writeInlineClasses(OutputList &ol) { - if (classSDict) classSDict->writeDocumentation(ol,this); + classes.writeDocumentation(ol,this); } void NamespaceDefImpl::writeNamespaceDeclarations(OutputList &ol,const QCString &title, bool const isConstantGroup) { - if (namespaceSDict) namespaceSDict->writeDeclaration(ol,title,isConstantGroup,TRUE); + namespaces.writeDeclaration(ol,title,isConstantGroup,TRUE); } void NamespaceDefImpl::writeMemberGroups(OutputList &ol) @@ -868,35 +828,35 @@ void NamespaceDefImpl::writeSummaryLinks(OutputList &ol) const SrcLangExt lang = getLanguage(); for (eli.toFirst();(lde=eli.current());++eli) { - if (lde->kind()==LayoutDocEntry::NamespaceClasses && classSDict && classSDict->declVisible()) + if (lde->kind()==LayoutDocEntry::NamespaceClasses && classes.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "nested-classes"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::NamespaceInterfaces && interfaceSDict && interfaceSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::NamespaceInterfaces && interfaces.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "interfaces"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::NamespaceStructs && structSDict && structSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::NamespaceStructs && structs.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "structs"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::NamespaceExceptions && exceptionSDict && exceptionSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::NamespaceExceptions && exceptions.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "exceptions"; ol.writeSummaryLink(0,label,ls->title(lang),first); first=FALSE; } - else if (lde->kind()==LayoutDocEntry::NamespaceNestedNamespaces && namespaceSDict && namespaceSDict->declVisible()) + else if (lde->kind()==LayoutDocEntry::NamespaceNestedNamespaces && namespaces.declVisible()) { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; QCString label = "namespaces"; @@ -935,11 +895,9 @@ void NamespaceDefImpl::addNamespaceAttributes(OutputList &ol) } } -void NamespaceDefImpl::writeClassesToTagFile(FTextStream &tagFile,ClassSDict *d) +void NamespaceDefImpl::writeClassesToTagFile(FTextStream &tagFile,const ClassLinkedRefMap &list) { - SDict<ClassDef>::Iterator ci(*d); - ClassDef *cd; - for (ci.toFirst();(cd=ci.current());++ci) + for (const auto &cd : list) { if (cd->isLinkableInProject()) { @@ -1001,25 +959,25 @@ void NamespaceDefImpl::writeDocumentation(OutputList &ol) case LayoutDocEntry::NamespaceClasses: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),classSDict); + writeClassDeclarations(ol,ls->title(lang),classes); } break; case LayoutDocEntry::NamespaceInterfaces: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),interfaceSDict); + writeClassDeclarations(ol,ls->title(lang),interfaces); } break; case LayoutDocEntry::NamespaceStructs: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),structSDict); + writeClassDeclarations(ol,ls->title(lang),structs); } break; case LayoutDocEntry::NamespaceExceptions: { LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde; - writeClassDeclarations(ol,ls->title(lang),exceptionSDict); + writeClassDeclarations(ol,ls->title(lang),exceptions); } break; case LayoutDocEntry::NamespaceNestedNamespaces: @@ -1152,25 +1110,25 @@ void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *cur { if (md->getNamespaceDef()==this && md->isLinkable() && !md->isEnumValue()) { - ol.writeString(" <tr><td class=\"navtab\">"); if (md->isLinkableInProject()) { if (md==currentMd) // selected item => highlight { - ol.writeString("<a class=\"qindexHL\" "); + ol.writeString(" <tr><td class=\"navtabHL\">"); } else { - ol.writeString("<a class=\"qindex\" "); + ol.writeString(" <tr><td class=\"navtab\">"); } + ol.writeString("<a class=\"navtab\" "); ol.writeString("href=\""); if (createSubDirs) ol.writeString("../../"); ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); ol.writeString("\">"); ol.writeString(convertToHtml(md->localName())); ol.writeString("</a>"); + ol.writeString("</td></tr>\n"); } - ol.writeString("</td></tr>\n"); } } } @@ -1208,33 +1166,13 @@ int NamespaceDefImpl::numDocMembers() const void NamespaceDefImpl::addUsingDirective(const NamespaceDef *nd) { - if (usingDirList==0) - { - usingDirList = new NamespaceSDict; - } - if (usingDirList->find(nd->qualifiedName())==0) - { - usingDirList->append(nd->qualifiedName(),nd); - } - //printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); + m_usingDirList.add(nd->qualifiedName(),nd); + //printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),m_usingDirList->count()); } -const NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const +void NamespaceDefImpl::addUsingDeclaration(const ClassDef *cd) { - //printf("%p: NamespaceDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); - return usingDirList; -} - -void NamespaceDefImpl::addUsingDeclaration(const Definition *d) -{ - if (usingDeclList==0) - { - usingDeclList = new SDict<Definition>(17); - } - if (usingDeclList->find(d->qualifiedName())==0) - { - usingDeclList->append(d->qualifiedName(),d); - } + m_usingDeclList.add(cd->qualifiedName(),cd); } QCString NamespaceDefImpl::getOutputFileBase() const @@ -1242,19 +1180,19 @@ QCString NamespaceDefImpl::getOutputFileBase() const return fileName; } -Definition *NamespaceDefImpl::findInnerCompound(const char *n) const +const Definition *NamespaceDefImpl::findInnerCompound(const char *n) const { if (n==0) return 0; - Definition *d = m_innerCompounds->find(n); + const Definition *d = m_innerCompounds->find(n); if (d==0) { - if (usingDirList) + if (!m_usingDirList.empty()) { - d = usingDirList->find(n); + d = m_usingDirList.find(n); } - if (d==0 && usingDeclList) + if (d==0 && !m_usingDeclList.empty()) { - d = usingDeclList->find(n); + d = m_usingDeclList.find(n); } } return d; @@ -1294,15 +1232,7 @@ void NamespaceDefImpl::addListReferences() QCString NamespaceDefImpl::displayName(bool includeScope) const { - QCString result=includeScope ? name() : localName(); - SrcLangExt lang = getLanguage(); - QCString sep = getLanguageSpecificSeparator(lang); - if (sep!="::") - { - result = substitute(result,"::",sep); - } - //printf("NamespaceDefImpl::displayName() %s->%s lang=%d\n",name().data(),result.data(),lang); - return result; + return makeDisplayName(this,includeScope); } QCString NamespaceDefImpl::localName() const @@ -1316,51 +1246,41 @@ QCString NamespaceDefImpl::localName() const return result; } -void NamespaceDefImpl::combineUsingRelations() +void NamespaceDefImpl::combineUsingRelations(NamespaceDefSet &visitedNamespaces) { - if (m_visited) return; // already done - m_visited=TRUE; - if (usingDirList) + if (visitedNamespaces.find(this)!=visitedNamespaces.end()) return; // already processed + visitedNamespaces.insert(this); + + LinkedRefMap<const NamespaceDef> usingDirList = m_usingDirList; + for (auto &nd : usingDirList) { - NamespaceSDict::Iterator nli(*usingDirList); - NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) { - nd->combineUsingRelations(); + ndm->combineUsingRelations(visitedNamespaces); } - for (nli.toFirst();(nd=nli.current());++nli) + } + + for (auto &nd : usingDirList) + { + // add used namespaces of namespace nd to this namespace + for (const auto &und : nd->getUsedNamespaces()) { - // add used namespaces of namespace nd to this namespace - if (nd->getUsedNamespaces()) - { - NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); - NamespaceDef *und; - for (unli.toFirst();(und=unli.current());++unli) - { - //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); - addUsingDirective(und); - } - } - // add used classes of namespace nd to this namespace - if (nd->getUsedClasses()) - { - SDict<Definition>::Iterator cli(*nd->getUsedClasses()); - Definition *ucd; - for (cli.toFirst();(ucd=cli.current());++cli) - { - //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); - addUsingDeclaration(ucd); - } - } + addUsingDirective(und); + } + // add used classes of namespace nd to this namespace + for (const auto &ucd : nd->getUsedClasses()) + { + addUsingDeclaration(ucd); } } } -bool NamespaceSDict::declVisible() const +//------------------------------------------------------------------------------- + +bool NamespaceLinkedRefMap::declVisible() const { - SDict<NamespaceDef>::Iterator ni(*this); - NamespaceDef *nd; - for (ni.toFirst();(nd=ni.current());++ni) + for (const auto &nd : *this) { if (nd->isLinkable()) { @@ -1370,20 +1290,17 @@ bool NamespaceSDict::declVisible() const return FALSE; } -void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, +void NamespaceLinkedRefMap::writeDeclaration(OutputList &ol,const char *title, bool const isConstantGroup,bool localName) { - if (count()==0) return; // no namespaces in the list + if (empty()) return; // no namespaces in the list if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) return; - - SDict<NamespaceDef>::Iterator ni(*this); - NamespaceDef *nd; bool found=FALSE; - for (ni.toFirst();(nd=ni.current()) && !found;++ni) + for (const auto &nd : *this) { if (nd->isLinkable() && nd->hasDocumentation()) { @@ -1416,7 +1333,7 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, ol.parseText(title); ol.endMemberHeader(); ol.startMemberList(); - for (ni.toFirst();(nd=ni.current());++ni) + for (const auto &nd : *this) { if (nd->isLinkable() && nd->hasDocumentation()) { @@ -1453,6 +1370,8 @@ void NamespaceSDict::writeDeclaration(OutputList &ol,const char *title, ol.endMemberList(); } +//------------------------------------------------------------------------------- + MemberList *NamespaceDefImpl::createMemberList(MemberListType lt) { m_memberLists.setAutoDelete(TRUE); @@ -1483,7 +1402,11 @@ void NamespaceDefImpl::addMemberToList(MemberListType lt,MemberDef *md) if (ml->listType()&MemberListType_declarationLists) { - md->setSectionList(this,ml); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setSectionList(this,ml); + } } } @@ -1495,26 +1418,31 @@ void NamespaceDefImpl::sortMemberLists() { if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); } } - if (classSDict) - { - classSDict->sort(); - } - if (interfaceSDict) - { - interfaceSDict->sort(); - } - if (structSDict) - { - structSDict->sort(); - } - if (exceptionSDict) + + + if (Config_getBool(SORT_BRIEF_DOCS)) { - exceptionSDict->sort(); + auto classComp = [](const ClassLinkedRefMap::Ptr &c1,const ClassLinkedRefMap::Ptr &c2) + { + return Config_getBool(SORT_BY_SCOPE_NAME) ? + qstricmp(c1->name(), c2->name())<0 : + qstricmp(c1->className(), c2->className())<0; + }; + + std::sort(classes.begin(), classes.end(), classComp); + std::sort(interfaces.begin(),interfaces.end(),classComp); + std::sort(structs.begin(), structs.end(), classComp); + std::sort(exceptions.begin(),exceptions.end(),classComp); + } - if (namespaceSDict) + + // TODO: inconsistent: should be only done when SORT_BRIEF_DOCS is enabled... + auto namespaceComp = [](const NamespaceLinkedRefMap::Ptr &n1,const NamespaceLinkedRefMap::Ptr &n2) { - namespaceSDict->sort(); - } + return qstricmp(n1->name(),n2->name())<0; + }; + + std::sort(namespaces.begin(),namespaces.end(),namespaceComp); } MemberList *NamespaceDefImpl::getMemberList(MemberListType lt) const @@ -1644,3 +1572,68 @@ void NamespaceDefImpl::setMetaData(const QCString &m) { metaData = m; } + +// --- Cast functions +// +NamespaceDef *toNamespaceDef(Definition *d) +{ + if (d && (typeid(*d)==typeid(NamespaceDefImpl) || typeid(*d)==typeid(NamespaceDefAliasImpl))) + { + return static_cast<NamespaceDef*>(d); + } + else + { + return 0; + } +} + +NamespaceDef *toNamespaceDef(DefinitionMutable *md) +{ + Definition *d = toDefinition(md); + if (d && typeid(*d)==typeid(NamespaceDefImpl)) + { + return static_cast<NamespaceDef*>(d); + } + else + { + return 0; + } +} + + +const NamespaceDef *toNamespaceDef(const Definition *d) +{ + if (d && (typeid(*d)==typeid(NamespaceDefImpl) || typeid(*d)==typeid(NamespaceDefAliasImpl))) + { + return static_cast<const NamespaceDef*>(d); + } + else + { + return 0; + } +} + +NamespaceDefMutable *toNamespaceDefMutable(Definition *d) +{ + if (d && typeid(*d)==typeid(NamespaceDefImpl)) + { + return static_cast<NamespaceDefMutable*>(d); + } + else + { + return 0; + } +} + +NamespaceDefMutable *toNamespaceDefMutable(const Definition *d) +{ + if (d && typeid(*d)==typeid(NamespaceDefImpl)) + { + return const_cast<NamespaceDefMutable*>(static_cast<const NamespaceDefMutable*>(d)); + } + else + { + return 0; + } +} + diff --git a/src/namespacedef.h b/src/namespacedef.h index a35f0b1..e9bf86f 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.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,104 +16,121 @@ #ifndef NAMESPACEDEF_H #define NAMESPACEDEF_H +#include <set> + #include <qstrlist.h> -#include <qdict.h> -#include "sortdict.h" #include "definition.h" #include "filedef.h" +#include "linkedmap.h" class MemberList; class ClassDef; class OutputList; -class ClassSDict; +class ClassLinkedRefMap; class MemberDef; class MemberGroupSDict; -class NamespaceSDict; +class NamespaceDef; class FTextStream; +class NamespaceDef; +class NamespaceDefMutable; + +// --- Set of namespaces + +using NamespaceDefSet = std::set<const NamespaceDef*>; + +class NamespaceLinkedMap : public LinkedMap<NamespaceDef> +{ +}; + +class NamespaceLinkedRefMap : public LinkedRefMap<const NamespaceDef> +{ + public: + void writeDeclaration(OutputList &ol,const char *title, + bool isConstantGroup=false, bool localName=FALSE); + bool declVisible() const; +}; /** An abstract interface of a namespace symbol. */ -class NamespaceDef : virtual public Definition +class NamespaceDef : public Definition { public: virtual ~NamespaceDef() {} virtual DefType definitionType() const = 0; + + // ---- getters virtual QCString getOutputFileBase() const = 0; virtual QCString anchor() const = 0; - virtual void insertUsedFile(FileDef *fd) = 0; - - virtual void writeDocumentation(OutputList &ol) = 0; - virtual void writeMemberPages(OutputList &ol) = 0; - virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; - virtual void writeTagFile(FTextStream &) = 0; - - virtual void insertClass(const ClassDef *cd) = 0; - virtual void insertNamespace(const NamespaceDef *nd) = 0; - virtual void insertMember(MemberDef *md) = 0; // md cannot be const, since setSectionList is called on it - - virtual void computeAnchors() = 0; - virtual void countMembers() = 0; virtual int numDocMembers() const = 0; - virtual void addUsingDirective(const NamespaceDef *nd) = 0; - virtual const NamespaceSDict *getUsedNamespaces() const = 0; - virtual void addUsingDeclaration(const Definition *def) = 0; - virtual const SDict<Definition> *getUsedClasses() const = 0; - virtual void combineUsingRelations() = 0; + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const = 0; + virtual LinkedRefMap<const ClassDef> getUsedClasses() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString localName() const = 0; - virtual void setInline(bool isInline) = 0; - virtual bool isConstantGroup() const = 0; virtual bool isModule() const = 0; virtual bool isLibrary() const = 0; virtual bool isInline() const = 0; - virtual bool isLinkableInProject() const = 0; virtual bool isLinkable() const = 0; virtual bool hasDetailedDescription() const = 0; - virtual void addMembersToMemberGroup() = 0; - virtual void distributeMemberGroupDocumentation() = 0; - virtual void findSectionsInDocumentation() = 0; - virtual void sortMemberLists() = 0; - - virtual Definition *findInnerCompound(const char *name) const = 0; - virtual void addInnerCompound(const Definition *d) = 0; - virtual void addListReferences() = 0; - virtual void setFileName(const QCString &fn) = 0; - + virtual const Definition *findInnerCompound(const char *name) const = 0; virtual bool subGrouping() const = 0; - virtual MemberList *getMemberList(MemberListType lt) const = 0; virtual const QList<MemberList> &getMemberLists() const = 0; - virtual MemberDef *getMemberByName(const QCString &) const = 0; + virtual MemberDef *getMemberByName(const QCString &) const = 0; /*! Returns the user defined member groups */ virtual MemberGroupSDict *getMemberGroupSDict() const = 0; /*! Returns the classes contained in this namespace */ - virtual ClassSDict *getClassSDict() const = 0; + virtual ClassLinkedRefMap getClasses() const = 0; /*! Returns the Slice interfaces contained in this namespace */ - virtual ClassSDict *getInterfaceSDict() const = 0; + virtual ClassLinkedRefMap getInterfaces() const = 0; /*! Returns the Slice structs contained in this namespace */ - virtual ClassSDict *getStructSDict() const = 0; + virtual ClassLinkedRefMap getStructs() const = 0; /*! Returns the Slice exceptions contained in this namespace */ - virtual ClassSDict *getExceptionSDict() const = 0; + virtual ClassLinkedRefMap getExceptions() const = 0; /*! Returns the namespaces contained in this namespace */ - virtual const NamespaceSDict *getNamespaceSDict() const = 0; + virtual NamespaceLinkedRefMap getNamespaces() const = 0; virtual QCString title() const = 0; virtual QCString compoundTypeString() const = 0; +}; + +class NamespaceDefMutable : public DefinitionMutable, public NamespaceDef +{ + public: + // --- setters/actions virtual void setMetaData(const QCString &m) = 0; - virtual void setVisited(bool v) = 0; - virtual bool isVisited() const = 0; + virtual void insertUsedFile(FileDef *fd) = 0; + virtual void writeDocumentation(OutputList &ol) = 0; + virtual void writeMemberPages(OutputList &ol) = 0; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; + virtual void writeTagFile(FTextStream &) = 0; + virtual void insertClass(const ClassDef *cd) = 0; + virtual void insertNamespace(const NamespaceDef *nd) = 0; + virtual void insertMember(MemberDef *md) = 0; // md cannot be const, since setSectionList is called on it + virtual void computeAnchors() = 0; + virtual void countMembers() = 0; + virtual void addMembersToMemberGroup() = 0; + virtual void distributeMemberGroupDocumentation() = 0; + virtual void findSectionsInDocumentation() = 0; + virtual void sortMemberLists() = 0; + virtual void addInnerCompound(const Definition *d) = 0; + virtual void addListReferences() = 0; + virtual void setFileName(const QCString &fn) = 0; + virtual void combineUsingRelations(NamespaceDefSet &visitedNamespace) = 0; + virtual void addUsingDirective(const NamespaceDef *nd) = 0; + virtual void addUsingDeclaration(const ClassDef *cd) = 0; + virtual void setInline(bool isInline) = 0; }; /** Factory method to create new NamespaceDef instance */ -NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColumn, +NamespaceDefMutable *createNamespaceDef(const char *defFileName,int defLine,int defColumn, const char *name,const char *ref=0, const char *refFile=0,const char*type=0, bool isPublished=false); @@ -123,49 +138,15 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu /** Factory method to create an alias of an existing namespace. Used for inline namespaces. */ NamespaceDef *createNamespaceDefAlias(const Definition *newScope, const NamespaceDef *nd); -/** A list of NamespaceDef objects. */ -class NamespaceList : public QList<NamespaceDef> -{ - public: - ~NamespaceList() {} - int compareValues(const NamespaceDef *nd1,const NamespaceDef *nd2) const - { - return qstricmp(nd1->name(), nd2->name()); - } -}; - -/** An iterator for NamespaceDef objects in a NamespaceList. */ -class NamespaceListIterator : public QListIterator<NamespaceDef> -{ - public: - NamespaceListIterator(const NamespaceList &l) : - QListIterator<NamespaceDef>(l) {} -}; - -/** An unsorted dictionary of NamespaceDef objects. */ -class NamespaceDict : public QDict<NamespaceDef> -{ - public: - NamespaceDict(uint size) : QDict<NamespaceDef>(size) {} - ~NamespaceDict() {} -}; -/** A sorted dictionary of NamespaceDef objects. */ -class NamespaceSDict : public SDict<NamespaceDef> -{ - public: - NamespaceSDict(uint size=17) : SDict<NamespaceDef>(size) {} - ~NamespaceSDict() {} - void writeDeclaration(OutputList &ol,const char *title, - bool isConstantGroup=false, bool localName=FALSE); - bool declVisible() const; - private: - int compareValues(const NamespaceDef *item1,const NamespaceDef *item2) const - { - return qstricmp(item1->name(),item2->name()); - } -}; +// --- Cast functions +NamespaceDef *toNamespaceDef(Definition *d); +NamespaceDef *toNamespaceDef(DefinitionMutable *d); +const NamespaceDef *toNamespaceDef(const Definition *d); +NamespaceDefMutable *toNamespaceDefMutable(Definition *d); +NamespaceDefMutable *toNamespaceDefMutable(const Definition *d); +//------------------------------------------------------------------------ #endif diff --git a/src/outputgen.cpp b/src/outputgen.cpp index b9f24fa..5be6817 100644 --- a/src/outputgen.cpp +++ b/src/outputgen.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. * @@ -15,63 +15,135 @@ * */ +#include <stdexcept> + #include <stdlib.h> #include <qfile.h> +#include "doxygen.h" #include "outputgen.h" #include "message.h" #include "portable.h" -OutputGenerator::OutputGenerator() +OutputGenerator::OutputGenerator(const char *dir) : m_dir(dir) { //printf("OutputGenerator::OutputGenerator()\n"); - m_file=0; - m_active=TRUE; - m_genStack = new QStack<bool>; - m_genStack->setAutoDelete(TRUE); } OutputGenerator::~OutputGenerator() { //printf("OutputGenerator::~OutputGenerator()\n"); - delete m_file; - delete m_genStack; +} + +OutputGenerator::OutputGenerator(const OutputGenerator &og) +{ + m_dir = og.m_dir; + // we don't copy the other fields. + // after copying startPlainFile() should be called + if (og.t.device()!=nullptr) + { + throw std::runtime_error("OutputGenerator copy constructor called while a file is processing"); + } +} + +OutputGenerator &OutputGenerator::operator=(const OutputGenerator &og) +{ + m_dir = og.m_dir; + // we don't copy the other fields. + // after assignment startPlainFile() should be called + if (og.t.device()!=nullptr) + { + throw std::runtime_error("OutputGenerator assignment operator called while a file is processing"); + } + return *this; } void OutputGenerator::startPlainFile(const char *name) { //printf("startPlainFile(%s)\n",name); m_fileName=m_dir+"/"+name; - m_file = new QFile(m_fileName); - if (!m_file->open(IO_WriteOnly)) + m_file.setName(m_fileName); + if (!m_file.open(IO_WriteOnly)) { term("Could not open file %s for writing\n",m_fileName.data()); } - t.setDevice(m_file); + t.setDevice(&m_file); } void OutputGenerator::endPlainFile() { t.unsetDevice(); - delete m_file; - m_file=0; + m_file.close(); m_fileName.resize(0); } +QCString OutputGenerator::dir() const +{ + return m_dir; +} + +QCString OutputGenerator::fileName() const +{ + return m_fileName; +} + void OutputGenerator::pushGeneratorState() { - m_genStack->push(new bool(isEnabled())); + m_genStack.push(isEnabled()); //printf("%p:pushGeneratorState(%d) enabled=%d\n",this,genStack->count(),isEnabled()); } void OutputGenerator::popGeneratorState() { //printf("%p:popGeneratorState(%d) enabled=%d\n",this,genStack->count(),isEnabled()); - bool *lb = m_genStack->pop(); - ASSERT(lb!=0); - if (lb==0) return; // for some robustness against superfluous \endhtmlonly commands. - if (*lb) enable(); else disable(); - delete lb; + if (!m_genStack.empty()) + { + bool lb = m_genStack.top(); + m_genStack.pop(); + if (lb) enable(); else disable(); + } +} + +void OutputGenerator::enable() +{ + if (!m_genStack.empty()) + { + m_active=m_genStack.top(); + } + else + { + m_active=true; + } +} + +void OutputGenerator::disable() +{ + m_active=false; +} + +void OutputGenerator::enableIf(OutputGenerator::OutputType o) +{ + if (o==type()) enable(); +} + +void OutputGenerator::disableIf(OutputGenerator::OutputType o) +{ + if (o==type()) disable(); +} + +void OutputGenerator::disableIfNot(OutputGenerator::OutputType o) +{ + if (o!=type()) disable(); +} + +bool OutputGenerator::isEnabled(OutputGenerator::OutputType o) +{ + return (o==type() && m_active); +} + +OutputGenerator *OutputGenerator::get(OutputGenerator::OutputType o) +{ + return (o==type()) ? this : 0; } diff --git a/src/outputgen.h b/src/outputgen.h index 009225f..0d64833 100644 --- a/src/outputgen.h +++ b/src/outputgen.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. * @@ -18,7 +18,10 @@ #ifndef OUTPUTGEN_H #define OUTPUTGEN_H -#include <qstack.h> +#include <memory> +#include <stack> + +#include <qfile.h> #include "index.h" #include "section.h" @@ -33,9 +36,7 @@ class DotGfxHierarchyTable; class DotGroupCollaboration; class DocNode; class MemberDef; -class GroupDef; class Definition; -class QFile; struct DocLinkInfo { @@ -54,15 +55,18 @@ struct SourceLinkInfo QCString anchor; }; -/** Output interface for code parser. +/** Output interface for code parser. */ class CodeOutputInterface { public: virtual ~CodeOutputInterface() {} - /*! Writes an code fragment to the output. This function should keep - * spaces visible, should break lines at a newline and should convert + /** Identifier for the output file */ + virtual int id() const { return 0; } + + /*! Writes an code fragment to the output. This function should keep + * spaces visible, should break lines at a newline and should convert * tabs to the right number of spaces. */ virtual void codify(const char *s) = 0; @@ -71,8 +75,8 @@ class CodeOutputInterface * \param ref If this is non-zero, the object is to be found in * an external documentation file. * \param file The file in which the object is located. - * \param anchor The anchor uniquely identifying the object within - * the file. + * \param anchor The anchor uniquely identifying the object within + * the file. * \param name The text to display as a placeholder for the link. * \param tooltip The tooltip to display when the mouse is on the link. */ @@ -89,7 +93,7 @@ class CodeOutputInterface virtual void writeLineNumber(const char *ref,const char *file, const char *anchor,int lineNumber) = 0; - /*! Writes a tool tip definition + /*! Writes a tool tip definition * \param id unique identifier for the tooltip * \param docInfo Info about the symbol's documentation. * \param decl full declaration of the symbol (for functions) @@ -97,14 +101,14 @@ class CodeOutputInterface * \param defInfo Info about the symbol's definition in the source code * \param declInfo Info about the symbol's declaration in the source code */ - virtual void writeTooltip(const char *id, + virtual void writeTooltip(const char *id, const DocLinkInfo &docInfo, const char *decl, const char *desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo ) = 0; - + virtual void startCodeLine(bool hasLineNumbers) = 0; /*! Ends a line of code started with startCodeLine() */ @@ -126,6 +130,16 @@ class CodeOutputInterface virtual void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) = 0; virtual void addWord(const char *word,bool hiPriority) = 0; + + /*! Starts a source code fragment. The fragment will be + * fed to the code parser (see code.h) for syntax highlighting + * and cross-referencing. The fragment ends by a call to + * endCodeFragment() + * @param style The kind of code fragment. + */ + virtual void startCodeFragment(const char *style) = 0; + /*! Ends a block of code */ + virtual void endCodeFragment(const char *style) = 0; }; /** Base Interface used for generating output outside of the @@ -141,29 +155,29 @@ class BaseOutputDocInterface : public CodeOutputInterface public: virtual ~BaseOutputDocInterface() {} enum ParamListTypes { Param, RetVal, Exception }; - enum SectionTypes { /*See, Return, Author, Version, + enum SectionTypes { /*See, Return, Author, Version, Since, Date, Bug, Note, - Warning, Par, Deprecated, Pre, - Post, Invar, Remark, Attention, + Warning, Par, Deprecated, Pre, + Post, Invar, Remark, Attention, Todo, Test, RCS, */ - EnumValues, - Examples + EnumValues, + Examples }; virtual void parseText(const QCString &) {} - + /*! Start of a bullet list: e.g. \c \<ul\> in html. startItemListItem() is * Used for the bullet items. */ virtual void startItemList() = 0; - /*! Writes a list item for a bullet or enumerated - * list: e.g. \c \<li\> in html + /*! Writes a list item for a bullet or enumerated + * list: e.g. \c \<li\> in html */ virtual void startItemListItem() = 0; - /*! Writes a list item for a bullet or enumerated - * list: e.g. \c \</li\> in html + /*! Writes a list item for a bullet or enumerated + * list: e.g. \c \</li\> in html */ virtual void endItemListItem() = 0; @@ -171,7 +185,7 @@ class BaseOutputDocInterface : public CodeOutputInterface virtual void endItemList() = 0; /*! Writes an ASCII string to the output. Converts characters that have - * A special meaning, like \c & in html. + * A special meaning, like \c & in html. */ virtual void docify(const char *s) = 0; @@ -180,8 +194,8 @@ class BaseOutputDocInterface : public CodeOutputInterface */ virtual void writeChar(char c) = 0; - /*! Writes an ASCII string to the output, \e without converting - * special characters. + /*! Writes an ASCII string to the output, \e without converting + * special characters. */ virtual void writeString(const char *text) = 0; @@ -197,8 +211,8 @@ class BaseOutputDocInterface : public CodeOutputInterface * \param ref If this is non-zero, the object is to be found in * an external documentation file. * \param file The file in which the object is located. - * \param anchor The anchor uniquely identifying the object within - * the file. + * \param anchor The anchor uniquely identifying the object within + * the file. * \param name The text to display as a placeholder for the link. */ virtual void writeObjectLink(const char *ref,const char *file, @@ -214,7 +228,7 @@ class BaseOutputDocInterface : public CodeOutputInterface */ virtual void endHtmlLink() = 0; - + /*! Changes the text font to bold face. The bold section ends with * endBold() */ @@ -239,24 +253,10 @@ class BaseOutputDocInterface : public CodeOutputInterface /*! Ends a section of text displayed in italic. */ virtual void endEmphasis() = 0; - /*! Starts a source code fragment. The fragment will be - * fed to the code parser (see code.h) for syntax highlighting - * and cross-referencing. The fragment ends by a call to - * endCodeFragment() - */ - virtual void startCodeFragment() = 0; - - /*! Ends a source code fragment - */ - virtual void endCodeFragment() = 0; - - - - /*! Writes a horizontal ruler to the output */ virtual void writeRuler() = 0; - - /*! Starts a description list: e.g. \c \<dl\> in HTML + + /*! Starts a description list: e.g. \c \<dl\> in HTML * Items are surrounded by startDescItem() and endDescItem() */ virtual void startDescription() = 0; @@ -270,8 +270,8 @@ class BaseOutputDocInterface : public CodeOutputInterface virtual void startDescForItem() = 0; virtual void endDescForItem() = 0; - /*! Ends an item of a description list and starts the - * description itself: e.g. \c \</dt\> in HTML. + /*! Ends an item of a description list and starts the + * description itself: e.g. \c \</dt\> in HTML. */ virtual void endDescItem() = 0; @@ -324,19 +324,27 @@ class OutputGenerator : public BaseOutputDocInterface public: enum OutputType { Html, Latex, Man, RTF, XML, DEF, Perl , Docbook}; - OutputGenerator(); + OutputGenerator(const char *dir); + OutputGenerator(const OutputGenerator &o); + OutputGenerator &operator=(const OutputGenerator &o); virtual ~OutputGenerator(); + virtual OutputType type() const = 0; + virtual std::unique_ptr<OutputGenerator> clone() const = 0; + /////////////////////////////////////////////////////////////// // generic generator methods /////////////////////////////////////////////////////////////// - virtual void enable() = 0; - virtual void disable() = 0; - virtual void enableIf(OutputType o) = 0; - virtual void disableIf(OutputType o) = 0; - virtual void disableIfNot(OutputType o) = 0; - virtual bool isEnabled(OutputType o) = 0; - virtual OutputGenerator *get(OutputType o) = 0; + void enable(); + void disable(); + void enableIf(OutputType o); + void disableIf(OutputType o); + void disableIfNot(OutputType o); + bool isEnabled(OutputType o); + OutputGenerator *get(OutputType o); + QCString dir() const; + QCString fileName() const; + void startPlainFile(const char *name); void endPlainFile(); //QCString getContents() const; @@ -346,13 +354,13 @@ class OutputGenerator : public BaseOutputDocInterface //void setEncoding(const QCString &enc) { encoding = enc; } //virtual void postProcess(QByteArray &) { } - virtual void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md) = 0; + virtual void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md,int id) = 0; /////////////////////////////////////////////////////////////// // structural output interface /////////////////////////////////////////////////////////////// virtual void startFile(const char *name,const char *manName, - const char *title) = 0; + const char *title,int id=0) = 0; virtual void writeSearchInfo() = 0; virtual void writeFooter(const char *navPath) = 0; virtual void endFile() = 0; @@ -489,21 +497,18 @@ class OutputGenerator : public BaseOutputDocInterface protected: FTextStream t; - QFile *m_file; - QCString m_fileName; - QCString m_dir; - bool m_active; - QStack<bool> *m_genStack; - private: - OutputGenerator(const OutputGenerator &o); - OutputGenerator &operator=(const OutputGenerator &o); + QCString m_dir; + QCString m_fileName; + QFile m_file; + bool m_active = true; + std::stack<bool> m_genStack; }; /** Interface used for generating documentation. * * This abstract class is used by several functions - * to generate the output for a specific format. + * to generate the output for a specific format. * This interface contains some state saving and changing * functions for dealing with format specific output. */ @@ -512,18 +517,13 @@ class OutputDocInterface : public BaseOutputDocInterface public: virtual ~OutputDocInterface() {} - /*! Create a new output generator. This can later by appended - * to the current one using append(). - */ - //virtual OutputDocInterface *clone() = 0; - - /*! Disables all output formats except format \a o - * (useful for OutputList only) + /*! Disables all output formats except format \a o + * (useful for OutputList only) */ virtual void disableAllBut(OutputGenerator::OutputType o) = 0; /*! Enables all output formats as far as they have been enabled in - * the config file. (useful for OutputList only) + * the config file. (useful for OutputList only) */ virtual void enableAll() = 0; @@ -536,27 +536,26 @@ class OutputDocInterface : public BaseOutputDocInterface /*! Enables a specific output format (useful for OutputList only) */ virtual void enable(OutputGenerator::OutputType o) = 0; - /*! Check whether a specific output format is currently enabled - * (useful for OutputList only) + /*! Check whether a specific output format is currently enabled + * (useful for OutputList only) */ virtual bool isEnabled(OutputGenerator::OutputType o) = 0; /*! Appends the output generated by generator \a g to this * generator. - */ + */ //virtual void append(const OutputDocInterface *g) = 0; - /*! Pushes the state of the current generator (or list of + /*! Pushes the state of the current generator (or list of * generators) on a stack. */ virtual void pushGeneratorState() = 0; - /*! Pops the state of the current generator (or list of + /*! Pops the state of the current generator (or list of * generators) on a stack. Should be preceded by a call * the pushGeneratorState(). */ virtual void popGeneratorState() = 0; }; - #endif diff --git a/src/outputlist.cpp b/src/outputlist.cpp index e942465..f968c8b 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -29,20 +29,46 @@ #include "definition.h" #include "docparser.h" #include "vhdldocgen.h" +#include "doxygen.h" -OutputList::OutputList(bool) +static AtomicInt g_outId; + +OutputList::OutputList() { + newId(); //printf("OutputList::OutputList()\n"); } +OutputList::OutputList(const OutputList &ol) +{ + m_id = ol.m_id; + for (const auto &og : ol.m_outputs) + { + m_outputs.emplace_back(og->clone()); + } +} + +OutputList &OutputList::operator=(const OutputList &ol) +{ + if (this!=&ol) + { + m_id = ol.m_id; + for (const auto &og : ol.m_outputs) + { + m_outputs.emplace_back(og->clone()); + } + } + return *this; +} + OutputList::~OutputList() { //printf("OutputList::~OutputList()\n"); } -void OutputList::add(OutputGenerator *og) +void OutputList::newId() { - if (og) m_outputs.emplace_back(og); + m_id = ++g_outId; } void OutputList::disableAllBut(OutputGenerator::OutputType o) @@ -134,17 +160,17 @@ void OutputList::generateDoc(const char *fileName,int startLine, root = validatingParseDoc(fileName,startLine, ctx,md,docStr,indexWords,isExample,exampleName, singleLine,linkFromIndex,markdownSupport); - if (count>0) writeDoc(root,ctx,md); + if (count>0) writeDoc(root,ctx,md,m_id); delete root; } -void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md) +void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md,int) { for (const auto &og : m_outputs) { //printf("og->printDoc(extension=%s)\n", // ctx?ctx->getDefFileExtension().data():"<null>"); - if (og->isEnabled()) og->writeDoc(root,ctx,md); + if (og->isEnabled()) og->writeDoc(root,ctx,md,m_id); } VhdlDocGen::setFlowMember(0); } @@ -167,7 +193,7 @@ void OutputList::parseText(const QCString &textStr) { for (const auto &og : m_outputs) { - if (og->isEnabled()) og->writeDoc(root,0,0); + if (og->isEnabled()) og->writeDoc(root,0,0,m_id); } } diff --git a/src/outputlist.h b/src/outputlist.h index 9393a59..7baef7a 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -37,11 +37,19 @@ class DocRoot; class OutputList : public OutputDocInterface { public: - OutputList(bool); + OutputList(); + OutputList(const OutputList &ol); + OutputList &operator=(const OutputList &ol); virtual ~OutputList(); - void add(OutputGenerator *); - uint count() const { return static_cast<uint>(m_outputs.size()); } + template<class Generator> + void add() + { + m_outputs.emplace_back(std::make_unique<Generator>()); + } + + size_t size() const { return m_outputs.size(); } + int id() const { return m_id; } void disableAllBut(OutputGenerator::OutputType o); void enableAll(); @@ -62,7 +70,7 @@ class OutputList : public OutputDocInterface 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 writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md,int id=0); void parseText(const QCString &textStr); void startIndexSection(IndexSections is) @@ -78,7 +86,10 @@ class OutputList : public OutputDocInterface 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); } + { + newId(); + forall(&OutputGenerator::startFile,name,manName,title,m_id); + } void writeSearchInfo() { forall(&OutputGenerator::writeSearchInfo); } void writeFooter(const char *navPath) @@ -222,10 +233,10 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::writeRuler); } void writeAnchor(const char *fileName,const char *name) { forall(&OutputGenerator::writeAnchor,fileName,name); } - void startCodeFragment() - { forall(&OutputGenerator::startCodeFragment); } - void endCodeFragment() - { forall(&OutputGenerator::endCodeFragment); } + void startCodeFragment(const char *style) + { forall(&OutputGenerator::startCodeFragment,style); } + void endCodeFragment(const char *style) + { forall(&OutputGenerator::endCodeFragment,style); } void startCodeLine(bool hasLineNumbers) { forall(&OutputGenerator::startCodeLine,hasLineNumbers); } void endCodeLine() @@ -479,6 +490,7 @@ class OutputList : public OutputDocInterface private: void debug(); void clear(); + void newId(); // For each output format that is enabled (OutputGenerator::isEnabled()) we forward // the method call. @@ -493,8 +505,9 @@ class OutputList : public OutputDocInterface } } - OutputList(const OutputList &ol); std::vector< std::unique_ptr<OutputGenerator> > m_outputs; + int m_id; + }; #endif diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 09152de..b0d375e 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -29,7 +29,7 @@ //------------------------------------------------------------------------------------------ -class PageDefImpl : public DefinitionImpl, public PageDef +class PageDefImpl : public DefinitionMixin<PageDef> { public: PageDefImpl(const char *f,int l,const char *n,const char *d,const char *t); @@ -56,7 +56,7 @@ class PageDefImpl : public DefinitionImpl, public PageDef virtual LocalToc localToc() const { return m_localToc; } virtual void setPageScope(Definition *d){ m_pageScope = d; } virtual Definition *getPageScope() const { return m_pageScope; } - virtual QCString displayName(bool=TRUE) const { return hasTitle() ? m_title : DefinitionImpl::name(); } + virtual QCString displayName(bool=TRUE) const { return hasTitle() ? m_title : DefinitionMixin::name(); } virtual bool showLineNo() const; virtual void writeDocumentation(OutputList &ol); virtual void writeTagFile(FTextStream &); @@ -82,7 +82,7 @@ PageDef *createPageDef(const char *f,int l,const char *n,const char *d,const cha PageDefImpl::PageDefImpl(const char *f,int l,const char *n, const char *d,const char *t) - : DefinitionImpl(f,l,1,n), m_title(t) + : DefinitionMixin(f,l,1,n), m_title(t) { setDocumentation(d,f,l); m_subPageDict = new PageSDict(7); @@ -99,6 +99,7 @@ PageDefImpl::~PageDefImpl() void PageDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); } @@ -121,21 +122,23 @@ void PageDefImpl::setFileName(const char *name) m_fileName = name; } -void PageDefImpl::addInnerCompound(const Definition *const_def) +void PageDefImpl::addInnerCompound(const Definition *def) { - if (const_def->definitionType()==Definition::TypePage) + if (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); - if (this==Doxygen::mainPage) + PageDef *pd = const_cast<PageDef*>(toPageDef(def)); + if (pd) { - pd->setNestingLevel(m_nestingLevel); - } - else - { - pd->setNestingLevel(m_nestingLevel+1); + m_subPageDict->append(pd->name(),pd); + pd->setOuterScope(this); + if (this==Doxygen::mainPage) + { + pd->setNestingLevel(m_nestingLevel); + } + else + { + pd->setNestingLevel(m_nestingLevel+1); + } } } } @@ -208,7 +211,11 @@ void PageDefImpl::writeDocumentation(OutputList &ol) { if (getOuterScope()!=Doxygen::globalScope && !Config_getBool(DISABLE_INDEX)) { - getOuterScope()->writeNavigationPath(ol); + DefinitionMutable *outerScope = toDefinitionMutable(getOuterScope()); + if (outerScope) + { + outerScope->writeNavigationPath(ol); + } } ol.endQuickIndices(); } @@ -229,7 +236,7 @@ void PageDefImpl::writeDocumentation(OutputList &ol) if (si->title() != manPageName) { - ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + ol.generateDoc(docFile(),getStartBodyLine(),this,0,si->title(),TRUE,FALSE, 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endSection(si->label(),si->type()); } @@ -249,7 +256,7 @@ void PageDefImpl::writeDocumentation(OutputList &ol) 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, + ol.generateDoc(docFile(),getStartBodyLine(),this,0,si->title(),TRUE,FALSE, 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); //stringToSearchIndex(getOutputFileBase(), // theTranslator->trPage(TRUE,TRUE)+" "+si->title, @@ -398,3 +405,31 @@ bool PageDefImpl::hasTitle() const return !m_title.isEmpty() && m_title.lower()!="notitle"; } +// --- Cast functions + +PageDef *toPageDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(PageDefImpl)) + { + return static_cast<PageDef*>(d); + } + else + { + return 0; + } +} + +const PageDef *toPageDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(PageDefImpl)) + { + return static_cast<const PageDef*>(d); + } + else + { + return 0; + } +} + diff --git a/src/pagedef.h b/src/pagedef.h index e4d0268..03cc5a8 100644 --- a/src/pagedef.h +++ b/src/pagedef.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. * @@ -26,7 +24,7 @@ class OutputList; class FTextStream; /** @brief A model of a page symbol. */ -class PageDef : virtual public Definition +class PageDef : public DefinitionMutable, public Definition { public: virtual ~PageDef() {} @@ -67,6 +65,13 @@ class PageDef : virtual public Definition PageDef *createPageDef(const char *f,int l,const char *n,const char *d,const char *t); +// --- Cast functions + +PageDef *toPageDef(Definition *d); +const PageDef *toPageDef(const Definition *d); + +// ------------------ + class PageSDict : public SDict<PageDef> { public: diff --git a/src/parserintf.h b/src/parserintf.h index 911b707..2fde2f1 100644 --- a/src/parserintf.h +++ b/src/parserintf.h @@ -137,6 +137,7 @@ class CodeParserInterface //----------------------------------------------------------------------------- using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterface>()>; +using CodeParserFactory = std::function<std::unique_ptr<CodeParserInterface>()>; /** \brief Manages programming language parsers. * @@ -145,38 +146,42 @@ using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterfac */ class ParserManager { - public: struct ParserPair { - ParserPair(OutlineParserFactory opf, std::unique_ptr<CodeParserInterface> cpi) - : outlineParserFactory(opf), codeParserInterface(std::move(cpi)) + ParserPair(OutlineParserFactory opf, CodeParserFactory cpf, const QCString pn) + : outlineParserFactory(opf), codeParserFactory(cpf), parserName(pn) { } OutlineParserFactory outlineParserFactory; - std::unique_ptr<CodeParserInterface> codeParserInterface; + CodeParserFactory codeParserFactory; + QCString parserName; }; + public: + /** Create the parser manager + * @param outlineParserFactory the fallback outline parser factory to use for unknown extensions + * @param codeParserFactory the fallback code parser factory to use for unknown extensions + */ ParserManager(OutlineParserFactory outlineParserFactory, - std::unique_ptr<CodeParserInterface> codeParserInterface) - : m_defaultParsers(outlineParserFactory,std::move(codeParserInterface)) + CodeParserFactory codeParserFactory) + : m_defaultParsers(outlineParserFactory,codeParserFactory, "") { } /** Registers an additional parser. * @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. + * @param[in] outlineParserFactory A factory method to create a language parser (scanner) that + * is to be used for the given name. + * @param[in] codeParserFactory A factory method to create a code parser that is to be used + * for the given name. */ void registerParser(const char *name,OutlineParserFactory outlineParserFactory, - std::unique_ptr<CodeParserInterface> codeParserInterface) + CodeParserFactory codeParserFactory) { - m_parsers.emplace(std::string(name), - ParserPair(outlineParserFactory,std::move(codeParserInterface))); + m_parsers.emplace(std::string(name),ParserPair(outlineParserFactory,codeParserFactory,name)); } /** Registers a file \a extension with a parser with name \a parserName. @@ -198,7 +203,7 @@ class ParserManager return TRUE; } - /** Gets the interface to the parser associated with given \a extension. + /** Gets the interface to the parser associated with a given \a extension. * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ @@ -207,13 +212,29 @@ class ParserManager return getParsers(extension).outlineParserFactory(); } - /** Gets the interface to the parser associated with given \a extension. + /** Gets the interface to the parser associated with a given \a 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) + std::unique_ptr<CodeParserInterface> getCodeParser(const char *extension) + { + auto factory = getCodeParserFactory(extension); + return factory(); + } + + /** Get the factory for create code parser objects with a given \a extension. */ + CodeParserFactory &getCodeParserFactory(const char *extension) + { + return getParsers(extension).codeParserFactory; + } + + /** Gets the name of the parser associated with given \a extension. + * If there is no parser explicitly registered for the supplied extension, + * te empty string will be reurned. + */ + QCString getParserName(const char *extension) { - return *getParsers(extension).codeParserInterface; + return getParsers(extension).parserName; } private: diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index a6e9f22..d84d5e4 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -1569,6 +1569,7 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini // (templateArguments(), definitionTemplateParameterLists()) QCString memType; + QCString name; bool isFunc=FALSE; switch (md->memberType()) { @@ -1590,9 +1591,12 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini case MemberType_Dictionary: memType="dictionary"; break; } + name = md->name(); + if (md->isAnonymous()) name = "__unnamed" + name.right(name.length() - 1)+"__"; + m_output.openHash() .addFieldQuotedString("kind", memType) - .addFieldQuotedString("name", md->name()) + .addFieldQuotedString("name", name) .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness())) .addFieldQuotedString("protection", getProtectionName(md->protection())) .addFieldBoolean("static", md->isStatic()); @@ -1696,14 +1700,12 @@ 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); + 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) @@ -1830,42 +1832,40 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) m_output.openHash() .addFieldQuotedString("name", cd->name()); + /* DGA: fix # #7547 Perlmod does not generate "kind" information to discriminate struct/union */ + m_output.addFieldQuotedString("kind", cd->compoundTypeString()); - if (cd->baseClasses()) + if (!cd->baseClasses().empty()) { m_output.openList("base"); - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + for (const auto &bcd : cd->baseClasses()) + { m_output.openHash() - .addFieldQuotedString("name", bcd->classDef->displayName()) - .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt)) - .addFieldQuotedString("protection", getProtectionName(bcd->prot)) + .addFieldQuotedString("name", bcd.classDef->displayName()) + .addFieldQuotedString("virtualness", getVirtualnessName(bcd.virt)) + .addFieldQuotedString("protection", getProtectionName(bcd.prot)) .closeHash(); + } m_output.closeList(); } - if (cd->subClasses()) + if (!cd->subClasses().empty()) { m_output.openList("derived"); - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + for (const auto &bcd : cd->subClasses()) + { m_output.openHash() - .addFieldQuotedString("name", bcd->classDef->displayName()) - .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt)) - .addFieldQuotedString("protection", getProtectionName(bcd->prot)) + .addFieldQuotedString("name", bcd.classDef->displayName()) + .addFieldQuotedString("virtualness", getVirtualnessName(bcd.virt)) + .addFieldQuotedString("protection", getProtectionName(bcd.prot)) .closeHash(); + } m_output.closeList(); } - ClassSDict *cl = cd->getClassSDict(); - if (cl) { m_output.openList("inner"); - ClassSDict::Iterator cli(*cl); - const ClassDef *icd; - for (cli.toFirst();(icd=cli.current());++cli) + for (const auto &icd : cd->getClasses()) m_output.openHash() .addFieldQuotedString("name", icd->name()) .closeHash(); @@ -1966,26 +1966,20 @@ void PerlModGenerator::generatePerlModForNamespace(const NamespaceDef *nd) m_output.openHash() .addFieldQuotedString("name", nd->name()); - ClassSDict *cl = nd->getClassSDict(); - if (cl) + if (!nd->getClasses().empty()) { m_output.openList("classes"); - ClassSDict::Iterator cli(*cl); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : nd->getClasses()) m_output.openHash() .addFieldQuotedString("name", cd->name()) .closeHash(); m_output.closeList(); } - const NamespaceSDict *nl = nd->getNamespaceSDict(); - if (nl) + if (!nd->getNamespaces().empty()) { m_output.openList("namespaces"); - NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *ind; - for (nli.toFirst();(ind=nli.current());++nli) + for (const auto &ind : nd->getNamespaces()) m_output.openHash() .addFieldQuotedString("name", ind->name()) .closeHash(); @@ -2112,26 +2106,20 @@ void PerlModGenerator::generatePerlModForGroup(const GroupDef *gd) m_output.closeList(); } - ClassSDict *cl = gd->getClasses(); - if (cl) + if (!gd->getClasses().empty()) { m_output.openList("classes"); - ClassSDict::Iterator cli(*cl); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : gd->getClasses()) m_output.openHash() .addFieldQuotedString("name", cd->name()) .closeHash(); m_output.closeList(); } - NamespaceSDict *nl = gd->getNamespaces(); - if (nl) + if (!gd->getNamespaces().empty()) { m_output.openList("namespaces"); - NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : gd->getNamespaces()) m_output.openHash() .addFieldQuotedString("name", nd->name()) .closeHash(); @@ -2210,17 +2198,13 @@ bool PerlModGenerator::generatePerlModOutput() m_output.add("$doxydocs=").openHash(); m_output.openList("classes"); - ClassSDict::Iterator cli(*Doxygen::classSDict); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) - generatePerlModForClass(cd); + for (const auto &cd : *Doxygen::classLinkedMap) + generatePerlModForClass(cd.get()); m_output.closeList(); m_output.openList("namespaces"); - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) - generatePerlModForNamespace(nd); + for (const auto &nd : *Doxygen::namespaceLinkedMap) + generatePerlModForNamespace(nd.get()); m_output.closeList(); m_output.openList("files"); diff --git a/src/portable.cpp b/src/portable.cpp index d3799c7..0ffbd49 100644 --- a/src/portable.cpp +++ b/src/portable.cpp @@ -196,7 +196,7 @@ int Portable::system(const char *command,const char *args,bool commandHasConsole } -unsigned int Portable::pid(void) +unsigned int Portable::pid() { unsigned int pid; #if !defined(_WIN32) || defined(__CYGWIN__) @@ -322,7 +322,7 @@ FILE *Portable::fopen(const char *fileName,const char *mode) #endif } -char Portable::pathSeparator(void) +char Portable::pathSeparator() { #if defined(_WIN32) && !defined(__CYGWIN__) return '\\'; @@ -331,7 +331,7 @@ char Portable::pathSeparator(void) #endif } -char Portable::pathListSeparator(void) +char Portable::pathListSeparator() { #if defined(_WIN32) && !defined(__CYGWIN__) return ';'; @@ -386,7 +386,7 @@ bool Portable::checkForExecutable(const char *fileName) #endif } -const char *Portable::ghostScriptCommand(void) +const char *Portable::ghostScriptCommand() { #if defined(_WIN32) && !defined(__CYGWIN__) static char *gsexe = NULL; @@ -410,7 +410,7 @@ const char *Portable::ghostScriptCommand(void) #endif } -const char *Portable::commandExtension(void) +const char *Portable::commandExtension() { #if defined(_WIN32) && !defined(__CYGWIN__) return ".exe"; @@ -419,7 +419,7 @@ const char *Portable::commandExtension(void) #endif } -bool Portable::fileSystemIsCaseSensitive(void) +bool Portable::fileSystemIsCaseSensitive() { #if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__) || defined(__CYGWIN__) return FALSE; @@ -446,17 +446,17 @@ int Portable::pclose(FILE *stream) #endif } -void Portable::sysTimerStart(void) +void Portable::sysTimerStart() { g_time.start(); } -void Portable::sysTimerStop(void) +void Portable::sysTimerStop() { g_sysElapsedTime+=((double)g_time.elapsed())/1000.0; } -double Portable::getSysElapsedTime(void) +double Portable::getSysElapsedTime() { return g_sysElapsedTime; } @@ -492,7 +492,7 @@ bool Portable::isAbsolutePath(const char *fileName) * * This routine was inspired by the cause for bug 766059 was that in the Windows path there were forward slashes. */ -void Portable::correct_path(void) +void Portable::correct_path() { #if defined(_WIN32) && !defined(__CYGWIN__) const char *p = Portable::getenv("PATH"); @@ -511,7 +511,7 @@ void Portable::unlink(const char *fileName) #endif } -void Portable::setShortDir(void) +void Portable::setShortDir() { #if defined(_WIN32) && !defined(__CYGWIN__) long length = 0; diff --git a/src/portable.h b/src/portable.h index bf6cfea..d2b3036 100644 --- a/src/portable.h +++ b/src/portable.h @@ -20,7 +20,7 @@ typedef off_t portable_off_t; namespace Portable { int system(const char *command,const char *args,bool commandHasConsole=true); - unsigned int pid(void); + unsigned int pid(); const char * getenv(const char *variable); void setenv(const char *variable,const char *value); void unsetenv(const char *variable); @@ -28,20 +28,20 @@ namespace Portable portable_off_t ftell(FILE *f); FILE * fopen(const char *fileName,const char *mode); void unlink(const char *fileName); - char pathSeparator(void); - char pathListSeparator(void); - const char * ghostScriptCommand(void); - const char * commandExtension(void); + char pathSeparator(); + char pathListSeparator(); + const char * ghostScriptCommand(); + const char * commandExtension(); bool fileSystemIsCaseSensitive(); FILE * popen(const char *name,const char *type); int pclose(FILE *stream); - void sysTimerStart(void); - void sysTimerStop(void); - double getSysElapsedTime(void); + void sysTimerStart(); + void sysTimerStop(); + double getSysElapsedTime(); void sleep(int ms); bool isAbsolutePath(const char *fileName); - void correct_path(void); - void setShortDir(void); + void correct_path(); + void setShortDir(); const char * strnstr(const char *haystack, const char *needle, size_t haystack_len); const char * devNull(); bool checkForExecutable(const char *fileName); @@ -1502,7 +1502,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) } } <SkipDoubleQuote>"//"[/]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } -<SkipDoubleQuote>"/*" { yyextra->defText += yytext; yyextra->defLitText+=yytext; } +<SkipDoubleQuote>"/*"[*]? { yyextra->defText += yytext; yyextra->defLitText+=yytext; } <SkipDoubleQuote>\" { yyextra->defText += *yytext; yyextra->defLitText+=yytext; BEGIN(DefineText); @@ -2036,7 +2036,7 @@ static bool replaceFunctionMacro(yyscan_t yyscanner,const QCString &expr,QCStrin QCString arg; int argCount=0; bool done=FALSE; - + // PHASE 1: read the macro arguments if (def->nargs==0) { @@ -2395,7 +2395,7 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in } else if (def && def->nargs>=0) // function macro { - //printf(" >>>> call replaceFunctionMacro\n"); + //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr)); replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level); //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced); len+=l; @@ -2416,6 +2416,10 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1); state->expandedDict.erase(toStdString(macroName)); } + else if (def && def->nonRecursive) + { + expanded = true; + } if (expanded) { expr=expr.left(p)+resultExpr+restExpr; @@ -3186,22 +3190,34 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) 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 + bool varArgs = false; + int count = 0; + int i,pi,l; 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))) + QRegExp reId("[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*"); // regexp matching an id + if (ds.mid(i_obrace+1,i_cbrace-i_obrace-1)=="...") { - if (l>0) // see bug375037 - { - argMap.emplace(toStdString(ds.mid(pi,l)),count); - count++; - i=pi+l; - } - else + varArgs = true; + argMap.emplace("__VA_ARGS__",count); + count++; + } + else + { + //printf("predefined function macro '%s'\n",qPrint(ds.mid(i_obrace+1,i_cbrace-i_obrace-1))); + i=i_obrace+1; + // gather the formal arguments in a dictionary + while (i<i_cbrace && (pi=reId.match(ds,i,&l))) { - i++; + if (l>0) // see bug375037 + { + argMap.emplace(toStdString(ds.mid(pi,l)),count); + count++; + i=pi+l; + } + else + { + i++; + } } } // strip definition part @@ -3241,6 +3257,7 @@ static void initPredefined(yyscan_t yyscanner,const char *fileName) def.nonRecursive = nonRecursive; def.fileDef = state->yyFileDef; def.fileName = fileName; + def.varArgs = varArgs; state->contextDefines.insert(std::make_pair(def.name.str(),def)); //printf("#define '%s' '%s' #nargs=%d\n", diff --git a/src/pycode.h b/src/pycode.h index e3a01b4..8bce2a9 100644 --- a/src/pycode.h +++ b/src/pycode.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. * @@ -36,6 +34,8 @@ class Definition; class PythonCodeParser : public CodeParserInterface { public: + PythonCodeParser(); + virtual ~PythonCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -52,6 +52,9 @@ class PythonCodeParser : public CodeParserInterface bool collectXrefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/pycode.l b/src/pycode.l index 8cb85a3..b7f3b66 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -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. * @@ -23,6 +21,8 @@ %option never-interactive %option prefix="pycodeYY" +%option reentrant +%option extra-type="struct pycodeYY_state *" %option noyy_top_state %top{ #include <stdint.h> @@ -30,12 +30,15 @@ %{ +#include <vector> +#include <unordered_map> +#include <string> +#include <stack> + #include <stdio.h> -#include <qvaluestack.h> #include "pycode.h" #include "message.h" - #include "scanner.h" #include "entry.h" #include "doxygen.h" @@ -49,6 +52,8 @@ #include "filedef.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" +#include "symbolresolver.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -59,279 +64,911 @@ #define USE_STATE2STRING 0 -static ClassSDict g_codeClassSDict(17); -static QCString g_curClassName; -static QStrList g_curClassBases; - - -static CodeOutputInterface * g_code; -static const char * g_inputString; //!< the code fragment as text -static int g_inputPosition; //!< read offset during parsing -static const char * g_currentFontClass; -static bool g_needsTermination; -static const Definition *g_searchCtx; -static bool g_collectXRefs; -static int g_inputLines; //!< number of line in the code fragment -static int g_yyLineNr; //!< current line number -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; -static QCString g_realScope; -//static bool g_insideBody; -static int g_bodyCurlyCount; -static bool g_searchingForBody; -static QCString g_classScope; -static int g_paramParens; -//static int g_anchorCount; - -static bool g_exampleBlock; -static QCString g_exampleName; - -static QCString g_type; -static QCString g_name; - -static bool g_doubleStringIsDoc; -static bool g_doubleQuote; -static bool g_noSuiteFound; -static int g_stringContext; - -static QValueStack<uint> g_indents; //!< Tracks indentation levels for scoping in python - -static QCString g_docBlock; //!< contents of all lines of a documentation block -static bool g_endComment; - -static void endFontClass(); -static void adjustScopesAndSuites(unsigned indentLength); + +struct pycodeYY_state +{ + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; + QCString curClassName; + QStrList curClassBases; + + CodeOutputInterface * code = 0; + const char * inputString = 0; //!< the code fragment as text + yy_size_t inputPosition = 0; //!< read offset during parsing + const char * currentFontClass = 0; + bool needsTermination = FALSE; + const Definition *searchCtx = 0; + bool collectXRefs = FALSE; + int inputLines = 0; //!< number of line in the code fragment + int yyLineNr = 0; //!< current line number + FileDef * sourceFileDef = 0; + Definition * currentDefinition = 0; + MemberDef * currentMemberDef = 0; + bool includeCodeFragment = FALSE; + QCString realScope; + int bodyCurlyCount = 0; + bool searchingForBody = FALSE; + QCString classScope; + int paramParens = 0; + + bool exampleBlock = FALSE; + QCString exampleName; + + QCString type; + QCString name; + + bool doubleStringIsDoc = FALSE; + bool doubleQuote = FALSE; + bool noSuiteFound = FALSE; + int stringContext = 0; + + std::stack<yy_size_t> indents; //!< Tracks indentation levels for scoping in python + + QCString docBlock; //!< contents of all lines of a documentation block + bool endComment = FALSE; + VariableContext theVarContext; + CallContext theCallContext; + SymbolResolver symbolResolver; +}; + #if USE_STATE2STRING static const char *stateToString(int state); #endif +static void startCodeLine(yyscan_t yyscanner); +static int countLines(yyscan_t yyscanner); +static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor); +static void addToSearchIndex(yyscan_t yyscanner, const char *text); +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d); +static void codify(yyscan_t yyscanner,const char* text); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void writeMultiLineCodeLink(yyscan_t yyscanner, CodeOutputInterface &ol, const Definition *d, const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void endFontClass(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, const QCString &m, + const char *memberText, CodeOutputInterface &ol, const char *text); +static bool getLink(yyscan_t yyscanner, const char *className, const char *memberName, + CodeOutputInterface &ol, const char *text=0); +static void generateClassOrGlobalLink(yyscan_t yyscanner, CodeOutputInterface &ol, + const char *clName, bool typeOnly=FALSE); +static void generateFunctionLink(yyscan_t yyscanner, CodeOutputInterface &ol, + const char *funcName); +static bool findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, + Definition *sym, const char *symName); +static void findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, + const char *symName); +static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + +#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l +static void addVariable(yyscan_t yyscanner, QCString type, QCString name); +#endif -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class PyVariableContext -{ - public: - static const ClassDef *dummyContext; - class Scope : public SDict<ClassDef> - { - public: - Scope() : SDict<ClassDef>(17) {} - }; - - PyVariableContext() - { - m_scopes.setAutoDelete(TRUE); - } +//------------------------------------------------------------------- - virtual ~PyVariableContext() - { - } - - void pushScope() - { - m_scopes.append(new Scope); - } +static std::mutex g_searchIndexMutex; +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_countFlowKeywordsMutex; - void popScope() - { - if (m_scopes.count()>0) - { - m_scopes.remove(m_scopes.count()-1); - } - } +//------------------------------------------------------------------- - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); - void clearExceptGlobal() - { - m_scopes.clear(); - } +%} - void addVariable(const QCString &type,const QCString &name); - ClassDef *findVariable(const QCString &name); - - private: - Scope m_globalScope; - QList<Scope> m_scopes; -}; -void PyVariableContext::addVariable(const QCString &type,const QCString &name) +BB [ \t]+ +B [ \t]* +NEWLINE \n + +DIGIT [0-9] +LETTER [A-Za-z\x80-\xFF] +NONEMPTY [A-Za-z0-9_\x80-\xFF] +EXPCHAR [#(){}\[\],:.%/\\=`*~|&<>!;+-] +NONEMPTYEXP [^ \t\n:] +PARAMNONEMPTY [^ \t\n():] +IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* +SCOPE {IDENTIFIER}("."{IDENTIFIER})* +CALLANY "("[^)]*")" +BORDER ([^A-Za-z0-9]) + +POUNDCOMMENT "##" + +TRISINGLEQUOTE "'''" +TRIDOUBLEQUOTE "\"\"\"" +LONGSTRINGCHAR [^\\"'] +ESCAPESEQ ("\\")(.) +LONGSTRINGITEM ({LONGSTRINGCHAR}|{ESCAPESEQ}) +SMALLQUOTE ("\"\""|"\""|"'"|"''") +LONGSTRINGBLOCK ({LONGSTRINGITEM}+|{SMALLQUOTE}) + +SHORTSTRING ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"') +SHORTSTRINGITEM ({SHORTSTRINGCHAR}|{ESCAPESEQ}) +SHORTSTRINGCHAR [^\\\n"] +STRINGLITERAL {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING}) +STRINGPREFIX ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR") +KEYWORD ("lambda"|"import"|"class"|"assert"|"with"|"as"|"from"|"global"|"def"|"True"|"False") +FLOWKW ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally") +QUOTES ("\""[^"]*"\"") +SINGLEQUOTES ("'"[^']*"'") + +LONGINTEGER {INTEGER}("l"|"L") +INTEGER ({DECIMALINTEGER}|{OCTINTEGER}|{HEXINTEGER}) +DECIMALINTEGER ({NONZERODIGIT}{DIGIT}*|"0") +OCTINTEGER "0"{OCTDIGIT}+ +HEXINTEGER "0"("x"|"X"){HEXDIGIT}+ +NONZERODIGIT [1-9] +OCTDIGIT [0-7] +HEXDIGIT ({DIGIT}|[a-f]|[A-F]) +FLOATNUMBER ({POINTFLOAT}|{EXPONENTFLOAT}) +POINTFLOAT ({INTPART}?{FRACTION}|{INTPART}".") +EXPONENTFLOAT ({INTPART}|{POINTFLOAT}){EXPONENT} +INTPART {DIGIT}+ +FRACTION "."{DIGIT}+ +EXPONENT ("e"|"E")("+"|"-")?{DIGIT}+ +IMAGNUMBER ({FLOATNUMBER}|{INTPART})("j"|"J") +ATOM ({IDENTIFIER}|{LITERAL}|{ENCLOSURE}) +ENCLOSURE ({PARENTH_FORM}|{LIST_DISPLAY}|{DICT_DISPLAY}|{STRING_CONVERSION}) +LITERAL ({STRINGLITERAL}|{INTEGER}|{LONGINTEGER}|{FLOATNUMBER}|{IMAGNUMBER}) +PARENTH_FORM "("{EXPRESSION_LIST}?")" +TEST ({AND_TEST}("or"{AND_TEST})*|{LAMBDA_FORM}) +TESTLIST {TEST}( ","{TEST})*","? +LIST_DISPLAY "["{LISTMAKER}?"]" +LISTMAKER {EXPRESSION}({LIST_FOR}|(","{EXPRESSION})*","?) +LIST_ITER ({LIST_FOR}|{LIST_IF}) +LIST_FOR "for"{EXPRESSION_LIST}"in"{TESTLIST}{LIST_ITER}? +LIST_IF "if"{TEST}{LIST_ITER}? +DICT_DISPLAY "\{"{KEY_DATUM_LIST}?"\}" +KEY_DATUM_LIST {KEY_DATUM}(","{KEY_DATUM})*","? +KEY_DATUM {EXPRESSION}":"{EXPRESSION} +STRING_CONVERSION "`"{EXPRESSION_LIST}"`" +PRIMARY ({ATOM}|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}|{CALL}) +ATTRIBUTEREF {PRIMARY}"."{IDENTIFIER} +SUBSCRIPTION {PRIMARY}"["{EXPRESSION_LIST}"]" +SLICING ({SIMPLE_SLICING}|{EXTENDED_SLICING}) +SIMPLE_SLICING {PRIMARY}"["{SHORT_SLICE}"]" +EXTENDED_SLICING {PRIMARY}"["{SLICE_LIST}"]" +SLICE_LIST {SLICE_ITEM}(","{SLICE_ITEM})*","? +SLICE_ITEM ({EXPRESSION}|{PROPER_SLICE}|{ELLIPSIS}) +PROPER_SLICE ({SHORT_SLICE}|{LONG_SLICE}) +SHORT_SLICE {LOWER_BOUND}?":"{UPPER_BOUND}? +LONG_SLICE {SHORT_SLICE}":"{STRIDE}? +LOWER_BOUND {EXPRESSION} +UPPER_BOUND {EXPRESSION} +STRIDE {EXPRESSION} +ELLIPSIS "..." +CALL {PRIMARY}"("({ARGUMENT_LIST}","?)?")" +ARGUMENT_LIST ({POSITIONAL_ARGUMENTS}(","{KEYWORD_ARGUMENTS})?(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|{KEYWORD_ARGUMENTS}(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|"*"{EXPRESSION}(",""**"{EXPRESSION})?|"**"{EXPRESSION}) +POSITIONAL_ARGUMENTS {EXPRESSION}(","{EXPRESSION})* +KEYWORD_ARGUMENTS {KEYWORD_ITEM}(","{KEYWORD_ITEM})* +KEYWORD_ITEM {IDENTIFIER}"="{EXPRESSION} +POWER {PRIMARY}("**"{U_EXPR})? +U_EXPR ({POWER}|"-"{U_EXPR}|"+"{U_EXPR}|"\~"{U_EXPR}) +M_EXPR ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"//"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR}) +A_EXPR ({M_EXPR}|{A_EXPR}"+"{M_EXPR}|{A_EXPR}"-"{M_EXPR} +SHIFT_EXPR ({A_EXPR}|{SHIFT_EXPR}("<<"|">>"){A_EXPR}) +AND_EXPR ({SHIFT_EXPR}|{AND_EXPR}"\;SPMamp;"{SHIFT_EXPR} +XOR_EXPR ({AND_EXPR}|{XOR_EXPR}"\textasciicircum"{AND_EXPR}) +OR_EXPR ({XOR_EXPR}|{OR_EXPR}"|"{ XOR_EXPR}) + +COMPARISON {OR_EXPR}({COMP_OPERATOR}{OR_EXPR})* +COMP_OPERATOR ("<"|">"|"=="|">="|"<="|"<>"|"!="|"is""not"?|"not"?"in") +EXPRESSION ({OR_TEST}|{LAMBDA_FORM}) +OR_TEST ({AND_TEST}|{OR_TEST}"or"{AND_TEST}) +AND_TEST ({NOT_TEST}|{AND_TEST}"and"{NOT_TEST}) +NOT_TEST ({COMPARISON}|"not"{NOT_TEST}) +LAMBDA_FORM "lambda"{PARAMETER_LIST}?":"{EXPRESSION} +EXPRESSION_LIST {EXPRESSION}(","{EXPRESSION})*","? +SIMPLE_STMT ({EXPRESSION_STMT}|{ASSERT_STMT}|{ASSIGNMENT_STMT}|{AUGMENTED_ASSIGNMENT_STMT}|{PASS_STMT}|{DEL_STMT}|{PRINT_STMT}|{RETURN_STMT}|{YIELD_STMT}|{RAISE_STMT}|{BREAK_STMT}|{CONTINUE_STMT}|{IMPORT_STMT}|{GLOBAL_STMT}|{EXEC_STMT}) +EXPRESSION_STMT {EXPRESSION_LIST} +ASSERT_STMT "assert"{EXPRESSION}(","{EXPRESSION})? +ASSIGNMENT_STMT ({TARGET_LIST}"=")+{EXPRESSION_LIST} +TARGET_LIST {TARGET}(","{TARGET})*","? +TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}) + +%option noyywrap +%option stack + +%x Body + +%x FunctionDec +%x FunctionParams + +%x ClassDec +%x ClassInheritance + +%x Suite +%x SuiteCaptureIndent +%x SuiteStart +%x SuiteMaintain +%x SuiteContinuing + +%x LongString + +%x SingleQuoteString +%x DoubleQuoteString +%x TripleString + +%x DocBlock +%% + +<Body,Suite>{ + "def"{BB} { + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( FunctionDec ); + } + + "class"{BB} { + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( ClassDec ); + } + "None" { + startFontClass(yyscanner,"keywordtype"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } + "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "self."{IDENTIFIER}/"(" { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "self."{IDENTIFIER} { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "cls."{IDENTIFIER}/"(" { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "cls."{IDENTIFIER} { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "@"{SCOPE}{CALLANY}? { // decorator + startFontClass(yyscanner,"preprocessor"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } +} + +<ClassDec>{IDENTIFIER} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + // codify(yyscanner,yytext); + yyextra->curClassName = yytext; + yyextra->curClassBases.clear(); + BEGIN( ClassInheritance ); + } + +<ClassInheritance>{ + ({BB}|[(,)]) { + codify(yyscanner,yytext); + } + + ({IDENTIFIER}".")*{IDENTIFIER} { + // The parser + // is assuming + // that ALL identifiers + // in this state + // are base classes; + // it doesn't check to see + // that the first parenthesis + // has been seen. + + // This is bad - it should + // probably be more strict + // about what to accept. + + yyextra->curClassBases.inSort(yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + // codify(yyscanner,yytext); + } + + ":" { + codify(yyscanner,yytext); + + // Assume this will + // be a one-line suite; + // found counter-example + // in SuiteStart. + + // Push a class scope + + std::unique_ptr<ClassDef> classDefToAdd { createClassDef("<code>",1,1,yyextra->curClassName,ClassDef::Class,0,0,FALSE) }; + ScopedTypeVariant var(yyextra->curClassName); + char *s=yyextra->curClassBases.first(); + while (s) + { + const ClassDef *baseDefToAdd = 0; + // find class in the local scope + auto it = yyextra->codeClassMap.find(s); + if (it != yyextra->codeClassMap.end()) + { + baseDefToAdd = toClassDef(it->second.globalDef()); + } + // Try to find class in global scope + if (baseDefToAdd==0) + { + baseDefToAdd=yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,s); + } + + if (baseDefToAdd && baseDefToAdd->name()!=yyextra->curClassName) + { + var.localDef()->insertBaseClass(baseDefToAdd->name()); + } + + s=yyextra->curClassBases.next(); + } + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); + + // Reset class-parsing variables. + yyextra->curClassName.resize(0); + yyextra->curClassBases.clear(); + + yyextra->noSuiteFound = TRUE; + BEGIN( SuiteStart ); + } +} + + +<FunctionDec>{ + {IDENTIFIER} { + generateFunctionLink(yyscanner,*yyextra->code,yytext); + } + + {B}"(" { + codify(yyscanner,yytext); + BEGIN( FunctionParams ); + } +} + +<FunctionParams>{ + ({BB}|",") { + // Parses delimiters + codify(yyscanner,yytext); + } + + ({IDENTIFIER}|{PARAMNONEMPTY}+) { + codify(yyscanner,yytext); + } + + ")" { + codify(yyscanner,yytext); + } + + "\n" { + codifyLines(yyscanner,yytext); + } + + ":" { + codify(yyscanner,yytext); + + // Assume this will + // be a one-line suite; + // found counter-example + // in SuiteStart. + yyextra->noSuiteFound = TRUE; + BEGIN( SuiteStart ); + } +} + +<Body,Suite>{ + + {KEYWORD} { + // Position-sensitive rules! + // Must come AFTER keyword-triggered rules + // Must come BEFORE identifier NONEMPTY-like rules + // to syntax highlight. + + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } + + {FLOWKW} { + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); + if (mdm) + { + mdm->incrementFlowKeyWordCount(); + } + } + startFontClass(yyscanner,"keywordflow"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } + ({IDENTIFIER}".")*{IDENTIFIER}/"(" { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } + ({IDENTIFIER}".")+{IDENTIFIER} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,TRUE); + } + {IDENTIFIER} { codify(yyscanner,yytext); } + +} + + + +<SuiteStart>{ + + {BB} { + codify(yyscanner,yytext); + } + "pass" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(Body); + } + {KEYWORD} { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + + // No indentation necessary + yyextra->noSuiteFound = FALSE; + } + + {FLOWKW} { + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); + if (mdm) + { + mdm->incrementFlowKeyWordCount(); + } + } + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + + // No indentation necessary + yyextra->noSuiteFound = FALSE; + } + {IDENTIFIER} { + codify(yyscanner,yytext); + } + + + {POUNDCOMMENT} { + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString + ) + { + REJECT; + } + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } + + {NEWLINE} { + codifyLines(yyscanner,yytext); + if ( yyextra->noSuiteFound ) + { + // printf("New suite to capture! [%d]\n", yyextra->yyLineNr); + BEGIN ( SuiteCaptureIndent ); + } + } +} + +<SuiteCaptureIndent>{ + "\n"|({BB}"\n") { + // Blankline - ignore, keep looking for indentation. + codifyLines(yyscanner,yytext); + } + + {BB} { + // This state lasts momentarily, + // to check the indentation + // level that is about to be + // used. + codifyLines(yyscanner,yytext); + yyextra->indents.push(yyleng); + // printf("Captured indent of %d [line %d]\n", yyleng, yyextra->yyLineNr); + BEGIN( Suite ); + } +} + +<SuiteMaintain>{ + + {BB}/({NONEMPTY}|{EXPCHAR}) { + // This implements poor + // indentation-tracking; + // should be improved. + // (translate tabs to space, etc) + codifyLines(yyscanner,yytext); + adjustScopesAndSuites(yyscanner,static_cast<int>(yyleng)); + } + + "\n"|({BB}"\n") { + // If this ever succeeds, + // it means that this is + // a blank line, and + // can be ignored. + codifyLines(yyscanner,yytext); + } + + ""/({NONEMPTY}|{EXPCHAR}) { + // Default rule; matches + // the empty string, assuming + // real text starts here. + // Just go straight to Body. + adjustScopesAndSuites(yyscanner,0); + } +} + + +<Suite>{NEWLINE} { + codifyLines(yyscanner,yytext); + BEGIN( SuiteMaintain ); + } +<Body>{IDENTIFIER} { + codify(yyscanner,yytext); + } +<Body>{NEWLINE} { + codifyLines(yyscanner,yytext); + } + +<SingleQuoteString>{ // Single quoted string like 'That\'s a """nice""" string!' + \\{B}\n { // line continuation + codifyLines(yyscanner,yytext); + } + \\. { // escaped char + codify(yyscanner,yytext); + } + {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple double quotes + codify(yyscanner,yytext); + } + "'" { // end of the string + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(yyextra->stringContext); + } + [^"'\n\\]+ { // normal chars + codify(yyscanner,yytext); + } + . { // normal char + codify(yyscanner,yytext); + } +} + +<DoubleQuoteString>{ // Double quoted string like "That's \"a '''nice'''\" string!" + \\{B}\n { // line continuation + codifyLines(yyscanner,yytext); + } + \\. { // escaped char + codify(yyscanner,yytext); + } + {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes + codify(yyscanner,yytext); + } + "\"" { // end of the string + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(yyextra->stringContext); + } + [^"'\n\\]+ { // normal chars + codify(yyscanner,yytext); + } + . { // normal char + codify(yyscanner,yytext); + } +} + +<TripleString>{ + {TRIDOUBLEQUOTE} | + {TRISINGLEQUOTE} { + codify(yyscanner,yytext); + if (yyextra->doubleQuote==(yytext[0]=='"')) + { + endFontClass(yyscanner); + BEGIN(yyextra->stringContext); + } + } + {LONGSTRINGBLOCK} { + codifyLines(yyscanner,yytext); + } + \n { + codifyLines(yyscanner,yytext); + } + . { + codify(yyscanner,yytext); + } +} + + +<*>{STRINGPREFIX}?{TRISINGLEQUOTE} { + if (YY_START==SingleQuoteString) REJECT; + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + yyextra->doubleQuote=yytext[yyleng-1]=='"'; + codify(yyscanner,yytext); + BEGIN(TripleString); + } +<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} { + if (YY_START==DoubleQuoteString) REJECT; + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + yyextra->doubleQuote=yytext[yyleng-1]=='"'; + codify(yyscanner,yytext); + BEGIN(TripleString); + } +<*>{STRINGPREFIX}?"'" { // single quoted string + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + codify(yyscanner,yytext); + BEGIN(SingleQuoteString); + } +<*>{STRINGPREFIX}?"\"" { // double quoted string + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + codify(yyscanner,yytext); + BEGIN(DoubleQuoteString); + } +<DocBlock>.* { // contents of current comment line + yyextra->docBlock+=yytext; + } +<DocBlock>"\n"{B}("#") { // comment block (next line is also comment line) + yyextra->docBlock+=yytext; + } +<DocBlock>{NEWLINE} { // comment block ends at the end of this line + // remove special comment (default config) + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=((QCString)yyextra->docBlock).contains('\n'); + yyextra->endComment=TRUE; + } + else // do not remove comment + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + unput(*yytext); + yy_pop_state(yyscanner); + } +<*>{POUNDCOMMENT}.* { + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } +<*>"#".* { // normal comment + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<*>{NEWLINE} { + if (yyextra->endComment) + { + yyextra->endComment=FALSE; + } + else + { + codifyLines(yyscanner,yytext); + } + //printf("[pycode] %d NEWLINE [line %d] no match\n", + // YY_START, yyextra->yyLineNr); + + BEGIN(Body); + } + +<*>[ \t]+ { + codify(yyscanner,yytext); + BEGIN(Body); + } +<*>. { + codify(yyscanner,yytext); + // printf("[pycode] '%s' [ state %d ] [line %d] no match\n", + // yytext, YY_START, yyextra->yyLineNr); + + BEGIN(Body); + } + +<*><<EOF>> { + if (YY_START==DocBlock && !Config_getBool(STRIP_CODE_COMMENTS)) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + yyterminate(); + } +%% + +/*@ ---------------------------------------------------------------------------- + */ + +#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l +static void addVariable(yyscan_t yyscanner, QCString type, QCString name) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("PyVariableContext::addVariable(%s,%s)\n",type.data(),name.data()); QCString ltype = type.simplifyWhiteSpace(); QCString lname = name.simplifyWhiteSpace(); - Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - const ClassDef *varType; - if ( - (varType=g_codeClassSDict[ltype]) || // look for class definitions inside the code block - (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions - ) + auto it = yyextra->codeClassMap.find(ltype.str()); + if (it!=yyextra->codeClassMap.end()) { - scope->append(lname,varType); // add it to a list + yyextra->theVarContext.addVariable(lname,std::move(it->second)); } - else + else { - if (m_scopes.count()>0) // for local variables add a dummy entry so the name - // is hidden to avoid FALSE links to global variables with the same name - // TODO: make this work for namespaces as well! + const ClassDef *varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions + if (varType) { - scope->append(lname,dummyContext); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varType)); + } + else + { + if (!yyextra->theVarContext.atGlobalScope()) // for local variable add a dummy entry to avoid linking to a global that is shadowed. + { + yyextra->theVarContext.addVariable(lname.str(),ScopedTypeVariant()); + } } } } +#endif + +//------------------------------------------------------------------------------- -ClassDef *PyVariableContext::findVariable(const QCString &name) +static yy_size_t yyread(yyscan_t yyscanner, char *buf,yy_size_t max_size) { - if (name.isEmpty()) return 0; - ClassDef *result = 0; - QListIterator<Scope> sli(m_scopes); - Scope *scope; - // search from inner to outer scope - for (sli.toLast();(scope=sli.current());--sli) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s ) { - result = scope->find(name); - if (result) - { - return result; - } + *buf++ = *s++; + c++; } - // nothing found -> also try the global scope - result=m_globalScope.find(name); - return result; + yyextra->inputPosition += c; + return c; } -static PyVariableContext g_theVarContext; -const ClassDef *PyVariableContext::dummyContext = (ClassDef*)0x8; +//------------------------------------------------------------------------------- -class PyCallContext +/*! + Examines current stack of white-space indentations; + re-syncs the parser with the correct scope. +*/ +static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength) { - public: - struct Ctx - { - Ctx() : name(g_name), type(g_type), cd(0) {} - QCString name; - QCString type; - const ClassDef *cd; - }; - - PyCallContext() - { - m_classList.append(new Ctx); - m_classList.setAutoDelete(TRUE); - } - - virtual ~PyCallContext() {} - - void setClass(const ClassDef *cd) - { - Ctx *ctx = m_classList.getLast(); - if (ctx) - { - ctx->cd=cd; - } - } - void pushScope() - { - m_classList.append(new Ctx); - } - - void popScope() - { - if (m_classList.count()>1) - { - Ctx *ctx = m_classList.getLast(); - if (ctx) - { - g_name = ctx->name; - g_type = ctx->type; - } - m_classList.removeLast(); - } - else - { - } - } - - void clear() - { - m_classList.clear(); - m_classList.append(new Ctx); - } - - const ClassDef *getClass() const + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + // States to pop + if (!yyextra->indents.empty() && indentLength < yyextra->indents.top()) + { + while (!yyextra->indents.empty() && indentLength < yyextra->indents.top()) { - Ctx *ctx = m_classList.getLast(); + // printf("Exited scope indent of [%d]\n", yyextra->indents.top()); + yyextra->indents.pop(); // Pop the old suite's indentation - if (ctx) - return ctx->cd; - else - return 0; + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); } + } - private: - QList<Ctx> m_classList; -}; - -static PyCallContext g_theCallContext; + // Are there any remaining indentation levels for suites? + if (!yyextra->indents.empty()) + { + BEGIN( Suite ); + } + else + { + BEGIN( Body ); + } +} +//------------------------------------------------------------------------------- /*! counts the number of lines in the input */ -static int countLines() +static int countLines(yyscan_t yyscanner) { - const char *p=g_inputString; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->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>yyextra->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++; + yyextra->needsTermination=TRUE; + } return count; } -static void setCurrentDoc(const QCString &anchor) +//------------------------------------------------------------------------------- + +static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - if (g_searchCtx) + std::lock_guard<std::mutex> lock(g_searchIndexMutex); + if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); } } } -static void addToSearchIndex(const char *text) +//------------------------------------------------------------------------------- + +static void addToSearchIndex(yyscan_t yyscanner, const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - Doxygen::searchIndex->addWord(text,FALSE); + std::lock_guard<std::mutex> lock(g_searchIndexMutex); + yyextra->code->addWord(text,FALSE); } } +//------------------------------------------------------------------------------- -static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int pos=0; QCString type = s; QCString className; @@ -339,15 +976,14 @@ static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefin while (extractClassNameFromType(type,pos,className,templSpec)!=-1) { QCString clName=className+templSpec; - const ClassDef *cd=0; - if (!g_classScope.isEmpty()) + if (!yyextra->classScope.isEmpty()) { - cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName); + cd=yyextra->symbolResolver.resolveClass(d,yyextra->classScope+"::"+clName); } if (cd==0) { - cd=getResolvedClass(d,g_sourceFileDef,clName); + cd=yyextra->symbolResolver.resolveClass(d,clName); } if (cd) { @@ -358,104 +994,117 @@ static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefin return 0; } +//------------------------------------------------------------------------------- - -/*! start a new line of code, inserting a line number if g_sourceFileDef +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef * is TRUE. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ -static void startCodeLine() +static void startCodeLine(yyscan_t yyscanner) { - //if (g_currentFontClass) { g_code->endFontClass(); } - if (g_sourceFileDef) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //if (yyextra->currentFontClass) { yyextra->code->endFontClass(yyscanner); } + if (yyextra->sourceFileDef) { //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=%p\n",g_yyLineNr,d); - //g_code->startLineNumber(); - - if (!g_includeCodeFragment && d && d->isLinkableInProject()) + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("startCodeLine %d d=%p\n",yyextra->yyLineNr,d); + //yyextra->code->startLineNumber(); + + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - //g_insideBody = FALSE; - g_endComment = FALSE; - g_searchingForBody = TRUE; - g_realScope = d->name().copy(); - g_classScope = d->name().copy(); - //printf("Real scope: '%s'\n",g_realScope.data()); - g_bodyCurlyCount = 0; + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + //yyextra->insideBody = FALSE; + yyextra->endComment = FALSE; + yyextra->searchingForBody = TRUE; + yyextra->realScope = d->name().copy(); + yyextra->classScope = d->name().copy(); + //printf("Real scope: '%s'\n",yyextra->realScope.data()); + yyextra->bodyCurlyCount = 0; QCString lineAnchor; - lineAnchor.sprintf("l%05d",g_yyLineNr); - if (g_currentMemberDef) + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) { - g_code->writeLineNumber(g_currentMemberDef->getReference(), - g_currentMemberDef->getOutputFileBase(), - g_currentMemberDef->anchor(),g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } else { - g_code->writeLineNumber(d->getReference(), - d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - //g_code->codify(lineNumber); - g_code->writeLineNumber(0,0,0,g_yyLineNr); + //yyextra->code->codify(lineNumber); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } - //g_code->endLineNumber(); + //yyextra->code->endLineNumber(); } - g_code->startCodeLine(g_sourceFileDef); - if (g_currentFontClass) + yyextra->code->startCodeLine(yyextra->sourceFileDef); + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void codify(const char* text) -{ - g_code->codify(text); +//------------------------------------------------------------------------------- + +static void codify(yyscan_t yyscanner,const char* text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->code->codify(text); } -static void endCodeLine() +//------------------------------------------------------------------------------- + +static void endCodeLine(yyscan_t yyscanner) { - endFontClass(); - g_code->endCodeLine(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); } -static void nextCodeLine() +//------------------------------------------------------------------------------- + +static void nextCodeLine(yyscan_t yyscanner) { - const char *fc = g_currentFontClass; - endCodeLine(); - if (g_yyLineNr<g_inputLines) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) { - g_currentFontClass = fc; - startCodeLine(); + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); } } +//------------------------------------------------------------------------------- /*! 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, +static void writeMultiLineCodeLink(yyscan_t yyscanner, + CodeOutputInterface &ol, const Definition *d, const char *text) { - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + TooltipManager::instance().addTooltip(ol,d); 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(); @@ -469,11 +1118,11 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); - nextCodeLine(); + nextCodeLine(yyscanner); } else { @@ -484,141 +1133,150 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, } } -static void startFontClass(const char *s) +//------------------------------------------------------------------------------- + +static void startFontClass(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // if font class is already set don't stop and start it. // strcmp does not like null pointers as input. - if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s)) + if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s)) { - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } } -static void endFontClass() +//------------------------------------------------------------------------------- + +static void endFontClass(yyscan_t yyscanner) { - if (g_currentFontClass) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) { - g_code->endFontClass(); - g_currentFontClass=0; + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; } } -static void codifyLines(char *text) +//------------------------------------------------------------------------------- + +static void codifyLines(yyscan_t yyscanner,const char *text) { - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); - char *p=text,*sp=p; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); + const char *p=text,*sp=p; char c; bool done=FALSE; - const char * tmp_currentFontClass = g_currentFontClass; while (!done) { sp=p; while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; - *(p-1)='\0'; - g_code->codify(sp); - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } - if (tmp_currentFontClass) - { - startFontClass(tmp_currentFontClass); - } + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); + yyextra->code->codify(sp); done=TRUE; } } } -static void codifyLines(const QCString &str) -{ - char *tmp= (char *)malloc(str.length()+1); - qstrcpy(tmp, str); - codifyLines(tmp); - free(tmp); -} +//------------------------------------------------------------------------------- -static bool getLinkInScope(const QCString &c, // scope +static bool getLinkInScope(yyscan_t yyscanner, + const QCString &c, // scope const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text - ) + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text + ) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const MemberDef *md = 0; const ClassDef *cd = 0; const FileDef *fd = 0; const NamespaceDef *nd = 0; const GroupDef *gd = 0; //printf("Trying '%s'::'%s'\n",c.data(),m.data()); - if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) && + if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef) && md->isLinkable()) { //Definition *d=0; //if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + md->getBodyDef() : md->getOuterScope(); //printf("Found! d=%s\n",d?d->name().data():"<none>"); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { - g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope())); - //printf("g_currentDefinition=%p g_currentMemberDef=%p\n", - // g_currentDefinition,g_currentMemberDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n", + // yyextra->currentDefinition,yyextra->currentMemberDef); - if (g_currentDefinition && g_currentMemberDef && - md!=g_currentMemberDef && g_collectXRefs) + if (yyextra->currentDefinition && yyextra->currentMemberDef && + md!=yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } //printf("d->getReference()='%s' d->getOutputBase()='%s' name='%s' member name='%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data()); - - writeMultiLineCodeLink(ol,md, text ? text : memberText); - addToSearchIndex(text ? text : memberText); + + writeMultiLineCodeLink(yyscanner,ol,md, text ? text : memberText); + addToSearchIndex(yyscanner,text ? text : memberText); return TRUE; - } + } } return FALSE; } -static bool getLink(const char *className, +//------------------------------------------------------------------------------- + +static bool getLink(yyscan_t yyscanner, + const char *className, const char *memberName, - CodeOutputInterface &ol, - const char *text=0) + CodeOutputInterface &ol, + const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString m=removeRedundantWhiteSpace(memberName); QCString c=className; - if (!getLinkInScope(c,m,memberName,ol,text)) + if (!getLinkInScope(yyscanner,c,m,memberName,ol,text)) { - if (!g_curClassName.isEmpty()) + if (!yyextra->curClassName.isEmpty()) { if (!c.isEmpty()) c.prepend("::"); - c.prepend(g_curClassName); - return getLinkInScope(c,m,memberName,ol,text); + c.prepend(yyextra->curClassName); + return getLinkInScope(yyscanner,c,m,memberName,ol,text); } return FALSE; } return TRUE; } +//------------------------------------------------------------------------------- /* For a given string in the source code, finds its class or global id and links to it. */ -static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, - bool typeOnly=FALSE) +static void generateClassOrGlobalLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *clName, + bool typeOnly) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString className=clName; // Don't do anything for empty text @@ -626,20 +1284,22 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data())); - const ClassDef *cd=0,*lcd=0; /** Class def that we may find */ - const MemberDef *md=0; /** Member def that we may find */ + const ScopedTypeVariant *lcd = 0; + const ClassDef *cd=0; // Class def that we may find + const MemberDef *md=0; // Member def that we may find //bool isLocal=FALSE; - if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable + if ((lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { - Definition *d = g_currentDefinition; + Definition *d = yyextra->currentDefinition; QCString scope = substitute(className,".","::"); - cd = getResolvedClass(d,g_sourceFileDef,substitute(className,".","::"),&md); + cd = yyextra->symbolResolver.resolveClass(d,substitute(className,".","::")); + md = yyextra->symbolResolver.getTypedef(); - DBG_CTX((stderr,"d=%s g_sourceFileDef=%s\n", + DBG_CTX((stderr,"d=%s yyextra->sourceFileDef=%s\n", d?d->displayName().data():"<null>", - g_currentDefinition?g_currentDefinition->displayName().data():"<null>")); + yyextra->currentDefinition?yyextra->currentDefinition->displayName().data():"<null>")); DBG_CTX((stderr,"is found as a type %s\n",cd?cd->name().data():"<null>")); if (cd==0 && md==0) // also see if it is variable or enum or enum value @@ -647,21 +1307,21 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, const NamespaceDef *nd = getResolvedNamespace(scope); if (nd) { - writeMultiLineCodeLink(ol,nd,clName); - addToSearchIndex(className); + writeMultiLineCodeLink(yyscanner,ol,nd,clName); + addToSearchIndex(yyscanner,className); return; } - else if (getLink(g_classScope,clName,ol,clName)) + else if (getLink(yyscanner,yyextra->classScope,clName,ol,clName)) { - return; + return; } } } else { - if (lcd!=PyVariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { - g_theCallContext.setClass(lcd); + yyextra->theCallContext.setScope(*lcd); } //isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); @@ -669,17 +1329,18 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, if (cd && cd->isLinkable()) // is it a linkable class { - writeMultiLineCodeLink(ol,cd,clName); - addToSearchIndex(className); + writeMultiLineCodeLink(yyscanner,ol,cd,clName); + addToSearchIndex(yyscanner,className); if (md) { const Definition *d = md->getOuterScope()==Doxygen::globalScope ? md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); - if (d && d->isLinkable() && md->isLinkable() && - g_currentMemberDef && g_collectXRefs) + if (d && d->isLinkable() && md->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } } } @@ -694,55 +1355,59 @@ 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 *mmd = mcd->getMemberByName(locName); - if (mmd) - { - g_theCallContext.setClass(stripClassName(mmd->typeString(),mmd->getOuterScope())); - writeMultiLineCodeLink(ol,mmd,clName); - addToSearchIndex(className); - 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,mmd); - } - return; - } + MemberDef *mmd = mcd->getMemberByName(locName); + if (mmd) + { + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()))); + writeMultiLineCodeLink(yyscanner,ol,mmd,clName); + addToSearchIndex(yyscanner,className); + const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? + mmd->getBodyDef() : mmd->getOuterScope(); + if (mmd->getGroupDef()) d = mmd->getGroupDef(); + if (d && d->isLinkable() && mmd->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); + } + return; + } } else // check namespace as well { const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd) { - MemberDef *mmd=mnd->getMemberByName(locName); - if (mmd) + MemberDef *mmd=mnd->getMemberByName(locName); + if (mmd) { - //printf("name=%s scope=%s\n",locName.data(),scope.data()); - g_theCallContext.setClass(stripClassName(mmd->typeString(),mmd->getOuterScope())); - writeMultiLineCodeLink(ol,mmd,clName); - addToSearchIndex(className); - 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,mmd); - } - return; + //printf("name=%s scope=%s\n",locName.data(),scope.data()); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()))); + writeMultiLineCodeLink(yyscanner,ol,mmd,clName); + addToSearchIndex(yyscanner,className); + const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? + mmd->getBodyDef() : mmd->getOuterScope(); + if (mmd->getGroupDef()) d = mmd->getGroupDef(); + if (d && d->isLinkable() && mmd->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); + } + return; } } } } - + // nothing found, just write out the word - codifyLines(clName); - addToSearchIndex(clName); + codifyLines(yyscanner,clName); + addToSearchIndex(yyscanner,clName); } } +//------------------------------------------------------------------------------- + /* As of June 1, this function seems to work for file members, but scopes are not @@ -750,11 +1415,12 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, so it doesn't work for classes yet. */ -static void generateFunctionLink(CodeOutputInterface &ol,char *funcName) +static void generateFunctionLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *funcName) { - //CodeClassDef *ccd=0; - ClassDef *ccd=0; - QCString locScope=g_classScope.copy(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data())); int i=locFunc.findRev("::"); @@ -764,915 +1430,213 @@ static void generateFunctionLink(CodeOutputInterface &ol,char *funcName) locFunc=locFunc.right(locFunc.length()-i-2).stripWhiteSpace(); } //printf("generateFunctionLink(%s) classScope='%s'\n",locFunc.data(),locScope.data()); - if (!locScope.isEmpty() && (ccd=g_codeClassSDict[locScope])) + if (!locScope.isEmpty()) { - //printf("using classScope %s\n",g_classScope.data()); - if (ccd->baseClasses()) + auto it = yyextra->codeClassMap.find(locScope.str()); + if (it!=yyextra->codeClassMap.end()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + //printf("using classScope %s\n",yyextra->classScope.data()); + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName)) - { - return; - } + for (const auto &bcName : ccd.localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + return; + } + } } } } - if (!getLink(locScope,locFunc,ol,funcName)) + if (!getLink(yyscanner,locScope,locFunc,ol,funcName)) { - generateClassOrGlobalLink(ol,funcName); + generateClassOrGlobalLink(yyscanner,ol,funcName); } return; } -static bool findMemberLink(CodeOutputInterface &ol,Definition *sym,const char *symName) +//------------------------------------------------------------------------------- + +static bool findMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + Definition *sym, + const char *symName) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("sym %s outerScope=%s equal=%d\n", // sym->name().data(),sym->getOuterScope()->name().data(), - // sym->getOuterScope()==g_currentDefinition); + // sym->getOuterScope()==yyextra->currentDefinition); if (sym->getOuterScope() && sym->getOuterScope()->definitionType()==Definition::TypeClass && - g_currentDefinition->definitionType()==Definition::TypeClass) + yyextra->currentDefinition->definitionType()==Definition::TypeClass) { - ClassDef *cd = dynamic_cast<ClassDef*>(sym->getOuterScope()); - ClassDef *thisCd = dynamic_cast<ClassDef *>(g_currentDefinition); + ClassDef *cd = toClassDef(sym->getOuterScope()); + ClassDef *thisCd = toClassDef(yyextra->currentDefinition); if (sym->definitionType()==Definition::TypeMember) { - if (g_currentMemberDef && g_collectXRefs) + if (yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,dynamic_cast<MemberDef*>(sym)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(toMemberDef(sym))); } } DBG_CTX((stderr,"cd=%s thisCd=%s\n",cd?cd->name().data():"<none>",thisCd?thisCd->name().data():"<none>")); // TODO: find the nearest base class in case cd is a base class of - // thisCd + // thisCd if (cd==thisCd || (thisCd && thisCd->isBaseClass(cd,TRUE))) { - writeMultiLineCodeLink(ol,sym,symName); + writeMultiLineCodeLink(yyscanner,ol,sym,symName); return TRUE; } } return FALSE; } -static void findMemberLink(CodeOutputInterface &ol,char *symName) +//------------------------------------------------------------------------------- + +static void findMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *symName) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("Member reference: %s scope=%s member=%s\n", // yytext, - // g_currentDefinition?g_currentDefinition->name().data():"<none>", - // g_currentMemberDef?g_currentMemberDef->name().data():"<none>" + // yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>", + // yyextra->currentMemberDef?yyextra->currentMemberDef->name().data():"<none>" // ); - if (g_currentDefinition) + if (yyextra->currentDefinition) { - DefinitionIntf *di = Doxygen::symbolMap->find(symName); - if (di) + auto range = Doxygen::symbolMap.find(symName); + for (auto it = range.first; it!=range.second; ++it) { - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // multiple symbols - { - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *sym; - for (dli.toFirst();(sym=dli.current());++dli) - { - if (findMemberLink(ol,sym,symName)) return; - } - } - else // single symbol - { - if (findMemberLink(ol,(Definition*)di,symName)) return; - } + findMemberLink(yyscanner,ol,it->second,symName); } } //printf("sym %s not found\n",&yytext[5]); - codify(symName); -} - -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static yy_size_t yyread(char *buf,yy_size_t max_size) -{ - yy_size_t c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} - - -BB [ \t]+ -B [ \t]* -NEWLINE \n - -DIGIT [0-9] -LETTER [A-Za-z\x80-\xFF] -NONEMPTY [A-Za-z0-9_\x80-\xFF] -EXPCHAR [#(){}\[\],:.%/\\=`*~|&<>!;+-] -NONEMPTYEXP [^ \t\n:] -PARAMNONEMPTY [^ \t\n():] -IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* -BORDER ([^A-Za-z0-9]) - -POUNDCOMMENT "##" - -TRISINGLEQUOTE "'''" -TRIDOUBLEQUOTE "\"\"\"" -LONGSTRINGCHAR [^\\"'] -ESCAPESEQ ("\\")(.) -LONGSTRINGITEM ({LONGSTRINGCHAR}|{ESCAPESEQ}) -SMALLQUOTE ("\"\""|"\""|"'"|"''") -LONGSTRINGBLOCK ({LONGSTRINGITEM}+|{SMALLQUOTE}) - -SHORTSTRING ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"') -SHORTSTRINGITEM ({SHORTSTRINGCHAR}|{ESCAPESEQ}) -SHORTSTRINGCHAR [^\\\n"] -STRINGLITERAL {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING}) -STRINGPREFIX ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR") -KEYWORD ("lambda"|"import"|"class"|"assert"|"with"|"as"|"from"|"global"|"def"|"True"|"False") -FLOWKW ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally") -QUOTES ("\""[^"]*"\"") -SINGLEQUOTES ("'"[^']*"'") - -LONGINTEGER {INTEGER}("l"|"L") -INTEGER ({DECIMALINTEGER}|{OCTINTEGER}|{HEXINTEGER}) -DECIMALINTEGER ({NONZERODIGIT}{DIGIT}*|"0") -OCTINTEGER "0"{OCTDIGIT}+ -HEXINTEGER "0"("x"|"X"){HEXDIGIT}+ -NONZERODIGIT [1-9] -OCTDIGIT [0-7] -HEXDIGIT ({DIGIT}|[a-f]|[A-F]) -FLOATNUMBER ({POINTFLOAT}|{EXPONENTFLOAT}) -POINTFLOAT ({INTPART}?{FRACTION}|{INTPART}".") -EXPONENTFLOAT ({INTPART}|{POINTFLOAT}){EXPONENT} -INTPART {DIGIT}+ -FRACTION "."{DIGIT}+ -EXPONENT ("e"|"E")("+"|"-")?{DIGIT}+ -IMAGNUMBER ({FLOATNUMBER}|{INTPART})("j"|"J") -ATOM ({IDENTIFIER}|{LITERAL}|{ENCLOSURE}) -ENCLOSURE ({PARENTH_FORM}|{LIST_DISPLAY}|{DICT_DISPLAY}|{STRING_CONVERSION}) -LITERAL ({STRINGLITERAL}|{INTEGER}|{LONGINTEGER}|{FLOATNUMBER}|{IMAGNUMBER}) -PARENTH_FORM "("{EXPRESSION_LIST}?")" -TEST ({AND_TEST}("or"{AND_TEST})*|{LAMBDA_FORM}) -TESTLIST {TEST}( ","{TEST})*","? -LIST_DISPLAY "["{LISTMAKER}?"]" -LISTMAKER {EXPRESSION}({LIST_FOR}|(","{EXPRESSION})*","?) -LIST_ITER ({LIST_FOR}|{LIST_IF}) -LIST_FOR "for"{EXPRESSION_LIST}"in"{TESTLIST}{LIST_ITER}? -LIST_IF "if"{TEST}{LIST_ITER}? -DICT_DISPLAY "\{"{KEY_DATUM_LIST}?"\}" -KEY_DATUM_LIST {KEY_DATUM}(","{KEY_DATUM})*","? -KEY_DATUM {EXPRESSION}":"{EXPRESSION} -STRING_CONVERSION "`"{EXPRESSION_LIST}"`" -PRIMARY ({ATOM}|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}|{CALL}) -ATTRIBUTEREF {PRIMARY}"."{IDENTIFIER} -SUBSCRIPTION {PRIMARY}"["{EXPRESSION_LIST}"]" -SLICING ({SIMPLE_SLICING}|{EXTENDED_SLICING}) -SIMPLE_SLICING {PRIMARY}"["{SHORT_SLICE}"]" -EXTENDED_SLICING {PRIMARY}"["{SLICE_LIST}"]" -SLICE_LIST {SLICE_ITEM}(","{SLICE_ITEM})*","? -SLICE_ITEM ({EXPRESSION}|{PROPER_SLICE}|{ELLIPSIS}) -PROPER_SLICE ({SHORT_SLICE}|{LONG_SLICE}) -SHORT_SLICE {LOWER_BOUND}?":"{UPPER_BOUND}? -LONG_SLICE {SHORT_SLICE}":"{STRIDE}? -LOWER_BOUND {EXPRESSION} -UPPER_BOUND {EXPRESSION} -STRIDE {EXPRESSION} -ELLIPSIS "..." -CALL {PRIMARY}"("({ARGUMENT_LIST}","?)?")" -ARGUMENT_LIST ({POSITIONAL_ARGUMENTS}(","{KEYWORD_ARGUMENTS})?(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|{KEYWORD_ARGUMENTS}(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|"*"{EXPRESSION}(",""**"{EXPRESSION})?|"**"{EXPRESSION}) -POSITIONAL_ARGUMENTS {EXPRESSION}(","{EXPRESSION})* -KEYWORD_ARGUMENTS {KEYWORD_ITEM}(","{KEYWORD_ITEM})* -KEYWORD_ITEM {IDENTIFIER}"="{EXPRESSION} -POWER {PRIMARY}("**"{U_EXPR})? -U_EXPR ({POWER}|"-"{U_EXPR}|"+"{U_EXPR}|"\~"{U_EXPR}) -M_EXPR ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"//"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR}) -A_EXPR ({M_EXPR}|{A_EXPR}"+"{M_EXPR}|{A_EXPR}"-"{M_EXPR} -SHIFT_EXPR ({A_EXPR}|{SHIFT_EXPR}("<<"|">>"){A_EXPR}) -AND_EXPR ({SHIFT_EXPR}|{AND_EXPR}"\;SPMamp;"{SHIFT_EXPR} -XOR_EXPR ({AND_EXPR}|{XOR_EXPR}"\textasciicircum"{AND_EXPR}) -OR_EXPR ({XOR_EXPR}|{OR_EXPR}"|"{ XOR_EXPR}) - -COMPARISON {OR_EXPR}({COMP_OPERATOR}{OR_EXPR})* -COMP_OPERATOR ("<"|">"|"=="|">="|"<="|"<>"|"!="|"is""not"?|"not"?"in") -EXPRESSION ({OR_TEST}|{LAMBDA_FORM}) -OR_TEST ({AND_TEST}|{OR_TEST}"or"{AND_TEST}) -AND_TEST ({NOT_TEST}|{AND_TEST}"and"{NOT_TEST}) -NOT_TEST ({COMPARISON}|"not"{NOT_TEST}) -LAMBDA_FORM "lambda"{PARAMETER_LIST}?":"{EXPRESSION} -EXPRESSION_LIST {EXPRESSION}(","{EXPRESSION})*","? -SIMPLE_STMT ({EXPRESSION_STMT}|{ASSERT_STMT}|{ASSIGNMENT_STMT}|{AUGMENTED_ASSIGNMENT_STMT}|{PASS_STMT}|{DEL_STMT}|{PRINT_STMT}|{RETURN_STMT}|{YIELD_STMT}|{RAISE_STMT}|{BREAK_STMT}|{CONTINUE_STMT}|{IMPORT_STMT}|{GLOBAL_STMT}|{EXEC_STMT}) -EXPRESSION_STMT {EXPRESSION_LIST} -ASSERT_STMT "assert"{EXPRESSION}(","{EXPRESSION})? -ASSIGNMENT_STMT ({TARGET_LIST}"=")+{EXPRESSION_LIST} -TARGET_LIST {TARGET}(","{TARGET})*","? -TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}) - - -%option noyywrap -%option stack - -%x Body - -%x FunctionDec -%x FunctionParams - -%x ClassDec -%x ClassInheritance - -%x Suite -%x SuiteCaptureIndent -%x SuiteStart -%x SuiteMaintain -%x SuiteContinuing - -%x LongString - -%x SingleQuoteString -%x DoubleQuoteString -%x TripleString - -%x DocBlock -%% - -<Body,Suite>{ - "def"{BB} { - startFontClass("keyword"); - codify(yytext); - endFontClass(); - BEGIN( FunctionDec ); - } - - "class"{BB} { - startFontClass("keyword"); - codify(yytext); - endFontClass(); - BEGIN( ClassDec ); - } - "None" { - startFontClass("keywordtype"); - codify(yytext); - endFontClass(); - } - "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "self."{IDENTIFIER}/"(" { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "self."{IDENTIFIER} { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } - "cls."{IDENTIFIER}/"(" { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } - "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } - "cls."{IDENTIFIER} { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } -} - -<ClassDec>{IDENTIFIER} { - - generateClassOrGlobalLink(*g_code,yytext); - // codify(yytext); - g_curClassName = yytext; - g_curClassBases.clear(); - BEGIN( ClassInheritance ); - } - -<ClassInheritance>{ - ({BB}|[(,)]) { - codify(yytext); - } - - ({IDENTIFIER}".")*{IDENTIFIER} { - // The parser - // is assuming - // that ALL identifiers - // in this state - // are base classes; - // it doesn't check to see - // that the first parenthesis - // has been seen. - - // This is bad - it should - // probably be more strict - // about what to accept. - - g_curClassBases.inSort(yytext); - generateClassOrGlobalLink(*g_code,yytext); - // codify(yytext); - } - - ":" { - codify(yytext); - - // Assume this will - // be a one-line suite; - // found counter-example - // in SuiteStart. - - // Push a class scope - - ClassDef *classDefToAdd = createClassDef("<code>",1,1,g_curClassName,ClassDef::Class,0,0,FALSE); - g_codeClassSDict.append(g_curClassName,classDefToAdd); - char *s=g_curClassBases.first(); - while (s) - { - const ClassDef *baseDefToAdd=g_codeClassSDict[s]; - - // Try to find class in global - // scope - if (baseDefToAdd==0) - { - baseDefToAdd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s); - } - - if (baseDefToAdd && baseDefToAdd!=classDefToAdd) - { - classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal); - } - - s=g_curClassBases.next(); - } - - // Reset class-parsing variables. - g_curClassName.resize(0); - g_curClassBases.clear(); - - g_noSuiteFound = TRUE; - BEGIN( SuiteStart ); - } + codify(yyscanner,symName); } -<FunctionDec>{ - {IDENTIFIER} { - generateFunctionLink(*g_code,yytext); - } +//------------------------------------------------------------------------------- - {B}"(" { - codify(yytext); - BEGIN( FunctionParams ); - } -} - -<FunctionParams>{ - ({BB}|",") { - // Parses delimiters - codify(yytext); - } - - ({IDENTIFIER}|{PARAMNONEMPTY}+) { - codify(yytext); - } - - ")" { - codify(yytext); - } - - "\n" { - codifyLines(yytext); - } - - ":" { - codify(yytext); - - // Assume this will - // be a one-line suite; - // found counter-example - // in SuiteStart. - g_noSuiteFound = TRUE; - BEGIN( SuiteStart ); - } -} - -<Body,Suite>{ - - {KEYWORD} { - // Position-sensitive rules! - // Must come AFTER keyword-triggered rules - // Must come BEFORE identifier NONEMPTY-like rules - // to syntax highlight. - - startFontClass("keyword"); - codify(yytext); - endFontClass(); - } - - {FLOWKW} { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) - { - g_currentMemberDef->incrementFlowKeyWordCount(); - } - startFontClass("keywordflow"); - codify(yytext); - endFontClass(); - } - ({IDENTIFIER}".")*{IDENTIFIER}/"(" { - generateClassOrGlobalLink(*g_code,yytext); - } - ({IDENTIFIER}".")+{IDENTIFIER} { - generateClassOrGlobalLink(*g_code,yytext,TRUE); - } - {IDENTIFIER} { codify(yytext); } - -} - - - -<SuiteStart>{ - - {BB} { - codify(yytext); - } - "pass" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - BEGIN(Body); - } - {KEYWORD} { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - - // No indentation necessary - g_noSuiteFound = FALSE; - } - - {FLOWKW} { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) - { - g_currentMemberDef->incrementFlowKeyWordCount(); - } - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - - // No indentation necessary - g_noSuiteFound = FALSE; - } - {IDENTIFIER} { - codify(yytext); - } - - - {POUNDCOMMENT} { - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - yy_push_state(YY_START); - BEGIN(DocBlock); - g_docBlock=yytext; - } - - {NEWLINE} { - codifyLines(yytext); - if ( g_noSuiteFound ) - { - // printf("New suite to capture! [%d]\n", g_yyLineNr); - BEGIN ( SuiteCaptureIndent ); - } - } -} - -<SuiteCaptureIndent>{ - "\n"|({BB}"\n") { - // Blankline - ignore, keep looking for indentation. - codifyLines(yytext); - } - - {BB} { - // This state lasts momentarily, - // to check the indentation - // level that is about to be - // used. - codifyLines(yytext); - g_indents.push(static_cast<int>(yyleng)); - // printf("Captured indent of %d [line %d]\n", yyleng, g_yyLineNr); - BEGIN( Suite ); - } -} - -<SuiteMaintain>{ - - {BB}/({NONEMPTY}|{EXPCHAR}) { - // This implements poor - // indentation-tracking; - // should be improved. - // (translate tabs to space, etc) - codifyLines(yytext); - adjustScopesAndSuites(static_cast<int>(yyleng)); - } - - "\n"|({BB}"\n") { - // If this ever succeeds, - // it means that this is - // a blank line, and - // can be ignored. - codifyLines(yytext); - } - - ""/({NONEMPTY}|{EXPCHAR}) { - // Default rule; matches - // the empty string, assuming - // real text starts here. - // Just go straight to Body. - adjustScopesAndSuites(0); - } -} - - -<Suite>{NEWLINE} { - codifyLines(yytext); - BEGIN( SuiteMaintain ); - } -<Body>{IDENTIFIER} { - codify(yytext); - } -<Body>{NEWLINE} { - codifyLines(yytext); - } - -<SingleQuoteString>{ // Single quoted string like 'That\'s a """nice""" string!' - \\{B}\n { // line continuation - codifyLines(yytext); - } - \\. { // escaped char - codify(yytext); - } - {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple double quotes - codify(yytext); - } - "'" { // end of the string - codify(yytext); - endFontClass(); - BEGIN(g_stringContext); - } - [^"'\n\\]+ { // normal chars - codify(yytext); - } - . { // normal char - codify(yytext); - } -} - -<DoubleQuoteString>{ // Double quoted string like "That's \"a '''nice'''\" string!" - \\{B}\n { // line continuation - codifyLines(yytext); - } - \\. { // escaped char - codify(yytext); - } - {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes - codify(yytext); - } - "\"" { // end of the string - codify(yytext); - endFontClass(); - BEGIN(g_stringContext); - } - [^"'\n\\]+ { // normal chars - codify(yytext); - } - . { // normal char - codify(yytext); - } -} +struct PythonCodeParser::Private +{ + yyscan_t yyscanner; + pycodeYY_state state; +}; -<TripleString>{ - {TRIDOUBLEQUOTE} | - {TRISINGLEQUOTE} { - codify(yytext); - if (g_doubleQuote==(yytext[0]=='"')) - { - endFontClass(); - BEGIN(g_stringContext); - } - } - {LONGSTRINGBLOCK} { - codifyLines(yytext); - } - \n { - codifyLines(yytext); - } - . { - codify(yytext); - } +PythonCodeParser::PythonCodeParser() : p(std::make_unique<Private>()) +{ + pycodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + pycodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); } - /* -<*>({NONEMPTY}|{EXPCHAR}|{BB}) { // This should go one character at a time. - codify(yytext); - // printf("[pycode] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, g_yyLineNr); - - //endFontClass(); - BEGIN(Body); - } - */ - -<*>{STRINGPREFIX}?{TRISINGLEQUOTE} { - if (YY_START==SingleQuoteString) REJECT; - startFontClass("stringliteral"); - g_stringContext=YY_START; - g_doubleQuote=yytext[yyleng-1]=='"'; - codify(yytext); - BEGIN(TripleString); - } -<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} { - if (YY_START==DoubleQuoteString) REJECT; - startFontClass("stringliteral"); - g_stringContext=YY_START; - g_doubleQuote=yytext[yyleng-1]=='"'; - codify(yytext); - BEGIN(TripleString); - } -<*>{STRINGPREFIX}?"'" { // single quoted string - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - startFontClass("stringliteral"); - g_stringContext=YY_START; - codify(yytext); - BEGIN(SingleQuoteString); - } -<*>{STRINGPREFIX}?"\"" { // double quoted string - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - startFontClass("stringliteral"); - g_stringContext=YY_START; - codify(yytext); - BEGIN(DoubleQuoteString); - } -<DocBlock>.* { // contents of current comment line - g_docBlock+=yytext; - } -<DocBlock>"\n"{B}("#") { // comment block (next line is also comment line) - g_docBlock+=yytext; - } -<DocBlock>{NEWLINE} { // comment block ends at the end of this line - // remove special comment (default config) - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - g_yyLineNr+=((QCString)g_docBlock).contains('\n'); - g_endComment=TRUE; - } - else // do not remove comment - { - startFontClass("comment"); - codifyLines(g_docBlock); - endFontClass(); - } - unput(*yytext); - yy_pop_state(); - } -<*>{POUNDCOMMENT}.* { - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - yy_push_state(YY_START); - BEGIN(DocBlock); - g_docBlock=yytext; - } -<*>"#".* { // normal comment - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } -<*>{NEWLINE} { - if (g_endComment) - { - g_endComment=FALSE; - } - else - { - codifyLines(yytext); - } - //printf("[pycode] %d NEWLINE [line %d] no match\n", - // YY_START, g_yyLineNr); - - //endFontClass(); - BEGIN(Body); - } - -<*>[ \t]+ { - codify(yytext); - BEGIN(Body); - } -<*>. { - codify(yytext); - // printf("[pycode] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, g_yyLineNr); - - //endFontClass(); - BEGIN(Body); - } - -<*><<EOF>> { - if (YY_START == DocBlock) { - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass("comment"); - codifyLines(g_docBlock); - endFontClass(); - } - } - yyterminate(); - } -%% - -/*@ ---------------------------------------------------------------------------- - */ - -void resetPythonCodeParserState() +PythonCodeParser::~PythonCodeParser() { - g_codeClassSDict.setAutoDelete(TRUE); - g_codeClassSDict.clear(); - g_currentDefinition = 0; - g_currentMemberDef = 0; - g_doubleStringIsDoc = FALSE; - g_paramParens = 0; - g_indents.clear(); - BEGIN( Body ); + pycodeYYlex_destroy(p->yyscanner); } -/*! - Examines current stack of white-space indentations; - re-syncs the parser with the correct scope. -*/ -static void adjustScopesAndSuites(unsigned indentLength) +void PythonCodeParser::resetCodeParserState() { - // States to pop - if (!g_indents.isEmpty() && indentLength < g_indents.top()) - { - while (!g_indents.isEmpty() && indentLength < g_indents.top()) - { - // printf("Exited scope indent of [%d]\n", g_indents.top()); - g_indents.pop(); // Pop the old suite's indentation - - g_currentMemberDef=0; - if (g_currentDefinition) - g_currentDefinition=g_currentDefinition->getOuterScope(); - } - } - - // Are there any remaining indentation levels for suites? - if (!g_indents.isEmpty()) - { - BEGIN( Suite ); - } - else - { - BEGIN( Body ); - } + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->codeClassMap.clear(); + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->doubleStringIsDoc = FALSE; + yyextra->paramParens = 0; + while (!yyextra->indents.empty()) yyextra->indents.pop(); + BEGIN( Body ); } -void parsePythonCode(CodeOutputInterface &od,const char * /*className*/, - const QCString &s,bool exBlock, const char *exName, - FileDef *fd,int startLine,int endLine,bool inlineFragment, - const MemberDef *,bool,const Definition *searchCtx,bool collectXRefs) +void PythonCodeParser::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 + ) { + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("***parseCode()\n"); - - //-------------------------------------- - if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - g_codeClassSDict.setAutoDelete(TRUE); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx=searchCtx; - g_collectXRefs=collectXRefs; + + if (input.isEmpty()) return; + printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + yyextra->searchCtx=searchCtx; + yyextra->collectXRefs=collectXRefs; if (startLine!=-1) - g_yyLineNr = startLine; + yyextra->yyLineNr = startLine; else - g_yyLineNr = 1; + yyextra->yyLineNr = 1; if (endLine!=-1) - g_inputLines = endLine+1; + yyextra->inputLines = endLine+1; else - g_inputLines = g_yyLineNr + countLines() - 1; - - - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + yyextra->symbolResolver.setFileScope(fileDef); bool cleanupSourceDef = FALSE; - if (exBlock && fd==0) + if (yyextra->exampleBlock && fileDef==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",(exName?exName:"generated")); + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); cleanupSourceDef = TRUE; } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_includeCodeFragment = inlineFragment; - // Starts line 1 on the output - startCodeLine(); + yyextra->includeCodeFragment = inlineFragment; + // Starts line 1 on the output + startCodeLine(yyscanner); - pycodeYYrestart( pycodeYYin ); + pycodeYYrestart(0,yyscanner); - pycodeYYlex(); + pycodeYYlex(yyscanner); - if (!g_indents.isEmpty()) + if (!yyextra->indents.empty()) { // printf("Exited pysourceparser in inconsistent state!\n"); } - if (g_needsTermination) + if (yyextra->needsTermination) { - endCodeLine(); + endCodeLine(yyscanner); } if (cleanupSourceDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - return; -} - -//---------------------------------------------------------------------------- - -void PythonCodeParser::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 - ) -{ - ::parsePythonCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); -} - -void PythonCodeParser::resetCodeParserState() -{ - ::resetPythonCodeParserState(); + // write the tooltips + TooltipManager::instance().writeTooltips(codeOutIntf); + printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } #if USE_STATE2STRING diff --git a/src/pyscanner.l b/src/pyscanner.l index d7996b4..4a9552e 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -113,6 +113,7 @@ struct pyscannerYY_state int search_count = 0; QCString argType; bool funcParamsEnd = FALSE; + std::vector<QCString> decorators; }; //----------------------------------------------------------------------------- @@ -175,6 +176,7 @@ NONEMPTYEXP [^ \t\n:] PARAMNONEMPTY [^ \t\n():] IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* SCOPE {IDENTIFIER}("."{IDENTIFIER})* +CALL "("[^)]*")" BORDER ([^A-Za-z0-9]) TRISINGLEQUOTE {STRINGPREFIX}?"'''"(!)? @@ -335,6 +337,8 @@ STARTDOCSYMS "##" "@staticmethod" { yyextra->stat=TRUE; } + "@"{SCOPE}{CALL}? { // decorator + } {SCRIPTCOMMENT} { // Unix type script comment if (yyextra->yyLineNr != 1) REJECT; } @@ -651,6 +655,7 @@ STARTDOCSYMS "##" {B}":"{B} { // function without arguments yyextra->specialBlock = TRUE; // expecting a docstring yyextra->bodyEntry = yyextra->current; + yyextra->current->bodyLine = yyextra->yyLineNr; BEGIN(FunctionBody); } @@ -1322,7 +1327,6 @@ STARTDOCSYMS "##" \n/{B}"#" { // continuation of the comment on the next line yyextra->docBlock+='\n'; yyextra->docBrief = FALSE; - startCommentBlock(yyscanner,FALSE); incLineNr(yyscanner); } [^#\n]+ { // any other stuff @@ -1426,7 +1430,7 @@ STARTDOCSYMS "##" } <*>"'" { - fprintf(stderr,"Quote: %d\n",YY_START); + //fprintf(stderr,"Quote: %d\n",YY_START); } <*>. { @@ -1626,7 +1630,7 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief } int position = 0; - bool needsEntry; + bool needsEntry = false; 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; @@ -1711,7 +1715,7 @@ static void initSpecialBlock(yyscan_t yyscanner) yyextra->docBrief = TRUE; yyextra->docBlock.resize(0); yyextra->commentIndent = yyextra->curIndent; - startCommentBlock(yyscanner,TRUE); + startCommentBlock(yyscanner,FALSE); } static void searchFoundDef(yyscan_t yyscanner) @@ -1757,8 +1761,8 @@ static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt) std::shared_ptr<Entry> ce = rt->children()[i]; if (!ce->program.isEmpty()) { - //printf("-- %s ---------\n%s\n---------------\n", - // ce->name.data(),ce->program.data()); + //fprintf(stderr,"parseCompounds: -- %s (line %d) ---------\n%s\n---------------\n", + // ce->name.data(), ce->bodyLine, ce->program.data()); // init scanner state yyextra->inputString = ce->program; yyextra->inputPosition = 0; diff --git a/src/reflist.cpp b/src/reflist.cpp index 0aaa75f..5840138 100644 --- a/src/reflist.cpp +++ b/src/reflist.cpp @@ -60,7 +60,7 @@ void RefList::generatePage() std::sort(m_entries.begin(),m_entries.end(), [](std::unique_ptr<RefItem> &left,std::unique_ptr<RefItem> &right) - { return qstricmp(left->title(),left->title()); }); + { return qstricmp(left->title(),right->title()) < 0; }); //RefItem *item; QCString doc; int cnt = 0; @@ -124,6 +124,6 @@ void RefList::generatePage() //printf("generatePage('%s')\n",doc.data()); if (cnt>0) { - addRelatedPage(m_listName,m_pageTitle,doc,m_fileName,1,RefItemVector(),0,0,TRUE); + addRelatedPage(m_listName,m_pageTitle,doc,m_fileName,1,1,RefItemVector(),0,0,TRUE); } } diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index fbe7cc1..2bd2c29 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -306,9 +306,8 @@ void RTFDocVisitor::visit(DocVerbatim *s) m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); //m_t << "\\par" << endl; m_t << "}" << endl; break; @@ -433,8 +432,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << rtf_Style_Reset << getStyle("CodeExample"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -455,8 +453,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(),langExt,inc->isExample(), inc->exampleFile(), 0, // fileDef @@ -492,8 +489,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; if (!m_lastIsPara) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -509,8 +505,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; if (!m_lastIsPara) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -567,8 +562,7 @@ void RTFDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef op->line(), // startLine diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 9d0a957..a8aa898 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -48,8 +48,6 @@ #include "filename.h" #include "namespacedef.h" -static bool DoxyCodeLineOpen = FALSE; - //#define DBG_RTF(x) x; #define DBG_RTF(x) @@ -63,16 +61,23 @@ static QCString dateToRTFDateString() return result; } -RTFGenerator::RTFGenerator() : OutputGenerator() +RTFGenerator::RTFGenerator() : OutputGenerator(Config_getString(RTF_OUTPUT)) { - m_dir=Config_getString(RTF_OUTPUT); - m_col=0; - //insideTabbing=FALSE; - m_listLevel = 0; - m_bstartedBody = FALSE; - m_omitParagraph = FALSE; - m_numCols = 0; - m_prettyCode=Config_getBool(RTF_SOURCE_CODE); +} + +RTFGenerator::RTFGenerator(const RTFGenerator &og) : OutputGenerator(og) +{ +} + +RTFGenerator &RTFGenerator::operator=(const RTFGenerator &og) +{ + OutputGenerator::operator=(og); + return *this; +} + +std::unique_ptr<OutputGenerator> RTFGenerator::clone() const +{ + return std::make_unique<RTFGenerator>(*this); } RTFGenerator::~RTFGenerator() @@ -367,7 +372,7 @@ void RTFGenerator::beginRTFSection() t << rtf_Style["Heading2"]->reference() << "\n"; } -void RTFGenerator::startFile(const char *name,const char *,const char *) +void RTFGenerator::startFile(const char *name,const char *,const char *,int) { //setEncoding(QCString().sprintf("CP%s",theTranslator->trRTFansicp())); QCString fileName=name; @@ -468,13 +473,12 @@ void RTFGenerator::startIndexSection(IndexSections is) //Module Documentation GroupSDict::Iterator gli(*Doxygen::groupSDict); GroupDef *gd; - bool found=FALSE; - for (gli.toFirst();(gd=gli.current()) && !found;++gli) + for (gli.toFirst();(gd=gli.current());++gli) { if (!gd->isReference()) { beginRTFChapter(); - found=TRUE; + break; } } } @@ -484,13 +488,12 @@ void RTFGenerator::startIndexSection(IndexSections is) //Directory Documentation SDict<DirDef>::Iterator dli(*Doxygen::directories); DirDef *dd; - bool found=FALSE; - for (dli.toFirst();(dd=dli.current()) && !found;++dli) + for (dli.toFirst();(dd=dli.current());++dli) { if (dd->isLinkableInProject()) { beginRTFChapter(); - found=TRUE; + break; } } } @@ -498,15 +501,12 @@ void RTFGenerator::startIndexSection(IndexSections is) case isNamespaceDocumentation: { // Namespace Documentation - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - bool found=FALSE; - for (nli.toFirst();(nd=nli.current()) && !found;++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { if (nd->isLinkableInProject()) { beginRTFChapter(); - found=TRUE; + break; } } } @@ -514,18 +514,16 @@ void RTFGenerator::startIndexSection(IndexSections is) case isClassDocumentation: { //Compound Documentation - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - bool found=FALSE; - for (cli.toFirst();(cd=cli.current()) && !found;++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { beginRTFChapter(); - found=TRUE; + break; } } } @@ -548,6 +546,10 @@ void RTFGenerator::startIndexSection(IndexSections is) } } } + if (!isFirst) + { + break; + } } } break; @@ -577,8 +579,8 @@ void RTFGenerator::endIndexSection(IndexSections is) { bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); - static QCString projectName = Config_getString(PROJECT_NAME); + bool sourceBrowser = Config_getBool(SOURCE_BROWSER); + QCString projectName = Config_getString(PROJECT_NAME); switch (is) { @@ -623,7 +625,7 @@ void RTFGenerator::endIndexSection(IndexSections is) { DocText *root = validatingParseText(projectName); t << "{\\field\\fldedit {\\*\\fldinst TITLE \\\\*MERGEFORMAT}{\\fldrslt "; - writeDoc(root,0,0); + writeDoc(root,0,0,0); t << "}}\\par" << endl; } @@ -773,39 +775,27 @@ void RTFGenerator::endIndexSection(IndexSections is) break; case isNamespaceDocumentation: { - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - bool found=FALSE; - for (nli.toFirst();(nd=nli.current()) && !found;++nli) + bool first=true; + for (const auto &nd : *Doxygen::namespaceLinkedMap) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "\\par " << rtf_Style_Reset << endl; - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - t << nd->getOutputFileBase(); - t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; - found=TRUE; - } - } - while ((nd=nli.current())) - { - if (nd->isLinkableInProject()) - { - t << "\\par " << rtf_Style_Reset << endl; - beginRTFSection(); + if (!first) + { + beginRTFSection(); + } + first=false; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << nd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } - ++nli; } } break; case isClassDocumentation: { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; - bool found=FALSE; + bool first=true; if (fortranOpt) { t << "{\\tc \\v " << theTranslator->trTypeDocumentation() << "}"<< endl; @@ -814,29 +804,20 @@ void RTFGenerator::endIndexSection(IndexSections is) { t << "{\\tc \\v " << theTranslator->trClassDocumentation() << "}"<< endl; } - for (cli.toFirst();(cd=cli.current()) && !found;++cli) - { - if (cd->isLinkableInProject() && - cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() - ) - { - t << "\\par " << rtf_Style_Reset << endl; - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - t << cd->getOutputFileBase(); - t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; - found=TRUE; - } - } - for (;(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << "\\par " << rtf_Style_Reset << endl; - beginRTFSection(); + if (!first) + { + beginRTFSection(); + } + first=false; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << cd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; @@ -855,31 +836,19 @@ void RTFGenerator::endIndexSection(IndexSections is) { if (fd->isLinkableInProject()) { - if (isFirst) + t << "\\par " << rtf_Style_Reset << endl; + if (!isFirst) { - t << "\\par " << rtf_Style_Reset << endl; - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - t << fd->getOutputFileBase(); - t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; - if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) - { - t << "\\par " << rtf_Style_Reset << endl; - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"" << fd->getSourceFileBase() << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; - } - isFirst=FALSE; + beginRTFSection(); } - else + isFirst=FALSE; + t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; + t << fd->getOutputFileBase(); + t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; + if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) { t << "\\par " << rtf_Style_Reset << endl; - beginRTFSection(); - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - t << fd->getOutputFileBase(); - t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; - if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) - { - t << "\\par " << rtf_Style_Reset << endl; - t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"" << fd->getSourceFileBase() << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; - } + t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"" << fd->getSourceFileBase() << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } } } @@ -1872,7 +1841,7 @@ void RTFGenerator::endClassDiagram(const ClassDiagram &d, newParagraph(); // create a png file - d.writeImage(t,m_dir,m_relPath,fileName,FALSE); + d.writeImage(t,dir(),m_relPath,fileName,FALSE); // display the file t << "{" << endl; @@ -1928,22 +1897,15 @@ void RTFGenerator::writeRTFReference(const char *label) t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}"; } -void RTFGenerator::startCodeFragment() +void RTFGenerator::startCodeFragment(const char *) { DBG_RTF(t << "{\\comment (startCodeFragment) }" << endl) t << "{" << endl; - //newParagraph(); t << rtf_Style_Reset << rtf_Code_DepthStyle(); - //styleStack.push(rtf_Style_CodeExample); } -void RTFGenerator::endCodeFragment() +void RTFGenerator::endCodeFragment(const char *) { - //newParagraph(); - //styleStack.pop(); - //printf("RTFGenerator::endCodeFragment() top=%s\n",styleStack.top()); - //t << rtf_Style_Reset << styleStack.top() << endl; - //endCodeLine checks is there is still an open code line, if so closes it. endCodeLine(); DBG_RTF(t << "{\\comment (endCodeFragment) }" << endl) @@ -2500,7 +2462,7 @@ void RTFGenerator::endDotGraph(DotClassGraph &g) newParagraph(); QCString fn = - g.writeGraph(t,GOF_BITMAP,EOF_Rtf,Config_getString(RTF_OUTPUT),m_fileName,m_relPath,TRUE,FALSE); + g.writeGraph(t,GOF_BITMAP,EOF_Rtf,dir(),fileName(),m_relPath,TRUE,FALSE); // display the file t << "{" << endl; @@ -2523,8 +2485,7 @@ void RTFGenerator::endInclDepGraph(DotInclDepGraph &g) { newParagraph(); - QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_Rtf,Config_getString(RTF_OUTPUT), - m_fileName,m_relPath,FALSE); + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_Rtf,dir(),fileName(),m_relPath,FALSE); // display the file t << "{" << endl; @@ -2554,8 +2515,7 @@ void RTFGenerator::endCallGraph(DotCallGraph &g) { newParagraph(); - QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_Rtf,Config_getString(RTF_OUTPUT), - m_fileName,m_relPath,FALSE); + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_Rtf,dir(),fileName(),m_relPath,FALSE); // display the file t << "{" << endl; @@ -2577,8 +2537,7 @@ void RTFGenerator::endDirDepGraph(DotDirDeps &g) { newParagraph(); - QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_Rtf,Config_getString(RTF_OUTPUT), - m_fileName,m_relPath,FALSE); + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_Rtf,dir(),fileName(),m_relPath,FALSE); // display the file t << "{" << endl; @@ -2801,7 +2760,7 @@ void RTFGenerator::exceptionEntry(const char* prefix,bool closeBracket) t << " "; } -void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int) { RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); @@ -3037,9 +2996,9 @@ void RTFGenerator::endInlineMemberDoc() void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l) { - static bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS); + bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS); - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = true; QCString lineNumber; lineNumber.sprintf("%05d",l); if (m_prettyCode) @@ -3066,13 +3025,13 @@ void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const ch } void RTFGenerator::startCodeLine(bool) { - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = true; m_col=0; } void RTFGenerator::endCodeLine() { - if (DoxyCodeLineOpen) lineBreak(); - DoxyCodeLineOpen = FALSE; + if (m_doxyCodeLineOpen) lineBreak(); + m_doxyCodeLineOpen = false; } void RTFGenerator::startLabels() diff --git a/src/rtfgen.h b/src/rtfgen.h index 9330b13..0aebd15 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 by Parker Waechter & 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,7 @@ #ifndef RTFGEN_H #define RTFGEN_H +#include "config.h" #include "outputgen.h" class QFile; @@ -27,31 +28,28 @@ class RTFGenerator : public OutputGenerator { public: RTFGenerator(); - ~RTFGenerator(); + RTFGenerator(const RTFGenerator &); + RTFGenerator &operator=(const RTFGenerator &); + virtual ~RTFGenerator(); + virtual std::unique_ptr<OutputGenerator> clone() const; + static void init(); static void writeStyleSheetFile(QFile &f); static void writeExtensionsFile(QFile &file); + OutputType type() const { return RTF; } 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; } - void enableIf(OutputType o) { if (o==RTF) enable(); } - void disableIf(OutputType o) { if (o==RTF) disable(); } - void disableIfNot(OutputType o) { if (o!=RTF) disable(); } - bool isEnabled(OutputType o) { return (o==RTF && m_active); } - OutputGenerator *get(OutputType o) { return (o==RTF) ? this : 0; } - void writeDoc(DocNode *,const Definition *,const MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *,int); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int id); void writeSearchInfo() {} void writeFooter(const char *) {} void endFile(); void clearBuffer(); //void postProcess(QByteArray &); - + void startIndexSection(IndexSections); void endIndexSection(IndexSections); void writePageLink(const char *,bool); @@ -61,7 +59,7 @@ class RTFGenerator : public OutputGenerator void startTitleHead(const char *); void startTitle(); void endTitleHead(const char *,const char *name); - void endTitle() {} + void endTitle() {} void newParagraph(); void startParagraph(const char *classDef); @@ -102,13 +100,13 @@ class RTFGenerator : public OutputGenerator void endItemListItem(); void startMemberSections() {} - void endMemberSections() {} + void endMemberSections() {} void startHeaderSection() {} void endHeaderSection() {} void startMemberHeader(const char *,int) { startGroupHeader(FALSE); } void endMemberHeader() { endGroupHeader(FALSE); } - void startMemberSubtitle(); - void endMemberSubtitle(); + void startMemberSubtitle(); + void endMemberSubtitle(); void startMemberDocList() {} void endMemberDocList() {} void startMemberList(); @@ -125,10 +123,10 @@ class RTFGenerator : public OutputGenerator void insertMemberAlignLeft(int,bool){} void writeRuler() { rtfwriteRuler_thin(); } - + void writeAnchor(const char *fileName,const char *name); - void startCodeFragment(); - void endCodeFragment(); + void startCodeFragment(const char *style); + void endCodeFragment(const char *style); void writeLineNumber(const char *,const char *,const char *,int l); void startCodeLine(bool); void endCodeLine(); @@ -147,7 +145,7 @@ class RTFGenerator : public OutputGenerator void endDoxyAnchor(const char *,const char *); void writeChar(char c); void writeLatexSpacing() {};//{ t << "\\hspace{0.3cm}"; } - void writeStartAnnoItem(const char *type,const char *file, + void writeStartAnnoItem(const char *type,const char *file, const char *path,const char *name); void writeEndAnnoItem(const char *name); void startSubsection(); @@ -161,7 +159,7 @@ class RTFGenerator : public OutputGenerator void startMemberDescription(const char *,const char *,bool); void endMemberDescription(); - void startMemberDeclaration() {} + void startMemberDeclaration() {} void endMemberDeclaration(const char *,const char *) {} void writeInheritedSectionTitle(const char *,const char *,const char *, const char *,const char *,const char *) {} @@ -193,7 +191,7 @@ class RTFGenerator : public OutputGenerator void startContents() {} void endContents() {} void writeNonBreakableSpace(int); - + void startDescTable(const char *title); void endDescTable(); void startDescTableRow(); @@ -202,7 +200,7 @@ class RTFGenerator : public OutputGenerator void endDescTableTitle(); void startDescTableData(); void endDescTableData(); - + void startDotGraph(); void endDotGraph(DotClassGraph &); void startInclDepGraph(); @@ -221,7 +219,7 @@ class RTFGenerator : public OutputGenerator void endMemberGroupDocs(); void startMemberGroup(); void endMemberGroup(bool); - + void startTextBlock(bool dense); void endTextBlock(bool); void lastIndexPage(); @@ -268,11 +266,8 @@ class RTFGenerator : public OutputGenerator void addWord(const char *,bool) {} static bool preProcessFileInplace(const char *path,const char *name); - - private: - RTFGenerator(const RTFGenerator &); - RTFGenerator &operator=(const RTFGenerator &); + private: const char *rtf_BList_DepthStyle(); const char *rtf_CList_DepthStyle(); const char *rtf_EList_DepthStyle(); @@ -281,16 +276,6 @@ class RTFGenerator : public OutputGenerator const char *rtf_Code_DepthStyle(); void incrementIndentLevel(); void decrementIndentLevel(); - QCString m_sourceFileName; - int m_col; - bool m_prettyCode; - - bool m_bstartedBody; // has startbody been called yet? - int m_listLevel; // // RTF does not really have a additive indent...manually set list level. - bool m_omitParagraph; // should a the next paragraph command be ignored? - int m_numCols; // number of columns in a table - QCString m_relPath; - void beginRTFDocument(); void beginRTFChapter(); void beginRTFSection(); @@ -299,7 +284,16 @@ class RTFGenerator : public OutputGenerator void rtfwriteRuler_thick(); void rtfwriteRuler_thin(); void writeRTFReference(const char *label); - //char *getMultiByte(int c); + + QCString m_sourceFileName; + int m_col = 0; + bool m_prettyCode = Config_getBool(RTF_SOURCE_CODE); + bool m_bstartedBody = false; // has startbody been called yet? + int m_listLevel = 0; // // RTF does not really have a additive indent...manually set list level. + bool m_omitParagraph = false; // should a the next paragraph command be ignored? + int m_numCols = 0; // number of columns in a table + QCString m_relPath; + bool m_doxyCodeLineOpen = false; }; #endif diff --git a/src/scanner.l b/src/scanner.l index 7c710fa..66437bc 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -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,7 +25,7 @@ %{ /* - * includes + * includes */ #include <algorithm> @@ -60,6 +60,9 @@ #define USE_STATE2STRING 0 +static AtomicInt anonCount; +static AtomicInt anonNSCount; + struct scannerYY_state { OutlineParserInterface *thisParser; @@ -105,8 +108,6 @@ struct scannerYY_state int yyBegLineNr = 1 ; int yyColNr = 1 ; int yyBegColNr = 1 ; - int anonCount = 0 ; - int anonNSCount = 0 ; QCString yyFileName; MethodTypes mtype = Method; bool stat = false; @@ -226,15 +227,15 @@ 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(yyscanner,buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} /* start command character */ -CMD ("\\"|"@") +CMD ("\\"|"@") BN [ \t\n\r] -BL [ \t\r]*"\n" +BL [ \t\r]*"\n" B [ \t] ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID}) @@ -243,7 +244,7 @@ CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID}) PRE [pP][rR][eE] CODE [cC][oO][dD][eE] CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) -PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;] +PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;] PHPUSEKW ("public"|"private"|"protected") IDLATTR ("["[^\]]*"]"){BN}* TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) @@ -261,138 +262,139 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) %x AlignAs %x AlignAsEnd -%x Define -%x DefineEnd -%x CompoundName -%x ClassVar -%x CSConstraintName -%x CSConstraintType -%x CSIndexer -%x ClassCategory -%x ClassTemplSpec +%x Define +%x DefineEnd +%x CompoundName +%x ClassVar +%x CSConstraintName +%x CSConstraintType +%x CSIndexer +%x ClassCategory +%x ClassTemplSpec %x CliPropertyType %x CliPropertyIndex %x CliOverride -%x Bases -%x BasesProt -%x NextSemi -%x BitFields -%x EnumBaseType -%x FindMembers -%x FindMembersPHP -%x FindMemberName +%x Bases +%x BasesProt +%x NextSemi +%x BitFields +%x EnumBaseType +%x FindMembers +%x FindMembersPHP +%x FindMemberName %x FindFields %x FindFieldArg -%x Function -%x FuncRound -%x ExcpRound -%x ExcpList -%x FuncQual +%x Function +%x FuncRound +%x ExcpRound +%x ExcpList +%x FuncQual %x TrailingReturn -%x Operator -%x Array -%x ReadBody -%x ReadNSBody -%x ReadBodyIntf -%x Using -%x UsingAlias -%x UsingAliasEnd -%x UsingDirective -%x SkipCurly -%x SkipCurlyCpp -%x SkipCurlyEndDoc +%x Operator +%x Array +%x ReadBody +%x ReadNSBody +%x ReadBodyIntf +%x Using +%x UsingAlias +%x UsingAliasEnd +%x UsingDirective +%x SkipCurly +%x SkipCurlyCpp +%x SkipCurlyEndDoc %x SkipString %x SkipPHPString -%x SkipInits -%x SkipC11Inits +%x SkipInits +%x SkipC11Inits %x SkipC11Attribute -%x SkipCPP -%x SkipCPPBlock -%x SkipComment -%x SkipCxxComment +%x SkipCPP +%x SkipCPPBlock +%x SkipComment +%x SkipCxxComment %x SkipCurlyBlock %x SkipRoundBlock -%x Sharp -%x SkipRound -%x SkipSquare -%x SkipRemainder +%x Sharp +%x SkipRound +%x SkipSquare +%x SkipRemainder %x StaticAssert %x DeclType -%x TypedefName -%x TryFunctionBlock -%x TryFunctionBlockEnd -%x Comment -%x PackageName -%x JavaImport -%x PHPUse -%x PHPUseAs -%x CSAccessorDecl -%x CSGeneric -%x PreLineCtrl -%x DefinePHP -%x DefinePHPEnd -%x OldStyleArgs -%x SkipVerbString +%x TypedefName +%x TryFunctionBlock +%x TryFunctionBlockEnd +%x Comment +%x PackageName +%x JavaImport +%x PHPUse +%x PHPUseAs +%x CSAccessorDecl +%x CSGeneric +%x PreLineCtrl +%x DefinePHP +%x DefinePHPEnd +%x OldStyleArgs +%x SkipVerbString %x ObjCMethod %x ObjCReturnType %x ObjCParams %x ObjCParamType %x ObjCProtocolList -%x ObjCPropAttr -%x ObjCSkipStatement -%x QtPropType -%x QtPropName -%x QtPropAttr -%x QtPropRead -%x QtPropWrite -%x ReadInitializer -%x UNOIDLAttributeBlock -%x GetCallType -%x CppQuote -%x EndCppQuote +%x ObjCPropAttr +%x ObjCSkipStatement +%x QtPropType +%x QtPropName +%x QtPropAttr +%x QtPropRead +%x QtPropWrite +%x ReadInitializer +%x ReadInitializerPtr +%x UNOIDLAttributeBlock +%x GetCallType +%x CppQuote +%x EndCppQuote %x MemberSpec %x MemberSpecSkip -%x EndTemplate -%x FuncPtr -%x FuncPtrOperator -%x EndFuncPtr -%x ReadFuncArgType -%x ReadTempArgs -%x IDLUnionCase -%x NSAliasName -%x NSAliasArg -%x CopyString -%x CopyPHPString -%x CopyGString -%x CopyPHPGString -%x CopyRound -%x CopyCurly -%x GCopyRound -%x GCopySquare -%x GCopyCurly -%x SkipUnionSwitch -%x Specialization -%x SpecializationSingleQuote -%x SpecializationDoubleQuote -%x FuncPtrInit -%x FuncFunc -%x FuncFuncEnd -%x FuncFuncType -%x FuncFuncArray +%x EndTemplate +%x FuncPtr +%x FuncPtrOperator +%x EndFuncPtr +%x ReadFuncArgType +%x ReadTempArgs +%x IDLUnionCase +%x NSAliasName +%x NSAliasArg +%x CopyString +%x CopyPHPString +%x CopyGString +%x CopyPHPGString +%x CopyRound +%x CopyCurly +%x GCopyRound +%x GCopySquare +%x GCopyCurly +%x SkipUnionSwitch +%x Specialization +%x SpecializationSingleQuote +%x SpecializationDoubleQuote +%x FuncPtrInit +%x FuncFunc +%x FuncFuncEnd +%x FuncFuncType +%x FuncFuncArray %x CopyArgString %x CopyArgPHPString -%x CopyArgRound -%x CopyArgSharp -%x CopyArgComment -%x CopyArgCommentLine -%x CopyArgVerbatim -%x HereDoc -%x HereDocEnd -%x CopyHereDoc -%x CopyHereDocEnd -%x RawString -%x RawGString -%x CSString +%x CopyArgRound +%x CopyArgSharp +%x CopyArgComment +%x CopyArgCommentLine +%x CopyArgVerbatim +%x HereDoc +%x HereDocEnd +%x CopyHereDoc +%x CopyHereDocEnd +%x RawString +%x RawGString +%x CSString %x IDLAttribute %x IDLProp @@ -417,421 +419,421 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /** comment parsing states */ -%x DocLine -%x DocBlock +%x DocLine +%x DocBlock %x DocCopyBlock %% -<NextSemi>"{" { - yyextra->curlyCount=0; - yyextra->needsSemi = TRUE; - BEGIN(SkipCurlyBlock); - } -<NextSemi>"(" { - yyextra->roundCount=0; - BEGIN(SkipRoundBlock); - } -<SkipRoundBlock>"(" { - ++yyextra->roundCount; - } -<SkipRoundBlock>")" { - if (yyextra->roundCount ) - --yyextra->roundCount ; - else - BEGIN( NextSemi ) ; - } -<SkipCurlyBlock>"{" { - ++yyextra->curlyCount ; - } -<SkipCurlyBlock>"}" { - if( yyextra->curlyCount ) - { - --yyextra->curlyCount ; - } - else if (yyextra->needsSemi) - { - BEGIN( NextSemi ); - } - else - { - BEGIN( FindMembers ); - } - } -<NextSemi>\' { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=NextSemi; - BEGIN(SkipPHPString); - } - } -<NextSemi>{CHARLIT} { if (yyextra->insidePHP) REJECT; } -<NextSemi>\" { - yyextra->lastStringContext=NextSemi; - BEGIN(SkipString); - } -<NextSemi>[;,] { - unput(*yytext); - BEGIN( FindMembers ); - } -<BitFields>[;,] { - unput(*yytext); - BEGIN( FindMembers ); - } +<NextSemi>"{" { + yyextra->curlyCount=0; + yyextra->needsSemi = TRUE; + BEGIN(SkipCurlyBlock); + } +<NextSemi>"(" { + yyextra->roundCount=0; + BEGIN(SkipRoundBlock); + } +<SkipRoundBlock>"(" { + ++yyextra->roundCount; + } +<SkipRoundBlock>")" { + if (yyextra->roundCount ) + --yyextra->roundCount ; + else + BEGIN( NextSemi ) ; + } +<SkipCurlyBlock>"{" { + ++yyextra->curlyCount ; + } +<SkipCurlyBlock>"}" { + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else if (yyextra->needsSemi) + { + BEGIN( NextSemi ); + } + else + { + BEGIN( FindMembers ); + } + } +<NextSemi>\' { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=NextSemi; + BEGIN(SkipPHPString); + } + } +<NextSemi>{CHARLIT} { if (yyextra->insidePHP) REJECT; } +<NextSemi>\" { + yyextra->lastStringContext=NextSemi; + BEGIN(SkipString); + } +<NextSemi>[;,] { + unput(*yytext); + BEGIN( FindMembers ); + } +<BitFields>[;,] { + unput(*yytext); + BEGIN( FindMembers ); + } <EnumBaseType>[{;,] { yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - unput(*yytext); - BEGIN( ClassVar ); + unput(*yytext); + BEGIN( ClassVar ); } -<FindMembers>"<?php" { // PHP code with unsupported extension? +<FindMembers>"<?php" { // PHP code with unsupported extension? yyextra->insidePHP = TRUE; - } + } <FindMembersPHP>"<?"("php"?) { // PHP code start BEGIN( FindMembers ); - } + } <FindMembersPHP>"<script"{BN}+"language"{BN}*"="{BN}*['"]?"php"['"]?{BN}*">" { // PHP code start - lineCount(yyscanner) ; + lineCount(yyscanner) ; BEGIN( FindMembers ); - } + } <FindMembers>"?>"|"</script>" { // PHP code end - if (yyextra->insidePHP) - BEGIN( FindMembersPHP ); - else - REJECT; + if (yyextra->insidePHP) + BEGIN( FindMembersPHP ); + else + REJECT; } <FindMembersPHP>[^\n<]+ { // Non-PHP code text, ignore - } + } <FindMembersPHP>\n { // Non-PHP code text, ignore lineCount(yyscanner); - } + } <FindMembersPHP>. { // Non-PHP code text, ignore - } -<FindMembers>{PHPKW} { if (yyextra->insidePHP) - BEGIN( NextSemi ); - else - REJECT; - } -<FindMembers>"%{"[^\n]* { // Mozilla XPIDL lang-specific block - if (!yyextra->insideIDL) - REJECT; - } -<FindMembers>"%}" { // Mozilla XPIDL lang-specific block end - if (!yyextra->insideIDL) - REJECT; - } -<FindMembers>{B}*("properties"){BN}*":"{BN}* { // IDL or Borland C++ builder property - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + } +<FindMembers>{PHPKW} { if (yyextra->insidePHP) + BEGIN( NextSemi ); + else + REJECT; + } +<FindMembers>"%{"[^\n]* { // Mozilla XPIDL lang-specific block + if (!yyextra->insideIDL) + REJECT; + } +<FindMembers>"%}" { // Mozilla XPIDL lang-specific block end + if (!yyextra->insideIDL) + REJECT; + } +<FindMembers>{B}*("properties"){BN}*":"{BN}* { // IDL or Borland C++ builder property + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*"k_dcop"{BN}*":"{BN}* { yyextra->current->mtype = yyextra->mtype = DCOP; - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*("signals"|"Q_SIGNALS"){BN}*":"{BN}* { yyextra->current->mtype = yyextra->mtype = Signal; - - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*"public"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->mtype = yyextra->mtype = Slot; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner); - } + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->mtype = yyextra->mtype = Slot; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner); + } <FindMembers>{B}*"protected"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Protected ; - yyextra->current->mtype = yyextra->mtype = Slot; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner); - } + yyextra->current->protection = yyextra->protection = Protected ; + yyextra->current->mtype = yyextra->mtype = Slot; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner); + } <FindMembers>{B}*"private"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Private ; - yyextra->current->mtype = yyextra->mtype = Slot; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner); - } -<FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Public ; - 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(); - lineCount(yyscanner) ; - } + yyextra->current->protection = yyextra->protection = Private ; + yyextra->current->mtype = yyextra->mtype = Slot; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner); + } +<FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* { + yyextra->current->protection = yyextra->protection = Public ; + 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(); + lineCount(yyscanner) ; + } <FindMembers>{B}*"internal"{BN}*":"{BN}* { // for now treat C++/CLI's internal as package... - if (yyextra->insideCli) - { - yyextra->current->protection = yyextra->protection = Package ; - 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(); - lineCount(yyscanner) ; - } - else - { - REJECT; - } - } -<FindMembers>{B}*"protected"{BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Protected ; - 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(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"private"{BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Private ; - 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(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"event"{BN}+ { - if (yyextra->insideCli) - { - // C++/CLI event - lineCount(yyscanner) ; - yyextra->current->mtype = yyextra->mtype = Event; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( CliPropertyType ); - } - else if (yyextra->insideCS) - { - lineCount(yyscanner) ; - yyextra->current->mtype = Event; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } - else - { - REJECT; - } - } -<FindMembers>{B}*"property"{BN}+ { - if (yyextra->insideCli) - { - // C++/CLI property - lineCount(yyscanner) ; - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( CliPropertyType ); - } - else - { - REJECT; - } - } -<CliPropertyType>{ID} { - addType(yyscanner); - yyextra->current->name = yytext; - } -<CliPropertyType>"[" { // C++/CLI indexed property - yyextra->current->args = "["; - BEGIN( CliPropertyIndex ); - } -<CliPropertyType>"{" { - yyextra->curlyCount=0; - //printf("event: '%s' '%s'\n",yyextra->current->type.data(),yyextra->current->name.data()); - BEGIN( CSAccessorDecl ); - } -<CliPropertyType>";" { - unput(*yytext); - BEGIN( FindMembers ); - } -<CliPropertyType>\n { + if (yyextra->insideCli) + { + yyextra->current->protection = yyextra->protection = Package ; + 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(); + lineCount(yyscanner) ; + } + else + { + REJECT; + } + } +<FindMembers>{B}*"protected"{BN}*":"{BN}* { + yyextra->current->protection = yyextra->protection = Protected ; + 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(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"private"{BN}*":"{BN}* { + yyextra->current->protection = yyextra->protection = Private ; + 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(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"event"{BN}+ { + if (yyextra->insideCli) + { + // C++/CLI event + lineCount(yyscanner) ; + yyextra->current->mtype = yyextra->mtype = Event; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( CliPropertyType ); + } + else if (yyextra->insideCS) + { + lineCount(yyscanner) ; + yyextra->current->mtype = Event; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } + else + { + REJECT; + } + } +<FindMembers>{B}*"property"{BN}+ { + if (yyextra->insideCli) + { + // C++/CLI property + lineCount(yyscanner) ; + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( CliPropertyType ); + } + else + { + REJECT; + } + } +<CliPropertyType>{ID} { + addType(yyscanner); + yyextra->current->name = yytext; + } +<CliPropertyType>"[" { // C++/CLI indexed property + yyextra->current->args = "["; + BEGIN( CliPropertyIndex ); + } +<CliPropertyType>"{" { + yyextra->curlyCount=0; + //printf("event: '%s' '%s'\n",yyextra->current->type.data(),yyextra->current->name.data()); + BEGIN( CSAccessorDecl ); + } +<CliPropertyType>";" { + unput(*yytext); + BEGIN( FindMembers ); + } +<CliPropertyType>\n { lineCount(yyscanner); - } -<CliPropertyType>{B}* { - } -<CliPropertyType>. { - addType(yyscanner); - yyextra->current->type += yytext; - } -<CliPropertyIndex>"]" { + } +<CliPropertyType>{B}* { + } +<CliPropertyType>. { + addType(yyscanner); + yyextra->current->type += yytext; + } +<CliPropertyIndex>"]" { BEGIN( CliPropertyType ); - yyextra->current->args+=yytext; - } -<CliPropertyIndex>. { - yyextra->current->args+=yytext; - } + yyextra->current->args+=yytext; + } +<CliPropertyIndex>. { + yyextra->current->args+=yytext; + } /* -<FindMembers>{B}*"property"{BN}+ { +<FindMembers>{B}*"property"{BN}+ { if (!yyextra->current->type.isEmpty()) - { - REJECT; + { + REJECT; } - else - { + else + { yyextra->current->mtype = yyextra->mtype = Property; lineCount(yyscanner); - } + } } */ -<FindMembers>{B}*"@private"{BN}+ { - yyextra->current->protection = yyextra->protection = Private ; - 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(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"@protected"{BN}+ { - yyextra->current->protection = yyextra->protection = Protected ; - 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(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"@public"{BN}+ { - yyextra->current->protection = yyextra->protection = Public ; - 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(); - lineCount(yyscanner) ; - } -<FindMembers>[\-+]{BN}* { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { - lineCount(yyscanner); - 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->section = Entry::FUNCTION_SEC; - yyextra->current->protection = yyextra->protection = Public ; - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - yyextra->current->virt = Virtual; - yyextra->current->stat=yytext[0]=='+'; - 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(); - BEGIN( ObjCMethod ); - } - } -<ObjCMethod>"(" { // start of method's return type - BEGIN( ObjCReturnType ); - } -<ObjCMethod>{ID} { // found method name - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type = "id"; - } - yyextra->current->name = yytext; +<FindMembers>{B}*"@private"{BN}+ { + yyextra->current->protection = yyextra->protection = Private ; + 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(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"@protected"{BN}+ { + yyextra->current->protection = yyextra->protection = Protected ; + 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(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"@public"{BN}+ { + yyextra->current->protection = yyextra->protection = Public ; + 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(); + lineCount(yyscanner) ; + } +<FindMembers>[\-+]{BN}* { + if (!yyextra->insideObjC) + { + REJECT; + } + else + { + lineCount(yyscanner); + 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->section = Entry::FUNCTION_SEC; + yyextra->current->protection = yyextra->protection = Public ; + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + yyextra->current->virt = Virtual; + yyextra->current->stat=yytext[0]=='+'; + 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(); + BEGIN( ObjCMethod ); + } + } +<ObjCMethod>"(" { // start of method's return type + BEGIN( ObjCReturnType ); + } +<ObjCMethod>{ID} { // found method name + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type = "id"; + } + yyextra->current->name = yytext; if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - } -<ObjCMethod>":"{B}* { // start of parameter list - yyextra->current->name += ':'; - Argument a; - yyextra->current->argList.push_back(a); - BEGIN( ObjCParams ); - } -<ObjCReturnType>[^)]* { // TODO: check if nested braches are possible. - yyextra->current->type = yytext; - } -<ObjCReturnType>")" { - BEGIN( ObjCMethod ); - } -<ObjCParams>({ID})?{BN}*":" { // Keyword of parameter - QCString keyw = yytext; - keyw=keyw.left(keyw.length()-1).stripWhiteSpace(); // strip : - if (keyw.isEmpty()) - { - yyextra->current->name += " :"; - } - else - { - yyextra->current->name += keyw+":"; - } - if (yyextra->current->argList.back().type.isEmpty()) - { - yyextra->current->argList.back().type="id"; - } - Argument a; - a.attrib=(QCString)"["+keyw+"]"; - yyextra->current->argList.push_back(a); - } -<ObjCParams>{ID}{BN}* { // name of parameter - lineCount(yyscanner); - yyextra->current->argList.back().name=QCString(yytext).stripWhiteSpace(); - } -<ObjCParams>","{BN}*"..." { // name of parameter - lineCount(yyscanner); - // do we want the comma as part of the name? - //yyextra->current->name += ","; - Argument a; - a.attrib="[,]"; - a.type="..."; - yyextra->current->argList.push_back(a); - } + } +<ObjCMethod>":"{B}* { // start of parameter list + yyextra->current->name += ':'; + Argument a; + yyextra->current->argList.push_back(a); + BEGIN( ObjCParams ); + } +<ObjCReturnType>[^)]* { // TODO: check if nested braches are possible. + yyextra->current->type = yytext; + } +<ObjCReturnType>")" { + BEGIN( ObjCMethod ); + } +<ObjCParams>({ID})?{BN}*":" { // Keyword of parameter + QCString keyw = yytext; + keyw=keyw.left(keyw.length()-1).stripWhiteSpace(); // strip : + if (keyw.isEmpty()) + { + yyextra->current->name += " :"; + } + else + { + yyextra->current->name += keyw+":"; + } + if (yyextra->current->argList.back().type.isEmpty()) + { + yyextra->current->argList.back().type="id"; + } + Argument a; + a.attrib=(QCString)"["+keyw+"]"; + yyextra->current->argList.push_back(a); + } +<ObjCParams>{ID}{BN}* { // name of parameter + lineCount(yyscanner); + yyextra->current->argList.back().name=QCString(yytext).stripWhiteSpace(); + } +<ObjCParams>","{BN}*"..." { // name of parameter + lineCount(yyscanner); + // do we want the comma as part of the name? + //yyextra->current->name += ","; + Argument a; + a.attrib="[,]"; + a.type="..."; + yyextra->current->argList.push_back(a); + } /* -<ObjCParams>":" { - yyextra->current->name += ':'; - } +<ObjCParams>":" { + yyextra->current->name += ':'; + } */ -<ObjCParams>"(" { - yyextra->roundCount=0; - yyextra->current->argList.back().type.resize(0); - BEGIN( ObjCParamType ); - } +<ObjCParams>"(" { + yyextra->roundCount=0; + yyextra->current->argList.back().type.resize(0); + BEGIN( ObjCParamType ); + } <ObjCParamType>"(" { yyextra->roundCount++; - yyextra->current->argList.back().type+=yytext; + yyextra->current->argList.back().type+=yytext; } -<ObjCParamType>")"/{B}* { +<ObjCParamType>")"/{B}* { if (yyextra->roundCount<=0) { BEGIN( ObjCParams ); @@ -841,221 +843,221 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->argList.back().type+=yytext; yyextra->roundCount--; } - } -<ObjCParamType>[^()]* { - yyextra->current->argList.back().type+=QCString(yytext).stripWhiteSpace(); - } -<ObjCMethod,ObjCParams>";" { // end of method declaration - if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) - { - yyextra->current->argList.back().type="id"; - } + } +<ObjCParamType>[^()]* { + yyextra->current->argList.back().type+=QCString(yytext).stripWhiteSpace(); + } +<ObjCMethod,ObjCParams>";" { // end of method declaration + if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) + { + yyextra->current->argList.back().type="id"; + } if (yyextra->current->argList.empty()) // method without parameters { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); - //printf("argList=%s\n",yyextra->current->args.data()); - unput(';'); - BEGIN( Function ); + yyextra->current->args = argListToString(yyextra->current->argList); + //printf("argList=%s\n",yyextra->current->args.data()); + unput(';'); + BEGIN( Function ); } -<ObjCMethod,ObjCParams>(";"{BN}+)?"{" { // start of a method body - lineCount(yyscanner); +<ObjCMethod,ObjCParams>(";"{BN}+)?"{" { // start of a method body + lineCount(yyscanner); //printf("Type=%s Name=%s args=%s\n", - // yyextra->current->type.data(),yyextra->current->name.data(),argListToString(yyextra->current->argList).data() - // ); - if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) - { - yyextra->current->argList.back().type="id"; - } + // yyextra->current->type.data(),yyextra->current->name.data(),argListToString(yyextra->current->argList).data() + // ); + if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) + { + yyextra->current->argList.back().type="id"; + } if (yyextra->current->argList.empty()) // method without parameters { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); + yyextra->current->args = argListToString(yyextra->current->argList); unput('{'); - BEGIN( Function ); - } + BEGIN( Function ); + } <FindMembers>{B}*"sequence"{BN}*"<"{BN}* { - if (yyextra->insideSlice) - { + if (yyextra->insideSlice) + { lineCount(yyscanner); - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; + 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; + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args.resize(0); - yyextra->current->section = Entry::TYPEDEF_SEC ; + yyextra->current->section = Entry::TYPEDEF_SEC ; yyextra->isTypedef = TRUE; - BEGIN( SliceSequence ); - } - else - REJECT; - } + BEGIN( SliceSequence ); + } + else + REJECT; + } <FindMembers>{B}*"dictionary"{BN}*"<"{BN}* { - if (yyextra->insideSlice) - { + if (yyextra->insideSlice) + { lineCount(yyscanner); - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; + 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; + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args.resize(0); - yyextra->current->section = Entry::TYPEDEF_SEC ; + yyextra->current->section = Entry::TYPEDEF_SEC ; yyextra->isTypedef = TRUE; - BEGIN( SliceDictionary ); - } - else - REJECT; - } -<FindMembers>{BN}{1,80} { - lineCount(yyscanner); - } -<FindMembers>"@"({ID}".")*{ID}{BN}*"(" { - if (yyextra->insideJava) // Java annotation - { - lineCount(yyscanner); - yyextra->lastSkipRoundContext = YY_START; - yyextra->roundCount=0; - BEGIN( SkipRound ); - } - else if (qstrncmp(yytext,"@property",9)==0) // ObjC 2.0 property - { - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->spec|=Entry::Readable | Entry::Writable | Entry::Assign; - yyextra->current->protection = Public ; - unput('('); - BEGIN( ObjCPropAttr ); - } - else - { - REJECT; - } - } -<ObjCPropAttr>"getter="{ID} { + BEGIN( SliceDictionary ); + } + else + REJECT; + } +<FindMembers>{BN}{1,80} { + lineCount(yyscanner); + } +<FindMembers>"@"({ID}".")*{ID}{BN}*"(" { + if (yyextra->insideJava) // Java annotation + { + lineCount(yyscanner); + yyextra->lastSkipRoundContext = YY_START; + yyextra->roundCount=0; + BEGIN( SkipRound ); + } + else if (qstrncmp(yytext,"@property",9)==0) // ObjC 2.0 property + { + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->spec|=Entry::Readable | Entry::Writable | Entry::Assign; + yyextra->current->protection = Public ; + unput('('); + BEGIN( ObjCPropAttr ); + } + else + { + REJECT; + } + } +<ObjCPropAttr>"getter="{ID} { yyextra->current->read = yytext+7; - } -<ObjCPropAttr>"setter="{ID} { + } +<ObjCPropAttr>"setter="{ID} { yyextra->current->write = yytext+7; - } -<ObjCPropAttr>"readonly" { - yyextra->current->spec&=~Entry::Writable; - } -<ObjCPropAttr>"readwrite" { // default - } -<ObjCPropAttr>"assign" { // default - } + } +<ObjCPropAttr>"readonly" { + yyextra->current->spec&=~Entry::Writable; + } +<ObjCPropAttr>"readwrite" { // default + } +<ObjCPropAttr>"assign" { // default + } <ObjCPropAttr>"unsafe_unretained" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Unretained; - } -<ObjCPropAttr>"retain" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Retain; - } -<ObjCPropAttr>"copy" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Copy; - } + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Unretained; + } +<ObjCPropAttr>"retain" { + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Retain; + } +<ObjCPropAttr>"copy" { + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Copy; + } <ObjCPropAttr>"weak" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Weak; + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Weak; } <ObjCPropAttr>"strong" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Strong; - } -<ObjCPropAttr>"nonatomic" { - yyextra->current->spec|=Entry::NonAtomic; - } -<ObjCPropAttr>")" { - BEGIN(FindMembers); - } -<FindMembers>"@"{ID} { - if (yyextra->insideJava) // Java annotation - { - // skip annotation - } - else if (qstrcmp(yytext,"@property")==0) // ObjC 2.0 property - { - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->spec|=Entry::Writable | Entry::Readable; - yyextra->current->protection = Public ; - } - else if (qstrcmp(yytext,"@synthesize")==0) - { - BEGIN( ObjCSkipStatement ); - } - else if (qstrcmp(yytext,"@dynamic")==0) - { - BEGIN( ObjCSkipStatement ); - } - else - { - REJECT; - } - } -<ObjCSkipStatement>";" { - BEGIN(FindMembers); - } -<PackageName>{ID}(("."|"\\"){ID})* { - yyextra->isTypedef=FALSE; - //printf("Found namespace %s lang=%d\n",yytext,yyextra->current->lang); - yyextra->current->name = yytext; - yyextra->current->name = substitute(yyextra->current->name,".","::"); - yyextra->current->name = substitute(yyextra->current->name,"\\","::"); - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "namespace" ; - 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; - lineCount(yyscanner); - } -<PackageName>";" { + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Strong; + } +<ObjCPropAttr>"nonatomic" { + yyextra->current->spec|=Entry::NonAtomic; + } +<ObjCPropAttr>")" { + BEGIN(FindMembers); + } +<FindMembers>"@"{ID} { + if (yyextra->insideJava) // Java annotation + { + // skip annotation + } + else if (qstrcmp(yytext,"@property")==0) // ObjC 2.0 property + { + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->spec|=Entry::Writable | Entry::Readable; + yyextra->current->protection = Public ; + } + else if (qstrcmp(yytext,"@synthesize")==0) + { + BEGIN( ObjCSkipStatement ); + } + else if (qstrcmp(yytext,"@dynamic")==0) + { + BEGIN( ObjCSkipStatement ); + } + else + { + REJECT; + } + } +<ObjCSkipStatement>";" { + BEGIN(FindMembers); + } +<PackageName>{ID}(("."|"\\"){ID})* { + yyextra->isTypedef=FALSE; + //printf("Found namespace %s lang=%d\n",yytext,yyextra->current->lang); + yyextra->current->name = yytext; + yyextra->current->name = substitute(yyextra->current->name,".","::"); + yyextra->current->name = substitute(yyextra->current->name,"\\","::"); + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "namespace" ; + 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; + lineCount(yyscanner); + } +<PackageName>";" { std::shared_ptr<Entry> tmp = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); yyextra->current_root = tmp; - initEntry(yyscanner); - BEGIN(FindMembers); - } -<PackageName>"{" { - yyextra->curlyCount=0; - BEGIN( ReadNSBody ); - } -<FindMembers>{B}*"initonly"{BN}+ { - yyextra->current->type += " initonly "; - if (yyextra->insideCli) yyextra->current->spec |= Entry::Initonly; - lineCount(yyscanner); - } -<FindMembers>{B}*"static"{BN}+ { yyextra->current->type += " static "; - yyextra->current->stat = TRUE; - lineCount(yyscanner); - } -<FindMembers>{B}*"extern"{BN}+ { - yyextra->current->stat = FALSE; - yyextra->current->explicitExternal = 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; - lineCount(yyscanner); - } -<FindMembers>{B}*"constexpr"{BN}+ { + initEntry(yyscanner); + BEGIN(FindMembers); + } +<PackageName>"{" { + yyextra->curlyCount=0; + BEGIN( ReadNSBody ); + } +<FindMembers>{B}*"initonly"{BN}+ { + yyextra->current->type += " initonly "; + if (yyextra->insideCli) yyextra->current->spec |= Entry::Initonly; + lineCount(yyscanner); + } +<FindMembers>{B}*"static"{BN}+ { yyextra->current->type += " static "; + yyextra->current->stat = TRUE; + lineCount(yyscanner); + } +<FindMembers>{B}*"extern"{BN}+ { + yyextra->current->stat = FALSE; + yyextra->current->explicitExternal = 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; + lineCount(yyscanner); + } +<FindMembers>{B}*"constexpr"{BN}+ { if (yyextra->insideCpp) { yyextra->current->type += " constexpr "; @@ -1066,300 +1068,300 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { REJECT; } - } -<FindMembers>{B}*"published"{BN}+ { // UNO IDL published keyword - if (yyextra->insideIDL) - { - lineCount(yyscanner); - yyextra->current->spec |= Entry::Published; - } - else - { - REJECT; - } - } -<FindMembers>{B}*"abstract"{BN}+ { - if (!yyextra->insidePHP) - { - yyextra->current->type += " abstract "; - if (!yyextra->insideJava) - { + } +<FindMembers>{B}*"published"{BN}+ { // UNO IDL published keyword + if (yyextra->insideIDL) + { + lineCount(yyscanner); + yyextra->current->spec |= Entry::Published; + } + else + { + REJECT; + } + } +<FindMembers>{B}*"abstract"{BN}+ { + if (!yyextra->insidePHP) + { + yyextra->current->type += " abstract "; + if (!yyextra->insideJava) + { yyextra->current->virt = Pure; - } - else - { + } + else + { yyextra->current->spec|=Entry::Abstract; - } - } - else - { - yyextra->current->spec|=Entry::Abstract; - } - lineCount(yyscanner); - } -<FindMembers>{B}*"inline"{BN}+ { yyextra->current->spec|=Entry::Inline; - lineCount(yyscanner); - } -<FindMembers>{B}*"mutable"{BN}+ { yyextra->current->spec|=Entry::Mutable; - lineCount(yyscanner); - } -<FindMembers>{B}*"explicit"{BN}+ { yyextra->current->spec|=Entry::Explicit; - lineCount(yyscanner); - } -<FindMembers>{B}*"local"{BN}+ { yyextra->current->spec|=Entry::Local; - lineCount(yyscanner); - } -<FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section + } + } + else + { + yyextra->current->spec|=Entry::Abstract; + } + lineCount(yyscanner); + } +<FindMembers>{B}*"inline"{BN}+ { yyextra->current->spec|=Entry::Inline; + lineCount(yyscanner); + } +<FindMembers>{B}*"mutable"{BN}+ { yyextra->current->spec|=Entry::Mutable; + lineCount(yyscanner); + } +<FindMembers>{B}*"explicit"{BN}+ { yyextra->current->spec|=Entry::Explicit; + lineCount(yyscanner); + } +<FindMembers>{B}*"local"{BN}+ { yyextra->current->spec|=Entry::Local; + lineCount(yyscanner); + } +<FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section yyextra->current->spec=(yyextra->current->spec & ~Entry::Optional) | Entry::Required; - lineCount(yyscanner); + lineCount(yyscanner); } -<FindMembers>{B}*"@optional"{BN}+ { // Objective C 2.0 protocol optional section +<FindMembers>{B}*"@optional"{BN}+ { // Objective C 2.0 protocol optional section yyextra->current->spec=(yyextra->current->spec & ~Entry::Required) | Entry::Optional; - lineCount(yyscanner); + lineCount(yyscanner); } /* -<FindMembers>{B}*"import"{BN}+ { // IDL import keyword - BEGIN( NextSemi ); - } +<FindMembers>{B}*"import"{BN}+ { // IDL import keyword + BEGIN( NextSemi ); + } */ -<FindMembers>{B}*"typename"{BN}+ { lineCount(yyscanner); } -<FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "namespace" ; - 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; - lineCount(yyscanner); - if (yyextra->insidePHP) - { - BEGIN( PackageName ); - } - else - { - BEGIN( CompoundName ); - } - } -<FindMembers>{B}*"module"{BN}+ { - lineCount(yyscanner); +<FindMembers>{B}*"typename"{BN}+ { lineCount(yyscanner); } +<FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "namespace" ; + 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; + lineCount(yyscanner); + if (yyextra->insidePHP) + { + BEGIN( PackageName ); + } + else + { + BEGIN( CompoundName ); + } + } +<FindMembers>{B}*"module"{BN}+ { + lineCount(yyscanner); if (yyextra->insideIDL || yyextra->insideSlice) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "module" ; - 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; - BEGIN( CompoundName ); - } - else if (yyextra->insideD) - { - lineCount(yyscanner); - BEGIN(PackageName); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{B}*"library"{BN}+ { - lineCount(yyscanner); + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "module" ; + 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; + BEGIN( CompoundName ); + } + else if (yyextra->insideD) + { + lineCount(yyscanner); + BEGIN(PackageName); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{B}*"library"{BN}+ { + lineCount(yyscanner); if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "library" ; - 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; - BEGIN( CompoundName ); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{B}*"constants"{BN}+ { // UNO IDL constant group - lineCount(yyscanner); - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "constants"; - 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; - BEGIN( CompoundName ); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{BN}*("service"){BN}+ { // UNO IDL service - lineCount(yyscanner); - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Service | - // preserve UNO IDL [optional] or published - (yyextra->current->spec & (Entry::Optional|Entry::Published)); - addType(yyscanner); - yyextra->current->type += " service " ; - 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 - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{BN}*("singleton"){BN}+ { // UNO IDL singleton - lineCount(yyscanner); - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Singleton | - (yyextra->current->spec & Entry::Published); // preserve - addType(yyscanner); - yyextra->current->type += " singleton " ; - 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 - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{BN}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba/UNO IDL/Java/Slice interface - lineCount(yyscanner); + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "library" ; + 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; + BEGIN( CompoundName ); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{B}*"constants"{BN}+ { // UNO IDL constant group + lineCount(yyscanner); + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "constants"; + 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; + BEGIN( CompoundName ); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{BN}*("service"){BN}+ { // UNO IDL service + lineCount(yyscanner); + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Service | + // preserve UNO IDL [optional] or published + (yyextra->current->spec & (Entry::Optional|Entry::Published)); + addType(yyscanner); + yyextra->current->type += " service " ; + 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 + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{BN}*("singleton"){BN}+ { // UNO IDL singleton + lineCount(yyscanner); + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Singleton | + (yyextra->current->spec & Entry::Published); // preserve + addType(yyscanner); + yyextra->current->type += " singleton " ; + 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 + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{BN}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba/UNO IDL/Java/Slice interface + lineCount(yyscanner); if (yyextra->insideIDL || yyextra->insideJava || yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideSlice) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Interface | + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Interface | // preserve UNO IDL [optional], published, Slice local (yyextra->current->spec & (Entry::Optional|Entry::Published|Entry::Local)); - addType(yyscanner); - yyextra->current->type += " interface" ; - 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; - BEGIN( CompoundName ); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{B}*"@implementation"{BN}+ { // Objective-C class implementation - lineCount(yyscanner); - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::OBJCIMPL_SEC; - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - yyextra->current->protection = yyextra->protection = Public ; - addType(yyscanner); - yyextra->current->type += " implementation" ; - 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 - lineCount(yyscanner); - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + addType(yyscanner); + yyextra->current->type += " interface" ; + 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; + BEGIN( CompoundName ); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{B}*"@implementation"{BN}+ { // Objective-C class implementation + lineCount(yyscanner); + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::OBJCIMPL_SEC; + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + yyextra->current->protection = yyextra->protection = Public ; + addType(yyscanner); + yyextra->current->type += " implementation" ; + 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 + lineCount(yyscanner); + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Interface; - if (!yyextra->insideJava) - { - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - } - yyextra->current->protection = yyextra->protection = Public ; - addType(yyscanner); - yyextra->current->type += " interface" ; - 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; - BEGIN( CompoundName ); - } -<FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition - lineCount(yyscanner); - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + if (!yyextra->insideJava) + { + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + } + yyextra->current->protection = yyextra->protection = Public ; + addType(yyscanner); + yyextra->current->type += " interface" ; + 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; + BEGIN( CompoundName ); + } +<FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition + lineCount(yyscanner); + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Protocol; - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - yyextra->current->protection = yyextra->protection = Public ; - addType(yyscanner); - yyextra->current->type += " protocol" ; - 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; - BEGIN( CompoundName ); - } -<FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + yyextra->current->protection = yyextra->protection = Public ; + addType(yyscanner); + yyextra->current->type += " protocol" ; + 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; + BEGIN( CompoundName ); + } +<FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; // preserve UNO IDL, Slice local - yyextra->current->spec = Entry::Exception | - (yyextra->current->spec & Entry::Published) | - (yyextra->current->spec & Entry::Local); - addType(yyscanner); - yyextra->current->type += " exception" ; - 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; - lineCount(yyscanner); - BEGIN( CompoundName ); - } + yyextra->current->spec = Entry::Exception | + (yyextra->current->spec & Entry::Published) | + (yyextra->current->spec & Entry::Local); + addType(yyscanner); + yyextra->current->type += " exception" ; + 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; + lineCount(yyscanner); + BEGIN( CompoundName ); + } <FindMembers>"@class" | // for Objective C class declarations <FindMembers>{B}*{TYPEDEFPREFIX}"class{" | -<FindMembers>{B}*{TYPEDEFPREFIX}"class"{BN}+ { +<FindMembers>{B}*{TYPEDEFPREFIX}"class"{BN}+ { QCString decl = yytext; - yyextra->isTypedef=decl.find("typedef")!=-1; + yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - yyextra->current->section = Entry::CLASS_SEC; - addType(yyscanner); + yyextra->current->section = Entry::CLASS_SEC; + addType(yyscanner); uint64 spec = yyextra->current->spec; - if (yyextra->insidePHP && yyextra->current->spec&Entry::Abstract) - { - // convert Abstract to AbstractClass - yyextra->current->spec=(yyextra->current->spec&~Entry::Abstract)|Entry::AbstractClass; - } + if (yyextra->insidePHP && yyextra->current->spec&Entry::Abstract) + { + // convert Abstract to AbstractClass + yyextra->current->spec=(yyextra->current->spec&~Entry::Abstract)|Entry::AbstractClass; + } if (yyextra->insideSlice && spec&Entry::Local) { yyextra->current->spec|=Entry::Local; @@ -1372,107 +1374,107 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->type += " volatile"; } - yyextra->current->type += " class" ; - 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; - if (yytext[0]=='@') - { - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - } - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->type += " class" ; + 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; + if (yytext[0]=='@') + { + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + } + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"value class{" | // C++/CLI extension <FindMembers>{B}*"value class"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Value; - addType(yyscanner); - yyextra->current->type += " value class" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " value class" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"ref class{" | // C++/CLI extension <FindMembers>{B}*"ref class"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Ref; - addType(yyscanner); - yyextra->current->type += " ref class" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " ref class" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"interface class{" | // C++/CLI extension <FindMembers>{B}*"interface class"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Interface; - addType(yyscanner); - yyextra->current->type += " interface class" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } -<FindMembers>{B}*"coclass"{BN}+ { - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - addType(yyscanner); - yyextra->current->type += " coclass" ; - 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; - lineCount(yyscanner) ; - BEGIN( CompoundName ) ; - } - else - { - addType(yyscanner); - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - lineCount(yyscanner); - } - } -<FindMembers>{B}*{TYPEDEFPREFIX}"struct{" | -<FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ { + addType(yyscanner); + yyextra->current->type += " interface class" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } +<FindMembers>{B}*"coclass"{BN}+ { + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + addType(yyscanner); + yyextra->current->type += " coclass" ; + 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; + lineCount(yyscanner) ; + BEGIN( CompoundName ) ; + } + else + { + addType(yyscanner); + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + lineCount(yyscanner); + } + } +<FindMembers>{B}*{TYPEDEFPREFIX}"struct{" | +<FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ { QCString decl = yytext; - yyextra->isTypedef=decl.find("typedef")!=-1; + yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - yyextra->current->section = Entry::CLASS_SEC ; + yyextra->current->section = Entry::CLASS_SEC ; // preserve UNO IDL & Inline attributes, Slice local - yyextra->current->spec = Entry::Struct | - (yyextra->current->spec & Entry::Published) | + yyextra->current->spec = Entry::Struct | + (yyextra->current->spec & Entry::Published) | (yyextra->current->spec & Entry::Inline) | - (yyextra->current->spec & Entry::Local); - // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state - //yyextra->current->objc = yyextra->insideObjC = FALSE; - addType(yyscanner); + (yyextra->current->spec & Entry::Local); + // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state + //yyextra->current->objc = yyextra->insideObjC = FALSE; + addType(yyscanner); if (isConst) { yyextra->current->type += " const"; @@ -1481,75 +1483,75 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->type += " volatile"; } - yyextra->current->type += " struct" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->type += " struct" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"value struct{" | // C++/CLI extension <FindMembers>{B}*"value struct"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Struct | Entry::Value; - addType(yyscanner); - yyextra->current->type += " value struct" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " value struct" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"ref struct{" | // C++/CLI extension <FindMembers>{B}*"ref struct"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Struct | Entry::Ref; - addType(yyscanner); - yyextra->current->type += " ref struct" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " ref struct" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"interface struct{" | // C++/CLI extension <FindMembers>{B}*"interface struct"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Struct | Entry::Interface; - addType(yyscanner); - yyextra->current->type += " interface struct"; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " interface struct"; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*{TYPEDEFPREFIX}"union{" | -<FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ { +<FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ { QCString decl=yytext; - yyextra->isTypedef=decl.find("typedef")!=-1; + yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Union; - // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state - //yyextra->current->objc = yyextra->insideObjC = FALSE; - addType(yyscanner); + // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state + //yyextra->current->objc = yyextra->insideObjC = FALSE; + addType(yyscanner); if (isConst) { yyextra->current->type += " const"; @@ -1558,239 +1560,239 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->type += " volatile"; } - yyextra->current->type += " union" ; - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->type += " union" ; + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?"{" | <FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?{BN}+ { // for IDL: typedef [something] enum QCString text=yytext; - yyextra->isTypedef = text.find("typedef")!=-1; + yyextra->isTypedef = text.find("typedef")!=-1; bool isStrongEnum = text.find("struct")!=-1 || text.find("class")!=-1 || yyextra->insideCS; - if (yyextra->insideJava) - { - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Enum; - } - else - { - yyextra->current->section = Entry::ENUM_SEC ; - } - addType(yyscanner); - yyextra->current->type += " enum"; + if (yyextra->insideJava) + { + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Enum; + } + else + { + yyextra->current->section = Entry::ENUM_SEC ; + } + addType(yyscanner); + yyextra->current->type += " enum"; if (isStrongEnum) { yyextra->current->spec |= Entry::Strong; } - 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; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + 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; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BN}*/"(" { // A::operator()<int>(int arg) - lineCount(yyscanner); - yyextra->current->name += "()"; - BEGIN( FindMembers ); - } -<Operator>"("{BN}*")"{BN}*/"(" { - lineCount(yyscanner); - yyextra->current->name += yytext ; - yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); - BEGIN( FindMembers ) ; - } -<Operator>";" { // can occur when importing members - unput(';'); - BEGIN( FindMembers ) ; - } -<Operator>[^(] { - lineCount(yyscanner); - yyextra->current->name += *yytext ; - } -<Operator>"<>" { /* skip guided templ specifiers */ } -<Operator>"(" { - yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); - unput(*yytext); - BEGIN( FindMembers ) ; - } -<FindMembers>("template"|"generic")({BN}*)"<"/[>]? { // generic is a C++/CLI extension - lineCount(yyscanner); - ArgumentList al; - //yyextra->current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template; - yyextra->current->tArgLists.push_back(al); - yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); - yyextra->templateStr="<"; - yyextra->fullArgString = yyextra->templateStr; - yyextra->copyArgString = &yyextra->templateStr; - yyextra->currentArgumentContext = FindMembers; - BEGIN( ReadTempArgs ); - } + lineCount(yyscanner); + yyextra->current->name += "()"; + BEGIN( FindMembers ); + } +<Operator>"("{BN}*")"{BN}*/"(" { + lineCount(yyscanner); + yyextra->current->name += yytext ; + yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); + BEGIN( FindMembers ) ; + } +<Operator>";" { // can occur when importing members + unput(';'); + BEGIN( FindMembers ) ; + } +<Operator>[^(] { + lineCount(yyscanner); + yyextra->current->name += *yytext ; + } +<Operator>"<>" { /* skip guided templ specifiers */ } +<Operator>"(" { + yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); + unput(*yytext); + BEGIN( FindMembers ) ; + } +<FindMembers>("template"|"generic")({BN}*)"<"/[>]? { // generic is a C++/CLI extension + lineCount(yyscanner); + ArgumentList al; + //yyextra->current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template; + yyextra->current->tArgLists.push_back(al); + yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); + yyextra->templateStr="<"; + yyextra->fullArgString = yyextra->templateStr; + yyextra->copyArgString = &yyextra->templateStr; + yyextra->currentArgumentContext = FindMembers; + BEGIN( ReadTempArgs ); + } <FindMembers>"namespace"{BN}+/{ID}{BN}*"=" { // namespace alias - lineCount(yyscanner); - BEGIN( NSAliasName ); - } -<NSAliasName>{ID} { - yyextra->aliasName = yytext; - BEGIN( NSAliasArg ); - } -<NSAliasArg>({ID}"::")*{ID} { - //printf("Inserting namespace alias %s::%s->%s\n",yyextra->current_root->name.data(),yyextra->aliasName.data(),yytext); + lineCount(yyscanner); + BEGIN( NSAliasName ); + } +<NSAliasName>{ID} { + yyextra->aliasName = yytext; + BEGIN( NSAliasArg ); + } +<NSAliasArg>({ID}"::")*{ID} { + //printf("Inserting namespace alias %s::%s->%s\n",yyextra->current_root->name.data(),yyextra->aliasName.data(),yytext); // TODO: namespace aliases are now treated as global entities // while they should be aware of the scope they are in Doxygen::namespaceAliasMap.insert({yyextra->aliasName.data(),std::string(yytext)}); - } -<NSAliasArg>";" { - BEGIN( FindMembers ); - } + } +<NSAliasArg>";" { + BEGIN( FindMembers ); + } <PHPUse>({ID}{BN}*"\\"{BN}*)*{ID}/{BN}+"as" { - lineCount(yyscanner); - yyextra->aliasName=yytext; - BEGIN(PHPUseAs); - } -<PHPUse>({ID}{BN}*"\\"{BN}*)*{ID} { - lineCount(yyscanner); - yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::")); - //printf("PHP: adding use relation: %s\n",yyextra->current->name.data()); - yyextra->current->fileName = yyextra->yyFileName; + lineCount(yyscanner); + yyextra->aliasName=yytext; + BEGIN(PHPUseAs); + } +<PHPUse>({ID}{BN}*"\\"{BN}*)*{ID} { + lineCount(yyscanner); + yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::")); + //printf("PHP: adding use relation: %s\n",yyextra->current->name.data()); + yyextra->current->fileName = yyextra->yyFileName; // add a using declaration - yyextra->current->section=Entry::USINGDECL_SEC; - yyextra->current_root->copyToSubEntry(yyextra->current); + yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current_root->copyToSubEntry(yyextra->current); // also add it as a using directive - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - yyextra->aliasName.resize(0); - } -<PHPUseAs>{BN}+"as"{BN}+ { - lineCount(yyscanner); - } + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + yyextra->aliasName.resize(0); + } +<PHPUseAs>{BN}+"as"{BN}+ { + lineCount(yyscanner); + } <PHPUseAs>{PHPUSEKW} { } -<PHPUseAs>{ID} { - //printf("PHP: adding use as relation: %s->%s\n",yytext,yyextra->aliasName.data()); +<PHPUseAs>{ID} { + //printf("PHP: adding use as relation: %s->%s\n",yytext,yyextra->aliasName.data()); if (!yyextra->aliasName.isEmpty()) { Doxygen::namespaceAliasMap.insert({yytext, - std::string(removeRedundantWhiteSpace( - substitute(yyextra->aliasName,"\\","::")).data())}); - } - yyextra->aliasName.resize(0); - } -<PHPUse,PHPUseAs>[,;] { - if (*yytext==',') - { - BEGIN(PHPUse); - } - else - { - BEGIN(FindMembers); - } - } -<JavaImport>({ID}{BN}*"."{BN}*)+"*" { // package import => add as a using directive - lineCount(yyscanner); - QCString scope=yytext; - yyextra->current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::")); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Using); - } -<JavaImport>({ID}{BN}*"."{BN}*)+{ID} { // class import => add as a using declaration + std::string(removeRedundantWhiteSpace( + substitute(yyextra->aliasName,"\\","::")).data())}); + } + yyextra->aliasName.resize(0); + } +<PHPUse,PHPUseAs>[,;] { + if (*yytext==',') + { + BEGIN(PHPUse); + } + else + { + BEGIN(FindMembers); + } + } +<JavaImport>({ID}{BN}*"."{BN}*)+"*" { // package import => add as a using directive lineCount(yyscanner); - QCString scope=yytext; - yyextra->current->name=removeRedundantWhiteSpace(substitute(scope,".","::")); - yyextra->current->fileName = yyextra->yyFileName; - if (yyextra->insideD) - { - yyextra->current->section=Entry::USINGDIR_SEC; - } - else - { - //printf("import name = %s -> %s\n",yytext,yyextra->current->name.data()); - yyextra->current->section=Entry::USINGDECL_SEC; - } + QCString scope=yytext; + yyextra->current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::")); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Using); + } +<JavaImport>({ID}{BN}*"."{BN}*)+{ID} { // class import => add as a using declaration + lineCount(yyscanner); + QCString scope=yytext; + yyextra->current->name=removeRedundantWhiteSpace(substitute(scope,".","::")); + yyextra->current->fileName = yyextra->yyFileName; + if (yyextra->insideD) + { + yyextra->current->section=Entry::USINGDIR_SEC; + } + else + { + //printf("import name = %s -> %s\n",yytext,yyextra->current->name.data()); + yyextra->current->section=Entry::USINGDECL_SEC; + } yyextra->previous = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Using); - } -<FindMembers>"using"{BN}+ { - yyextra->current->startLine=yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - lineCount(yyscanner); - BEGIN(Using); - } -<Using>"namespace"{BN}+ { lineCount(yyscanner); BEGIN(UsingDirective); } + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Using); + } +<FindMembers>"using"{BN}+ { + yyextra->current->startLine=yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + lineCount(yyscanner); + BEGIN(Using); + } +<Using>"namespace"{BN}+ { lineCount(yyscanner); BEGIN(UsingDirective); } <Using>({ID}{BN}*("::"|"."){BN}*)*({ID}|{OPERATOR}) { lineCount(yyscanner); - yyextra->current->name=yytext; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current->name=yytext; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->section=Entry::USINGDECL_SEC; yyextra->current->startLine = yyextra->yyLineNr; yyextra->previous = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - if (yyextra->insideCS) /* Hack: in C# a using declaration and - directive have the same syntax, so we - also add it as a using directive here - */ - { - yyextra->current->name=yytext; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - } - BEGIN(Using); - } + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + if (yyextra->insideCS) /* Hack: in C# a using declaration and + directive have the same syntax, so we + also add it as a using directive here + */ + { + yyextra->current->name=yytext; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + } + BEGIN(Using); + } <Using>"=" { // C++11 style template alias? BEGIN(UsingAlias); } -<UsingAlias>";" { +<UsingAlias>";" { yyextra->previous->section=Entry::VARIABLE_SEC; yyextra->previous->type = "typedef "+yyextra->previous->args; - yyextra->previous->type=yyextra->previous->type.simplifyWhiteSpace(); + yyextra->previous->type=yyextra->previous->type.simplifyWhiteSpace(); yyextra->previous->args.resize(0); - yyextra->previous->name=yyextra->previous->name.stripWhiteSpace(); - yyextra->previous->bodyLine = yyextra->yyLineNr; - yyextra->previous->bodyColumn = yyextra->yyColNr; + yyextra->previous->name=yyextra->previous->name.stripWhiteSpace(); + yyextra->previous->bodyLine = yyextra->yyLineNr; + yyextra->previous->bodyColumn = yyextra->yyColNr; yyextra->previous->spec |= Entry::Alias; - BEGIN(FindMembers); + BEGIN(FindMembers); } <UsingAlias>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { - yyextra->docBlockContext = UsingAliasEnd; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlockContext = UsingAliasEnd; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - lineCount(yyscanner); - - yyextra->docBlockTerm = ';'; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } + lineCount(yyscanner); + + yyextra->docBlockTerm = ';'; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } <UsingAlias>">>" { yyextra->previous->args+="> >"; // see bug769552 } @@ -1809,300 +1811,301 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(';'); BEGIN(UsingAlias); } -<UsingDirective>{SCOPENAME} { yyextra->current->name=removeRedundantWhiteSpace(yytext); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Using); - } -<Using>";" { BEGIN(FindMembers); } -<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl - QCString n=yytext; - addType(yyscanner); - yyextra->current->name=n.left(n.length()-2); - } -<FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type! +<UsingDirective>{SCOPENAME} { yyextra->current->name=removeRedundantWhiteSpace(yytext); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Using); + } +<Using>";" { BEGIN(FindMembers); } +<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl + QCString n=yytext; + addType(yyscanner); + yyextra->current->name=n.left(n.length()-2); + } +<FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type! yyextra->roundCount=0; - yyextra->sharpCount=0; - lineCount(yyscanner); - addType(yyscanner); - yyextra->current->name=yytext; - yyextra->current->name=yyextra->current->name.stripWhiteSpace(); - //yyextra->current->scopeSpec.resize(0); - // yyextra->currentTemplateSpec = &yyextra->current->scopeSpec; - if (nameIsOperator(yyextra->current->name)) - BEGIN( Operator ); - else - BEGIN( EndTemplate ); - } -<FindMemberName>{SCOPENAME}{BN}*/"<" { - yyextra->sharpCount=0; - yyextra->roundCount=0; - lineCount(yyscanner); - yyextra->current->name+=((QCString)yytext).stripWhiteSpace(); - //yyextra->current->memberSpec.resize(0); - // yyextra->currentTemplateSpec = &yyextra->current->memberSpec; - if (nameIsOperator(yyextra->current->name)) - BEGIN( Operator ); - else - BEGIN( EndTemplate ); - } -<EndTemplate>"<<<" { - if (!yyextra->insidePHP) - { - REJECT; - } - else - { + yyextra->sharpCount=0; + lineCount(yyscanner); + addType(yyscanner); + yyextra->current->name=yytext; + yyextra->current->name=yyextra->current->name.stripWhiteSpace(); + //yyextra->current->scopeSpec.resize(0); + // yyextra->currentTemplateSpec = &yyextra->current->scopeSpec; + if (nameIsOperator(yyextra->current->name)) + BEGIN( Operator ); + else + BEGIN( EndTemplate ); + } +<FindMemberName>{SCOPENAME}{BN}*/"<" { + yyextra->sharpCount=0; + yyextra->roundCount=0; + lineCount(yyscanner); + yyextra->current->name+=((QCString)yytext).stripWhiteSpace(); + //yyextra->current->memberSpec.resize(0); + // yyextra->currentTemplateSpec = &yyextra->current->memberSpec; + if (nameIsOperator(yyextra->current->name)) + BEGIN( Operator ); + else + BEGIN( EndTemplate ); + } +<EndTemplate>"<<<" { + if (!yyextra->insidePHP) + { + REJECT; + } + else + { yyextra->lastHereDocContext = YY_START; - BEGIN(HereDoc); - } - } -<ClassTemplSpec,EndTemplate>"<<" { - yyextra->current->name+=yytext; - // *yyextra->currentTemplateSpec+=yytext; - } -<EndTemplate>"<" { + BEGIN(HereDoc); + } + } +<ClassTemplSpec,EndTemplate>"<<" { + yyextra->current->name+=yytext; + // *yyextra->currentTemplateSpec+=yytext; + } +<EndTemplate>"<" { if (yyextra->roundCount==0) { - // *yyextra->currentTemplateSpec+='<'; - yyextra->sharpCount++; - } - yyextra->current->name+=yytext; - } -<ClassTemplSpec,EndTemplate>">>" { - if (yyextra->insideJava || yyextra->insideCS || yyextra->insideCli || yyextra->roundCount==0) - { - unput('>'); - unput(' '); - unput('>'); - } - else - { - yyextra->current->name+=yytext; - } - // *yyextra->currentTemplateSpec+=yytext; - } -<EndTemplate>">" { - yyextra->current->name+='>'; - // *yyextra->currentTemplateSpec+='>'; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - //printf("Found %s\n",yyextra->current->name.data()); - BEGIN(FindMembers); - } - } -<EndTemplate>">"{BN}*"(" { - lineCount(yyscanner); - yyextra->current->name+='>'; - // *yyextra->currentTemplateSpec+='>'; - 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(); - yyextra->copyArgString = &yyextra->current->args; - //printf("Found %s\n",yyextra->current->name.data()); - BEGIN( ReadFuncArgType ) ; - } - } + // *yyextra->currentTemplateSpec+='<'; + yyextra->sharpCount++; + } + yyextra->current->name+=yytext; + } +<ClassTemplSpec,EndTemplate>">>" { + if (yyextra->insideJava || yyextra->insideCS || yyextra->insideCli || yyextra->roundCount==0) + { + unput('>'); + unput(' '); + unput('>'); + } + else + { + yyextra->current->name+=yytext; + } + // *yyextra->currentTemplateSpec+=yytext; + } +<EndTemplate>">" { + yyextra->current->name+='>'; + // *yyextra->currentTemplateSpec+='>'; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + //printf("Found %s\n",yyextra->current->name.data()); + BEGIN(FindMembers); + } + } +<EndTemplate>">"{BN}*"(" { + lineCount(yyscanner); + yyextra->current->name+='>'; + // *yyextra->currentTemplateSpec+='>'; + 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(); + yyextra->copyArgString = &yyextra->current->args; + //printf("Found %s\n",yyextra->current->name.data()); + BEGIN( ReadFuncArgType ) ; + } + } <EndTemplate>">"{BN}*/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance - lineCount(yyscanner); - yyextra->current->name+='>'; + lineCount(yyscanner); + yyextra->current->name+='>'; if (yyextra->roundCount==0) { - BEGIN(FindMembers); - } - } -<EndTemplate>">"{BN}*/"::" { - lineCount(yyscanner); - yyextra->current->name+='>'; - // *yyextra->currentTemplateSpec+='>'; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - BEGIN(FindMemberName); - } - } + BEGIN(FindMembers); + } + } +<EndTemplate>">"{BN}*/"::" { + lineCount(yyscanner); + yyextra->current->name+='>'; + // *yyextra->currentTemplateSpec+='>'; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + BEGIN(FindMemberName); + } + } <ClassTemplSpec,EndTemplate>"(" { yyextra->current->name+=*yytext; - yyextra->roundCount++; + yyextra->roundCount++; } <ClassTemplSpec,EndTemplate>")" { yyextra->current->name+=*yytext; - if (yyextra->roundCount>0) yyextra->roundCount--; - } -<EndTemplate>. { - yyextra->current->name+=*yytext; - // *yyextra->currentTemplateSpec+=*yytext; - } -<FindMembers>"define"{BN}*"("{BN}*["'] { - if (yyextra->insidePHP) - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( DefinePHP ); - } - else - REJECT; - } + if (yyextra->roundCount>0) yyextra->roundCount--; + } +<EndTemplate>. { + yyextra->current->name+=*yytext; + // *yyextra->currentTemplateSpec+=*yytext; + } +<FindMembers>"define"{BN}*"("{BN}*["'] { + if (yyextra->insidePHP) + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( DefinePHP ); + } + else + REJECT; + } <CopyHereDoc>{ID} { // PHP heredoc - yyextra->delimiter = yytext; + yyextra->delimiter = yytext; *yyextra->pCopyHereDocGString += yytext; - BEGIN(CopyHereDocEnd); + BEGIN(CopyHereDocEnd); } -<CopyHereDoc>"'"{ID}/"'" { // PHP nowdoc - yyextra->delimiter = &yytext[1]; +<CopyHereDoc>"'"{ID}/"'" { // PHP nowdoc + yyextra->delimiter = &yytext[1]; *yyextra->pCopyHereDocGString += yytext; - BEGIN(CopyHereDocEnd); - } -<HereDoc>{ID} { // PHP heredoc - yyextra->delimiter = yytext; - BEGIN(HereDocEnd); - } -<HereDoc>"'"{ID}/"'" { // PHP nowdoc - yyextra->delimiter = &yytext[1]; - BEGIN(HereDocEnd); - } -<HereDocEnd>^{ID} { // id at start of the line could mark the end of the block - if (yyextra->delimiter==yytext) // it is the end marker - { - BEGIN(yyextra->lastHereDocContext); - } - } -<HereDocEnd>. { } -<CopyHereDocEnd>^{ID} { // id at start of the line could mark the end of the block + BEGIN(CopyHereDocEnd); + } +<HereDoc>{ID} { // PHP heredoc + yyextra->delimiter = yytext; + BEGIN(HereDocEnd); + } +<HereDoc>"'"{ID}/"'" { // PHP nowdoc + yyextra->delimiter = &yytext[1]; + BEGIN(HereDocEnd); + } +<HereDocEnd>^{ID} { // id at start of the line could mark the end of the block + if (yyextra->delimiter==yytext) // it is the end marker + { + BEGIN(yyextra->lastHereDocContext); + } + } +<HereDocEnd>. { } +<CopyHereDocEnd>^{ID} { // id at start of the line could mark the end of the block *yyextra->pCopyHereDocGString += yytext; - if (yyextra->delimiter==yytext) // it is the end marker - { - BEGIN(yyextra->lastHereDocContext); - } - } -<CopyHereDocEnd>\n { + if (yyextra->delimiter==yytext) // it is the end marker + { + BEGIN(yyextra->lastHereDocContext); + } + } +<CopyHereDocEnd>\n { lineCount(yyscanner); *yyextra->pCopyHereDocGString += yytext; } -<CopyHereDocEnd>{ID} { +<CopyHereDocEnd>{ID} { *yyextra->pCopyHereDocGString += yytext; } -<CopyHereDocEnd>. { +<CopyHereDocEnd>. { *yyextra->pCopyHereDocGString += yytext; } -<FindMembers>"Q_OBJECT" { // Qt object macro - } -<FindMembers>"Q_PROPERTY" { // Qt property declaration - yyextra->current->protection = Public ; // see bug734245 & bug735462 - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->type.resize(0); - BEGIN(QtPropType); - } -<QtPropType>"(" { // start of property arguments - } -<QtPropAttr>")" { // end of property arguments - unput(';'); - BEGIN(FindMembers); - } -<QtPropType>{B}+ { - yyextra->current->name+=yytext; - } -<QtPropType>"*" { - yyextra->current->type+= yyextra->current->name; - yyextra->current->type+= yytext; - yyextra->current->name=""; - } -<QtPropType>({TSCOPE}"::")*{TSCOPE} { - yyextra->current->type+= yyextra->current->name; - yyextra->current->name=yytext; - } -<QtPropType,QtPropAttr>{B}+"READ"{B}+ { - yyextra->current->spec |= Entry::Readable; - BEGIN(QtPropRead); - } -<QtPropType,QtPropAttr>{B}+"WRITE"{B}+ { - yyextra->current->spec |= Entry::Writable; - BEGIN(QtPropWrite); - } -<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; - BEGIN(QtPropAttr); - } -<QtPropWrite>{ID} { - yyextra->current->write = yytext; - BEGIN(QtPropAttr); - } +<FindMembers>"Q_OBJECT" { // Qt object macro + } +<FindMembers>"Q_PROPERTY" { // Qt property declaration + yyextra->current->protection = Public ; // see bug734245 & bug735462 + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->type.resize(0); + BEGIN(QtPropType); + } +<QtPropType>"(" { // start of property arguments + } +<QtPropAttr>")" { // end of property arguments + unput(';'); + BEGIN(FindMembers); + } +<QtPropType>{B}+ { + yyextra->current->name+=yytext; + } +<QtPropType>"*" { + yyextra->current->type+= yyextra->current->name; + yyextra->current->type+= yytext; + yyextra->current->name=""; + } +<QtPropType>({TSCOPE}"::")*{TSCOPE} { + yyextra->current->type+= yyextra->current->name; + yyextra->current->name=yytext; + } +<QtPropType,QtPropAttr>{B}+"READ"{B}+ { + yyextra->current->spec |= Entry::Readable; + BEGIN(QtPropRead); + } +<QtPropType,QtPropAttr>{B}+"WRITE"{B}+ { + yyextra->current->spec |= Entry::Writable; + BEGIN(QtPropWrite); + } +<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; + BEGIN(QtPropAttr); + } +<QtPropWrite>{ID} { + yyextra->current->write = yytext; + BEGIN(QtPropAttr); + } <FindMembers>"friend"{BN}+("class"|"union"|"struct"){BN}+ { - yyextra->current->name=yytext; - BEGIN(FindMembers); - } -<FindMembers,FindMemberName>{SCOPENAME} { + yyextra->current->name=yytext; + BEGIN(FindMembers); + } +<FindMembers,FindMemberName>{SCOPENAME} { + if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - yyextra->yyBegColNr=yyextra->yyColNr; - yyextra->yyBegLineNr=yyextra->yyLineNr; - lineCount(yyscanner); + yyextra->yyBegColNr=yyextra->yyColNr; + yyextra->yyBegLineNr=yyextra->yyLineNr; + lineCount(yyscanner); if (yyextra->insideIDL && yyleng==9 && qstrcmp(yytext,"cpp_quote")==0) - { - BEGIN(CppQuote); - } - else if ((yyextra->insideIDL || yyextra->insideJava || yyextra->insideD) && yyleng==6 && qstrcmp(yytext,"import")==0) - { - if (yyextra->insideIDL) - BEGIN(NextSemi); - else // yyextra->insideJava or yyextra->insideD - BEGIN(JavaImport); - } - else if (yyextra->insidePHP && qstrcmp(yytext,"use")==0) - { - BEGIN(PHPUse); - } - else if (yyextra->insideJava && qstrcmp(yytext,"package")==0) - { - lineCount(yyscanner); - BEGIN(PackageName); - } - else if (yyextra->insideIDL && qstrcmp(yytext,"case")==0) - { - BEGIN(IDLUnionCase); - } - else if (yyextra->insideTryBlock && qstrcmp(yytext,"catch")==0) - { - yyextra->insideTryBlock=FALSE; - BEGIN(TryFunctionBlock); - } + { + BEGIN(CppQuote); + } + else if ((yyextra->insideIDL || yyextra->insideJava || yyextra->insideD) && yyleng==6 && qstrcmp(yytext,"import")==0) + { + if (yyextra->insideIDL) + BEGIN(NextSemi); + else // yyextra->insideJava or yyextra->insideD + BEGIN(JavaImport); + } + else if (yyextra->insidePHP && qstrcmp(yytext,"use")==0) + { + BEGIN(PHPUse); + } + else if (yyextra->insideJava && qstrcmp(yytext,"package")==0) + { + lineCount(yyscanner); + BEGIN(PackageName); + } + else if (yyextra->insideIDL && qstrcmp(yytext,"case")==0) + { + BEGIN(IDLUnionCase); + } + else if (yyextra->insideTryBlock && qstrcmp(yytext,"catch")==0) + { + yyextra->insideTryBlock=FALSE; + BEGIN(TryFunctionBlock); + } else if (yyextra->insideCpp && qstrcmp(yytext,"alignas")==0) { yyextra->lastAlignAsContext = YY_START; BEGIN(AlignAs); } - else if (yyextra->insideJS && qstrcmp(yytext,"var")==0) - { // javascript variable - yyextra->current->type="var"; - } - else if (yyextra->insideJS && qstrcmp(yytext,"function")==0) - { // javascript function - yyextra->current->type="function"; - } - else if (yyextra->insideCS && qstrcmp(yytext,"this")==0) - { - // C# indexer - addType(yyscanner); - yyextra->current->name="this"; - BEGIN(CSIndexer); - } + else if (yyextra->insideJS && qstrcmp(yytext,"var")==0) + { // javascript variable + yyextra->current->type="var"; + } + else if (yyextra->insideJS && qstrcmp(yytext,"function")==0) + { // javascript function + yyextra->current->type="function"; + } + else if (yyextra->insideCS && qstrcmp(yytext,"this")==0) + { + // C# indexer + addType(yyscanner); + yyextra->current->name="this"; + BEGIN(CSIndexer); + } else if (yyextra->insideCpp && qstrcmp(yytext,"static_assert")==0) { // C++11 static_assert @@ -2111,7 +2114,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else if (yyextra->insideCpp && qstrcmp(yytext,"decltype")==0) { // C++11 decltype(x) - yyextra->current->type+=yytext; + yyextra->current->type+=yytext; BEGIN(DeclType); } else if (yyextra->insideSlice && qstrcmp(yytext,"optional")==0) @@ -2127,88 +2130,88 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->lastModifierContext = YY_START; BEGIN(SliceOptional); } - else - { - if (YY_START==FindMembers) - { - addType(yyscanner); - } - bool javaLike = yyextra->insideJava || yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS; - if (javaLike && qstrcmp(yytext,"public")==0) - { - yyextra->current->protection = Public; - } - else if (javaLike && qstrcmp(yytext,"protected")==0) - { - yyextra->current->protection = Protected; - } - else if ((yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS) && qstrcmp(yytext,"internal")==0) - { - yyextra->current->protection = Package; - } - else if (javaLike && qstrcmp(yytext,"private")==0) - { - yyextra->current->protection = Private; - } - else if (javaLike && qstrcmp(yytext,"static")==0) - { - if (YY_START==FindMembers) - yyextra->current->name = yytext; - else - yyextra->current->name += yytext; - yyextra->current->stat = TRUE; - } - else - { - if (YY_START==FindMembers) - yyextra->current->name = yytext; - else - yyextra->current->name += yytext; - if (yyextra->current->name.left(7)=="static ") - { - yyextra->current->stat = TRUE; - yyextra->current->name= yyextra->current->name.mid(7); - } - else if (yyextra->current->name.left(7)=="inline ") - { - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type="inline"; - } - else - { - yyextra->current->type+="inline "; - } - yyextra->current->name= yyextra->current->name.mid(7); - } - else if (yyextra->current->name.left(6)=="const ") - { - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type="const"; - } - else - { - yyextra->current->type+="const "; - } - yyextra->current->name=yyextra->current->name.mid(6); - } - } - QCString tmp=yytext; - if (nameIsOperator(tmp)) + else + { + if (YY_START==FindMembers) + { + addType(yyscanner); + } + bool javaLike = yyextra->insideJava || yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS; + if (javaLike && qstrcmp(yytext,"public")==0) + { + yyextra->current->protection = Public; + } + else if (javaLike && qstrcmp(yytext,"protected")==0) + { + yyextra->current->protection = Protected; + } + else if ((yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS) && qstrcmp(yytext,"internal")==0) + { + yyextra->current->protection = Package; + } + else if (javaLike && qstrcmp(yytext,"private")==0) + { + yyextra->current->protection = Private; + } + else if (javaLike && qstrcmp(yytext,"static")==0) { - BEGIN( Operator ); + if (YY_START==FindMembers) + yyextra->current->name = yytext; + else + yyextra->current->name += yytext; + yyextra->current->stat = TRUE; } - else + else + { + if (YY_START==FindMembers) + yyextra->current->name = yytext; + else + yyextra->current->name += yytext; + if (yyextra->current->name.left(7)=="static ") + { + yyextra->current->stat = TRUE; + yyextra->current->name= yyextra->current->name.mid(7); + } + else if (yyextra->current->name.left(7)=="inline ") + { + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type="inline"; + } + else + { + yyextra->current->type+="inline "; + } + yyextra->current->name= yyextra->current->name.mid(7); + } + else if (yyextra->current->name.left(6)=="const ") + { + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type="const"; + } + else + { + yyextra->current->type+="const "; + } + yyextra->current->name=yyextra->current->name.mid(6); + } + } + QCString tmp=yytext; + if (nameIsOperator(tmp)) + { + BEGIN( Operator ); + } + else { - yyextra->externC=FALSE; // see bug759247 - BEGIN(FindMembers); + yyextra->externC=FALSE; // see bug759247 + BEGIN(FindMembers); } - } - } + } + } <StaticAssert>"(" { - yyextra->lastSkipRoundContext = FindMembers; - yyextra->roundCount=0; + yyextra->lastSkipRoundContext = FindMembers; + yyextra->roundCount=0; BEGIN(SkipRound); } <StaticAssert>{BN}+ { lineCount(yyscanner); } @@ -2217,10 +2220,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(FindMembers); } <DeclType>"(" { - yyextra->current->type+=yytext; - yyextra->lastRoundContext=FindMembers; - yyextra->pCopyRoundString=&yyextra->current->type; - yyextra->roundCount=0; + yyextra->current->type+=yytext; + yyextra->lastRoundContext=FindMembers; + yyextra->pCopyRoundString=&yyextra->current->type; + yyextra->roundCount=0; BEGIN(CopyRound); } <DeclType>{BN}+ { lineCount(yyscanner); } @@ -2228,433 +2231,446 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(*yytext); BEGIN(FindMembers); } -<CSIndexer>"["[^\n\]]*"]" { - yyextra->current->name+=removeRedundantWhiteSpace(yytext); - BEGIN(FindMembers); - } -<FindMembers>[0-9]{ID} { // some number where we did not expect one - } -<FindMembers>"." { - if (yyextra->insideJava || yyextra->insideCS || yyextra->insideD) - { - yyextra->current->name+="."; - } - } -<FindMembers>"::" { - yyextra->current->name+=yytext; - } -<CppQuote>"("{B}*"\"" { - yyextra->insideCppQuote=TRUE; - BEGIN(FindMembers); - } +<CSIndexer>"["[^\n\]]*"]" { + yyextra->current->name+=removeRedundantWhiteSpace(yytext); + BEGIN(FindMembers); + } +<FindMembers>[0-9]{ID} { // some number where we did not expect one + } +<FindMembers>"." { + if (yyextra->insideJava || yyextra->insideCS || yyextra->insideD) + { + yyextra->current->name+="."; + } + } +<FindMembers>"::" { + yyextra->current->name+=yytext; + } +<CppQuote>"("{B}*"\"" { + yyextra->insideCppQuote=TRUE; + BEGIN(FindMembers); + } <IDLUnionCase>"::" -<IDLUnionCase>":" { BEGIN(FindMembers); } -<IDLUnionCase>\n { lineCount(yyscanner); } +<IDLUnionCase>":" { BEGIN(FindMembers); } +<IDLUnionCase>\n { lineCount(yyscanner); } <IDLUnionCase>. -<TryFunctionBlock>\n { lineCount(yyscanner); } -<TryFunctionBlock>"{" { - yyextra->curlyCount=0; - yyextra->lastCurlyContext = TryFunctionBlockEnd ; - BEGIN( SkipCurly ); - } +<TryFunctionBlock>\n { lineCount(yyscanner); } +<TryFunctionBlock>"{" { + yyextra->curlyCount=0; + yyextra->lastCurlyContext = TryFunctionBlockEnd ; + BEGIN( SkipCurly ); + } <TryFunctionBlock>. -<TryFunctionBlockEnd>{BN}*"catch" { lineCount(yyscanner); BEGIN(TryFunctionBlock); // {BN}* added to fix bug 611193 - } -<TryFunctionBlockEnd>\n { unput(*yytext); // rule added to fix bug id 601138 - BEGIN( FindMembers ); - } -<TryFunctionBlockEnd>. { unput(*yytext); - BEGIN( FindMembers ); - } -<EndCppQuote>")" { - yyextra->insideCppQuote=FALSE; - BEGIN(FindMembers); - } -<FindMembers,FindFields>{B}*"#" { if (yyextra->insidePHP) - REJECT; - yyextra->lastCPPContext = YY_START; - BEGIN( SkipCPP ) ; - } -<FindMembers,FindFields>{B}*"#"{B}*("cmake")?"define" { - if (yyextra->insidePHP) - REJECT; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; +<TryFunctionBlockEnd>{BN}*"catch" { lineCount(yyscanner); BEGIN(TryFunctionBlock); // {BN}* added to fix bug 611193 + } +<TryFunctionBlockEnd>\n { unput(*yytext); // rule added to fix bug id 601138 + BEGIN( FindMembers ); + } +<TryFunctionBlockEnd>. { unput(*yytext); + BEGIN( FindMembers ); + } +<EndCppQuote>")" { + yyextra->insideCppQuote=FALSE; + BEGIN(FindMembers); + } +<FindMembers,FindFields>{B}*"#" { if (yyextra->insidePHP) + REJECT; + yyextra->lastCPPContext = YY_START; + BEGIN( SkipCPP ) ; + } +<FindMembers,FindFields>{B}*"#"{B}*("cmake")?"define" { + if (yyextra->insidePHP) + REJECT; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->lastDefineContext = YY_START; - BEGIN( Define ); - } -<FindMembers,ReadBody,ReadNSBody,ReadBodyIntf,SkipCurly,SkipCurlyCpp>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + BEGIN( Define ); + } +<FindMembers,ReadBody,ReadNSBody,ReadBodyIntf,SkipCurly,SkipCurlyCpp>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ yyextra->yyLineNr = atoi(&yytext[1]); - //printf("setting line number to %d\n",yyextra->yyLineNr); - yyextra->lastPreLineCtrlContext = YY_START; - if (YY_START==ReadBody || - YY_START==ReadNSBody || - YY_START==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } - BEGIN( PreLineCtrl ); - } -<PreLineCtrl>"\""[^\n\"]*"\"" { - yyextra->yyFileName = stripQuotes(yytext); - if (yyextra->lastPreLineCtrlContext==ReadBody || - yyextra->lastPreLineCtrlContext==ReadNSBody || - yyextra->lastPreLineCtrlContext==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } - } -<PreLineCtrl>. { - if (yyextra->lastPreLineCtrlContext==ReadBody || - yyextra->lastPreLineCtrlContext==ReadNSBody || - yyextra->lastPreLineCtrlContext==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } - } -<PreLineCtrl>\n { - if (yyextra->lastPreLineCtrlContext==ReadBody || - yyextra->lastPreLineCtrlContext==ReadNSBody || - yyextra->lastPreLineCtrlContext==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } + //printf("setting line number to %d\n",yyextra->yyLineNr); + yyextra->lastPreLineCtrlContext = YY_START; + if (YY_START==ReadBody || + YY_START==ReadNSBody || + YY_START==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } + BEGIN( PreLineCtrl ); + } +<PreLineCtrl>"\""[^\n\"]*"\"" { + yyextra->yyFileName = stripQuotes(yytext); + if (yyextra->lastPreLineCtrlContext==ReadBody || + yyextra->lastPreLineCtrlContext==ReadNSBody || + yyextra->lastPreLineCtrlContext==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } + } +<PreLineCtrl>. { + if (yyextra->lastPreLineCtrlContext==ReadBody || + yyextra->lastPreLineCtrlContext==ReadNSBody || + yyextra->lastPreLineCtrlContext==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } + } +<PreLineCtrl>\n { + if (yyextra->lastPreLineCtrlContext==ReadBody || + yyextra->lastPreLineCtrlContext==ReadNSBody || + yyextra->lastPreLineCtrlContext==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } lineCount(yyscanner); - BEGIN( yyextra->lastPreLineCtrlContext ); - } + BEGIN( yyextra->lastPreLineCtrlContext ); + } <SkipCPP>. -<SkipCPP>\\[\r]*"\n"[\r]* { lineCount(yyscanner); } -<SkipCPP>[\r]*\n[\r]* { lineCount(yyscanner); - BEGIN( yyextra->lastCPPContext) ; - } -<Define>{ID}{B}*"(" { - yyextra->current->name = yytext; - 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; - BEGIN( ReadFuncArgType ) ; - } +<SkipCPP>\\[\r]*"\n"[\r]* { lineCount(yyscanner); } +<SkipCPP>[\r]*\n[\r]* { lineCount(yyscanner); + BEGIN( yyextra->lastCPPContext) ; + } +<Define>{ID}{B}*"(" { + yyextra->current->name = yytext; + 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; + BEGIN( ReadFuncArgType ) ; + } /* -<DefineArg>")" { - //printf("Define with args\n"); - yyextra->current->args += ')'; - BEGIN( DefineEnd ); - } -<DefineArg>. { - yyextra->current->args += *yytext; - } +<DefineArg>")" { + //printf("Define with args\n"); + yyextra->current->args += ')'; + BEGIN( DefineEnd ); + } +<DefineArg>. { + yyextra->current->args += *yytext; + } */ -<Define>{ID} { - //printf("Define '%s' without args\n",yytext); +<Define>{ID} { + //printf("Define '%s' without args\n",yytext); if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { 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); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->type.resize(0); - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::DEFINE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + 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); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->type.resize(0); + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + 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); - } -<DefinePHPEnd>";" { - //printf("End define\n"); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->type.resize(0); + initEntry(yyscanner); + BEGIN(yyextra->lastDefineContext); + } +<DefinePHPEnd>";" { + //printf("End define\n"); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->type.resize(0); yyextra->current->type = "const"; QCString init = yyextra->current->initializer.data(); - init = init.simplifyWhiteSpace(); - init = init.left(init.length()-1); + init = init.simplifyWhiteSpace(); + init = init.left(init.length()-1); yyextra->current->initializer = init; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(FindMembers); - } + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(FindMembers); + } <DefinePHPEnd>. -<DefineEnd>\\[\r]?\n { +<DefineEnd>\\[\r]?\n { lineCount(yyscanner); - } -<DefineEnd>\" { - if (yyextra->insideIDL && yyextra->insideCppQuote) - { - BEGIN(EndCppQuote); - } - else - { - yyextra->lastStringContext=DefineEnd; - BEGIN(SkipString); - } - } -<DefineEnd>. -<DefinePHP>{ID}["']{BN}*","{BN}* { - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - 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; - BEGIN( GCopyRound ); - } - -<FindMembers>[\^%] { // ^ and % are C++/CLI extensions - if (yyextra->insideCli) - { - addType(yyscanner); - yyextra->current->name = yytext ; - } - else - { - REJECT; - } - } -<FindMembers>[*&]+ { - yyextra->current->name += yytext ; - addType(yyscanner); - } -<FindMembers,MemberSpec,Function,NextSemi,EnumBaseType,BitFields,ReadInitializer,OldStyleArgs,DefinePHPEnd>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { - if (yyextra->current->bodyLine==-1) - { - yyextra->current->bodyLine=yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + } +<DefineEnd>\" { + if (yyextra->insideIDL && yyextra->insideCppQuote) + { + BEGIN(EndCppQuote); + } + else + { + yyextra->lastStringContext=DefineEnd; + BEGIN(SkipString); + } + } +<DefineEnd>. +<DefinePHP>{ID}["']{BN}*","{BN}* { + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + 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; + BEGIN( GCopyRound ); + } + +<FindMembers>[\^%] { // ^ and % are C++/CLI extensions + if (yyextra->insideCli) + { + addType(yyscanner); + yyextra->current->name = yytext ; + } + else + { + REJECT; + } + } +<FindMembers>[*&]+ { + yyextra->current->name += yytext ; + addType(yyscanner); + } +<FindMembers,MemberSpec,Function,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs,DefinePHPEnd>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { + if (yyextra->current->bodyLine==-1) + { + yyextra->current->bodyLine=yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; //printf("indent=%d\n",computeIndent(yytext+1,yyextra->column)); - lineCount(yyscanner); + lineCount(yyscanner); - yyextra->docBlockTerm = ';'; + yyextra->docBlockTerm = ';'; if (YY_START==EnumBaseType && yyextra->current->section==Entry::ENUM_SEC) { yyextra->current->bitfields = ":"+yyextra->current->args; yyextra->current->args.resize(0); yyextra->current->section=Entry::VARIABLE_SEC; } - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } -<MemberSpec,FindFields,FindMembers,NextSemi,EnumBaseType,BitFields,ReadInitializer,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" { - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } +<MemberSpec,FindFields,FindMembers,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" { + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - lineCount(yyscanner); + lineCount(yyscanner); - yyextra->docBlockTerm = ','; + yyextra->docBlockTerm = ','; if (YY_START==EnumBaseType && yyextra->current->section==Entry::ENUM_SEC) { yyextra->current->bitfields = ":"+yyextra->current->args; yyextra->current->args.resize(0); yyextra->current->section=Entry::VARIABLE_SEC; } - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } -<DefineEnd,FindFields,FindFieldArg,ReadInitializer,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" { - if (yyextra->current->bodyLine==-1) - { - yyextra->current->bodyLine=yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } +<DefineEnd,FindFields,FindFieldArg,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" { + if (yyextra->current->bodyLine==-1) + { + yyextra->current->bodyLine=yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - lineCount(yyscanner); - - yyextra->docBlockTerm = 0; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } - -<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { - //handleGroupStartCommand(yyextra->current->name); + lineCount(yyscanner); + + yyextra->docBlockTerm = 0; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } + +<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { + //handleGroupStartCommand(yyextra->current->name); if (yyextra->previous && yyextra->previous->section==Entry::GROUPDOC_SEC) - { - // link open command to the group defined in the yyextra->previous entry - yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); - } - else - { - // link open command to the yyextra->current entry - yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); - } - //yyextra->current = tmp; - initEntry(yyscanner); - if (yytext[1]=='/') - { - if (yytext[2]=='!' || yytext[2]=='/') - { - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = FALSE; - yyextra->docBlock.resize(0); - yyextra->docBlockTerm = 0; - startCommentBlock(yyscanner,TRUE); - BEGIN(DocLine); - } - else - { - yyextra->lastCContext=YY_START; - BEGIN(SkipCxxComment); - } - } - else - { - if (yytext[2]=='!' || yytext[2]=='*') - { - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlock.resize(0); - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); - yyextra->docBlockTerm = 0; - startCommentBlock(yyscanner,FALSE); - BEGIN(DocBlock); - } - else - { - yyextra->lastCContext=YY_START; - BEGIN(SkipComment); - } - } - } -<FindMembers,FindFields,ReadInitializer>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { - bool insideEnum = YY_START==FindFields || (YY_START==ReadInitializer && yyextra->lastInitializerContext==FindFields); // see bug746226 - 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; + { + // link open command to the group defined in the yyextra->previous entry + yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); + } + else + { + // link open command to the yyextra->current entry + yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); + } + //yyextra->current = tmp; + initEntry(yyscanner); + if (yytext[1]=='/') + { + if (yytext[2]=='!' || yytext[2]=='/') + { + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = FALSE; + yyextra->docBlock.resize(0); + yyextra->docBlockTerm = 0; + startCommentBlock(yyscanner,TRUE); + BEGIN(DocLine); + } + else + { + yyextra->lastCContext=YY_START; + BEGIN(SkipCxxComment); + } + } + else + { + if (yytext[2]=='!' || yytext[2]=='*') + { + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlock.resize(0); + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlockTerm = 0; + startCommentBlock(yyscanner,FALSE); + BEGIN(DocBlock); + } + else + { + yyextra->lastCContext=YY_START; + BEGIN(SkipComment); + } + } + } +<FindMembers,FindFields,ReadInitializer,ReadInitializerPtr>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { + bool insideEnum = YY_START==FindFields || ((YY_START==ReadInitializer || YY_START==ReadInitializerPtr) && yyextra->lastInitializerContext==FindFields); // see bug746226 + yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); + lineCount(yyscanner); + } +<FindMembers>"=>" { + if (!yyextra->insideCS) REJECT; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->initializer = yytext; + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->spec |= Entry::Gettable; + BEGIN(ReadInitializerPtr); + } +<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; - BEGIN(ReadInitializer); - } -<UNOIDLAttributeBlock>{BN}*[gs]"et"{BN}+"raises"{BN}*"("{BN}*{SCOPENAME}{BN}*(","{BN}*{SCOPENAME}{BN}*)*")"{BN}*";" { - lineCount(yyscanner); - yyextra->current->exception += " "; - yyextra->current->exception += removeRedundantWhiteSpace(yytext); - } -<UNOIDLAttributeBlock>"}" { - yyextra->current->exception += " }"; - BEGIN(FindMembers); - } + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; + BEGIN(ReadInitializer); + } +<UNOIDLAttributeBlock>{BN}*[gs]"et"{BN}+"raises"{BN}*"("{BN}*{SCOPENAME}{BN}*(","{BN}*{SCOPENAME}{BN}*)*")"{BN}*";" { + lineCount(yyscanner); + yyextra->current->exception += " "; + yyextra->current->exception += removeRedundantWhiteSpace(yytext); + } +<UNOIDLAttributeBlock>"}" { + yyextra->current->exception += " }"; + BEGIN(FindMembers); + } /* Read initializer rules */ -<ReadInitializer>"(" { - yyextra->lastRoundContext=YY_START; - yyextra->pCopyRoundGString=&yyextra->current->initializer; - yyextra->roundCount=0; - yyextra->current->initializer+=*yytext; - BEGIN(GCopyRound); - } -<ReadInitializer>"[" { +<ReadInitializer,ReadInitializerPtr>"(" { + yyextra->lastRoundContext=YY_START; + yyextra->pCopyRoundGString=&yyextra->current->initializer; + yyextra->roundCount=0; + yyextra->current->initializer+=*yytext; + BEGIN(GCopyRound); + } +<ReadInitializer,ReadInitializerPtr>"[" { if (!yyextra->insidePHP) REJECT; yyextra->lastSquareContext=YY_START; yyextra->pCopySquareGString=&yyextra->current->initializer; yyextra->squareCount=0; - yyextra->current->initializer+=*yytext; + yyextra->current->initializer+=*yytext; BEGIN(GCopySquare); } -<ReadInitializer>"{" { - yyextra->lastCurlyContext=YY_START; - yyextra->pCopyCurlyGString=&yyextra->current->initializer; - yyextra->curlyCount=0; - yyextra->current->initializer+=*yytext; - BEGIN(GCopyCurly); - } -<ReadInitializer>[;,] { - //printf(">> initializer '%s' <<\n",yyextra->current->initializer.data()); +<ReadInitializer,ReadInitializerPtr>"{" { + yyextra->lastCurlyContext=YY_START; + yyextra->pCopyCurlyGString=&yyextra->current->initializer; + yyextra->curlyCount=0; + yyextra->current->initializer+=*yytext; + BEGIN(GCopyCurly); + } +<ReadInitializer,ReadInitializerPtr>[;,] { + //printf(">> initializer '%s' <<\n",yyextra->current->initializer.data()); if (*yytext==';' && (yyextra->current_root->spec&Entry::Enum)) - { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(FindMembers); - } - else if (*yytext==';' || (yyextra->lastInitializerContext==FindFields && yyextra->initBracketCount==0)) // yyextra->initBracketCount==0 was added for bug 665778 - { - unput(*yytext); - BEGIN(yyextra->lastInitializerContext); - } - else if (*yytext==',' && yyextra->initBracketCount==0) // for "int a=0,b=0" - { - unput(*yytext); - BEGIN(yyextra->lastInitializerContext); - } - else - { - yyextra->current->initializer+=*yytext; - } - } -<ReadInitializer>{RAWBEGIN} { // C++11 raw string + { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(FindMembers); + } + else if (*yytext==';' || (yyextra->lastInitializerContext==FindFields && yyextra->initBracketCount==0)) // yyextra->initBracketCount==0 was added for bug 665778 + { + unput(*yytext); + if (YY_START == ReadInitializerPtr) yyextra->current->initializer.resize(0); + BEGIN(yyextra->lastInitializerContext); + } + else if (*yytext==',' && yyextra->initBracketCount==0) // for "int a=0,b=0" + { + unput(*yytext); + if (YY_START == ReadInitializerPtr) yyextra->current->initializer.resize(0); + BEGIN(yyextra->lastInitializerContext); + } + else + { + yyextra->current->initializer+=*yytext; + } + } +<ReadInitializer,ReadInitializerPtr>{RAWBEGIN} { // C++11 raw string if (!yyextra->insideCpp) - { + { REJECT; } else @@ -2691,7 +2707,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <RawString>{RAWEND} { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; QCString delimiter = yytext+1; delimiter=delimiter.left(delimiter.length()-1); if (delimiter==yyextra->delimiter) @@ -2701,265 +2717,265 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <RawString>[^)]+ { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; } <RawString>. { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; } <RawString>\n { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; lineCount(yyscanner); } -<ReadInitializer>\" { - if (yyextra->insideIDL && yyextra->insideCppQuote) - { - BEGIN(EndCppQuote); - } - else - { +<ReadInitializer,ReadInitializerPtr>\" { + if (yyextra->insideIDL && yyextra->insideCppQuote) + { + BEGIN(EndCppQuote); + } + else + { yyextra->lastStringContext=YY_START; - yyextra->current->initializer+=yytext; - yyextra->pCopyQuotedGString=&yyextra->current->initializer; - BEGIN(CopyGString); - } - } -<ReadInitializer>"->" { - yyextra->current->initializer+=yytext; - } -<ReadInitializer>"<<" { - yyextra->current->initializer+=yytext; - } -<ReadInitializer>">>" { - yyextra->current->initializer+=yytext; - } -<ReadInitializer>[<\[{(] { - yyextra->initBracketCount++; - yyextra->current->initializer+=*yytext; - } -<ReadInitializer>[>\]})] { - yyextra->initBracketCount--; - yyextra->current->initializer+=*yytext; - } -<ReadInitializer>\' { - if (yyextra->insidePHP) - { - yyextra->current->initializer+=yytext; + yyextra->current->initializer+=yytext; + yyextra->pCopyQuotedGString=&yyextra->current->initializer; + BEGIN(CopyGString); + } + } +<ReadInitializer,ReadInitializerPtr>"->" { + yyextra->current->initializer+=yytext; + } +<ReadInitializer,ReadInitializerPtr>"<<" { + yyextra->current->initializer+=yytext; + } +<ReadInitializer,ReadInitializerPtr>">>" { + yyextra->current->initializer+=yytext; + } +<ReadInitializer,ReadInitializerPtr>[<\[{(] { + yyextra->initBracketCount++; + yyextra->current->initializer+=*yytext; + } +<ReadInitializer,ReadInitializerPtr>[>\]})] { + yyextra->initBracketCount--; + yyextra->current->initializer+=*yytext; + } +<ReadInitializer,ReadInitializerPtr>\' { + if (yyextra->insidePHP) + { + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedGString = &yyextra->current->initializer; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - else - { - yyextra->current->initializer+=yytext; - } - } -<ReadInitializer>{CHARLIT} { - if (yyextra->insidePHP) - { - REJECT; - } - else - { - yyextra->current->initializer+=yytext; - } - } -<ReadInitializer>\n { - yyextra->current->initializer+=*yytext; + BEGIN(CopyPHPGString); + } + else + { + yyextra->current->initializer+=yytext; + } + } +<ReadInitializer,ReadInitializerPtr>{CHARLIT} { + if (yyextra->insidePHP) + { + REJECT; + } + else + { + yyextra->current->initializer+=yytext; + } + } +<ReadInitializer,ReadInitializerPtr>\n { + yyextra->current->initializer+=*yytext; lineCount(yyscanner); - } -<ReadInitializer>"@\"" { - //printf("yyextra->insideCS=%d\n",yyextra->insideCS); - yyextra->current->initializer+=yytext; - if (!yyextra->insideCS && !yyextra->insideObjC) - { - REJECT; - } - else - { - // C#/ObjC verbatim string - yyextra->lastSkipVerbStringContext=YY_START; - yyextra->pSkipVerbString=&yyextra->current->initializer; - BEGIN(SkipVerbString); - } - } -<SkipVerbString>[^\n"]+ { - *yyextra->pSkipVerbString+=yytext; - } -<SkipVerbString>"\"\"" { // quote escape - *yyextra->pSkipVerbString+=yytext; - } -<SkipVerbString>"\"" { - *yyextra->pSkipVerbString+=*yytext; - BEGIN(yyextra->lastSkipVerbStringContext); - } -<SkipVerbString>\n { - *yyextra->pSkipVerbString+=*yytext; + } +<ReadInitializer,ReadInitializerPtr>"@\"" { + //printf("yyextra->insideCS=%d\n",yyextra->insideCS); + yyextra->current->initializer+=yytext; + if (!yyextra->insideCS && !yyextra->insideObjC) + { + REJECT; + } + else + { + // C#/ObjC verbatim string + yyextra->lastSkipVerbStringContext=YY_START; + yyextra->pSkipVerbString=&yyextra->current->initializer; + BEGIN(SkipVerbString); + } + } +<SkipVerbString>[^\n"]+ { + *yyextra->pSkipVerbString+=yytext; + } +<SkipVerbString>"\"\"" { // quote escape + *yyextra->pSkipVerbString+=yytext; + } +<SkipVerbString>"\"" { + *yyextra->pSkipVerbString+=*yytext; + BEGIN(yyextra->lastSkipVerbStringContext); + } +<SkipVerbString>\n { + *yyextra->pSkipVerbString+=*yytext; lineCount(yyscanner); - } -<SkipVerbString>. { - *yyextra->pSkipVerbString+=*yytext; - } -<ReadInitializer>"?>" { - if (yyextra->insidePHP) - BEGIN( FindMembersPHP ); - else - yyextra->current->initializer+=yytext; - } -<ReadInitializer>. { - yyextra->current->initializer+=*yytext; - } + } +<SkipVerbString>. { + *yyextra->pSkipVerbString+=*yytext; + } +<ReadInitializer,ReadInitializerPtr>"?>" { + if (yyextra->insidePHP) + BEGIN( FindMembersPHP ); + else + yyextra->current->initializer+=yytext; + } +<ReadInitializer,ReadInitializerPtr>. { + yyextra->current->initializer+=*yytext; + } /* generic quoted string copy rules */ -<CopyString,CopyPHPString>\\. { - *yyextra->pCopyQuotedString+=yytext; - } -<CopyString>\" { - *yyextra->pCopyQuotedString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } -<CopyPHPString>\' { - *yyextra->pCopyQuotedString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } +<CopyString,CopyPHPString>\\. { + *yyextra->pCopyQuotedString+=yytext; + } +<CopyString>\" { + *yyextra->pCopyQuotedString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } +<CopyPHPString>\' { + *yyextra->pCopyQuotedString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } <CopyString,CopyPHPString>"/*"|"*/"|"//" { - *yyextra->pCopyQuotedString+=yytext; - } -<CopyString,CopyPHPString>\n { - *yyextra->pCopyQuotedString+=*yytext; + *yyextra->pCopyQuotedString+=yytext; + } +<CopyString,CopyPHPString>\n { + *yyextra->pCopyQuotedString+=*yytext; lineCount(yyscanner); - } -<CopyString,CopyPHPString>. { - *yyextra->pCopyQuotedString+=*yytext; - } + } +<CopyString,CopyPHPString>. { + *yyextra->pCopyQuotedString+=*yytext; + } /* generic quoted growable string copy rules */ -<CopyGString,CopyPHPGString>\\. { - *yyextra->pCopyQuotedGString+=yytext; - } -<CopyGString>\" { - *yyextra->pCopyQuotedGString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } -<CopyPHPGString>\' { - *yyextra->pCopyQuotedGString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } -<CopyGString,CopyPHPGString>"<?php" { // we had an odd number of quotes. - *yyextra->pCopyQuotedGString += yytext; - BEGIN( yyextra->lastStringContext ); - } +<CopyGString,CopyPHPGString>\\. { + *yyextra->pCopyQuotedGString+=yytext; + } +<CopyGString>\" { + *yyextra->pCopyQuotedGString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } +<CopyPHPGString>\' { + *yyextra->pCopyQuotedGString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } +<CopyGString,CopyPHPGString>"<?php" { // we had an odd number of quotes. + *yyextra->pCopyQuotedGString += yytext; + BEGIN( yyextra->lastStringContext ); + } <CopyGString,CopyPHPGString>"/*"|"*/"|"//" { - *yyextra->pCopyQuotedGString+=yytext; - } -<CopyGString,CopyPHPGString>\n { - *yyextra->pCopyQuotedGString+=*yytext; + *yyextra->pCopyQuotedGString+=yytext; + } +<CopyGString,CopyPHPGString>\n { + *yyextra->pCopyQuotedGString+=*yytext; lineCount(yyscanner); - } -<CopyGString,CopyPHPGString>. { - *yyextra->pCopyQuotedGString+=*yytext; - } + } +<CopyGString,CopyPHPGString>. { + *yyextra->pCopyQuotedGString+=*yytext; + } /* generic round bracket list copy rules */ -<CopyRound>\" { - *yyextra->pCopyRoundString+=*yytext; - yyextra->pCopyQuotedString=yyextra->pCopyRoundString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyString); - } -<CopyRound>"(" { - *yyextra->pCopyRoundString+=*yytext; - yyextra->roundCount++; - } -<CopyRound>")" { - *yyextra->pCopyRoundString+=*yytext; - if (--yyextra->roundCount<0) - BEGIN(yyextra->lastRoundContext); - } -<CopyRound>\n { +<CopyRound>\" { + *yyextra->pCopyRoundString+=*yytext; + yyextra->pCopyQuotedString=yyextra->pCopyRoundString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyString); + } +<CopyRound>"(" { + *yyextra->pCopyRoundString+=*yytext; + yyextra->roundCount++; + } +<CopyRound>")" { + *yyextra->pCopyRoundString+=*yytext; + if (--yyextra->roundCount<0) + BEGIN(yyextra->lastRoundContext); + } +<CopyRound>\n { lineCount(yyscanner); - *yyextra->pCopyRoundString+=*yytext; - } -<CopyRound>\' { - if (yyextra->insidePHP) - { - yyextra->current->initializer+=yytext; + *yyextra->pCopyRoundString+=*yytext; + } +<CopyRound>\' { + if (yyextra->insidePHP) + { + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedString = yyextra->pCopyRoundString; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPString); - } - else - { - *yyextra->pCopyRoundString+=yytext; - } - } -<CopyRound>{CHARLIT} { + BEGIN(CopyPHPString); + } + else + { + *yyextra->pCopyRoundString+=yytext; + } + } +<CopyRound>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyRoundString+=yytext; - } - } -<CopyRound>[^"'()\n,]+ { - *yyextra->pCopyRoundString+=yytext; - } -<CopyRound>. { - *yyextra->pCopyRoundString+=*yytext; - } + { + REJECT; + } + else + { + *yyextra->pCopyRoundString+=yytext; + } + } +<CopyRound>[^"'()\n,]+ { + *yyextra->pCopyRoundString+=yytext; + } +<CopyRound>. { + *yyextra->pCopyRoundString+=*yytext; + } /* generic round bracket list copy rules for growable strings */ -<GCopyRound>\" { - *yyextra->pCopyRoundGString+=*yytext; - yyextra->pCopyQuotedGString=yyextra->pCopyRoundGString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyGString); - } -<GCopyRound>"(" { - *yyextra->pCopyRoundGString+=*yytext; - yyextra->roundCount++; - } -<GCopyRound>")" { - *yyextra->pCopyRoundGString+=*yytext; - if (--yyextra->roundCount<0) - BEGIN(yyextra->lastRoundContext); - } -<GCopyRound>\n { +<GCopyRound>\" { + *yyextra->pCopyRoundGString+=*yytext; + yyextra->pCopyQuotedGString=yyextra->pCopyRoundGString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyGString); + } +<GCopyRound>"(" { + *yyextra->pCopyRoundGString+=*yytext; + yyextra->roundCount++; + } +<GCopyRound>")" { + *yyextra->pCopyRoundGString+=*yytext; + if (--yyextra->roundCount<0) + BEGIN(yyextra->lastRoundContext); + } +<GCopyRound>\n { lineCount(yyscanner); - *yyextra->pCopyRoundGString+=*yytext; - } -<GCopyRound>\' { - if (yyextra->insidePHP) - { - yyextra->current->initializer+=yytext; + *yyextra->pCopyRoundGString+=*yytext; + } +<GCopyRound>\' { + if (yyextra->insidePHP) + { + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedGString = yyextra->pCopyRoundGString; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - else - { - *yyextra->pCopyRoundGString+=yytext; - } - } -<GCopyRound>{CHARLIT} { + BEGIN(CopyPHPGString); + } + else + { + *yyextra->pCopyRoundGString+=yytext; + } + } +<GCopyRound>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyRoundGString+=yytext; - } - } -<GCopyRound>[^"'()\n\/,]+ { - *yyextra->pCopyRoundGString+=yytext; - } -<GCopyRound>. { - *yyextra->pCopyRoundGString+=*yytext; - } + { + REJECT; + } + else + { + *yyextra->pCopyRoundGString+=yytext; + } + } +<GCopyRound>[^"'()\n\/,]+ { + *yyextra->pCopyRoundGString+=yytext; + } +<GCopyRound>. { + *yyextra->pCopyRoundGString+=*yytext; + } /* generic square bracket list copy rules for growable strings, we should only enter here in case of php, left the test part as in GCopyRound to keep it compatible with the round bracket version */ <GCopySquare>\" { @@ -2984,7 +3000,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <GCopySquare>\' { if (yyextra->insidePHP) { - yyextra->current->initializer+=yytext; + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedGString = yyextra->pCopySquareGString; yyextra->lastStringContext=YY_START; BEGIN(CopyPHPGString); @@ -2994,14 +3010,14 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopySquareGString+=yytext; } } -<GCopySquare>{CHARLIT} { +<GCopySquare>{CHARLIT} { if (yyextra->insidePHP) { REJECT; } else { - *yyextra->pCopySquareGString+=yytext; + *yyextra->pCopySquareGString+=yytext; } } <GCopySquare>[^"\[\]\n\/,]+ { @@ -3012,230 +3028,230 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } /* generic curly bracket list copy rules */ -<CopyCurly>\" { - *yyextra->pCopyCurlyString+=*yytext; - yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyString); - } -<CopyCurly>\' { - *yyextra->pCopyCurlyString+=*yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPString); - } - } -<CopyCurly>"{" { - *yyextra->pCopyCurlyString+=*yytext; - yyextra->curlyCount++; - } -<CopyCurly>"}" { - *yyextra->pCopyCurlyString+=*yytext; - if (--yyextra->curlyCount<0) - BEGIN(yyextra->lastCurlyContext); - } -<CopyCurly>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyCurlyString+=yytext; - } - } -<CopyCurly>[^"'{}\/\n,]+ { - *yyextra->pCopyCurlyString+=yytext; - } -<CopyCurly>"/" { *yyextra->pCopyCurlyString+=yytext; } -<CopyCurly>\n { +<CopyCurly>\" { + *yyextra->pCopyCurlyString+=*yytext; + yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyString); + } +<CopyCurly>\' { + *yyextra->pCopyCurlyString+=*yytext; + if (yyextra->insidePHP) + { + yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyPHPString); + } + } +<CopyCurly>"{" { + *yyextra->pCopyCurlyString+=*yytext; + yyextra->curlyCount++; + } +<CopyCurly>"}" { + *yyextra->pCopyCurlyString+=*yytext; + if (--yyextra->curlyCount<0) + BEGIN(yyextra->lastCurlyContext); + } +<CopyCurly>{CHARLIT} { if (yyextra->insidePHP) + { + REJECT; + } + else + { + *yyextra->pCopyCurlyString+=yytext; + } + } +<CopyCurly>[^"'{}\/\n,]+ { + *yyextra->pCopyCurlyString+=yytext; + } +<CopyCurly>"/" { *yyextra->pCopyCurlyString+=yytext; } +<CopyCurly>\n { lineCount(yyscanner); - *yyextra->pCopyCurlyString+=*yytext; - } -<CopyCurly>. { - *yyextra->pCopyCurlyString+=*yytext; - } + *yyextra->pCopyCurlyString+=*yytext; + } +<CopyCurly>. { + *yyextra->pCopyCurlyString+=*yytext; + } /* generic curly bracket list copy rules for growable strings */ <GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"1"{B}*\n? { // start of included file marker } <GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"2"{B}*\n? { // end of included file marker - QCString line = QCString(yytext); - int s = line.find(' '); - int e = line.find('"',s); - yyextra->yyLineNr = line.mid(s,e-s).toInt(); - if (yytext[yyleng-1]=='\n') - { + QCString line = QCString(yytext); + int s = line.find(' '); + int e = line.find('"',s); + yyextra->yyLineNr = line.mid(s,e-s).toInt(); + if (yytext[yyleng-1]=='\n') + { lineCount(yyscanner); yyextra->column=0; - } - } -<GCopyCurly>\" { - *yyextra->pCopyCurlyGString+=*yytext; - yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyGString); - } -<GCopyCurly>\' { - *yyextra->pCopyCurlyGString+=*yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - } -<GCopyCurly>"{" { - *yyextra->pCopyCurlyGString+=*yytext; - yyextra->curlyCount++; - } -<GCopyCurly>"}" { - *yyextra->pCopyCurlyGString+=*yytext; - if (--yyextra->curlyCount<0) - BEGIN(yyextra->lastCurlyContext); - } -<GCopyCurly>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyCurlyGString+=yytext; - } - } -<GCopyCurly>[^"'{}\/\n,]+ { - *yyextra->pCopyCurlyGString+=yytext; - } -<GCopyCurly>[,]+ { - *yyextra->pCopyCurlyGString+=yytext; - } -<GCopyCurly>"/" { *yyextra->pCopyCurlyGString+=yytext; } -<GCopyCurly>\n { + } + } +<GCopyCurly>\" { + *yyextra->pCopyCurlyGString+=*yytext; + yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyGString); + } +<GCopyCurly>\' { + *yyextra->pCopyCurlyGString+=*yytext; + if (yyextra->insidePHP) + { + yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyPHPGString); + } + } +<GCopyCurly>"{" { + *yyextra->pCopyCurlyGString+=*yytext; + yyextra->curlyCount++; + } +<GCopyCurly>"}" { + *yyextra->pCopyCurlyGString+=*yytext; + if (--yyextra->curlyCount<0) + BEGIN(yyextra->lastCurlyContext); + } +<GCopyCurly>{CHARLIT} { if (yyextra->insidePHP) + { + REJECT; + } + else + { + *yyextra->pCopyCurlyGString+=yytext; + } + } +<GCopyCurly>[^"'{}\/\n,]+ { + *yyextra->pCopyCurlyGString+=yytext; + } +<GCopyCurly>[,]+ { + *yyextra->pCopyCurlyGString+=yytext; + } +<GCopyCurly>"/" { *yyextra->pCopyCurlyGString+=yytext; } +<GCopyCurly>\n { lineCount(yyscanner); - *yyextra->pCopyCurlyGString+=*yytext; - } -<GCopyCurly>. { - *yyextra->pCopyCurlyGString+=*yytext; - } + *yyextra->pCopyCurlyGString+=*yytext; + } +<GCopyCurly>. { + *yyextra->pCopyCurlyGString+=*yytext; + } /* ---------------------- */ -<FindMembers>":" { - if (yyextra->current->type.isEmpty() && +<FindMembers>":" { + if (yyextra->current->type.isEmpty() && yyextra->current->name=="enum") // see bug 69041, C++11 style anon enum: 'enum : unsigned int {...}' - { + { yyextra->current->section=Entry::ENUM_SEC; - yyextra->current->name.resize(0); + yyextra->current->name.resize(0); yyextra->current->args.resize(0); - BEGIN(EnumBaseType); - } - else + BEGIN(EnumBaseType); + } + else { if (yyextra->current->type.isEmpty()) // anonymous padding field, e.g. "int :7;" - { - addType(yyscanner); - yyextra->current->name.sprintf("__pad%d__",yyextra->padCount++); - } - BEGIN(BitFields); - yyextra->current->bitfields+=":"; - } - } -<BitFields>. { - yyextra->current->bitfields+=*yytext; - } -<EnumBaseType>. { - yyextra->current->args+=*yytext; - } -<EnumBaseType>\n { + { + addType(yyscanner); + yyextra->current->name.sprintf("__pad%d__",yyextra->padCount++); + } + BEGIN(BitFields); + yyextra->current->bitfields+=":"; + } + } +<BitFields>. { + yyextra->current->bitfields+=*yytext; + } +<EnumBaseType>. { + yyextra->current->args+=*yytext; + } +<EnumBaseType>\n { lineCount(yyscanner); - yyextra->current->args+=' '; - } -<FindMembers>[;,] { - QCString oldType = yyextra->current->type; - if (yyextra->current->bodyLine==-1) - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } + yyextra->current->args+=' '; + } +<FindMembers>[;,] { + QCString oldType = yyextra->current->type; + if (yyextra->current->bodyLine==-1) + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } if ( yyextra->insidePHP && yyextra->current->type.left(3) == "var" ) { yyextra->current->type = yyextra->current->type.mid(3); } - if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") - { - yyextra->current->type.prepend("typedef "); - } - bool stat = yyextra->current->stat; - if (!yyextra->current->name.isEmpty() && yyextra->current->section!=Entry::ENUM_SEC) - { - yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); - yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - yyextra->current->name=yyextra->current->name.stripWhiteSpace(); - if (yyextra->current->section==Entry::CLASS_SEC) // remove spec for "struct Bla bla;" - { - yyextra->current->spec = 0; - } - yyextra->current->section = Entry::VARIABLE_SEC ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyBegLineNr; - yyextra->current->startColumn = yyextra->yyBegColNr; - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") + { + yyextra->current->type.prepend("typedef "); + } + bool stat = yyextra->current->stat; + if (!yyextra->current->name.isEmpty() && yyextra->current->section!=Entry::ENUM_SEC) + { + yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); + yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); + yyextra->current->name=yyextra->current->name.stripWhiteSpace(); + if (yyextra->current->section==Entry::CLASS_SEC) // remove spec for "struct Bla bla;" + { + yyextra->current->spec = 0; + } + yyextra->current->section = Entry::VARIABLE_SEC ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyBegLineNr; + yyextra->current->startColumn = yyextra->yyBegColNr; + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; initEntry(yyscanner); - } - if ( *yytext == ',') - { - yyextra->current->stat = stat; // the static attribute holds for all variables - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->brief.resize(0); - yyextra->current->doc.resize(0); - yyextra->current->initializer.resize(0); - yyextra->current->bitfields.resize(0); - int i=oldType.length(); - while (i>0 && (oldType[i-1]=='*' || oldType[i-1]=='&' || oldType[i-1]==' ')) i--; - yyextra->current->type = oldType.left(i); - } - else - { + } + if ( *yytext == ',') + { + yyextra->current->stat = stat; // the static attribute holds for all variables + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->brief.resize(0); + yyextra->current->doc.resize(0); + yyextra->current->initializer.resize(0); + yyextra->current->bitfields.resize(0); + int i=oldType.length(); + while (i>0 && (oldType[i-1]=='*' || oldType[i-1]=='&' || oldType[i-1]==' ')) i--; + yyextra->current->type = oldType.left(i); + } + else + { yyextra->mtype = Method; yyextra->virt = Normal; - yyextra->current->groups.clear(); - initEntry(yyscanner); - } - } + yyextra->current->groups.clear(); + initEntry(yyscanner); + } + } -<FindMembers>"[" { +<FindMembers>"[" { if (yyextra->insideSlice) { - yyextra->squareCount=1; + yyextra->squareCount=1; yyextra->lastSquareContext = YY_START; yyextra->current->metaData += "["; BEGIN( SliceMetadata ); } - else if (!yyextra->insideCS && - (yyextra->current->name.isEmpty() || - yyextra->current->name=="typedef" - ) - ) // IDL function property - { - yyextra->squareCount=1; - yyextra->lastSquareContext = YY_START; - yyextra->idlAttr.resize(0); - yyextra->idlProp.resize(0); - yyextra->current->mtype = yyextra->mtype; - - if (Config_getBool(IDL_PROPERTY_SUPPORT) && - yyextra->current->mtype == Property) - { // we are yyextra->inside the properties section of a dispinterface - yyextra->odlProp = true; - yyextra->current->spec |= Entry::Gettable; - yyextra->current->spec |= Entry::Settable; - } - - BEGIN( IDLAttribute ); - } + else if (!yyextra->insideCS && + (yyextra->current->name.isEmpty() || + yyextra->current->name=="typedef" + ) + ) // IDL function property + { + yyextra->squareCount=1; + yyextra->lastSquareContext = YY_START; + yyextra->idlAttr.resize(0); + yyextra->idlProp.resize(0); + yyextra->current->mtype = yyextra->mtype; + + if (Config_getBool(IDL_PROPERTY_SUPPORT) && + yyextra->current->mtype == Property) + { // we are yyextra->inside the properties section of a dispinterface + yyextra->odlProp = true; + yyextra->current->spec |= Entry::Gettable; + yyextra->current->spec |= Entry::Settable; + } + + BEGIN( IDLAttribute ); + } else if (yyextra->insideCS && yyextra->current->name.isEmpty()) { @@ -3246,20 +3262,20 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->args.resize(0); BEGIN( SkipSquare ); } - else - { - yyextra->current->args += yytext ; - yyextra->squareCount=1; - yyextra->externC=FALSE; // see bug759247 - BEGIN( Array ) ; - } - } + else + { + yyextra->current->args += yytext ; + yyextra->squareCount=1; + yyextra->externC=FALSE; // see bug759247 + BEGIN( Array ) ; + } + } <SliceMetadata>"[" { // Global metadata. - yyextra->squareCount++; + yyextra->squareCount++; yyextra->current->metaData += "["; } <SliceMetadata>{BN}* { - lineCount(yyscanner); + lineCount(yyscanner); } <SliceMetadata>\"[^\"]*\" { yyextra->current->metaData += yytext; @@ -3288,294 +3304,294 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN (yyextra->lastModifierContext); } } -<IDLAttribute>"]" { - // end of IDL function attribute - if (--yyextra->squareCount<=0) - { - lineCount(yyscanner); - if (yyextra->current->mtype == Property) - BEGIN( IDLPropName ); - else - BEGIN( yyextra->lastSquareContext ); - } - } -<IDLAttribute>"propput" { +<IDLAttribute>"]" { + // end of IDL function attribute + if (--yyextra->squareCount<=0) + { + lineCount(yyscanner); + if (yyextra->current->mtype == Property) + BEGIN( IDLPropName ); + else + BEGIN( yyextra->lastSquareContext ); + } + } +<IDLAttribute>"propput" { if (Config_getBool(IDL_PROPERTY_SUPPORT)) - { - yyextra->current->mtype = Property; - } - yyextra->current->spec |= Entry::Settable; - } -<IDLAttribute>"propget" { + { + yyextra->current->mtype = Property; + } + yyextra->current->spec |= Entry::Settable; + } +<IDLAttribute>"propget" { if (Config_getBool(IDL_PROPERTY_SUPPORT)) - { - yyextra->current->mtype = Property; - } - yyextra->current->spec |= Entry::Gettable; - } + { + yyextra->current->mtype = Property; + } + yyextra->current->spec |= Entry::Gettable; + } <IDLAttribute>"property" { // UNO IDL property - yyextra->current->spec |= Entry::Property; - } + yyextra->current->spec |= Entry::Property; + } <IDLAttribute>"attribute" { // UNO IDL attribute - yyextra->current->spec |= Entry::Attribute; - } + yyextra->current->spec |= Entry::Attribute; + } <IDLAttribute>"optional" { // on UNO IDL interface/service/attribute/property yyextra->current->spec |= Entry::Optional; } <IDLAttribute>"readonly" { // on UNO IDL attribute or property - if (Config_getBool(IDL_PROPERTY_SUPPORT) && yyextra->odlProp) - { - yyextra->current->spec ^= Entry::Settable; - } - else - { - yyextra->current->spec |= Entry::Readonly; - } - } + if (Config_getBool(IDL_PROPERTY_SUPPORT) && yyextra->odlProp) + { + yyextra->current->spec ^= Entry::Settable; + } + else + { + yyextra->current->spec |= Entry::Readonly; + } + } <IDLAttribute>"bound" { // on UNO IDL attribute or property - yyextra->current->spec |= Entry::Bound; - } + yyextra->current->spec |= Entry::Bound; + } <IDLAttribute>"removable" { // on UNO IDL property - yyextra->current->spec |= Entry::Removable; - } + yyextra->current->spec |= Entry::Removable; + } <IDLAttribute>"constrained" { // on UNO IDL property - yyextra->current->spec |= Entry::Constrained; - } + yyextra->current->spec |= Entry::Constrained; + } <IDLAttribute>"transient" { // on UNO IDL property - yyextra->current->spec |= Entry::Transient; - } + yyextra->current->spec |= Entry::Transient; + } <IDLAttribute>"maybevoid" { // on UNO IDL property - yyextra->current->spec |= Entry::MaybeVoid; - } + yyextra->current->spec |= Entry::MaybeVoid; + } <IDLAttribute>"maybedefault" { // on UNO IDL property - yyextra->current->spec |= Entry::MaybeDefault; - } + yyextra->current->spec |= Entry::MaybeDefault; + } <IDLAttribute>"maybeambiguous" { // on UNO IDL property - yyextra->current->spec |= Entry::MaybeAmbiguous; - } -<IDLAttribute>. { - } -<IDLPropName>{BN}*{ID}{BN}* { - // return type (probably HRESULT) - skip it - - if (yyextra->odlProp) - { // property type - yyextra->idlProp = yytext; - } - } -<IDLPropName>{ID}{BN}*"(" { - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - BEGIN( IDLProp ); - } -<IDLPropName>{BN}*"("{BN}*{ID}{BN}*")"{BN}* { - if (yyextra->odlProp) - { - yyextra->idlProp += yytext; - } - } -<IDLPropName>{ID}{BN}*/";" { - if (yyextra->odlProp) - { - yyextra->current->name = yytext; - yyextra->idlProp = yyextra->idlProp.stripWhiteSpace(); - yyextra->odlProp = false; - - BEGIN( IDLProp ); - } - } -<IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter - yyextra->idlAttr = yytext; - yyextra->idlAttr=yyextra->idlAttr.stripWhiteSpace(); - } -<IDLProp>{ID} { // property type - yyextra->idlProp = yytext; - } -<IDLProp>{BN}*{ID}{BN}*"," { // Rare: Another parameter ([propput] HRESULT Item(int index, [in] Type theRealProperty);) - if (!yyextra->current->args) - yyextra->current->args = "("; - else - yyextra->current->args += ", "; - yyextra->current->args += yyextra->idlAttr; - yyextra->current->args += " "; - yyextra->current->args += yyextra->idlProp; // prop was actually type of extra parameter - yyextra->current->args += " "; - yyextra->current->args += yytext; - yyextra->current->args = yyextra->current->args.left(yyextra->current->args.length() - 1); // strip comma - yyextra->idlProp.resize(0); - yyextra->idlAttr.resize(0); - BEGIN( IDLProp ); - } -<IDLProp>{BN}*{ID}{BN}*")"{BN}* { - // the parameter name for the property - just skip. - } -<IDLProp>";" { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->type = yyextra->idlProp; - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - if (yyextra->current->args) - yyextra->current->args += ")"; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN( FindMembers ); - } -<IDLProp>. { // spaces, *, or other stuff - //yyextra->idlProp+=yytext; - } -<Array>"]" { yyextra->current->args += *yytext ; - if (--yyextra->squareCount<=0) - BEGIN( FindMembers ) ; - } -<FuncFuncArray>"]" { yyextra->current->args += *yytext ; - if (--yyextra->squareCount<=0) - BEGIN( Function ) ; - } -<Array,FuncFuncArray>"[" { yyextra->current->args += *yytext ; - yyextra->squareCount++; - } -<Array,FuncFuncArray>. { yyextra->current->args += *yytext ; } -<SkipSquare>"[" { yyextra->squareCount++; } -<SkipSquare>"]" { - if (--yyextra->squareCount<=0) - BEGIN( yyextra->lastSquareContext ); - } -<SkipSquare>\" { - yyextra->lastStringContext=YY_START; - BEGIN( SkipString ); - } + yyextra->current->spec |= Entry::MaybeAmbiguous; + } +<IDLAttribute>. { + } +<IDLPropName>{BN}*{ID}{BN}* { + // return type (probably HRESULT) - skip it + + if (yyextra->odlProp) + { // property type + yyextra->idlProp = yytext; + } + } +<IDLPropName>{ID}{BN}*"(" { + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + BEGIN( IDLProp ); + } +<IDLPropName>{BN}*"("{BN}*{ID}{BN}*")"{BN}* { + if (yyextra->odlProp) + { + yyextra->idlProp += yytext; + } + } +<IDLPropName>{ID}{BN}*/";" { + if (yyextra->odlProp) + { + yyextra->current->name = yytext; + yyextra->idlProp = yyextra->idlProp.stripWhiteSpace(); + yyextra->odlProp = false; + + BEGIN( IDLProp ); + } + } +<IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter + yyextra->idlAttr = yytext; + yyextra->idlAttr=yyextra->idlAttr.stripWhiteSpace(); + } +<IDLProp>{ID} { // property type + yyextra->idlProp = yytext; + } +<IDLProp>{BN}*{ID}{BN}*"," { // Rare: Another parameter ([propput] HRESULT Item(int index, [in] Type theRealProperty);) + if (!yyextra->current->args) + yyextra->current->args = "("; + else + yyextra->current->args += ", "; + yyextra->current->args += yyextra->idlAttr; + yyextra->current->args += " "; + yyextra->current->args += yyextra->idlProp; // prop was actually type of extra parameter + yyextra->current->args += " "; + yyextra->current->args += yytext; + yyextra->current->args = yyextra->current->args.left(yyextra->current->args.length() - 1); // strip comma + yyextra->idlProp.resize(0); + yyextra->idlAttr.resize(0); + BEGIN( IDLProp ); + } +<IDLProp>{BN}*{ID}{BN}*")"{BN}* { + // the parameter name for the property - just skip. + } +<IDLProp>";" { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->type = yyextra->idlProp; + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + if (yyextra->current->args) + yyextra->current->args += ")"; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN( FindMembers ); + } +<IDLProp>. { // spaces, *, or other stuff + //yyextra->idlProp+=yytext; + } +<Array>"]" { yyextra->current->args += *yytext ; + if (--yyextra->squareCount<=0) + BEGIN( FindMembers ) ; + } +<FuncFuncArray>"]" { yyextra->current->args += *yytext ; + if (--yyextra->squareCount<=0) + BEGIN( Function ) ; + } +<Array,FuncFuncArray>"[" { yyextra->current->args += *yytext ; + yyextra->squareCount++; + } +<Array,FuncFuncArray>. { yyextra->current->args += *yytext ; } +<SkipSquare>"[" { yyextra->squareCount++; } +<SkipSquare>"]" { + if (--yyextra->squareCount<=0) + BEGIN( yyextra->lastSquareContext ); + } +<SkipSquare>\" { + yyextra->lastStringContext=YY_START; + BEGIN( SkipString ); + } <SkipSquare>[^\n\[\]\"]+ -<FindMembers>"<" { addType(yyscanner); - yyextra->current->type += yytext ; - BEGIN( Sharp ) ; - } -<Sharp>">" { yyextra->current->type += *yytext ; - if (--yyextra->sharpCount<=0) - BEGIN( FindMembers ) ; - } -<Sharp>"<" { yyextra->current->type += *yytext ; - yyextra->sharpCount++; - } -<Sharp>{BN}+ { +<FindMembers>"<" { addType(yyscanner); + yyextra->current->type += yytext ; + BEGIN( Sharp ) ; + } +<Sharp>">" { yyextra->current->type += *yytext ; + if (--yyextra->sharpCount<=0) + BEGIN( FindMembers ) ; + } +<Sharp>"<" { yyextra->current->type += *yytext ; + yyextra->sharpCount++; + } +<Sharp>{BN}+ { yyextra->current->type += ' '; - lineCount(yyscanner); - } -<Sharp>. { yyextra->current->type += *yytext ; } -<FindFields>{ID} { + lineCount(yyscanner); + } +<Sharp>. { yyextra->current->type += *yytext ; } +<FindFields>{ID} { if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->name = yytext; - } -<FindFields>"(" { - // Java enum initializer - unput('('); - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=0; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->name = yytext; + } +<FindFields>"(" { + // Java enum initializer + unput('('); + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = "="; - BEGIN(ReadInitializer); - } -<FindFields>"=" { - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=0; + BEGIN(ReadInitializer); + } +<FindFields>"=" { + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = yytext; - BEGIN(ReadInitializer); - } + BEGIN(ReadInitializer); + } <FindFields>";" { - if (yyextra->insideJava) // yyextra->last enum field in Java class - { - if (!yyextra->current->name.isEmpty()) - { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - if (!(yyextra->current_root->spec&Entry::Enum)) - { - yyextra->current->type = "@"; // enum marker - } - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - } - - BEGIN( FindMembers ); - } - else - { - REJECT; - } - } -<SkipRemainder>\n { + if (yyextra->insideJava) // yyextra->last enum field in Java class + { + if (!yyextra->current->name.isEmpty()) + { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + if (!(yyextra->current_root->spec&Entry::Enum)) + { + yyextra->current->type = "@"; // enum marker + } + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + } + + BEGIN( FindMembers ); + } + else + { + REJECT; + } + } +<SkipRemainder>\n { lineCount(yyscanner); } <SkipRemainder>[^\n]* -<FindFields>"," { - //printf("adding '%s' '%s' '%s' to enum '%s' (mGrpId=%d)\n", - // yyextra->current->type.data(), yyextra->current->name.data(), - // yyextra->current->args.data(), yyextra->current_root->name.data(),yyextra->current->mGrpId); - if (!yyextra->current->name.isEmpty()) - { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - if (!(yyextra->current_root->spec&Entry::Enum)) - { - yyextra->current->type = "@"; // enum marker - } - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - // add to the scope of the enum - if (!yyextra->insideCS && !yyextra->insideJava && - !(yyextra->current_root->spec&Entry::Strong)) +<FindFields>"," { + //printf("adding '%s' '%s' '%s' to enum '%s' (mGrpId=%d)\n", + // yyextra->current->type.data(), yyextra->current->name.data(), + // yyextra->current->args.data(), yyextra->current_root->name.data(),yyextra->current->mGrpId); + if (!yyextra->current->name.isEmpty()) + { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + if (!(yyextra->current_root->spec&Entry::Enum)) + { + yyextra->current->type = "@"; // enum marker + } + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + // add to the scope of the enum + if (!yyextra->insideCS && !yyextra->insideJava && + !(yyextra->current_root->spec&Entry::Strong)) // for C# and Java 1.5+ enum values always have to be explicitly qualified, // same for C++11 style enums (enum class Name {}) - { - // add to the scope surrounding the enum (copy!) + { + // add to the scope surrounding the enum (copy!) // we cannot during it directly as that would invalidate the iterator in parseCompounds. //printf("*** adding outer scope entry for %s\n",yyextra->current->name.data()); yyextra->outerScopeEntries.emplace_back(yyextra->current_root->parent(), std::make_shared<Entry>(*yyextra->current)); - } - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - } - else // probably a redundant , - { - yyextra->current->reset(); - initEntry(yyscanner); - } - } -<FindFields>"[" { // attribute list in IDL - yyextra->squareCount=1; - yyextra->lastSquareContext = YY_START; - BEGIN(SkipSquare); - } + } + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + } + else // probably a redundant , + { + yyextra->current->reset(); + initEntry(yyscanner); + } + } +<FindFields>"[" { // attribute list in IDL + yyextra->squareCount=1; + yyextra->lastSquareContext = YY_START; + BEGIN(SkipSquare); + } /* -<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); } +<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); } */ -<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { yyextra->current->program += yytext ; } -<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { yyextra->current->program += yytext ; } -<ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP) - REJECT; - // append PHP comment. - yyextra->current->program += yytext ; - } -<ReadBody,ReadNSBody,ReadBodyIntf>@\" { yyextra->current->program += yytext ; +<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { yyextra->current->program += yytext ; } +<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { yyextra->current->program += yytext ; } +<ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP) + REJECT; + // append PHP comment. + yyextra->current->program += yytext ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>@\" { yyextra->current->program += yytext ; yyextra->pSkipVerbString = &yyextra->current->program; yyextra->lastSkipVerbStringContext=YY_START; BEGIN( SkipVerbString ); - } -<ReadBody,ReadNSBody,ReadBodyIntf>"<<<" { if (yyextra->insidePHP) + } +<ReadBody,ReadNSBody,ReadBodyIntf>"<<<" { if (yyextra->insidePHP) { - yyextra->current->program += yytext ; + yyextra->current->program += yytext ; yyextra->pCopyHereDocGString = &yyextra->current->program; yyextra->lastHereDocContext=YY_START; BEGIN( CopyHereDoc ); @@ -3584,61 +3600,61 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { REJECT; } - } -<ReadBody,ReadNSBody,ReadBodyIntf>\" { yyextra->current->program += yytext ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>\" { yyextra->current->program += yytext ; yyextra->pCopyQuotedGString = &yyextra->current->program; yyextra->lastStringContext=YY_START; BEGIN( CopyGString ); - } -<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { yyextra->current->program += yytext ; - yyextra->lastContext = YY_START ; - BEGIN( Comment ) ; - } -<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { yyextra->current->program += yytext ; - ++yyextra->yyLineNr ; - yyextra->lastContext = YY_START ; - BEGIN( Comment ) ; - } -<ReadBody,ReadNSBody,ReadBodyIntf>"'" { - if (!yyextra->insidePHP) - { - yyextra->current->program += yytext; - } - else - { // begin of single quoted string - yyextra->current->program += yytext; + } +<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { yyextra->current->program += yytext ; + yyextra->lastContext = YY_START ; + BEGIN( Comment ) ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { yyextra->current->program += yytext ; + ++yyextra->yyLineNr ; + yyextra->lastContext = YY_START ; + BEGIN( Comment ) ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>"'" { + if (!yyextra->insidePHP) + { + yyextra->current->program += yytext; + } + else + { // begin of single quoted string + yyextra->current->program += yytext; yyextra->pCopyQuotedGString = &yyextra->current->program; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - } -<ReadBody,ReadNSBody,ReadBodyIntf>{CHARLIT} { - if (yyextra->insidePHP) - { - REJECT; // for PHP code single quotes - // are used for strings of arbitrary length - } - else - { - yyextra->current->program += yytext; - } + BEGIN(CopyPHPGString); + } + } +<ReadBody,ReadNSBody,ReadBodyIntf>{CHARLIT} { + if (yyextra->insidePHP) + { + REJECT; // for PHP code single quotes + // are used for strings of arbitrary length + } + else + { + yyextra->current->program += yytext; + } } <ReadBody,ReadNSBody,ReadBodyIntf>"{" { yyextra->current->program += yytext ; - ++yyextra->curlyCount ; - } -<ReadBodyIntf>"}" { - yyextra->current->program += yytext ; - --yyextra->curlyCount ; - } -<ReadBody,ReadNSBody>"}" { //err("ReadBody count=%d\n",yyextra->curlyCount); - if ( yyextra->curlyCount>0 ) - { - yyextra->current->program += yytext ; - --yyextra->curlyCount ; - } - else - { - yyextra->current->endBodyLine = yyextra->yyLineNr; + ++yyextra->curlyCount ; + } +<ReadBodyIntf>"}" { + yyextra->current->program += yytext ; + --yyextra->curlyCount ; + } +<ReadBody,ReadNSBody>"}" { //err("ReadBody count=%d\n",yyextra->curlyCount); + if ( yyextra->curlyCount>0 ) + { + yyextra->current->program += yytext ; + --yyextra->curlyCount ; + } + else + { + yyextra->current->endBodyLine = yyextra->yyLineNr; std::shared_ptr<Entry> original_root = yyextra->current_root; // save root this namespace is in if (yyextra->current->section == Entry::NAMESPACE_SEC && yyextra->current->type == "namespace") { @@ -3677,817 +3693,817 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->briefLine = briefLine; yyextra->current->briefFile = briefFile; } - QCString &cn = yyextra->current->name; - QCString rn = yyextra->current_root->name.copy(); - //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); - if (!cn.isEmpty() && !rn.isEmpty()) - { - prependScope(yyscanner); - } - if (yyextra->isTypedef && cn.isEmpty()) - { - //printf("Typedef Name\n"); - BEGIN( TypedefName ); - } - else - { - if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) - { - yyextra->current->program+=','; // add field terminator - } - // add compound definition to the tree - yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - // was: yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - //printf("adding '%s' '%s' '%s' brief=%s yyextra->insideObjC=%d %x\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data(),yyextra->current->brief.data(),yyextra->insideObjC,yyextra->current->section); - if (yyextra->insideObjC && - ((yyextra->current->spec&Entry::Interface) || (yyextra->current->spec==Entry::Category)) - ) // method definition follows - { - BEGIN( ReadBodyIntf ) ; - } - else - { - yyextra->memspecEntry = 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 || + QCString &cn = yyextra->current->name; + QCString rn = yyextra->current_root->name.copy(); + //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); + if (!cn.isEmpty() && !rn.isEmpty()) + { + prependScope(yyscanner); + } + if (yyextra->isTypedef && cn.isEmpty()) + { + //printf("Typedef Name\n"); + BEGIN( TypedefName ); + } + else + { + if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) + { + yyextra->current->program+=','; // add field terminator + } + // add compound definition to the tree + yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); + // was: yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + //printf("adding '%s' '%s' '%s' brief=%s yyextra->insideObjC=%d %x\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data(),yyextra->current->brief.data(),yyextra->insideObjC,yyextra->current->section); + if (yyextra->insideObjC && + ((yyextra->current->spec&Entry::Interface) || (yyextra->current->spec==Entry::Category)) + ) // method definition follows + { + BEGIN( ReadBodyIntf ) ; + } + else + { + yyextra->memspecEntry = 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 || yyextra->insideSlice - ) - { // namespaces and interfaces and java classes ends with a closing bracket without semicolon + ) + { // namespaces and interfaces and java classes ends with a closing bracket without semicolon yyextra->current->reset(); yyextra->current_root = original_root; // restore scope from before namespace descent - initEntry(yyscanner); - yyextra->memspecEntry.reset(); - BEGIN( FindMembers ) ; - } - else - { + initEntry(yyscanner); + yyextra->memspecEntry.reset(); + BEGIN( FindMembers ) ; + } + else + { static QRegExp re("@[0-9]+$"); - if (!yyextra->isTypedef && yyextra->memspecEntry && + if (!yyextra->isTypedef && yyextra->memspecEntry && yyextra->memspecEntry->name.find(re)==-1) // not typedef or anonymous type (see bug691071) - { - // enabled the next two lines for bug 623424 - yyextra->current->doc.resize(0); - yyextra->current->brief.resize(0); - } - BEGIN( MemberSpec ) ; - } - } - } - } - } -<ReadBody>"}"{BN}+"typedef"{BN}+ { //err("ReadBody count=%d\n",yyextra->curlyCount); - lineCount(yyscanner); - if ( yyextra->curlyCount>0 ) - { - yyextra->current->program += yytext ; - --yyextra->curlyCount ; - } - else - { - yyextra->isTypedef = TRUE; - yyextra->current->endBodyLine = yyextra->yyLineNr; - QCString &cn = yyextra->current->name; - QCString rn = yyextra->current_root->name.copy(); - if (!cn.isEmpty() && !rn.isEmpty()) - { - prependScope(yyscanner); - } - BEGIN( TypedefName ); - } - } -<TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword - lineCount(yyscanner); - yyextra->current->type.prepend(yytext); - } -<TypedefName>{ID} { - if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) - { - yyextra->current->program+=","; // add field terminator - } - yyextra->current->name=yytext; - prependScope(yyscanner); - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); - //printf("Adding compound %s %s %s\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); - if (!yyextra->firstTypedefEntry) - { - yyextra->firstTypedefEntry = yyextra->current; - } - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; - initEntry(yyscanner); - yyextra->isTypedef=TRUE; // to undo reset by initEntry(yyscanner) - BEGIN(MemberSpecSkip); - } -<TypedefName>";" { /* typedef of anonymous type */ - yyextra->current->name.sprintf("@%d",yyextra->anonCount++); - if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) - { - yyextra->current->program+=','; // add field terminator - } - // add compound definition to the tree - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); - yyextra->memspecEntry = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; - initEntry(yyscanner); - unput(';'); - BEGIN( MemberSpec ) ; - } + { + // enabled the next two lines for bug 623424 + yyextra->current->doc.resize(0); + yyextra->current->brief.resize(0); + } + BEGIN( MemberSpec ) ; + } + } + } + } + } +<ReadBody>"}"{BN}+"typedef"{BN}+ { //err("ReadBody count=%d\n",yyextra->curlyCount); + lineCount(yyscanner); + if ( yyextra->curlyCount>0 ) + { + yyextra->current->program += yytext ; + --yyextra->curlyCount ; + } + else + { + yyextra->isTypedef = TRUE; + yyextra->current->endBodyLine = yyextra->yyLineNr; + QCString &cn = yyextra->current->name; + QCString rn = yyextra->current_root->name.copy(); + if (!cn.isEmpty() && !rn.isEmpty()) + { + prependScope(yyscanner); + } + BEGIN( TypedefName ); + } + } +<TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword + lineCount(yyscanner); + yyextra->current->type.prepend(yytext); + } +<TypedefName>{ID} { + if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) + { + yyextra->current->program+=","; // add field terminator + } + yyextra->current->name=yytext; + prependScope(yyscanner); + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); + //printf("Adding compound %s %s %s\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); + if (!yyextra->firstTypedefEntry) + { + yyextra->firstTypedefEntry = yyextra->current; + } + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + initEntry(yyscanner); + yyextra->isTypedef=TRUE; // to undo reset by initEntry(yyscanner) + BEGIN(MemberSpecSkip); + } +<TypedefName>";" { /* typedef of anonymous type */ + yyextra->current->name.sprintf("@%d",anonCount++); + if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) + { + yyextra->current->program+=','; // add field terminator + } + // add compound definition to the tree + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); + yyextra->memspecEntry = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + initEntry(yyscanner); + unput(';'); + BEGIN( MemberSpec ) ; + } <MemberSpec>([*&]*{BN}*)*{ID}{BN}*("["[^\]\n]*"]")* { // the [] part could be improved. - lineCount(yyscanner); - int i=0,l=(int)yyleng,j; - while (i<l && (!isId(yytext[i]))) i++; - yyextra->msName = QCString(yytext).right(l-i).stripWhiteSpace(); - j=yyextra->msName.find("["); - if (j!=-1) - { - yyextra->msArgs=yyextra->msName.right(yyextra->msName.length()-j); - yyextra->msName=yyextra->msName.left(j); - } - yyextra->msType=QCString(yytext).left(i); - - // handle *pName in: typedef { ... } name, *pName; - if (yyextra->firstTypedefEntry) - { - if (yyextra->firstTypedefEntry->spec&Entry::Struct) - { - yyextra->msType.prepend("struct "+yyextra->firstTypedefEntry->name); - } - else if (yyextra->firstTypedefEntry->spec&Entry::Union) - { - yyextra->msType.prepend("union "+yyextra->firstTypedefEntry->name); - } - else if (yyextra->firstTypedefEntry->section==Entry::ENUM_SEC) - { - yyextra->msType.prepend("enum "+yyextra->firstTypedefEntry->name); - } - else - { - yyextra->msType.prepend(yyextra->firstTypedefEntry->name); - } - } - } -<MemberSpec>"(" { // function with struct return type - addType(yyscanner); - yyextra->current->name = yyextra->msName; - yyextra->current->spec = 0; - unput('('); - BEGIN(FindMembers); - } -<MemberSpec>[,;] { - if (yyextra->msName.isEmpty() && !yyextra->current->name.isEmpty()) - { - // see if the compound does not have a name or is yyextra->inside another - // anonymous compound. If so we insert a - // special 'anonymous' variable. - //Entry *p=yyextra->current_root; + lineCount(yyscanner); + int i=0,l=(int)yyleng,j; + while (i<l && (!isId(yytext[i]))) i++; + yyextra->msName = QCString(yytext).right(l-i).stripWhiteSpace(); + j=yyextra->msName.find("["); + if (j!=-1) + { + yyextra->msArgs=yyextra->msName.right(yyextra->msName.length()-j); + yyextra->msName=yyextra->msName.left(j); + } + yyextra->msType=QCString(yytext).left(i); + + // handle *pName in: typedef { ... } name, *pName; + if (yyextra->firstTypedefEntry) + { + if (yyextra->firstTypedefEntry->spec&Entry::Struct) + { + yyextra->msType.prepend("struct "+yyextra->firstTypedefEntry->name); + } + else if (yyextra->firstTypedefEntry->spec&Entry::Union) + { + yyextra->msType.prepend("union "+yyextra->firstTypedefEntry->name); + } + else if (yyextra->firstTypedefEntry->section==Entry::ENUM_SEC) + { + yyextra->msType.prepend("enum "+yyextra->firstTypedefEntry->name); + } + else + { + yyextra->msType.prepend(yyextra->firstTypedefEntry->name); + } + } + } +<MemberSpec>"(" { // function with struct return type + addType(yyscanner); + yyextra->current->name = yyextra->msName; + yyextra->current->spec = 0; + unput('('); + BEGIN(FindMembers); + } +<MemberSpec>[,;] { + if (yyextra->msName.isEmpty() && !yyextra->current->name.isEmpty()) + { + // see if the compound does not have a name or is yyextra->inside another + // anonymous compound. If so we insert a + // special 'anonymous' variable. + //Entry *p=yyextra->current_root; const Entry *p=yyextra->current.get(); - while (p) - { - // only look for class scopes, not namespace scopes - if ((p->section & Entry::COMPOUND_MASK) && !p->name.isEmpty()) - { - //printf("Trying scope '%s'\n",p->name.data()); - int i=p->name.findRev("::"); - int pi = (i==-1) ? 0 : i+2; - if (p->name.at(pi)=='@') - { - // anonymous compound yyextra->inside -> insert dummy variable name - //printf("Adding anonymous variable for scope %s\n",p->name.data()); - yyextra->msName.sprintf("@%d",yyextra->anonCount++); - break; - } - } - //p=p->parent; - if (p==yyextra->current.get()) p=yyextra->current_root.get(); else p=p->parent(); - } - } - //printf("yyextra->msName=%s yyextra->current->name=%s\n",yyextra->msName.data(),yyextra->current->name.data()); - if (!yyextra->msName.isEmpty() - /*&& yyextra->msName!=yyextra->current->name*/) // skip typedef T {} T;, removed due to bug608493 - { - bool typedefHidesStruct = Config_getBool(TYPEDEF_HIDES_STRUCT); - // case 1: typedef struct _S { ... } S_t; - // -> omit typedef and use S_t as the struct name - if (typedefHidesStruct && - yyextra->isTypedef && - ((yyextra->current->spec&(Entry::Struct|Entry::Union)) || - yyextra->current->section==Entry::ENUM_SEC )&& - yyextra->msType.stripWhiteSpace().isEmpty() && - yyextra->memspecEntry) - { - yyextra->memspecEntry->name=yyextra->msName; - } - else // case 2: create a typedef field - { + while (p) + { + // only look for class scopes, not namespace scopes + if ((p->section & Entry::COMPOUND_MASK) && !p->name.isEmpty()) + { + //printf("Trying scope '%s'\n",p->name.data()); + int i=p->name.findRev("::"); + int pi = (i==-1) ? 0 : i+2; + if (p->name.at(pi)=='@') + { + // anonymous compound yyextra->inside -> insert dummy variable name + //printf("Adding anonymous variable for scope %s\n",p->name.data()); + yyextra->msName.sprintf("@%d",anonCount++); + break; + } + } + //p=p->parent; + if (p==yyextra->current.get()) p=yyextra->current_root.get(); else p=p->parent(); + } + } + //printf("yyextra->msName=%s yyextra->current->name=%s\n",yyextra->msName.data(),yyextra->current->name.data()); + if (!yyextra->msName.isEmpty() + /*&& yyextra->msName!=yyextra->current->name*/) // skip typedef T {} T;, removed due to bug608493 + { + bool typedefHidesStruct = Config_getBool(TYPEDEF_HIDES_STRUCT); + // case 1: typedef struct _S { ... } S_t; + // -> omit typedef and use S_t as the struct name + if (typedefHidesStruct && + yyextra->isTypedef && + ((yyextra->current->spec&(Entry::Struct|Entry::Union)) || + yyextra->current->section==Entry::ENUM_SEC )&& + yyextra->msType.stripWhiteSpace().isEmpty() && + yyextra->memspecEntry) + { + yyextra->memspecEntry->name=yyextra->msName; + } + else // case 2: create a typedef field + { std::shared_ptr<Entry> varEntry=std::make_shared<Entry>(); - varEntry->lang = yyextra->language; - varEntry->protection = yyextra->current->protection ; - varEntry->mtype = yyextra->current->mtype; - varEntry->virt = yyextra->current->virt; - varEntry->stat = yyextra->current->stat; - varEntry->section = Entry::VARIABLE_SEC; - varEntry->name = yyextra->msName.stripWhiteSpace(); - varEntry->type = yyextra->current->type.simplifyWhiteSpace()+" "; - varEntry->args = yyextra->msArgs; - if (yyextra->isTypedef) - { - varEntry->type.prepend("typedef "); - // //printf("yyextra->current->name = %s %s\n",yyextra->current->name.data(),yyextra->msName.data()); - } - if (typedefHidesStruct && - yyextra->isTypedef && - (yyextra->current->spec&(Entry::Struct|Entry::Union)) && - yyextra->memspecEntry - ) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;" - { - varEntry->type+=yyextra->memspecEntry->name+yyextra->msType; - } - else // case 2: use _S as type for for pS_t - { - varEntry->type+=yyextra->current->name+yyextra->msType; - } - varEntry->fileName = yyextra->yyFileName; - varEntry->startLine = yyextra->yyLineNr; - varEntry->startColumn = yyextra->yyColNr; - varEntry->doc = yyextra->current->doc.copy(); - varEntry->brief = yyextra->current->brief.copy(); - varEntry->mGrpId = yyextra->current->mGrpId; + varEntry->lang = yyextra->language; + varEntry->protection = yyextra->current->protection ; + varEntry->mtype = yyextra->current->mtype; + varEntry->virt = yyextra->current->virt; + varEntry->stat = yyextra->current->stat; + varEntry->section = Entry::VARIABLE_SEC; + varEntry->name = yyextra->msName.stripWhiteSpace(); + varEntry->type = yyextra->current->type.simplifyWhiteSpace()+" "; + varEntry->args = yyextra->msArgs; + if (yyextra->isTypedef) + { + varEntry->type.prepend("typedef "); + // //printf("yyextra->current->name = %s %s\n",yyextra->current->name.data(),yyextra->msName.data()); + } + if (typedefHidesStruct && + yyextra->isTypedef && + (yyextra->current->spec&(Entry::Struct|Entry::Union)) && + yyextra->memspecEntry + ) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;" + { + varEntry->type+=yyextra->memspecEntry->name+yyextra->msType; + } + else // case 2: use _S as type for for pS_t + { + varEntry->type+=yyextra->current->name+yyextra->msType; + } + varEntry->fileName = yyextra->yyFileName; + varEntry->startLine = yyextra->yyLineNr; + varEntry->startColumn = yyextra->yyColNr; + varEntry->doc = yyextra->current->doc.copy(); + varEntry->brief = yyextra->current->brief.copy(); + varEntry->mGrpId = yyextra->current->mGrpId; varEntry->initializer = yyextra->current->initializer; varEntry->groups = yyextra->current->groups; varEntry->sli = yyextra->current->sli; - //printf("Add: type='%s',name='%s',args='%s' brief=%s doc=%s\n", - // varEntry->type.data(),varEntry->name.data(), - // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data()); - yyextra->current_root->moveToSubEntryAndKeep(varEntry); - } - } - if (*yytext==';') // end of a struct/class ... - { - if (!yyextra->isTypedef && yyextra->msName.isEmpty() && yyextra->memspecEntry && (yyextra->current->section&Entry::COMPOUND_MASK)) - { // case where a class/struct has a doc block after it - if (!yyextra->current->doc.isEmpty()) - { - yyextra->memspecEntry->doc += yyextra->current->doc; - } - if (!yyextra->current->brief.isEmpty()) - { - yyextra->memspecEntry->brief += yyextra->current->brief; - } - } - yyextra->msType.resize(0); - yyextra->msName.resize(0); - yyextra->msArgs.resize(0); - yyextra->isTypedef=FALSE; - yyextra->firstTypedefEntry.reset(); - yyextra->memspecEntry.reset(); - yyextra->current->reset(); - initEntry(yyscanner); - BEGIN( FindMembers ); - } - else - { - yyextra->current->doc.resize(0); - yyextra->current->brief.resize(0); - } - - } -<MemberSpec>"=" { - yyextra->lastInitializerContext=YY_START; - yyextra->initBracketCount=0; + //printf("Add: type='%s',name='%s',args='%s' brief=%s doc=%s\n", + // varEntry->type.data(),varEntry->name.data(), + // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data()); + yyextra->current_root->moveToSubEntryAndKeep(varEntry); + } + } + if (*yytext==';') // end of a struct/class ... + { + if (!yyextra->isTypedef && yyextra->msName.isEmpty() && yyextra->memspecEntry && (yyextra->current->section&Entry::COMPOUND_MASK)) + { // case where a class/struct has a doc block after it + if (!yyextra->current->doc.isEmpty()) + { + yyextra->memspecEntry->doc += yyextra->current->doc; + } + if (!yyextra->current->brief.isEmpty()) + { + yyextra->memspecEntry->brief += yyextra->current->brief; + } + } + yyextra->msType.resize(0); + yyextra->msName.resize(0); + yyextra->msArgs.resize(0); + yyextra->isTypedef=FALSE; + yyextra->firstTypedefEntry.reset(); + yyextra->memspecEntry.reset(); + yyextra->current->reset(); + initEntry(yyscanner); + BEGIN( FindMembers ); + } + else + { + yyextra->current->doc.resize(0); + yyextra->current->brief.resize(0); + } + + } +<MemberSpec>"=" { + yyextra->lastInitializerContext=YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = yytext; - BEGIN(ReadInitializer); - /* BEGIN(MemberSpecSkip); */ - } + BEGIN(ReadInitializer); + /* BEGIN(MemberSpecSkip); */ + } /* -<MemberSpecSkip>"{" { - yyextra->curlyCount=0; - yyextra->lastCurlyContext = MemberSpecSkip; - yyextra->previous = yyextra->current; - BEGIN(SkipCurly); - } +<MemberSpecSkip>"{" { + yyextra->curlyCount=0; + yyextra->lastCurlyContext = MemberSpecSkip; + yyextra->previous = yyextra->current; + BEGIN(SkipCurly); + } */ -<MemberSpecSkip>"," { BEGIN(MemberSpec); } -<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); } +<MemberSpecSkip>"," { BEGIN(MemberSpec); } +<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); } <ReadBody,ReadNSBody,ReadBodyIntf>{BN}{1,80} { yyextra->current->program += yytext ; - lineCount(yyscanner) ; - } -<ReadBodyIntf>"@end"/[^a-z_A-Z0-9] { // end of Objective C block - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; - initEntry(yyscanner); - yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; // see bug746361 - yyextra->insideObjC=FALSE; - BEGIN( FindMembers ); - } -<ReadBody,ReadNSBody,ReadBodyIntf>. { yyextra->current->program += yytext ; } + lineCount(yyscanner) ; + } +<ReadBodyIntf>"@end"/[^a-z_A-Z0-9] { // end of Objective C block + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + initEntry(yyscanner); + yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; // see bug746361 + yyextra->insideObjC=FALSE; + BEGIN( FindMembers ); + } +<ReadBody,ReadNSBody,ReadBodyIntf>. { yyextra->current->program += yytext ; } <FindMembers>"("/{BN}*"::"*{BN}*({TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */ <FindMembers>("("({BN}*"::"*{BN}*{TSCOPE}{BN}*"::")*({BN}*[*&\^]{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) or int (*func(int))[], the ^ is for Obj-C blocks */ - if (yyextra->insidePHP) // reference parameter - { - REJECT - } - else - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner); - addType(yyscanner); - yyextra->funcPtrType=yytext; - yyextra->roundCount=0; - //yyextra->current->type += yytext; - BEGIN( FuncPtr ); - } - } -<FuncPtr>{SCOPENAME} { - yyextra->current->name = yytext; - if (nameIsOperator(yyextra->current->name)) - { - BEGIN( FuncPtrOperator ); - } - else - { - if (yyextra->current->name=="const" || yyextra->current->name=="volatile") - { - yyextra->funcPtrType += yyextra->current->name; - } - else - { - BEGIN( EndFuncPtr ); - } - } - } -<FuncPtr>. { - //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName); - } -<FuncPtrOperator>"("{BN}*")"{BN}*/"(" { - yyextra->current->name += yytext; - yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); - lineCount(yyscanner); - } -<FuncPtrOperator>\n { + if (yyextra->insidePHP) // reference parameter + { + REJECT + } + else + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner); + addType(yyscanner); + yyextra->funcPtrType=yytext; + yyextra->roundCount=0; + //yyextra->current->type += yytext; + BEGIN( FuncPtr ); + } + } +<FuncPtr>{SCOPENAME} { + yyextra->current->name = yytext; + if (nameIsOperator(yyextra->current->name)) + { + BEGIN( FuncPtrOperator ); + } + else + { + if (yyextra->current->name=="const" || yyextra->current->name=="volatile") + { + yyextra->funcPtrType += yyextra->current->name; + } + else + { + BEGIN( EndFuncPtr ); + } + } + } +<FuncPtr>. { + //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName); + } +<FuncPtrOperator>"("{BN}*")"{BN}*/"(" { + yyextra->current->name += yytext; + yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); + lineCount(yyscanner); + } +<FuncPtrOperator>\n { + lineCount(yyscanner); + yyextra->current->name += *yytext; + } +<FuncPtrOperator>"(" { + unput(*yytext); + BEGIN( EndFuncPtr ); + } +<FuncPtrOperator>. { + yyextra->current->name += *yytext; + } +<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType.data()+1; + BEGIN(FindMembers); + } +<EndFuncPtr>")"{BN}*/"(" { // a function pointer + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType+")"; + BEGIN(FindMembers); + } +<EndFuncPtr>")"{BN}*/"[" { // an array of variables lineCount(yyscanner); - yyextra->current->name += *yytext; - } -<FuncPtrOperator>"(" { - unput(*yytext); - BEGIN( EndFuncPtr ); - } -<FuncPtrOperator>. { - yyextra->current->name += *yytext; - } -<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType.data()+1; - BEGIN(FindMembers); - } -<EndFuncPtr>")"{BN}*/"(" { // a function pointer - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType+")"; - BEGIN(FindMembers); - } -<EndFuncPtr>")"{BN}*/"[" { // an array of variables - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType.data(); - yyextra->current->args += ")"; - BEGIN(FindMembers); - } -<EndFuncPtr>"(" { // a function returning a function or + yyextra->current->type+=yyextra->funcPtrType.data(); + yyextra->current->args += ")"; + BEGIN(FindMembers); + } +<EndFuncPtr>"(" { // a function returning a function or // a function returning a pointer to an array - yyextra->current->args += *yytext ; - //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; - BEGIN( ReadFuncArgType ) ; - } -<EndFuncPtr>"["[^\n\]]*"]" { - yyextra->funcPtrType+=yytext; - } -<EndFuncPtr>")" { - BEGIN(FindMembers); - } -<FuncFunc>"(" { - yyextra->current->args += *yytext ; - ++yyextra->roundCount; - } -<FuncFunc>")" { - yyextra->current->args += *yytext ; - if ( yyextra->roundCount ) - --yyextra->roundCount; - else - { - BEGIN(FuncFuncEnd); - } - } -<FuncFuncEnd>")"{BN}*"(" { - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType+")("; - BEGIN(FuncFuncType); - } -<FuncFuncEnd>")"{BN}*/[;{] { - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType.data()+1; - BEGIN(Function); - } -<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array + yyextra->current->args += *yytext ; + //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; + BEGIN( ReadFuncArgType ) ; + } +<EndFuncPtr>"["[^\n\]]*"]" { + yyextra->funcPtrType+=yytext; + } +<EndFuncPtr>")" { + BEGIN(FindMembers); + } +<FuncFunc>"(" { + yyextra->current->args += *yytext ; + ++yyextra->roundCount; + } +<FuncFunc>")" { + yyextra->current->args += *yytext ; + if ( yyextra->roundCount ) + --yyextra->roundCount; + else + { + BEGIN(FuncFuncEnd); + } + } +<FuncFuncEnd>")"{BN}*"(" { + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType+")("; + BEGIN(FuncFuncType); + } +<FuncFuncEnd>")"{BN}*/[;{] { lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType; - yyextra->current->args+=")"; - BEGIN(FuncFuncArray); - } -<FuncFuncEnd>. { - yyextra->current->args += *yytext; - } -<FuncFuncType>"(" { - yyextra->current->type += *yytext; - yyextra->roundCount++; - } -<FuncFuncType>")" { - yyextra->current->type += *yytext; - if (yyextra->roundCount) - --yyextra->roundCount; - else - BEGIN(Function); - } -<FuncFuncType>{BN}*","{BN}* { lineCount(yyscanner) ; yyextra->current->type += ", " ; } -<FuncFuncType>{BN}+ { lineCount(yyscanner) ; yyextra->current->type += ' ' ; } -<FuncFuncType>. { - yyextra->current->type += *yytext; - } + yyextra->current->type+=yyextra->funcPtrType.data()+1; + BEGIN(Function); + } +<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType; + yyextra->current->args+=")"; + BEGIN(FuncFuncArray); + } +<FuncFuncEnd>. { + yyextra->current->args += *yytext; + } +<FuncFuncType>"(" { + yyextra->current->type += *yytext; + yyextra->roundCount++; + } +<FuncFuncType>")" { + yyextra->current->type += *yytext; + if (yyextra->roundCount) + --yyextra->roundCount; + else + BEGIN(Function); + } +<FuncFuncType>{BN}*","{BN}* { lineCount(yyscanner) ; yyextra->current->type += ", " ; } +<FuncFuncType>{BN}+ { lineCount(yyscanner) ; yyextra->current->type += ' ' ; } +<FuncFuncType>. { + yyextra->current->type += *yytext; + } <FindMembers>"("/{BN}*{ID}{BN}*"*"{BN}*{ID}*")"{BN}*"(" { // for catching typedef void (__stdcall *f)() like definitions - if (yyextra->current->type.left(7)=="typedef" && yyextra->current->bodyLine==-1) - // 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; - BEGIN( ReadFuncArgType ) ; - //printf(">>> Read function arguments!\n"); - } - } -<GetCallType>{BN}*{ID}{BN}*"*" { - lineCount(yyscanner); - addType(yyscanner); - yyextra->funcPtrType="("; - yyextra->funcPtrType+=yytext; - yyextra->roundCount=0; - BEGIN( FuncPtr ); - } -<FindMembers>"(" { + if (yyextra->current->type.left(7)=="typedef" && yyextra->current->bodyLine==-1) + // 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; + BEGIN( ReadFuncArgType ) ; + //printf(">>> Read function arguments!\n"); + } + } +<GetCallType>{BN}*{ID}{BN}*"*" { + lineCount(yyscanner); + addType(yyscanner); + yyextra->funcPtrType="("; + yyextra->funcPtrType+=yytext; + yyextra->roundCount=0; + BEGIN( FuncPtr ); + } +<FindMembers>"(" { if (!yyextra->current->name.isEmpty()) - { - 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; - BEGIN( ReadFuncArgType ) ; - //printf(">>> Read function arguments yyextra->current->argList.size()=%d\n",yyextra->current->argList.size()); - } - } + { + 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; + BEGIN( ReadFuncArgType ) ; + //printf(">>> Read function arguments yyextra->current->argList.size()=%d\n",yyextra->current->argList.size()); + } + } /* -<FindMembers>"("{BN}*("void"{BN}*)?")" { - lineCount(yyscanner); - yyextra->current->args = "()"; - BEGIN( FuncQual ); - } +<FindMembers>"("{BN}*("void"{BN}*)?")" { + lineCount(yyscanner); + yyextra->current->args = "()"; + BEGIN( FuncQual ); + } */ /*- Function argument reading rules ---------------------------------------*/ -<ReadFuncArgType>[^ \/\r\t\n\)\(\"\'#]+ { *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<CopyArgString,CopyArgPHPString>[^\n\\\"\']+ { *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<CopyArgRound>[^\/\n\)\(\"\']+ { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<ReadFuncArgType,ReadTempArgs>{BN}* { - *yyextra->copyArgString+=" "; - yyextra->fullArgString+=" "; - lineCount(yyscanner); - } -<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>{RAWBEGIN} { +<ReadFuncArgType>[^ \/\r\t\n\)\(\"\'#]+ { *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<CopyArgString,CopyArgPHPString>[^\n\\\"\']+ { *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<CopyArgRound>[^\/\n\)\(\"\']+ { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<ReadFuncArgType,ReadTempArgs>{BN}* { + *yyextra->copyArgString+=" "; + yyextra->fullArgString+=" "; + lineCount(yyscanner); + } +<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>{RAWBEGIN} { yyextra->delimiter = yytext+2; yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); yyextra->lastRawStringContext = YY_START; yyextra->pCopyRawString = yyextra->copyArgString; *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; BEGIN(RawString); } -<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->lastCopyArgStringContext = YY_START; - BEGIN( CopyArgString ); - } -<ReadFuncArgType,ReadTempArgs>"(" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argRoundCount=0; - yyextra->lastCopyArgContext = YY_START; - BEGIN( CopyArgRound ); - } -<ReadFuncArgType>")" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; +<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->lastCopyArgStringContext = YY_START; + BEGIN( CopyArgString ); + } +<ReadFuncArgType,ReadTempArgs>"(" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argRoundCount=0; + yyextra->lastCopyArgContext = YY_START; + BEGIN( CopyArgRound ); + } +<ReadFuncArgType>")" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); - if (yyextra->insideJS) - { - fixArgumentListForJavaScript(yyextra->current->argList); - } + if (yyextra->insideJS) + { + fixArgumentListForJavaScript(yyextra->current->argList); + } handleParametersCommentBlocks(yyscanner,yyextra->current->argList); - /* remember the yyextra->current documentation block, since - we could overwrite it with the documentation of - a function argument, which we then have to correct later - on - */ - yyextra->docBackup = yyextra->current->doc; - yyextra->briefBackup = yyextra->current->brief; - - BEGIN( yyextra->currentArgumentContext ); - } - /* a special comment */ -<ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) { + /* remember the yyextra->current documentation block, since + we could overwrite it with the documentation of + a function argument, which we then have to correct later + on + */ + yyextra->docBackup = yyextra->current->doc; + yyextra->briefBackup = yyextra->current->brief; + + BEGIN( yyextra->currentArgumentContext ); + } + /* a special comment */ +<ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) { if (yyextra->currentArgumentContext==DefineEnd) - { - // for defines we interpret a comment - // as documentation for the define - int i;for (i=(int)yyleng-1;i>=0;i--) - { - unput(yytext[i]); - } + { + // for defines we interpret a comment + // as documentation for the define + int i;for (i=(int)yyleng-1;i>=0;i--) + { + unput(yytext[i]); + } yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); handleParametersCommentBlocks(yyscanner,yyextra->current->argList); - BEGIN( yyextra->currentArgumentContext ); - } - else // not a define - { - // for functions we interpret a comment - // as documentation for the argument - yyextra->fullArgString+=yytext; - yyextra->lastCopyArgChar=0; - yyextra->lastCommentInArgContext=YY_START; - if (yytext[1]=='/') - BEGIN( CopyArgCommentLine ); - else - BEGIN( CopyArgComment ); - } - } - /* a non-special comment */ -<ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ } -<ReadFuncArgType,ReadTempArgs>"/*" { - yyextra->lastCContext = YY_START; - BEGIN( SkipComment ); - } -<ReadFuncArgType,ReadTempArgs>"//" { - yyextra->lastCContext = YY_START; - BEGIN( SkipCxxComment ); - } + BEGIN( yyextra->currentArgumentContext ); + } + else // not a define + { + // for functions we interpret a comment + // as documentation for the argument + yyextra->fullArgString+=yytext; + yyextra->lastCopyArgChar=0; + yyextra->lastCommentInArgContext=YY_START; + if (yytext[1]=='/') + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } + } + /* a non-special comment */ +<ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ } +<ReadFuncArgType,ReadTempArgs>"/*" { + yyextra->lastCContext = YY_START; + BEGIN( SkipComment ); + } +<ReadFuncArgType,ReadTempArgs>"//" { + yyextra->lastCContext = YY_START; + BEGIN( SkipCxxComment ); + } /* -<ReadFuncArgType,ReadTempArgs>"'#" { if (yyextra->insidePHP) +<ReadFuncArgType,ReadTempArgs>"'#" { if (yyextra->insidePHP) + REJECT; + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<ReadFuncArgType,ReadTempArgs>"#" { + if (!yyextra->insidePHP) REJECT; - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<ReadFuncArgType,ReadTempArgs>"#" { - if (!yyextra->insidePHP) - REJECT; - yyextra->lastCContext = YY_START; - BEGIN( SkipCxxComment ); - } + yyextra->lastCContext = YY_START; + BEGIN( SkipCxxComment ); + } */ - /* ')' followed by a special comment */ -<ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" { - lineCount(yyscanner); + /* ')' followed by a special comment */ +<ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" { + lineCount(yyscanner); if (yyextra->currentArgumentContext==DefineEnd) - { - // for defines we interpret a comment - // as documentation for the define - int i;for (i=(int)yyleng-1;i>0;i--) - { - unput(yytext[i]); - } - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; + { + // for defines we interpret a comment + // as documentation for the define + int i;for (i=(int)yyleng-1;i>0;i--) + { + unput(yytext[i]); + } + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); handleParametersCommentBlocks(yyscanner,yyextra->current->argList); - BEGIN( yyextra->currentArgumentContext ); - } - else - { - // for functions we interpret a comment - // as documentation for the yyextra->last argument - yyextra->lastCopyArgChar=*yytext; - QCString text=&yytext[1]; - text=text.stripWhiteSpace(); - yyextra->lastCommentInArgContext=YY_START; - yyextra->fullArgString+=text; - if (text.find("//")!=-1) - BEGIN( CopyArgCommentLine ); - else - BEGIN( CopyArgComment ); - } - } -<CopyArgComment>^{B}*"*"+/{BN}+ -<CopyArgComment>[^\n\\\@\*]+ { yyextra->fullArgString+=yytext; } -<CopyArgComment>"*/" { yyextra->fullArgString+=yytext; - if (yyextra->lastCopyArgChar!=0) - unput(yyextra->lastCopyArgChar); - BEGIN( yyextra->lastCommentInArgContext ); - } -<CopyArgCommentLine>\n { yyextra->fullArgString+=yytext; + BEGIN( yyextra->currentArgumentContext ); + } + else + { + // for functions we interpret a comment + // as documentation for the yyextra->last argument + yyextra->lastCopyArgChar=*yytext; + QCString text=&yytext[1]; + text=text.stripWhiteSpace(); + yyextra->lastCommentInArgContext=YY_START; + yyextra->fullArgString+=text; + if (text.find("//")!=-1) + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } + } +<CopyArgComment>^{B}*"*"+/{BN}+ +<CopyArgComment>[^\n\\\@\*]+ { yyextra->fullArgString+=yytext; } +<CopyArgComment>"*/" { yyextra->fullArgString+=yytext; + if (yyextra->lastCopyArgChar!=0) + unput(yyextra->lastCopyArgChar); + BEGIN( yyextra->lastCommentInArgContext ); + } +<CopyArgCommentLine>\n { yyextra->fullArgString+=yytext; lineCount(yyscanner); - if (yyextra->lastCopyArgChar!=0) - unput(yyextra->lastCopyArgChar); - BEGIN( yyextra->lastCommentInArgContext ); - } -<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); - } -<CopyArgCommentLine>{CMD}("f$"|"f["|"f{") { - yyextra->docBlockName=&yytext[1]; - if (yyextra->docBlockName.at(1)=='[') - { - yyextra->docBlockName.at(1)='}'; - } - if (yyextra->docBlockName.at(1)=='{') - { - yyextra->docBlockName.at(1)='}'; - } - yyextra->fullArgString+=yytext; - BEGIN(CopyArgVerbatim); + if (yyextra->lastCopyArgChar!=0) + unput(yyextra->lastCopyArgChar); + BEGIN( yyextra->lastCommentInArgContext ); + } +<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); + } +<CopyArgCommentLine>{CMD}("f$"|"f["|"f{") { + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='[') + { + yyextra->docBlockName.at(1)='}'; + } + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } + yyextra->fullArgString+=yytext; + BEGIN(CopyArgVerbatim); } <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 - { - BEGIN(CopyArgCommentLine); - } - if (&yytext[4]==yyextra->docBlockName) - { - BEGIN(CopyArgCommentLine); - } - } -<CopyArgCommentLine>[^\\\@\n]+ { yyextra->fullArgString+=yytext; } -<CopyArgCommentLine>. { yyextra->fullArgString+=*yytext; } -<CopyArgComment,CopyArgVerbatim>\n { yyextra->fullArgString+=*yytext; lineCount(yyscanner); } -<CopyArgComment,CopyArgVerbatim>. { yyextra->fullArgString+=*yytext; } + yyextra->fullArgString+=yytext; + if (yytext[1]=='f') // end of formula + { + BEGIN(CopyArgCommentLine); + } + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(CopyArgCommentLine); + } + } +<CopyArgCommentLine>[^\\\@\n]+ { yyextra->fullArgString+=yytext; } +<CopyArgCommentLine>. { yyextra->fullArgString+=*yytext; } +<CopyArgComment,CopyArgVerbatim>\n { yyextra->fullArgString+=*yytext; lineCount(yyscanner); } +<CopyArgComment,CopyArgVerbatim>. { yyextra->fullArgString+=*yytext; } <CopyArgComment>{CMD}("brief"|"short"){B}+ { - warn(yyextra->yyFileName,yyextra->yyLineNr, - "Ignoring %cbrief command inside argument documentation",*yytext - ); + warn(yyextra->yyFileName,yyextra->yyLineNr, + "Ignoring %cbrief command inside argument documentation",*yytext + ); yyextra->fullArgString+=' '; } -<ReadTempArgs>"<" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argSharpCount=1; - BEGIN( CopyArgSharp ); - } -<ReadTempArgs>">" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - //printf("end template list '%s'\n",yyextra->copyArgString->data()); +<ReadTempArgs>"<" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argSharpCount=1; + BEGIN( CopyArgSharp ); + } +<ReadTempArgs>">" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + //printf("end template list '%s'\n",yyextra->copyArgString->data()); *yyextra->currentArgumentList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); - BEGIN( yyextra->currentArgumentContext ); - } -<CopyArgRound>"(" { - yyextra->argRoundCount++; - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } -<CopyArgRound>")" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - if (yyextra->argRoundCount>0) - yyextra->argRoundCount--; - else - BEGIN( yyextra->lastCopyArgContext ); - } + BEGIN( yyextra->currentArgumentContext ); + } +<CopyArgRound>"(" { + yyextra->argRoundCount++; + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } +<CopyArgRound>")" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + if (yyextra->argRoundCount>0) + yyextra->argRoundCount--; + else + BEGIN( yyextra->lastCopyArgContext ); + } <CopyArgSharp>"(" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argRoundCount=0; - yyextra->lastCopyArgContext = YY_START; - BEGIN( CopyArgRound ); - } -<CopyArgSharp>"<" { - yyextra->argSharpCount++; - //printf("yyextra->argSharpCount++=%d copy\n",yyextra->argSharpCount); - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } -<CopyArgSharp>">" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argSharpCount--; - if (yyextra->argSharpCount>0) - { - //printf("yyextra->argSharpCount--=%d copy\n",yyextra->argSharpCount); - } - else - { - BEGIN( ReadTempArgs ); - //printf("end of yyextra->argSharpCount\n"); - } - } -<CopyArgString,CopyArgPHPString>\\. { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<CopyArgString>\" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - BEGIN( yyextra->lastCopyArgStringContext ); - } -<CopyArgPHPString>\' { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - BEGIN( yyextra->lastCopyArgStringContext ); - } -<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>{CHARLIT} { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argRoundCount=0; + yyextra->lastCopyArgContext = YY_START; + BEGIN( CopyArgRound ); + } +<CopyArgSharp>"<" { + yyextra->argSharpCount++; + //printf("yyextra->argSharpCount++=%d copy\n",yyextra->argSharpCount); + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } +<CopyArgSharp>">" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argSharpCount--; + if (yyextra->argSharpCount>0) + { + //printf("yyextra->argSharpCount--=%d copy\n",yyextra->argSharpCount); + } + else + { + BEGIN( ReadTempArgs ); + //printf("end of yyextra->argSharpCount\n"); + } + } +<CopyArgString,CopyArgPHPString>\\. { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<CopyArgString>\" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + BEGIN( yyextra->lastCopyArgStringContext ); + } +<CopyArgPHPString>\' { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + BEGIN( yyextra->lastCopyArgStringContext ); + } +<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } - } -<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>\' { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - if (yyextra->insidePHP) - { - yyextra->lastCopyArgStringContext=YY_START; - BEGIN(CopyArgPHPString); - } - } -<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>\n { + { + REJECT; + } + else + { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } + } +<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>\' { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + if (yyextra->insidePHP) + { + yyextra->lastCopyArgStringContext=YY_START; + BEGIN(CopyArgPHPString); + } + } +<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>\n { lineCount(yyscanner); - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } -<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>. { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } +<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>. { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } /*------------------------------------------------------------------------*/ -<FuncRound>"(" { yyextra->current->args += *yytext ; - ++yyextra->roundCount ; - } -<FuncRound>")" { yyextra->current->args += *yytext ; - if ( yyextra->roundCount ) - --yyextra->roundCount ; - else - BEGIN( FuncQual ) ; - } +<FuncRound>"(" { yyextra->current->args += *yytext ; + ++yyextra->roundCount ; + } +<FuncRound>")" { yyextra->current->args += *yytext ; + if ( yyextra->roundCount ) + --yyextra->roundCount ; + else + BEGIN( FuncQual ) ; + } /* -<FuncQual>"#" { if (yyextra->insidePHP) - REJECT; - yyextra->lastCPPContext = YY_START; - BEGIN(SkipCPP); - } +<FuncQual>"#" { if (yyextra->insidePHP) + REJECT; + yyextra->lastCPPContext = YY_START; + BEGIN(SkipCPP); + } */ <FuncQual>[{:;,] { - if ( qstrcmp(yytext,";")==0 && - yyextra->insidePHP && - !containsWord(yyextra->current->type,"function") ) + if ( qstrcmp(yytext,";")==0 && + yyextra->insidePHP && + !containsWord(yyextra->current->type,"function") ) { yyextra->current->reset(); initEntry(yyscanner); @@ -4499,54 +4515,54 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } <FuncQual>{BN}*"abstract"{BN}* { // pure virtual member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->virt = Pure; - yyextra->current->args += " override "; + yyextra->current->args += " override "; } <FuncQual,TrailingReturn>{BN}*"override"{BN}* { // C++11 overridden virtual member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::Override; - yyextra->current->args += " override "; + yyextra->current->args += " override "; BEGIN(FuncQual); } <FuncQual,TrailingReturn>{BN}*"final"{BN}* { // C++11 final method - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::Final; - yyextra->current->args += " final "; + yyextra->current->args += " final "; BEGIN(FuncQual); } <FuncQual>{BN}*"sealed"{BN}* { // sealed member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::Sealed; - yyextra->current->args += " sealed "; + yyextra->current->args += " sealed "; } <FuncQual>{BN}*"new"{BN}* { // new member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::New; - yyextra->current->args += " new "; - } -<FuncQual>{BN}*"const"{BN}* { // const member function - lineCount(yyscanner) ; - yyextra->current->args += " const "; - yyextra->current->argList.setConstSpecifier(TRUE); - } -<FuncQual>{BN}*"volatile"{BN}* { // volatile member function - lineCount(yyscanner) ; - yyextra->current->args += " volatile "; - yyextra->current->argList.setVolatileSpecifier(TRUE); - } -<FuncQual>{BN}*"noexcept"{BN}* { // noexcept qualifier - lineCount(yyscanner) ; - yyextra->current->args += " noexcept "; - yyextra->current->spec |= Entry::NoExcept; - } -<FuncQual>{BN}*"noexcept"{BN}*"(" { // noexcept expression - lineCount(yyscanner) ; - yyextra->current->args += " noexcept("; - yyextra->current->spec |= Entry::NoExcept; - yyextra->lastRoundContext=FuncQual; - yyextra->pCopyRoundString=&yyextra->current->args; - yyextra->roundCount=0; + yyextra->current->args += " new "; + } +<FuncQual>{BN}*"const"{BN}* { // const member function + lineCount(yyscanner) ; + yyextra->current->args += " const "; + yyextra->current->argList.setConstSpecifier(TRUE); + } +<FuncQual>{BN}*"volatile"{BN}* { // volatile member function + lineCount(yyscanner) ; + yyextra->current->args += " volatile "; + yyextra->current->argList.setVolatileSpecifier(TRUE); + } +<FuncQual>{BN}*"noexcept"{BN}* { // noexcept qualifier + lineCount(yyscanner) ; + yyextra->current->args += " noexcept "; + yyextra->current->spec |= Entry::NoExcept; + } +<FuncQual>{BN}*"noexcept"{BN}*"(" { // noexcept expression + lineCount(yyscanner) ; + yyextra->current->args += " noexcept("; + yyextra->current->spec |= Entry::NoExcept; + yyextra->lastRoundContext=FuncQual; + yyextra->pCopyRoundString=&yyextra->current->args; + yyextra->roundCount=0; BEGIN(CopyRound); } <FuncQual>{BN}*"&" { @@ -4558,36 +4574,57 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) 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.setPureSpecifier(TRUE); +<FuncQual,TrailingReturn>{BN}*"="{BN}*"0"{BN}* { // pure virtual member function + lineCount(yyscanner) ; + yyextra->current->args += " = 0"; + yyextra->current->virt = Pure; + 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.setIsDeleted(TRUE); + yyextra->current->spec |= Entry::Delete; + yyextra->current->argList.setIsDeleted(TRUE); BEGIN(FuncQual); } <FuncQual,TrailingReturn>{BN}*"="{BN}*"default"{BN}* { // C++11 explicitly defaulted constructor/assignment operator lineCount(yyscanner); yyextra->current->args += " = default"; - yyextra->current->spec |= Entry::Default; + yyextra->current->spec |= Entry::Default; BEGIN(FuncQual); } <FuncQual>{BN}*"->"{BN}* { lineCount(yyscanner); yyextra->current->argList.setTrailingReturnType(" -> "); yyextra->current->args += " -> "; + yyextra->roundCount=0; BEGIN(TrailingReturn); } <TrailingReturn>[{;] { + if (yyextra->roundCount>0) REJECT; unput(*yytext); BEGIN(FuncQual); } +<TrailingReturn>"(" { + yyextra->roundCount++; + yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); + yyextra->current->args+=yytext; + } +<TrailingReturn>")" { + if (yyextra->roundCount>0) + { + yyextra->roundCount--; + } + else + { + warn(yyextra->yyFileName,yyextra->yyLineNr, + "Found ')' without opening '(' for trailing return type '%s)...'", + yyextra->current->argList.trailingReturnType().data()); + } + yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); + yyextra->current->args+=yytext; + } <TrailingReturn>. { yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); yyextra->current->args+=yytext; @@ -4597,207 +4634,207 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); yyextra->current->args+=' '; } -<FuncRound,FuncFunc>{BN}*","{BN}* { - lineCount(yyscanner) ; - yyextra->current->args += ", " ; - } -<FuncQual,FuncRound,FuncFunc>{BN}+ { - lineCount(yyscanner) ; - yyextra->current->args += ' ' ; - } +<FuncRound,FuncFunc>{BN}*","{BN}* { + lineCount(yyscanner) ; + yyextra->current->args += ", " ; + } +<FuncQual,FuncRound,FuncFunc>{BN}+ { + lineCount(yyscanner) ; + yyextra->current->args += ' ' ; + } <Function,FuncQual,FuncRound,FuncFunc>"#" { if (yyextra->insidePHP) - REJECT; - yyextra->lastCPPContext = YY_START; - BEGIN(SkipCPP); - } -<FuncQual>"=" { - if (yyextra->insideCli && - (yyextra->current_root->section&Entry::COMPOUND_MASK) - ) - { - BEGIN(CliOverride); - } - else - { + REJECT; + yyextra->lastCPPContext = YY_START; + BEGIN(SkipCPP); + } +<FuncQual>"=" { + if (yyextra->insideCli && + (yyextra->current_root->section&Entry::COMPOUND_MASK) + ) + { + BEGIN(CliOverride); + } + else + { // typically an initialized function pointer - yyextra->lastInitializerContext=YY_START; - yyextra->initBracketCount=0; + yyextra->lastInitializerContext=YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = yytext; - BEGIN(ReadInitializer); - } - } -<CliOverride>{ID} { - } -<CliOverride>"{" { - unput(*yytext); - BEGIN(FuncQual); - } -<CliOverride>\n { + BEGIN(ReadInitializer); + } + } +<CliOverride>{ID} { + } +<CliOverride>"{" { + unput(*yytext); + BEGIN(FuncQual); + } +<CliOverride>\n { lineCount(yyscanner); - } -<CliOverride>. { - } -<FuncPtrInit>[{;] { - unput(*yytext); - BEGIN(FuncQual); - } -<FuncPtrInit>\" { - yyextra->current->args += *yytext; - yyextra->pCopyQuotedString=&yyextra->current->args; - yyextra->lastStringContext=FuncPtrInit; - BEGIN(CopyString); - } -<FuncPtrInit>\' { - yyextra->current->args += *yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedString=&yyextra->current->args; - yyextra->lastStringContext=FuncPtrInit; - BEGIN(CopyPHPString); - } - } -<FuncPtrInit>{CHARLIT} { + } +<CliOverride>. { + } +<FuncPtrInit>[{;] { + unput(*yytext); + BEGIN(FuncQual); + } +<FuncPtrInit>\" { + yyextra->current->args += *yytext; + yyextra->pCopyQuotedString=&yyextra->current->args; + yyextra->lastStringContext=FuncPtrInit; + BEGIN(CopyString); + } +<FuncPtrInit>\' { + yyextra->current->args += *yytext; if (yyextra->insidePHP) - { - REJECT; - } - else - { - yyextra->current->args += yytext; - } - } -<FuncPtrInit>{ID} { - yyextra->current->args += yytext; - } -<FuncPtrInit>. { - yyextra->current->args += *yytext; - } -<FuncPtrInit>\n { - yyextra->current->args += *yytext; + { + yyextra->pCopyQuotedString=&yyextra->current->args; + yyextra->lastStringContext=FuncPtrInit; + BEGIN(CopyPHPString); + } + } +<FuncPtrInit>{CHARLIT} { + if (yyextra->insidePHP) + { + REJECT; + } + else + { + yyextra->current->args += yytext; + } + } +<FuncPtrInit>{ID} { + yyextra->current->args += yytext; + } +<FuncPtrInit>. { + yyextra->current->args += *yytext; + } +<FuncPtrInit>\n { + yyextra->current->args += *yytext; lineCount(yyscanner); - } -<FuncQual>{ID} { // typically a K&R style C function + } +<FuncQual>{ID} { // typically a K&R style C function if (yyextra->insideCS && qstrcmp(yytext,"where")==0) - { - // type constraint for a method - yyextra->current->typeConstr.clear(); - yyextra->current->typeConstr.push_back(Argument()); - yyextra->lastCSConstraint = YY_START; - BEGIN( CSConstraintName ); - } - else if (checkForKnRstyleC(yyscanner)) - { - yyextra->current->args = yytext; - yyextra->oldStyleArgType.resize(0); - BEGIN(OldStyleArgs); - } - else - { - yyextra->current->args += yytext; - } - } -<OldStyleArgs>[,;] { - QCString oldStyleArgPtr; - QCString oldStyleArgName; - splitKnRArg(yyscanner,oldStyleArgPtr,oldStyleArgName); - QCString doc,brief; - if (yyextra->current->doc!=yyextra->docBackup) - { + { + // type constraint for a method + yyextra->current->typeConstr.clear(); + yyextra->current->typeConstr.push_back(Argument()); + yyextra->lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else if (checkForKnRstyleC(yyscanner)) + { + yyextra->current->args = yytext; + yyextra->oldStyleArgType.resize(0); + BEGIN(OldStyleArgs); + } + else + { + yyextra->current->args += yytext; + } + } +<OldStyleArgs>[,;] { + QCString oldStyleArgPtr; + QCString oldStyleArgName; + splitKnRArg(yyscanner,oldStyleArgPtr,oldStyleArgName); + QCString doc,brief; + if (yyextra->current->doc!=yyextra->docBackup) + { doc=yyextra->current->doc.copy(); - yyextra->current->doc=yyextra->docBackup; - } - if (yyextra->current->brief!=yyextra->briefBackup) - { + yyextra->current->doc=yyextra->docBackup; + } + if (yyextra->current->brief!=yyextra->briefBackup) + { brief=yyextra->current->brief.copy(); - yyextra->current->brief=yyextra->briefBackup; - } - addKnRArgInfo(yyscanner,yyextra->oldStyleArgType+oldStyleArgPtr, - oldStyleArgName,brief,doc); - yyextra->current->args.resize(0); - if (*yytext==';') yyextra->oldStyleArgType.resize(0); - } -<OldStyleArgs>{ID} { yyextra->current->args += yytext; } -<OldStyleArgs>"{" { + yyextra->current->brief=yyextra->briefBackup; + } + addKnRArgInfo(yyscanner,yyextra->oldStyleArgType+oldStyleArgPtr, + oldStyleArgName,brief,doc); + yyextra->current->args.resize(0); + if (*yytext==';') yyextra->oldStyleArgType.resize(0); + } +<OldStyleArgs>{ID} { yyextra->current->args += yytext; } +<OldStyleArgs>"{" { if (yyextra->current->argList.empty()) { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); - unput('{'); - BEGIN(FuncQual); - } -<OldStyleArgs>. { yyextra->current->args += *yytext; } -<FuncQual,FuncRound,FuncFunc>. { yyextra->current->args += *yytext; } -<FuncQual>{BN}*"try:" | -<FuncQual>{BN}*"try"{BN}+ { /* try-function-block */ - yyextra->insideTryBlock=TRUE; - lineCount(yyscanner); - if (yytext[yyleng-1]==':') - { - unput(':'); - BEGIN( Function ); - } - } -<FuncQual>{BN}*"throw"{BN}*"(" { // C++ style throw clause - yyextra->current->exception = " throw (" ; - yyextra->roundCount=0; - lineCount(yyscanner) ; - BEGIN( ExcpRound ) ; - } + yyextra->current->args = argListToString(yyextra->current->argList); + unput('{'); + BEGIN(FuncQual); + } +<OldStyleArgs>. { yyextra->current->args += *yytext; } +<FuncQual,FuncRound,FuncFunc>. { yyextra->current->args += *yytext; } +<FuncQual>{BN}*"try:" | +<FuncQual>{BN}*"try"{BN}+ { /* try-function-block */ + yyextra->insideTryBlock=TRUE; + lineCount(yyscanner); + if (yytext[yyleng-1]==':') + { + unput(':'); + BEGIN( Function ); + } + } +<FuncQual>{BN}*"throw"{BN}*"(" { // C++ style throw clause + yyextra->current->exception = " throw (" ; + yyextra->roundCount=0; + lineCount(yyscanner) ; + BEGIN( ExcpRound ) ; + } <FuncQual>{BN}*"raises"{BN}*"(" { - yyextra->current->exception = " raises (" ; - lineCount(yyscanner) ; - yyextra->roundCount=0; - BEGIN( ExcpRound ) ; - } -<FuncQual>{BN}*"throws"{BN}+ { // Java style throw clause - yyextra->current->exception = " throws " ; - lineCount(yyscanner) ; - BEGIN( ExcpList ); - } -<ExcpRound>"(" { yyextra->current->exception += *yytext ; - ++yyextra->roundCount ; - } -<ExcpRound>")" { yyextra->current->exception += *yytext ; - if ( yyextra->roundCount ) - --yyextra->roundCount ; - else - BEGIN( FuncQual ) ; - } -<ExcpRound>. { - yyextra->current->exception += *yytext; - } -<ExcpList>"{" { - unput('{'); BEGIN( FuncQual ); - } -<ExcpList>";" { - unput(';'); BEGIN( FuncQual ); - } -<ExcpList>"\n" { - yyextra->current->exception += ' '; + yyextra->current->exception = " raises (" ; + lineCount(yyscanner) ; + yyextra->roundCount=0; + BEGIN( ExcpRound ) ; + } +<FuncQual>{BN}*"throws"{BN}+ { // Java style throw clause + yyextra->current->exception = " throws " ; + lineCount(yyscanner) ; + BEGIN( ExcpList ); + } +<ExcpRound>"(" { yyextra->current->exception += *yytext ; + ++yyextra->roundCount ; + } +<ExcpRound>")" { yyextra->current->exception += *yytext ; + if ( yyextra->roundCount ) + --yyextra->roundCount ; + else + BEGIN( FuncQual ) ; + } +<ExcpRound>. { + yyextra->current->exception += *yytext; + } +<ExcpList>"{" { + unput('{'); BEGIN( FuncQual ); + } +<ExcpList>";" { + unput(';'); BEGIN( FuncQual ); + } +<ExcpList>"\n" { + yyextra->current->exception += ' '; lineCount(yyscanner); - } -<ExcpList>. { - yyextra->current->exception += *yytext; - } -<Function>"(" { yyextra->current->type += yyextra->current->name ; - yyextra->current->name = yyextra->current->args ; - yyextra->current->args = yytext ; - yyextra->roundCount=0; - BEGIN( FuncRound ) ; - } -<Function>":" { - if (!yyextra->insidePHP) BEGIN(SkipInits); - } -<Function>[;{,] { - yyextra->current->name=yyextra->current->name.simplifyWhiteSpace(); - yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); - yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - // was: yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyBegLineNr; - yyextra->current->startColumn = yyextra->yyBegColNr; - static QRegExp re("([^)]*[*&][^)]*)"); // (...*...) + } +<ExcpList>. { + yyextra->current->exception += *yytext; + } +<Function>"(" { yyextra->current->type += yyextra->current->name ; + yyextra->current->name = yyextra->current->args ; + yyextra->current->args = yytext ; + yyextra->roundCount=0; + BEGIN( FuncRound ) ; + } +<Function>":" { + if (!yyextra->insidePHP) BEGIN(SkipInits); + } +<Function>[;{,] { + yyextra->current->name=yyextra->current->name.simplifyWhiteSpace(); + yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); + yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); + // was: yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->fileName = yyextra->yyFileName; + 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); @@ -4806,117 +4843,117 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) 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 ")); + (!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('<'); - QCString tempName; - if (tempArg==-1) tempName=yyextra->current->name; else tempName=yyextra->current->name.left(tempArg); - 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 ") - { - yyextra->current->type.prepend("typedef "); - } - yyextra->current->section = Entry::VARIABLE_SEC ; - } - 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 ; - yyextra->current->proto = *yytext==';'; - } - } - 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 (isVariable) - { - if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") - { - yyextra->current->type.prepend("typedef "); - } - //printf("Scanner.l: found function variable!\n"); - yyextra->current->section = Entry::VARIABLE_SEC; - } - else - { - //printf("Scanner.l: found prototype\n"); - yyextra->current->section = Entry::FUNCTION_SEC; - yyextra->current->proto = TRUE; - } - } - //printf("Adding entry '%s'\n",yyextra->current->name.data()); - if ( yyextra->insidePHP) - { - if (findAndRemoveWord(yyextra->current->type,"final")) - { - yyextra->current->spec |= Entry::Final; - } - if (findAndRemoveWord(yyextra->current->type,"abstract")) - { - yyextra->current->spec |= Entry::Abstract; - } - } - if ( yyextra->insidePHP && !containsWord(yyextra->current->type,"function")) - { - initEntry(yyscanner); - if ( *yytext == '{' ) - { - yyextra->lastCurlyContext = FindMembers; - yyextra->curlyCount=0; - BEGIN( SkipCurly ); - } - else - { - BEGIN( FindMembers ); - } - } - else - { - if ( yyextra->insidePHP) - { - findAndRemoveWord(yyextra->current->type,"function"); - } - yyextra->previous = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - // Objective C 2.0: Required/Optional section - if (yyextra->previous->spec & (Entry::Optional | Entry::Required)) - { - yyextra->current->spec |= yyextra->previous->spec & (Entry::Optional|Entry::Required); - } - yyextra->lastCurlyContext = FindMembers; - if ( *yytext == ',' ) - { - yyextra->current->type = yyextra->previous->type; - // we need to strip any trailing * and & (see bugs 623023 and 649103 for test cases) - int i=yyextra->current->type.length(); - while (i>0 && (yyextra->current->type[i-1]=='*' || yyextra->current->type[i-1]=='&' || yyextra->current->type[i-1]==' ')) i--; - yyextra->current->type = yyextra->current->type.left(i); - } - if ( *yytext == '{' ) - { - if ( !yyextra->insidePHP && (yyextra->current_root->section & Entry::COMPOUND_MASK) ) - { - yyextra->previous->spec |= Entry::Inline; - } - //addToBody(yytext); - yyextra->curlyCount=0; - BEGIN( SkipCurly ) ; - } - else - { - if (yyextra->previous->section!=Entry::VARIABLE_SEC) - yyextra->previous->bodyLine=-1; // a function/member declaration - BEGIN( FindMembers ) ; - } - } + if (*yytext!=';' || (yyextra->current_root->section&Entry::COMPOUND_MASK) ) + { + int tempArg=yyextra->current->name.find('<'); + QCString tempName; + if (tempArg==-1) tempName=yyextra->current->name; else tempName=yyextra->current->name.left(tempArg); + 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 ") + { + yyextra->current->type.prepend("typedef "); + } + yyextra->current->section = Entry::VARIABLE_SEC ; + } + 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 ; + yyextra->current->proto = *yytext==';'; + } + } + 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 (isVariable) + { + if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") + { + yyextra->current->type.prepend("typedef "); + } + //printf("Scanner.l: found function variable!\n"); + yyextra->current->section = Entry::VARIABLE_SEC; + } + else + { + //printf("Scanner.l: found prototype\n"); + yyextra->current->section = Entry::FUNCTION_SEC; + yyextra->current->proto = TRUE; + } + } + //printf("Adding entry '%s'\n",yyextra->current->name.data()); + if ( yyextra->insidePHP) + { + if (findAndRemoveWord(yyextra->current->type,"final")) + { + yyextra->current->spec |= Entry::Final; + } + if (findAndRemoveWord(yyextra->current->type,"abstract")) + { + yyextra->current->spec |= Entry::Abstract; + } + } + if ( yyextra->insidePHP && !containsWord(yyextra->current->type,"function")) + { + initEntry(yyscanner); + if ( *yytext == '{' ) + { + yyextra->lastCurlyContext = FindMembers; + yyextra->curlyCount=0; + BEGIN( SkipCurly ); + } + else + { + BEGIN( FindMembers ); + } + } + else + { + if ( yyextra->insidePHP) + { + findAndRemoveWord(yyextra->current->type,"function"); + } + yyextra->previous = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + // Objective C 2.0: Required/Optional section + if (yyextra->previous->spec & (Entry::Optional | Entry::Required)) + { + yyextra->current->spec |= yyextra->previous->spec & (Entry::Optional|Entry::Required); + } + yyextra->lastCurlyContext = FindMembers; + if ( *yytext == ',' ) + { + yyextra->current->type = yyextra->previous->type; + // we need to strip any trailing * and & (see bugs 623023 and 649103 for test cases) + int i=yyextra->current->type.length(); + while (i>0 && (yyextra->current->type[i-1]=='*' || yyextra->current->type[i-1]=='&' || yyextra->current->type[i-1]==' ')) i--; + yyextra->current->type = yyextra->current->type.left(i); + } + if ( *yytext == '{' ) + { + if ( !yyextra->insidePHP && (yyextra->current_root->section & Entry::COMPOUND_MASK) ) + { + yyextra->previous->spec |= Entry::Inline; + } + //addToBody(yytext); + yyextra->curlyCount=0; + BEGIN( SkipCurly ) ; + } + else + { + if (yyextra->previous->section!=Entry::VARIABLE_SEC) + yyextra->previous->bodyLine=-1; // a function/member declaration + BEGIN( FindMembers ) ; + } + } } <SkipInits>">"{BN}*"{" { // C++11 style initializer (see bug 790788) lineCount(yyscanner); @@ -4932,7 +4969,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) ++yyextra->curlyCount; } <SkipC11Inits>"}" { - if ( --yyextra->curlyCount<=0 ) + if ( --yyextra->curlyCount<=0 ) { BEGIN(SkipInits); } @@ -4940,116 +4977,116 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <SkipC11Attribute>"]]" { BEGIN(yyextra->lastC11AttributeContext); } -<SkipInits>"{" { // C++11 style initializer - unput('{'); - BEGIN( Function ); - } -<SkipCurly>"{" { - //addToBody(yytext); - ++yyextra->curlyCount ; - } +<SkipInits>"{" { // C++11 style initializer + unput('{'); + BEGIN( Function ); + } +<SkipCurly>"{" { + //addToBody(yytext); + ++yyextra->curlyCount ; + } <SkipCurly>"}"/{BN}*("/*!"|"/**"|"//!"|"///")"<!--" | /* see bug710917 */ -<SkipCurly>"}" { - //addToBody(yytext); - if( yyextra->curlyCount ) - { - --yyextra->curlyCount ; - } - else - { - if (!yyextra->current->sli.empty() && yyextra->previous) // copy special list items - { +<SkipCurly>"}" { + //addToBody(yytext); + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else + { + if (!yyextra->current->sli.empty() && yyextra->previous) // copy special list items + { yyextra->previous->sli = yyextra->current->sli; - yyextra->current->sli.clear(); - } - if (yyextra->previous) yyextra->previous->endBodyLine=yyextra->yyLineNr; - BEGIN( yyextra->lastCurlyContext ) ; - } - } -<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { - lineCount(yyscanner); - if ( yyextra->curlyCount ) - { - //addToBody(yytext); - --yyextra->curlyCount ; - } - else - { - yyextra->current->endBodyLine=yyextra->yyLineNr; - yyextra->tempEntry = yyextra->current; // temporarily switch to the previous entry - yyextra->current = yyextra->previous; - - yyextra->docBlockContext = SkipCurlyEndDoc; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); - yyextra->docBlock.resize(0); - yyextra->docBlockTerm = '}'; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } - } + yyextra->current->sli.clear(); + } + if (yyextra->previous) yyextra->previous->endBodyLine=yyextra->yyLineNr; + BEGIN( yyextra->lastCurlyContext ) ; + } + } +<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { + lineCount(yyscanner); + if ( yyextra->curlyCount ) + { + //addToBody(yytext); + --yyextra->curlyCount ; + } + else + { + yyextra->current->endBodyLine=yyextra->yyLineNr; + yyextra->tempEntry = yyextra->current; // temporarily switch to the previous entry + yyextra->current = yyextra->previous; + + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlock.resize(0); + yyextra->docBlockTerm = '}'; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } + } <SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one - yyextra->docBlockContext = SkipCurlyEndDoc; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); - yyextra->docBlock.resize(0); - yyextra->docBlockTerm = '}'; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } -<SkipCurlyEndDoc>"}" { - //addToBody("}"); + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlock.resize(0); + yyextra->docBlockTerm = '}'; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } +<SkipCurlyEndDoc>"}" { + //addToBody("}"); if (yyextra->tempEntry) // we can only switch back to yyextra->current if no new item was created - { - yyextra->current = yyextra->tempEntry; - yyextra->tempEntry.reset(); - } - BEGIN( yyextra->lastCurlyContext ); - } -<SkipCurly>\" { - //addToBody(yytext); - yyextra->lastStringContext=SkipCurly; - BEGIN( SkipString ); - } -<SkipCurly>^{B}*"#" { - if (yyextra->insidePHP) - REJECT; - //addToBody(yytext); - BEGIN( SkipCurlyCpp ); - } -<SkipCurly,SkipC11Inits,SkipInits,SkipC11Attribute>\n { + { + yyextra->current = yyextra->tempEntry; + yyextra->tempEntry.reset(); + } + BEGIN( yyextra->lastCurlyContext ); + } +<SkipCurly>\" { + //addToBody(yytext); + yyextra->lastStringContext=SkipCurly; + BEGIN( SkipString ); + } +<SkipCurly>^{B}*"#" { + if (yyextra->insidePHP) + REJECT; + //addToBody(yytext); + BEGIN( SkipCurlyCpp ); + } +<SkipCurly,SkipC11Inits,SkipInits,SkipC11Attribute>\n { lineCount(yyscanner); - //addToBody(yytext); - } -<SkipCurly,SkipCurlyCpp,ReadInitializer>"<<<" { - if (!yyextra->insidePHP) - { - REJECT; - } - else - { + //addToBody(yytext); + } +<SkipCurly,SkipCurlyCpp,ReadInitializer,ReadInitializerPtr>"<<<" { + if (!yyextra->insidePHP) + { + REJECT; + } + else + { yyextra->lastHereDocContext = YY_START; - BEGIN(HereDoc); - } - } + BEGIN(HereDoc); + } + } <SkipCurly,SkipCurlyCpp>{B}*{RAWBEGIN} { QCString raw=QCString(yytext).stripWhiteSpace(); yyextra->delimiter = raw.data()+2; @@ -5062,191 +5099,191 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}<]+ { lineCount(yyscanner); // for yyextra->column updates - //addToBody(yytext); - } -<SkipCurlyCpp>\n { - //addToBody(yytext); + //addToBody(yytext); + } +<SkipCurlyCpp>\n { + //addToBody(yytext); lineCount(yyscanner); - yyextra->lastCurlyContext = FindMembers; - BEGIN( SkipCurly ); - } -<SkipCurlyCpp>\\[\r]*"\n"[\r]* { - //addToBody(yytext); + yyextra->lastCurlyContext = FindMembers; + BEGIN( SkipCurly ); + } +<SkipCurlyCpp>\\[\r]*"\n"[\r]* { + //addToBody(yytext); lineCount(yyscanner); - } -<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"/*" { - //addToBody(yytext); - yyextra->lastCContext = YY_START; - BEGIN(SkipComment); - } + } +<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"/*" { + //addToBody(yytext); + yyextra->lastCContext = YY_START; + BEGIN(SkipComment); + } <SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"//" { - //addToBody(yytext); - yyextra->lastCContext = YY_START; - BEGIN(SkipCxxComment); - } + //addToBody(yytext); + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } <SkipInits,SkipC11Inits,SkipC11Attribute>"(" { yyextra->roundCount=0; yyextra->lastSkipRoundContext=YY_START; BEGIN(SkipRound); } -<SkipInits,SkipC11Inits,SkipC11Attribute>\" { - yyextra->lastStringContext=YY_START; - BEGIN( SkipString ); - } -<SkipInits>; { - warn(yyextra->yyFileName,yyextra->yyLineNr, - "Found ';' while parsing initializer list! " - "(doxygen could be confused by a macro call without semicolon)" - ); - BEGIN( FindMembers ); - } +<SkipInits,SkipC11Inits,SkipC11Attribute>\" { + yyextra->lastStringContext=YY_START; + BEGIN( SkipString ); + } +<SkipInits>; { + warn(yyextra->yyFileName,yyextra->yyLineNr, + "Found ';' while parsing initializer list! " + "(doxygen could be confused by a macro call without semicolon)" + ); + BEGIN( FindMembers ); + } <SkipInits,SkipCurly,SkipCurlyCpp>"#" { - if (!yyextra->insidePHP) - REJECT; - //addToBody(yytext); - yyextra->lastCContext = YY_START; - BEGIN(SkipCxxComment); - } + if (!yyextra->insidePHP) + REJECT; + //addToBody(yytext); + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } <SkipInits,SkipCurly,SkipCurlyCpp>@\" { - if (!yyextra->insideCS) REJECT; - // C# verbatim string - yyextra->lastSkipVerbStringContext=YY_START; - yyextra->pSkipVerbString=&yyextra->current->initializer; - BEGIN(SkipVerbString); - } -<SkipInits,SkipCurly,SkipCurlyCpp>{CHARLIT} { + if (!yyextra->insideCS) REJECT; + // C# verbatim string + yyextra->lastSkipVerbStringContext=YY_START; + yyextra->pSkipVerbString=&yyextra->current->initializer; + BEGIN(SkipVerbString); + } +<SkipInits,SkipCurly,SkipCurlyCpp>{CHARLIT} { if (yyextra->insidePHP) REJECT; } -<SkipInits,SkipCurly,SkipCurlyCpp>\' { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=YY_START; - BEGIN(SkipPHPString); - } - } -<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>. { } -<SkipString,SkipPHPString>\\. { } -<SkipString>\" { - BEGIN( yyextra->lastStringContext ); - } -<SkipPHPString>\' { - BEGIN( yyextra->lastStringContext ); - } +<SkipInits,SkipCurly,SkipCurlyCpp>\' { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=YY_START; + BEGIN(SkipPHPString); + } + } +<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>. { } +<SkipString,SkipPHPString>\\. { } +<SkipString>\" { + BEGIN( yyextra->lastStringContext ); + } +<SkipPHPString>\' { + BEGIN( yyextra->lastStringContext ); + } <SkipString,SkipPHPString>"/*"|"*/"|"//" { } -<SkipString,SkipPHPString>\n { +<SkipString,SkipPHPString>\n { lineCount(yyscanner); - } -<SkipString,SkipPHPString>. { } -<CompoundName>":" { // for "class : public base {} var;" construct, see bug 608359 - unput(':'); - BEGIN(ClassVar); - } -<CompoundName>";" { - yyextra->current->section = Entry::EMPTY_SEC ; - yyextra->current->type.resize(0) ; - yyextra->current->name.resize(0) ; - yyextra->current->args.resize(0) ; - yyextra->current->argList.clear(); - BEGIN( FindMembers ) ; - } -<Bases>";" { - if (yyextra->insideIDL && (yyextra->current->spec & (Entry::Singleton | - Entry::Service))) - { - // in UNO IDL a service or singleton may be defined - // completely like this: "service Foo : XFoo;" - if (!yyextra->current->name.isEmpty() && !yyextra->current_root->name.isEmpty()) - { - prependScope(yyscanner); - } - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - // there can be only one base class here - if (!yyextra->baseName.isEmpty()) - { - yyextra->current->extends.push_back( - BaseInfo(yyextra->baseName,Public,Normal)); - yyextra->baseName.resize(0); - } - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + } +<SkipString,SkipPHPString>. { } +<CompoundName>":" { // for "class : public base {} var;" construct, see bug 608359 + unput(':'); + BEGIN(ClassVar); + } +<CompoundName>";" { + yyextra->current->section = Entry::EMPTY_SEC ; + yyextra->current->type.resize(0) ; + yyextra->current->name.resize(0) ; + yyextra->current->args.resize(0) ; + yyextra->current->argList.clear(); + BEGIN( FindMembers ) ; + } +<Bases>";" { + if (yyextra->insideIDL && (yyextra->current->spec & (Entry::Singleton | + Entry::Service))) + { + // in UNO IDL a service or singleton may be defined + // completely like this: "service Foo : XFoo;" + if (!yyextra->current->name.isEmpty() && !yyextra->current_root->name.isEmpty()) + { + prependScope(yyscanner); + } + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + // there can be only one base class here + if (!yyextra->baseName.isEmpty()) + { + yyextra->current->extends.push_back( + BaseInfo(yyextra->baseName,Public,Normal)); + yyextra->baseName.resize(0); + } + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; initEntry(yyscanner); - } - else - { - yyextra->current->section = Entry::EMPTY_SEC ; - yyextra->current->type.resize(0) ; - yyextra->current->name.resize(0) ; - yyextra->current->args.resize(0) ; - yyextra->current->argList.clear(); - } - BEGIN( FindMembers ) ; - } -<CompoundName>{SCOPENAME}/{BN}*"<" { - yyextra->sharpCount = 0; - yyextra->current->name = yytext ; - if (yyextra->current->spec & Entry::Protocol) - { - yyextra->current->name+="-p"; - } - lineCount(yyscanner); - yyextra->lastClassTemplSpecContext = ClassVar; - if (yyextra->insideObjC) // protocol list - { - BEGIN( ObjCProtocolList ); - } - else if (yyextra->insideCS) // C# generic class - { + } + else + { + yyextra->current->section = Entry::EMPTY_SEC ; + yyextra->current->type.resize(0) ; + yyextra->current->name.resize(0) ; + yyextra->current->args.resize(0) ; + yyextra->current->argList.clear(); + } + BEGIN( FindMembers ) ; + } +<CompoundName>{SCOPENAME}/{BN}*"<" { + yyextra->sharpCount = 0; + yyextra->current->name = yytext ; + if (yyextra->current->spec & Entry::Protocol) + { + yyextra->current->name+="-p"; + } + lineCount(yyscanner); + yyextra->lastClassTemplSpecContext = ClassVar; + if (yyextra->insideObjC) // protocol list + { + BEGIN( ObjCProtocolList ); + } + else if (yyextra->insideCS) // C# generic class + { //yyextra->current->name+="-g"; - BEGIN( CSGeneric ); - } - else // C++ template specialization - { - yyextra->roundCount=0; - BEGIN( ClassTemplSpec ); - } - } -<CSGeneric>"<" { - ArgumentList al; - // check bug 612858 before enabling the next line - //yyextra->current->spec |= Entry::Template; - yyextra->current->tArgLists.push_back(al); - yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); - yyextra->templateStr="<"; - yyextra->current->name += "<"; - yyextra->fullArgString = yyextra->templateStr; - yyextra->copyArgString = &yyextra->current->name; - //yyextra->copyArgString = &yyextra->templateStr; - yyextra->currentArgumentContext = ClassVar; - BEGIN( ReadTempArgs ); - } -<ObjCProtocolList>"<" { - yyextra->insideProtocolList=TRUE; - BEGIN( Bases ); - } -<ClassTemplSpec>">"({BN}*"::"{BN}*{SCOPENAME})? { - yyextra->current->name += yytext; - lineCount(yyscanner); - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); - if (yyextra->current->spec & Entry::Protocol) - { // Objective-C protocol - unput('{'); // fake start of body - BEGIN( ClassVar ); - } - else - { - BEGIN( yyextra->lastClassTemplSpecContext ); - } - } - } -<ClassTemplSpec>"<" { - yyextra->current->name += yytext; - if (yyextra->roundCount==0) yyextra->sharpCount++; - } -<ClassTemplSpec>. { - yyextra->current->name += yytext; - } -<CompoundName>{SCOPENAME}{BN}*";" { // forward declaration + BEGIN( CSGeneric ); + } + else // C++ template specialization + { + yyextra->roundCount=0; + BEGIN( ClassTemplSpec ); + } + } +<CSGeneric>"<" { + ArgumentList al; + // check bug 612858 before enabling the next line + //yyextra->current->spec |= Entry::Template; + yyextra->current->tArgLists.push_back(al); + yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); + yyextra->templateStr="<"; + yyextra->current->name += "<"; + yyextra->fullArgString = yyextra->templateStr; + yyextra->copyArgString = &yyextra->current->name; + //yyextra->copyArgString = &yyextra->templateStr; + yyextra->currentArgumentContext = ClassVar; + BEGIN( ReadTempArgs ); + } +<ObjCProtocolList>"<" { + yyextra->insideProtocolList=TRUE; + BEGIN( Bases ); + } +<ClassTemplSpec>">"({BN}*"::"{BN}*{SCOPENAME})? { + yyextra->current->name += yytext; + lineCount(yyscanner); + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); + if (yyextra->current->spec & Entry::Protocol) + { // Objective-C protocol + unput('{'); // fake start of body + BEGIN( ClassVar ); + } + else + { + BEGIN( yyextra->lastClassTemplSpecContext ); + } + } + } +<ClassTemplSpec>"<" { + yyextra->current->name += yytext; + if (yyextra->roundCount==0) yyextra->sharpCount++; + } +<ClassTemplSpec>. { + yyextra->current->name += yytext; + } +<CompoundName>{SCOPENAME}{BN}*";" { // forward declaration if (!yyextra->current->tArgLists.empty()) { // found a forward template declaration, this has @@ -5254,54 +5291,54 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name = yytext; yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); //printf("template class declaration for %s!\n",yyextra->current->name.data()); - QCString rn = yyextra->current_root->name.copy(); - //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); - if (!yyextra->current->name.isEmpty() && !rn.isEmpty()) - { - prependScope(yyscanner); - } + QCString rn = yyextra->current_root->name.copy(); + //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); + if (!yyextra->current->name.isEmpty() && !rn.isEmpty()) + { + prependScope(yyscanner); + } yyextra->current->spec|=Entry::ForwardDecl; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); } - else if (yyextra->insideIDL && - (((yyextra->current_root->spec & (Entry::Interface | - Entry::Service)) && - (yyextra->current->spec & Entry::Interface)) || - ((yyextra->current_root->spec & (Entry::Service | - Entry::Singleton)) && - (yyextra->current->spec & Entry::Service)))) - { - // interface yyextra->inside of UNO IDL service or interface - // service yyextra->inside of UNO IDL service or singleton - // there may be documentation on the member, - // so do not throw it away... - yyextra->current->name = yytext; - yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); - yyextra->current->section = (yyextra->current->spec & Entry::Interface) - ? Entry::EXPORTED_INTERFACE_SEC - : Entry::INCLUDED_SERVICE_SEC; -// yyextra->current->section = Entry::MEMBERDOC_SEC; - yyextra->current->spec &= ~(Entry::Interface|Entry::Service); // FIXME: horrible: Interface == Gettable, so need to clear it - actually we're mixing values from different enums in this case... granted only Optional and Interface are actually valid in this context but urgh... - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - } - - unput(';'); - yyextra->current->reset(); - initEntry(yyscanner); + else if (yyextra->insideIDL && + (((yyextra->current_root->spec & (Entry::Interface | + Entry::Service)) && + (yyextra->current->spec & Entry::Interface)) || + ((yyextra->current_root->spec & (Entry::Service | + Entry::Singleton)) && + (yyextra->current->spec & Entry::Service)))) + { + // interface yyextra->inside of UNO IDL service or interface + // service yyextra->inside of UNO IDL service or singleton + // there may be documentation on the member, + // so do not throw it away... + yyextra->current->name = yytext; + yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); + yyextra->current->section = (yyextra->current->spec & Entry::Interface) + ? Entry::EXPORTED_INTERFACE_SEC + : Entry::INCLUDED_SERVICE_SEC; +// yyextra->current->section = Entry::MEMBERDOC_SEC; + yyextra->current->spec &= ~(Entry::Interface|Entry::Service); // FIXME: horrible: Interface == Gettable, so need to clear it - actually we're mixing values from different enums in this case... granted only Optional and Interface are actually valid in this context but urgh... + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + } + + unput(';'); + yyextra->current->reset(); + initEntry(yyscanner); if (yyextra->insideObjC) // see bug746361 { - yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; + yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; yyextra->insideObjC = FALSE; } - if (yyextra->isTypedef) // typedef of a class, put typedef keyword back - { - yyextra->current->type.prepend("typedef"); - } - BEGIN( FindMembers ); - } -<CompoundName>{SCOPENAME}/{BN}*"(" { - yyextra->current->name = yytext ; - lineCount(yyscanner); + if (yyextra->isTypedef) // typedef of a class, put typedef keyword back + { + yyextra->current->type.prepend("typedef"); + } + BEGIN( FindMembers ); + } +<CompoundName>{SCOPENAME}/{BN}*"(" { + yyextra->current->name = yytext ; + lineCount(yyscanner); if (yyextra->insideCpp && yyextra->current->name=="alignas") // C++11 { yyextra->lastAlignAsContext = YY_START; @@ -5315,186 +5352,186 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } BEGIN( ClassVar ); } - } -<AlignAs>"(" { yyextra->roundCount=0; - BEGIN( AlignAsEnd ); + } +<AlignAs>"(" { yyextra->roundCount=0; + BEGIN( AlignAsEnd ); } <AlignAs>\n { lineCount(yyscanner); } <AlignAs>. <AlignAsEnd>"(" { yyextra->roundCount++; } -<AlignAsEnd>")" { if (--yyextra->roundCount<0) +<AlignAsEnd>")" { if (--yyextra->roundCount<0) { - BEGIN( yyextra->lastAlignAsContext ); + BEGIN( yyextra->lastAlignAsContext ); } } <AlignAsEnd>\n { lineCount(yyscanner); } <AlignAsEnd>. -<CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line +<CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line // e.g. @protocol A,B; - yyextra->current->reset(); - initEntry(yyscanner); - } -<CompoundName>{SCOPENAME} { - yyextra->current->name = yytext ; + yyextra->current->reset(); + initEntry(yyscanner); + } +<CompoundName>{SCOPENAME} { + yyextra->current->name = yytext ; if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - lineCount(yyscanner); - if (yyextra->current->spec & Entry::Protocol) - { - yyextra->current->name += "-p"; - } - if ((yyextra->current->spec & Entry::Protocol) || - yyextra->current->section == Entry::OBJCIMPL_SEC) - { - unput('{'); // fake start of body - } - BEGIN( ClassVar ); - } -<CompoundName>{CSSCOPENAME} { // C# style scope - yyextra->current->name = substitute(yytext,".","::"); - lineCount(yyscanner); - BEGIN( ClassVar ); - } -<ClassVar>{SCOPENAME}{BN}*/"(" { - if (yyextra->insideIDL && qstrncmp(yytext,"switch",6)==0 && !isId(yytext[6])) - { - // Corba IDL style union - yyextra->roundCount=0; - BEGIN(SkipUnionSwitch); - } - else - { - addType(yyscanner); - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - lineCount(yyscanner); - BEGIN( FindMembers ); - } - } -<ClassVar>"," { - if (yyextra->isTypedef) - { - // multiple types in one typedef - unput(','); - yyextra->current->type.prepend("typedef "); - BEGIN(FindMembers); - } - else - { - // Multiple class forward declaration - } - } + lineCount(yyscanner); + if (yyextra->current->spec & Entry::Protocol) + { + yyextra->current->name += "-p"; + } + if ((yyextra->current->spec & Entry::Protocol) || + yyextra->current->section == Entry::OBJCIMPL_SEC) + { + unput('{'); // fake start of body + } + BEGIN( ClassVar ); + } +<CompoundName>{CSSCOPENAME} { // C# style scope + yyextra->current->name = substitute(yytext,".","::"); + lineCount(yyscanner); + BEGIN( ClassVar ); + } +<ClassVar>{SCOPENAME}{BN}*/"(" { + if (yyextra->insideIDL && qstrncmp(yytext,"switch",6)==0 && !isId(yytext[6])) + { + // Corba IDL style union + yyextra->roundCount=0; + BEGIN(SkipUnionSwitch); + } + else + { + addType(yyscanner); + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + lineCount(yyscanner); + BEGIN( FindMembers ); + } + } +<ClassVar>"," { + if (yyextra->isTypedef) + { + // multiple types in one typedef + unput(','); + yyextra->current->type.prepend("typedef "); + BEGIN(FindMembers); + } + else + { + // Multiple class forward declaration + } + } <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") { - if (yyextra->insideCli) - { - if (yytext[0]=='s') // sealed - yyextra->current->spec |= Entry::SealedClass; - else // abstract - yyextra->current->spec |= Entry::AbstractClass; - BEGIN( ClassVar ); - } - else - { - REJECT; - } - } -<ClassVar>{ID} { + if (yyextra->insideCli) + { + if (yytext[0]=='s') // sealed + yyextra->current->spec |= Entry::SealedClass; + else // abstract + yyextra->current->spec |= Entry::AbstractClass; + BEGIN( ClassVar ); + } + else + { + REJECT; + } + } +<ClassVar>{ID} { if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - if (yyextra->insideIDL && qstrcmp(yytext,"switch")==0) - { - // Corba IDL style union - yyextra->roundCount=0; - BEGIN(SkipUnionSwitch); - } - else if ((yyextra->insideJava || yyextra->insidePHP || yyextra->insideJS || yyextra->insideSlice) && (qstrcmp(yytext,"implements")==0 || qstrcmp(yytext,"extends")==0)) - { - yyextra->current->type.resize(0); - yyextra->baseProt=Public; + if (yyextra->insideIDL && qstrcmp(yytext,"switch")==0) + { + // Corba IDL style union + yyextra->roundCount=0; + BEGIN(SkipUnionSwitch); + } + else if ((yyextra->insideJava || yyextra->insidePHP || yyextra->insideJS || yyextra->insideSlice) && (qstrcmp(yytext,"implements")==0 || qstrcmp(yytext,"extends")==0)) + { + yyextra->current->type.resize(0); + yyextra->baseProt=Public; yyextra->baseVirt=Normal; - yyextra->baseName.resize(0); - BEGIN( BasesProt ) ; - } - else if (yyextra->insideCS && qstrcmp(yytext,"where")==0) // C# type constraint - { + yyextra->baseName.resize(0); + BEGIN( BasesProt ) ; + } + else if (yyextra->insideCS && qstrcmp(yytext,"where")==0) // C# type constraint + { yyextra->current->typeConstr.clear(); - yyextra->current->typeConstr.push_back(Argument()); - yyextra->lastCSConstraint = YY_START; - BEGIN( CSConstraintName ); - } - else if (yyextra->insideCli && qstrcmp(yytext,"abstract")==0) - { - yyextra->current->spec|=Entry::Abstract; - } - else if (yyextra->insideCli && qstrcmp(yytext,"sealed")==0) - { - yyextra->current->spec|=Entry::Sealed; - } + yyextra->current->typeConstr.push_back(Argument()); + yyextra->lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else if (yyextra->insideCli && qstrcmp(yytext,"abstract")==0) + { + yyextra->current->spec|=Entry::Abstract; + } + else if (yyextra->insideCli && qstrcmp(yytext,"sealed")==0) + { + yyextra->current->spec|=Entry::Sealed; + } else if (qstrcmp(yytext,"final")==0) { yyextra->current->spec|=Entry::Final; } - else - { - if (yyextra->current->section == Entry::ENUM_SEC) - { // found "enum a b" -> variable - yyextra->current->section = Entry::VARIABLE_SEC ; - } - yyextra->current->type += ' ' ; - yyextra->current->type += yyextra->current->name ; - yyextra->current->name = yytext ; - - if (nameIsOperator(yyextra->current->name)) - { - BEGIN( Operator ); - } - } - } -<ClassVar>[(\[] { - if (yyextra->insideObjC && *yytext=='(') // class category - { - yyextra->current->name+='('; + else + { + if (yyextra->current->section == Entry::ENUM_SEC) + { // found "enum a b" -> variable + yyextra->current->section = Entry::VARIABLE_SEC ; + } + yyextra->current->type += ' ' ; + yyextra->current->type += yyextra->current->name ; + yyextra->current->name = yytext ; + + if (nameIsOperator(yyextra->current->name)) + { + BEGIN( Operator ); + } + } + } +<ClassVar>[(\[] { + if (yyextra->insideObjC && *yytext=='(') // class category + { + yyextra->current->name+='('; //if (yyextra->current->section!=Entry::OBJCIMPL_SEC) //{ - yyextra->current->spec|=Entry::Category; + yyextra->current->spec|=Entry::Category; //} - BEGIN( ClassCategory ); - } - else - { + BEGIN( ClassCategory ); + } + else + { // probably a function anyway unput(*yytext); - BEGIN( FindMembers ); - } - } + BEGIN( FindMembers ); + } + } <CSConstraintType,CSConstraintName>"/**/" { /* empty comment */ } -<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment +<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment yyextra->fullArgString.resize(0); - yyextra->lastCopyArgChar='#'; // end marker - yyextra->lastCommentInArgContext=YY_START; - if (yytext[1]=='/') - BEGIN( CopyArgCommentLine ); - else - BEGIN( CopyArgComment ); - } -<CSConstraintType,CSConstraintName>"#" { // artificially inserted token to signal end of comment block + yyextra->lastCopyArgChar='#'; // end marker + yyextra->lastCommentInArgContext=YY_START; + if (yytext[1]=='/') + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } +<CSConstraintType,CSConstraintName>"#" { // artificially inserted token to signal end of comment block yyextra->current->typeConstr.back().docs = yyextra->fullArgString; - } -<CSConstraintType>"{" { // end of type constraint reached + } +<CSConstraintType>"{" { // end of type constraint reached // parse documentation of the constraints handleParametersCommentBlocks(yyscanner,yyextra->current->typeConstr); - unput('{'); - BEGIN( yyextra->lastCSConstraint ); - } + unput('{'); + BEGIN( yyextra->lastCSConstraint ); + } <CSConstraintType,CSConstraintName>";" { handleParametersCommentBlocks(yyscanner,yyextra->current->typeConstr); - unput(';'); - BEGIN( yyextra->lastCSConstraint ); - } + unput(';'); + BEGIN( yyextra->lastCSConstraint ); + } <CSConstraintName>":" { BEGIN( CSConstraintType ); } @@ -5502,10 +5539,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) // parameter name yyextra->current->typeConstr.back().name=yytext; } -<CSConstraintType>"where" { // another constraint for a different param - yyextra->current->typeConstr.push_back(Argument()); +<CSConstraintType>"where" { // another constraint for a different param + yyextra->current->typeConstr.push_back(Argument()); BEGIN( CSConstraintName ); - } + } <CSConstraintType>({ID}".")*{ID}("<"{ID}">")?("()")? { if (yyextra->current->typeConstr.back().type.isEmpty()) // first type constraint for this parameter @@ -5520,300 +5557,300 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->typeConstr.back().type=yytext; } } -<CSConstraintName,CSConstraintType>\n { +<CSConstraintName,CSConstraintType>\n { lineCount(yyscanner); - } -<CSConstraintName,CSConstraintType>. { - } -<ClassCategory>{ID} { - yyextra->current->name+=yytext; - } -<ClassCategory>")"/{BN}*"{" { - yyextra->current->name+=')'; - BEGIN( ClassVar ); - } -<ClassCategory>")"/{BN}*"<" { - yyextra->current->name+=')'; - BEGIN( ObjCProtocolList ); - } -<ClassCategory>")" { - yyextra->current->name+=')'; - if ((yyextra->current->section & Entry::Protocol) || - yyextra->current->section == Entry::OBJCIMPL_SEC) - { - unput('{'); // fake start of body - } - else // category has no variables so push back an empty body - { - unput('}'); - unput('{'); - } - BEGIN( ClassVar ); - } -<ClassVar>":" { + } +<CSConstraintName,CSConstraintType>. { + } +<ClassCategory>{ID} { + yyextra->current->name+=yytext; + } +<ClassCategory>")"/{BN}*"{" { + yyextra->current->name+=')'; + BEGIN( ClassVar ); + } +<ClassCategory>")"/{BN}*"<" { + yyextra->current->name+=')'; + BEGIN( ObjCProtocolList ); + } +<ClassCategory>")" { + yyextra->current->name+=')'; + if ((yyextra->current->section & Entry::Protocol) || + yyextra->current->section == Entry::OBJCIMPL_SEC) + { + unput('{'); // fake start of body + } + else // category has no variables so push back an empty body + { + unput('}'); + unput('{'); + } + BEGIN( ClassVar ); + } +<ClassVar>":" { if (yyextra->current->section==Entry::VARIABLE_SEC) // enum A B:2, see bug 748208 { yyextra->current->bitfields+=":"; yyextra->current->args.resize(0); BEGIN(BitFields); } - else if (yyextra->current->section==Entry::ENUM_SEC) // enum E:2, see bug 313527, + else if (yyextra->current->section==Entry::ENUM_SEC) // enum E:2, see bug 313527, // or C++11 style enum: 'E : unsigned int {...}' - { - yyextra->current->args.resize(0); - BEGIN(EnumBaseType); - } - else - { - yyextra->current->type.resize(0); - if ((yyextra->current->spec & Entry::Interface) || - (yyextra->current->spec & Entry::Struct) || - (yyextra->current->spec & Entry::Ref) || - (yyextra->current->spec & Entry::Value) || - yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL - ) - yyextra->baseProt=Public; - else - yyextra->baseProt=Private; - yyextra->baseVirt=Normal; - yyextra->baseName.resize(0); - BEGIN( BasesProt ) ; - } - } -<ClassVar>[;=*&] { - unput(*yytext); - if (yyextra->isTypedef) // typedef of a class, put typedef keyword back - { - yyextra->current->type.prepend("typedef"); - } - if ((yytext[0]=='*' || yytext[0]=='&') && - yyextra->current->section == Entry::ENUM_SEC) - { // found "enum a *b" -> variable - yyextra->current->section = Entry::VARIABLE_SEC ; - } - BEGIN( FindMembers ); - } + { + yyextra->current->args.resize(0); + BEGIN(EnumBaseType); + } + else + { + yyextra->current->type.resize(0); + if ((yyextra->current->spec & Entry::Interface) || + (yyextra->current->spec & Entry::Struct) || + (yyextra->current->spec & Entry::Ref) || + (yyextra->current->spec & Entry::Value) || + yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL + ) + yyextra->baseProt=Public; + else + yyextra->baseProt=Private; + yyextra->baseVirt=Normal; + yyextra->baseName.resize(0); + BEGIN( BasesProt ) ; + } + } +<ClassVar>[;=*&] { + unput(*yytext); + if (yyextra->isTypedef) // typedef of a class, put typedef keyword back + { + yyextra->current->type.prepend("typedef"); + } + if ((yytext[0]=='*' || yytext[0]=='&') && + yyextra->current->section == Entry::ENUM_SEC) + { // found "enum a *b" -> variable + yyextra->current->section = Entry::VARIABLE_SEC ; + } + BEGIN( FindMembers ); + } <Bases,ClassVar>"///"/[^/] { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { - lineCount(yyscanner); - yyextra->current->program+=yytext; + if (!yyextra->insideObjC) + { + REJECT; + } + else + { + lineCount(yyscanner); + yyextra->current->program+=yytext; yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( ReadBodyIntf ); - } - } + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( ReadBodyIntf ); + } + } <Bases,ClassVar>("//"{B}*)?"/**"/[^/*] | <Bases,ClassVar>("//"{B}*)?"/*!" | <Bases,ClassVar>"//!" | -<Bases,ClassVar>[\-+]{BN}* { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { - lineCount(yyscanner); - yyextra->current->program+=yytext; +<Bases,ClassVar>[\-+]{BN}* { + if (!yyextra->insideObjC) + { + REJECT; + } + else + { + lineCount(yyscanner); + yyextra->current->program+=yytext; yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( ReadBodyIntf ); - } - } -<CompoundName,ClassVar>{B}*"{"{B}* { + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( ReadBodyIntf ); + } + } +<CompoundName,ClassVar>{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->current->name.isEmpty() && !yyextra->isTypedef) // anonymous compound - { - if (yyextra->current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces - { - if (Config_getBool(EXTRACT_ANON_NSPACES)) // use visible name - { - yyextra->current->name="anonymous_namespace{"+stripPath(yyextra->current->fileName)+"}"; - } - else // use invisible name - { - yyextra->current->name.sprintf("@%d",yyextra->anonNSCount); - } - } - else - { - yyextra->current->name.sprintf("@%d",yyextra->anonCount++); - } - } - yyextra->curlyCount=0; - if (yyextra->current_root && // not a nested struct yyextra->inside an @interface section - !(yyextra->current_root->spec & Entry::Interface) && - ((yyextra->current->spec & (Entry::Interface | Entry::Protocol | Entry::Category) || - yyextra->current->section==Entry::OBJCIMPL_SEC) - ) && - yyextra->insideObjC - ) - { // ObjC body that ends with @end - BEGIN( ReadBodyIntf ); - } - else if (yyextra->current->section==Entry::NAMESPACE_SEC) - { // namespace body - BEGIN( ReadNSBody ); - } - else - { // class body - BEGIN( ReadBody ) ; - } - } + 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 + { + if (yyextra->current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces + { + if (Config_getBool(EXTRACT_ANON_NSPACES)) // use visible name + { + yyextra->current->name="anonymous_namespace{"+stripPath(yyextra->current->fileName)+"}"; + } + else // use invisible name + { + yyextra->current->name.sprintf("@%d",anonNSCount.load()); + } + } + else + { + yyextra->current->name.sprintf("@%d",anonCount++); + } + } + yyextra->curlyCount=0; + if (yyextra->current_root && // not a nested struct yyextra->inside an @interface section + !(yyextra->current_root->spec & Entry::Interface) && + ((yyextra->current->spec & (Entry::Interface | Entry::Protocol | Entry::Category) || + yyextra->current->section==Entry::OBJCIMPL_SEC) + ) && + yyextra->insideObjC + ) + { // ObjC body that ends with @end + BEGIN( ReadBodyIntf ); + } + else if (yyextra->current->section==Entry::NAMESPACE_SEC) + { // namespace body + BEGIN( ReadNSBody ); + } + else + { // class body + BEGIN( ReadBody ) ; + } + } <BasesProt>"virtual"{BN}+ { lineCount(yyscanner); yyextra->baseVirt = Virtual; } <BasesProt>"public"{BN}+ { lineCount(yyscanner); yyextra->baseProt = Public; } <BasesProt>"protected"{BN}+ { lineCount(yyscanner); yyextra->baseProt = Protected; } <BasesProt>"internal"{BN}+ { if (!yyextra->insideCli) REJECT ; lineCount(yyscanner); yyextra->baseProt = Package; } <BasesProt>"private"{BN}+ { lineCount(yyscanner); yyextra->baseProt = Private; } -<BasesProt>{BN} { lineCount(yyscanner); } -<BasesProt>. { unput(*yytext); BEGIN(Bases); } -<Bases>("\\")?({ID}"\\")*{ID} { // PHP namespace token, not sure if interspacing is allowed but it gives problems (see bug 640847) +<BasesProt>{BN} { lineCount(yyscanner); } +<BasesProt>. { unput(*yytext); BEGIN(Bases); } +<Bases>("\\")?({ID}"\\")*{ID} { // PHP namespace token, not sure if interspacing is allowed but it gives problems (see bug 640847) if (!yyextra->insidePHP) - { - REJECT; - } - else // PHP base class of the form \Ns\Cl or Ns\Cl - { - lineCount(yyscanner); - QCString bn=yytext; - bn = substitute(bn,"\\","::"); - yyextra->baseName += bn; - yyextra->current->args += ' '; - yyextra->current->args += yytext; - } - } -<Bases>("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} { - lineCount(yyscanner); + { + REJECT; + } + else // PHP base class of the form \Ns\Cl or Ns\Cl + { + lineCount(yyscanner); + QCString bn=yytext; + bn = substitute(bn,"\\","::"); + yyextra->baseName += bn; + yyextra->current->args += ' '; + yyextra->current->args += yytext; + } + } +<Bases>("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} { + lineCount(yyscanner); QCString baseScope = yytext; if (yyextra->insideCS && baseScope.stripWhiteSpace()=="where") - { - // type constraint for a class + { + // type constraint for a class yyextra->current->typeConstr.clear(); - yyextra->current->typeConstr.push_back(Argument()); - yyextra->lastCSConstraint = YY_START; - BEGIN( CSConstraintName ); - } - else - { - yyextra->baseName+=yytext; - yyextra->current->args += ' '; - yyextra->current->args += yytext; - } - } -<Bases>{BN}*{ID}("."{ID})* { // Java style class - QCString name = substitute(yytext,".","::"); - yyextra->baseName += name; - yyextra->current->args += ' '; - yyextra->current->args += name; - } -<ClassVar,Bases>\n/{BN}*[^{, \t\n] { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { + yyextra->current->typeConstr.push_back(Argument()); + yyextra->lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else + { + yyextra->baseName+=yytext; + yyextra->current->args += ' '; + yyextra->current->args += yytext; + } + } +<Bases>{BN}*{ID}("."{ID})* { // Java style class + QCString name = substitute(yytext,".","::"); + yyextra->baseName += name; + yyextra->current->args += ' '; + yyextra->current->args += name; + } +<ClassVar,Bases>\n/{BN}*[^{, \t\n] { + if (!yyextra->insideObjC) + { + REJECT; + } + else + { lineCount(yyscanner); - unput('{'); - } - } -<ClassVar,Bases>"@end" { // empty ObjC interface - unput('d'); // insert fake body: {}@end - unput('n'); - unput('e'); - unput('@'); - unput('}'); - unput('{'); - } -<ClassVar>"<" { yyextra->current->name += *yytext; - yyextra->sharpCount=1; - yyextra->roundCount=0; - yyextra->lastSkipSharpContext = YY_START; - yyextra->specName = &yyextra->current->name; - BEGIN ( Specialization ); - } + unput('{'); + } + } +<ClassVar,Bases>"@end" { // empty ObjC interface + unput('d'); // insert fake body: {}@end + unput('n'); + unput('e'); + unput('@'); + unput('}'); + unput('{'); + } +<ClassVar>"<" { yyextra->current->name += *yytext; + yyextra->sharpCount=1; + yyextra->roundCount=0; + yyextra->lastSkipSharpContext = YY_START; + yyextra->specName = &yyextra->current->name; + BEGIN ( Specialization ); + } <Bases>{BN}*"<" { lineCount(yyscanner); - yyextra->sharpCount=1; - yyextra->roundCount=0; - yyextra->lastSkipSharpContext = YY_START; - if (yyextra->insideObjC) // start of protocol list - { - unput(','); - } - else // template specialization - { - //if (yyextra->insideCS) // generic - //{ - // yyextra->baseName+="-g"; - //} + yyextra->sharpCount=1; + yyextra->roundCount=0; + yyextra->lastSkipSharpContext = YY_START; + if (yyextra->insideObjC) // start of protocol list + { + unput(','); + } + else // template specialization + { + //if (yyextra->insideCS) // generic + //{ + // yyextra->baseName+="-g"; + //} yyextra->templateStr = yytext; - yyextra->specName = &yyextra->templateStr; - BEGIN ( Specialization ); - } - } -<Specialization>"<" { *yyextra->specName += *yytext; - if (yyextra->roundCount==0) yyextra->sharpCount++; - } -<Specialization>">" { - *yyextra->specName += *yytext; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - yyextra->baseName+=removeRedundantWhiteSpace(*yyextra->specName); - BEGIN(yyextra->lastSkipSharpContext); - } - } -<Specialization>{BN}+ { lineCount(yyscanner); *yyextra->specName +=' '; } -<Specialization>"<<" { *yyextra->specName += yytext; } -<Specialization>">>"/{B}*"::" { // M$ C++ extension to allow >> to close a template... - unput('>'); - unput(' '); - unput('>'); - } -<Specialization>">>" { + yyextra->specName = &yyextra->templateStr; + BEGIN ( Specialization ); + } + } +<Specialization>"<" { *yyextra->specName += *yytext; + if (yyextra->roundCount==0) yyextra->sharpCount++; + } +<Specialization>">" { + *yyextra->specName += *yytext; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + yyextra->baseName+=removeRedundantWhiteSpace(*yyextra->specName); + BEGIN(yyextra->lastSkipSharpContext); + } + } +<Specialization>{BN}+ { lineCount(yyscanner); *yyextra->specName +=' '; } +<Specialization>"<<" { *yyextra->specName += yytext; } +<Specialization>">>"/{B}*"::" { // M$ C++ extension to allow >> to close a template... + unput('>'); + unput(' '); + unput('>'); + } +<Specialization>">>" { if (yyextra->insideCS) // for C# >> ends a nested template - { - REJECT; - } - else // for C++ >> is a bitshift - // operator and > > would end - // a nested template. - // We require the bitshift to be enclosed in braces. - // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html - { - if (yyextra->roundCount>0) - { - *yyextra->specName += yytext; - } - else - { - unput('>'); - unput(' '); - unput('>'); - } - } - } -<Specialization>"typename"{BN}+ { lineCount(yyscanner); } -<Specialization>"(" { *yyextra->specName += *yytext; yyextra->roundCount++; } -<Specialization>")" { *yyextra->specName += *yytext; yyextra->roundCount--; } - -<Specialization>"\\\\" { *yyextra->specName += *yytext;} -<Specialization>"\\'" { *yyextra->specName += *yytext;} -<Specialization>"\\\"" { *yyextra->specName += *yytext;} -<Specialization>"'" { *yyextra->specName += *yytext;BEGIN(SpecializationSingleQuote);} -<Specialization>"\"" { *yyextra->specName += *yytext;BEGIN(SpecializationDoubleQuote);} + { + REJECT; + } + else // for C++ >> is a bitshift + // operator and > > would end + // a nested template. + // We require the bitshift to be enclosed in braces. + // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html + { + if (yyextra->roundCount>0) + { + *yyextra->specName += yytext; + } + else + { + unput('>'); + unput(' '); + unput('>'); + } + } + } +<Specialization>"typename"{BN}+ { lineCount(yyscanner); } +<Specialization>"(" { *yyextra->specName += *yytext; yyextra->roundCount++; } +<Specialization>")" { *yyextra->specName += *yytext; yyextra->roundCount--; } + +<Specialization>"\\\\" { *yyextra->specName += *yytext;} +<Specialization>"\\'" { *yyextra->specName += *yytext;} +<Specialization>"\\\"" { *yyextra->specName += *yytext;} +<Specialization>"'" { *yyextra->specName += *yytext;BEGIN(SpecializationSingleQuote);} +<Specialization>"\"" { *yyextra->specName += *yytext;BEGIN(SpecializationDoubleQuote);} <SpecializationSingleQuote,SpecializationDoubleQuote>"\\\\" { *yyextra->specName += *yytext;} <SpecializationSingleQuote>"\\'" { *yyextra->specName += *yytext;} <SpecializationSingleQuote>"'" { *yyextra->specName += *yytext; BEGIN(Specialization);} @@ -5821,154 +5858,154 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <SpecializationDoubleQuote>"\"" { *yyextra->specName += *yytext; BEGIN(Specialization);} <SpecializationSingleQuote,SpecializationDoubleQuote>. { *yyextra->specName += *yytext;} -<Specialization>. { - *yyextra->specName += *yytext; - } -<SkipRound>"(" { ++yyextra->roundCount; } -<SkipRound>")" { if (--yyextra->roundCount<0) - BEGIN ( yyextra->lastSkipRoundContext ); - } -<SkipRound>\" { - yyextra->lastStringContext=SkipRound; - BEGIN(SkipString); - } -<Bases>","|(">"({BN}*"{")?)|({BN}+"implements"{BN}*) { lineCount(yyscanner); +<Specialization>. { + *yyextra->specName += *yytext; + } +<SkipRound>"(" { ++yyextra->roundCount; } +<SkipRound>")" { if (--yyextra->roundCount<0) + BEGIN ( yyextra->lastSkipRoundContext ); + } +<SkipRound>\" { + yyextra->lastStringContext=SkipRound; + BEGIN(SkipString); + } +<Bases>","|(">"({BN}*"{")?)|({BN}+"implements"{BN}*) { lineCount(yyscanner); if (yyextra->insideProtocolList) - { - yyextra->baseName+="-p"; - } - else - { - yyextra->current->args += ',' ; - } - yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); - if (!yyextra->baseName.isEmpty()) - { - yyextra->current->extends.push_back( - BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) - ); - } - if ((yyextra->current->spec & (Entry::Interface|Entry::Struct)) || - yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || - yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL || yyextra->insideSlice) - { - yyextra->baseProt=Public; - } - else - { - yyextra->baseProt=Private; - } - yyextra->baseVirt=Normal; - yyextra->baseName.resize(0); + { + yyextra->baseName+="-p"; + } + else + { + yyextra->current->args += ',' ; + } + yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); + if (!yyextra->baseName.isEmpty()) + { + yyextra->current->extends.push_back( + BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) + ); + } + if ((yyextra->current->spec & (Entry::Interface|Entry::Struct)) || + yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || + yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL || yyextra->insideSlice) + { + yyextra->baseProt=Public; + } + else + { + yyextra->baseProt=Private; + } + yyextra->baseVirt=Normal; + yyextra->baseName.resize(0); if (*yytext=='>') - { // end of a ObjC protocol list - yyextra->insideProtocolList=FALSE; - if (yyleng==1) - { - unput('{'); // dummy start body - } - else - { - yyless(1); - } - } - else - { - if (*yytext==',' && yyextra->insideObjC) // Begin of protocol list - { - yyextra->insideProtocolList=TRUE; - } - BEGIN(BasesProt); - } - } -<Bases>{B}*"{"{B}* { + { // end of a ObjC protocol list + yyextra->insideProtocolList=FALSE; + if (yyleng==1) + { + unput('{'); // dummy start body + } + else + { + yyless(1); + } + } + else + { + if (*yytext==',' && yyextra->insideObjC) // Begin of protocol list + { + yyextra->insideProtocolList=TRUE; + } + BEGIN(BasesProt); + } + } +<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( - BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) - ); - yyextra->curlyCount=0; - if (yyextra->insideObjC) - { - BEGIN( ReadBodyIntf ); - } - else - { - BEGIN( ReadBody ) ; - } - } -<SkipUnionSwitch>{B}*"(" { - yyextra->roundCount++; - } -<SkipUnionSwitch>")" { - if (--yyextra->roundCount==0) - { - BEGIN(ClassVar); - } - } -<SkipUnionSwitch>\n { lineCount(yyscanner); } -<SkipUnionSwitch>. -<Comment>{BN}+ { yyextra->current->program += yytext ; - lineCount(yyscanner) ; - } -<Comment>"/*" { yyextra->current->program += yytext ; } -<Comment>"//" { yyextra->current->program += yytext ; } -<Comment>{CMD}("code"|"verbatim") { + 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( + BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) + ); + yyextra->curlyCount=0; + if (yyextra->insideObjC) + { + BEGIN( ReadBodyIntf ); + } + else + { + BEGIN( ReadBody ) ; + } + } +<SkipUnionSwitch>{B}*"(" { + yyextra->roundCount++; + } +<SkipUnionSwitch>")" { + if (--yyextra->roundCount==0) + { + BEGIN(ClassVar); + } + } +<SkipUnionSwitch>\n { lineCount(yyscanner); } +<SkipUnionSwitch>. +<Comment>{BN}+ { yyextra->current->program += yytext ; + lineCount(yyscanner) ; + } +<Comment>"/*" { yyextra->current->program += yytext ; } +<Comment>"//" { yyextra->current->program += yytext ; } +<Comment>{CMD}("code"|"verbatim") { yyextra->insideCode=TRUE; - yyextra->current->program += yytext ; - } -<Comment>{CMD}("endcode"|"endverbatim") { + yyextra->current->program += yytext ; + } +<Comment>{CMD}("endcode"|"endverbatim") { yyextra->insideCode=FALSE; - yyextra->current->program += yytext ; - } -<Comment>[^ \.\t\r\n\/\*]+ { yyextra->current->program += yytext ; } -<Comment>"*/" { yyextra->current->program += yytext ; - if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; - } -<Comment>. { yyextra->current->program += *yytext ; } - -<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,SkipC11Inits,SkipC11Attribute,Bases,OldStyleArgs>("//"{B}*)?"/*!" { - //printf("Start doc block at %d\n",yyextra->yyLineNr); - if (!yyextra->current->doc.isEmpty()) - { - yyextra->current->doc+="\n\n"; - } - else - { - yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; - } - - yyextra->lastDocContext = YY_START; - if (yyextra->current_root->section & Entry::SCOPE_MASK) - { - yyextra->current->inside = yyextra->current_root->name+"::"; - } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; - yyextra->docBlockAutoBrief = Config_getBool(QT_AUTOBRIEF); + yyextra->current->program += yytext ; + } +<Comment>[^ \.\t\r\n\/\*]+ { yyextra->current->program += yytext ; } +<Comment>"*/" { yyextra->current->program += yytext ; + if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; + } +<Comment>. { yyextra->current->program += *yytext ; } + +<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,SkipC11Inits,SkipC11Attribute,Bases,OldStyleArgs>("//"{B}*)?"/*!" { + //printf("Start doc block at %d\n",yyextra->yyLineNr); + if (!yyextra->current->doc.isEmpty()) + { + yyextra->current->doc+="\n\n"; + } + else + { + yyextra->current->docLine = yyextra->yyLineNr; + yyextra->current->docFile = yyextra->yyFileName; + } + + yyextra->lastDocContext = YY_START; + if (yyextra->current_root->section & Entry::SCOPE_MASK) + { + yyextra->current->inside = yyextra->current_root->name+"::"; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->docBlockAutoBrief = Config_getBool(QT_AUTOBRIEF); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - if (yyextra->docBlockAutoBrief) - { - yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; - } - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } + if (yyextra->docBlockAutoBrief) + { + yyextra->current->briefLine = yyextra->yyLineNr; + yyextra->current->briefFile = yyextra->yyFileName; + } + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>"/**"[*]+{BL} { - bool javadocBanner = Config_getBool(JAVADOC_BANNER); + bool javadocBanner = Config_getBool(JAVADOC_BANNER); lineCount(yyscanner); - if( javadocBanner ) + if( javadocBanner ) { yyextra->lastDocContext = YY_START; @@ -5998,185 +6035,185 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } else { - yyextra->current->program += yytext ; - yyextra->lastContext = YY_START ; - BEGIN( Comment ) ; - } - } + yyextra->current->program += yytext ; + yyextra->lastContext = YY_START ; + BEGIN( Comment ) ; + } + } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] { - yyextra->lastDocContext = YY_START; + yyextra->lastDocContext = YY_START; - //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); - if (yyextra->current_root->section & Entry::SCOPE_MASK) + //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); + if (yyextra->current_root->section & Entry::SCOPE_MASK) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->inside = yyextra->current_root->name+"::"; } - yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->current->docLine = yyextra->yyLineNr; + yyextra->current->docFile = yyextra->yyFileName; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF); - yyextra->docBlockAutoBrief = javadocAutoBrief; + yyextra->docBlockAutoBrief = javadocAutoBrief; QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - if (yyextra->docBlockAutoBrief) - { - yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; - } - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } -<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { - yyextra->lastDocContext = YY_START; - if (yyextra->current_root->section & Entry::SCOPE_MASK) + if (yyextra->docBlockAutoBrief) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->briefLine = yyextra->yyLineNr; + yyextra->current->briefFile = yyextra->yyFileName; } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; - yyextra->docBlockAutoBrief = FALSE; + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } +<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { + yyextra->lastDocContext = YY_START; + if (yyextra->current_root->section & Entry::SCOPE_MASK) + { + yyextra->current->inside = yyextra->current_root->name+"::"; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->docBlockAutoBrief = FALSE; QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); - BEGIN( DocLine ); - } -<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { - yyextra->lastDocContext = YY_START; - if (yyextra->current_root->section & Entry::SCOPE_MASK) + startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); + BEGIN( DocLine ); + } +<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { + yyextra->lastDocContext = YY_START; + if (yyextra->current_root->section & Entry::SCOPE_MASK) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->inside = yyextra->current_root->name+"::"; } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; - yyextra->docBlockAutoBrief = FALSE; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->docBlockAutoBrief = FALSE; QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); - BEGIN( DocLine ); - } + startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); + BEGIN( DocLine ); + } <FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? { - lineCount(yyscanner); - yyextra->externC=TRUE; - } -<FindMembers>"{" { - if (yyextra->externC) - { - yyextra->externC=FALSE; - } - else if (yyextra->insideCS && - !yyextra->current->name.isEmpty() && - !yyextra->current->type.isEmpty()) - { - if (containsWord(yyextra->current->type,"event")) // event - { - yyextra->current->mtype = yyextra->mtype = Event; - } - else // property - { - yyextra->current->mtype = yyextra->mtype = Property; - } - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( CSAccessorDecl ); - } - else if (yyextra->insideIDL && (yyextra->current->spec & Entry::Attribute)) - { - // UNO IDL: attributes may have setter and getter - // exception specifications - yyextra->current->exception = " {"; - BEGIN(UNOIDLAttributeBlock); - } - else - { - if ((yyextra->insideJava || yyextra->insideCS || yyextra->insideD) && - yyextra->current->name.isEmpty() - ) - { - // static Java initializer - yyextra->needsSemi = FALSE; - if (yyextra->current->stat) - { - yyextra->current->name="[static initializer]"; - yyextra->current->type.resize(0); - } - else - { - yyextra->current->name="[instance initializer]"; - } - unput(*yytext); - BEGIN( Function ); - } - else - { - // pre C++11 code -> ignore the initializer + lineCount(yyscanner); + yyextra->externC=TRUE; + } +<FindMembers>"{" { + if (yyextra->externC) + { + yyextra->externC=FALSE; + } + else if (yyextra->insideCS && + !yyextra->current->name.isEmpty() && + !yyextra->current->type.isEmpty()) + { + if (containsWord(yyextra->current->type,"event")) // event + { + yyextra->current->mtype = yyextra->mtype = Event; + } + else // property + { + yyextra->current->mtype = yyextra->mtype = Property; + } + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( CSAccessorDecl ); + } + else if (yyextra->insideIDL && (yyextra->current->spec & Entry::Attribute)) + { + // UNO IDL: attributes may have setter and getter + // exception specifications + yyextra->current->exception = " {"; + BEGIN(UNOIDLAttributeBlock); + } + else + { + if ((yyextra->insideJava || yyextra->insideCS || yyextra->insideD) && + yyextra->current->name.isEmpty() + ) + { + // static Java initializer + yyextra->needsSemi = FALSE; + if (yyextra->current->stat) + { + yyextra->current->name="[static initializer]"; + yyextra->current->type.resize(0); + } + else + { + yyextra->current->name="[instance initializer]"; + } + unput(*yytext); + BEGIN( Function ); + } + else + { + // pre C++11 code -> ignore the initializer //yyextra->needsSemi = TRUE; - //yyextra->current->type.resize(0); - //yyextra->current->name.resize(0); - //yyextra->current->args.resize(0); - //yyextra->current->argList.clear(); - //yyextra->curlyCount=0; - //BEGIN( SkipCurlyBlock ); + //yyextra->current->type.resize(0); + //yyextra->current->name.resize(0); + //yyextra->current->args.resize(0); + //yyextra->current->argList.clear(); + //yyextra->curlyCount=0; + //BEGIN( SkipCurlyBlock ); // C++11 style initializer list - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->initializer = yytext; - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=1; - BEGIN(ReadInitializer); - } - } - } -<CSAccessorDecl>"{" { yyextra->curlyCount++; } -<CSAccessorDecl>"}"{B}*"=" { - // fall back to next rule if it's not the right bracket - if (yyextra->curlyCount != 0) REJECT; - yyextra->current->initializer = "="; - yyextra->current->endBodyLine=yyextra->yyLineNr; - yyextra->lastInitializerContext = FindMembers; - BEGIN(ReadInitializer); - } -<CSAccessorDecl>"}" { - if (yyextra->curlyCount) - { - yyextra->curlyCount--; - } - else - { - yyextra->mtype = Method; + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=1; + BEGIN(ReadInitializer); + } + } + } +<CSAccessorDecl>"{" { yyextra->curlyCount++; } +<CSAccessorDecl>"}"{B}*"=" { + // fall back to next rule if it's not the right bracket + if (yyextra->curlyCount != 0) REJECT; + yyextra->current->initializer = "="; + yyextra->current->endBodyLine=yyextra->yyLineNr; + yyextra->lastInitializerContext = FindMembers; + BEGIN(ReadInitializer); + } +<CSAccessorDecl>"}" { + if (yyextra->curlyCount) + { + yyextra->curlyCount--; + } + else + { + yyextra->mtype = Method; yyextra->virt = Normal; - // not really important, but while we are at it - yyextra->current->endBodyLine=yyextra->yyLineNr; + // not really important, but while we are at it + yyextra->current->endBodyLine=yyextra->yyLineNr; unput(';'); - BEGIN(FindMembers); - } - } -<CSAccessorDecl>"private "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateSettable; } -<CSAccessorDecl>"protected "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedSettable; } -<CSAccessorDecl>"private "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateGettable; } -<CSAccessorDecl>"protected "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedGettable; } -<CSAccessorDecl>"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Settable; } -<CSAccessorDecl>"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Gettable; } -<CSAccessorDecl>"add" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Addable; } -<CSAccessorDecl>"remove" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Removable; } -<CSAccessorDecl>"raise" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Raisable; } -<CSAccessorDecl>"\"" { BEGIN(CSString);} -<CSAccessorDecl>"." {} -<CSAccessorDecl>\n { lineCount(yyscanner); } -<CSString>"\"" { BEGIN(CSAccessorDecl);} -<CSString>"//" {} // Otherwise the rule <*>"//" will kick in -<CSString>"/*" {} // Otherwise the rule <*>"/*" will kick in -<CSString>\n { lineCount(yyscanner); } -<CSString>"." {} + BEGIN(FindMembers); + } + } +<CSAccessorDecl>"private "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateSettable; } +<CSAccessorDecl>"protected "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedSettable; } +<CSAccessorDecl>"private "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateGettable; } +<CSAccessorDecl>"protected "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedGettable; } +<CSAccessorDecl>"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Settable; } +<CSAccessorDecl>"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Gettable; } +<CSAccessorDecl>"add" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Addable; } +<CSAccessorDecl>"remove" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Removable; } +<CSAccessorDecl>"raise" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Raisable; } +<CSAccessorDecl>"\"" { BEGIN(CSString);} +<CSAccessorDecl>"." {} +<CSAccessorDecl>\n { lineCount(yyscanner); } +<CSString>"\"" { BEGIN(CSAccessorDecl);} +<CSString>"//" {} // Otherwise the rule <*>"//" will kick in +<CSString>"/*" {} // Otherwise the rule <*>"/*" will kick in +<CSString>\n { lineCount(yyscanner); } +<CSString>"." {} /* ---- Slice-specific rules ------ */ @@ -6244,80 +6281,80 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /* ---- Single line comments ------ */ <DocLine>[^\n]*"\n"[ \t]*"//"[/!][<]? { // continuation of multiline C++-style comment - yyextra->docBlock+=yytext; + yyextra->docBlock+=yytext; int markerLen = yytext[yyleng-1]=='<' ? 4 : 3; - yyextra->docBlock.resize(yyextra->docBlock.length() - markerLen); + yyextra->docBlock.resize(yyextra->docBlock.length() - markerLen); lineCount(yyscanner); } -<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) - handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); - BEGIN( yyextra->docBlockContext ); - } -<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 - yyextra->docBlock+=yytext; - handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); - BEGIN( yyextra->docBlockContext ); - } -<DocLine>[^\n]*/"\n" { // whole line - yyextra->docBlock+=yytext; - handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); - BEGIN( yyextra->docBlockContext ); - } +<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) + handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 + yyextra->docBlock+=yytext; + handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n" { // whole line + yyextra->docBlock+=yytext; + handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); + BEGIN( yyextra->docBlockContext ); + } /* ---- Comments blocks ------ */ -<DocBlock>"*"*"*/" { // end of comment block - handleCommentBlock(yyscanner,yyextra->docBlock.data(),FALSE); - BEGIN(yyextra->docBlockContext); - } -<DocBlock>^{B}*"*"+/[^/] { +<DocBlock>"*"*"*/" { // end of comment block + handleCommentBlock(yyscanner,yyextra->docBlock.data(),FALSE); + BEGIN(yyextra->docBlockContext); + } +<DocBlock>^{B}*"*"+/[^/] { QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock+=indent; - } -<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line + } +<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock+=indent; - } -<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line - } -<DocBlock>"//" { // slashes in the middle of a comment block - yyextra->docBlock+=yytext; - } -<DocBlock>"/*" { // start of a new comment in the + } +<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line + } +<DocBlock>"//" { // slashes in the middle of a comment block + yyextra->docBlock+=yytext; + } +<DocBlock>"/*" { // start of a new comment in the // middle of a comment block - yyextra->docBlock+=yytext; - } + yyextra->docBlock+=yytext; + } <DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command - yyextra->docBlock+=yytext; - } -<DocBlock>{CMD}("f$"|"f["|"f{") { yyextra->docBlock+=yytext; - yyextra->docBlockName=&yytext[1]; - if (yyextra->docBlockName.at(1)=='{') - { - yyextra->docBlockName.at(1)='}'; - } + } +<DocBlock>{CMD}("f$"|"f["|"f{") { + yyextra->docBlock+=yytext; + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } yyextra->fencedSize=0; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); + BEGIN(DocCopyBlock); } -<DocBlock>{B}*"<"{PRE}">" { +<DocBlock>{B}*"<"{PRE}">" { yyextra->docBlock+=yytext; - yyextra->docBlockName="<pre>"; + yyextra->docBlockName="<pre>"; yyextra->fencedSize=0; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); - } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + BEGIN(DocCopyBlock); + } +<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->docBlockName=&yytext[1]; yyextra->fencedSize=0; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); - } + BEGIN(DocCopyBlock); + } <DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { QCString pat = substitute(yytext,"*"," "); @@ -6336,86 +6373,86 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(DocCopyBlock); } <DocBlock>{B}*"<code>" { - if (yyextra->insideCS) - { - yyextra->docBlock+=yytext; - yyextra->docBlockName="<code>"; + if (yyextra->insideCS) + { + yyextra->docBlock+=yytext; + yyextra->docBlockName="<code>"; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); - } - else - { - REJECT; - } - } -<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special - yyextra->docBlock+=yytext; - } -<DocBlock>\n { // newline + BEGIN(DocCopyBlock); + } + else + { + REJECT; + } + } +<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special + yyextra->docBlock+=yytext; + } +<DocBlock>\n { // newline lineCount(yyscanner); - yyextra->docBlock+=*yytext; - } -<DocBlock>. { // command block - yyextra->docBlock+=*yytext; - } + yyextra->docBlock+=*yytext; + } +<DocBlock>. { // command block + yyextra->docBlock+=*yytext; + } /* ---- Copy verbatim sections ------ */ -<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block - yyextra->docBlock+=yytext; - if (yyextra->docBlockName=="<pre>") - { - BEGIN(DocBlock); - } - } -<DocCopyBlock>"</"{CODE}">" { // end of a <code> block - yyextra->docBlock+=yytext; - if (yyextra->docBlockName=="<code>") - { - BEGIN(DocBlock); - } - } +<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block + yyextra->docBlock+=yytext; + if (yyextra->docBlockName=="<pre>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>"</"{CODE}">" { // end of a <code> block + yyextra->docBlock+=yytext; + if (yyextra->docBlockName=="<code>") + { + BEGIN(DocBlock); + } + } <DocCopyBlock>[\\@]("f$"|"f]"|"f}") { - yyextra->docBlock+=yytext; - BEGIN(DocBlock); - } + yyextra->docBlock+=yytext; + BEGIN(DocBlock); + } <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) - { - BEGIN(DocBlock); - } - } -<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line - if (yyextra->docBlockName=="verbatim") - { - REJECT; - } - else if (yyextra->docBlockName=="code") - { - REJECT; - } + yyextra->docBlock+=yytext; + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + if (yyextra->docBlockName=="verbatim") + { + REJECT; + } + else if (yyextra->docBlockName=="code") + { + REJECT; + } else { QCString indent; indent.fill(' ',computeIndent(yytext,0)); yyextra->docBlock+=indent; } - } -<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s - if (yyextra->docBlockName=="code") + } +<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s + if (yyextra->docBlockName=="code") { QCString indent; indent.fill(' ',computeIndent(yytext,0)); yyextra->docBlock+=indent; } else - { - REJECT; - } - } -<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) - if (yyextra->docBlockName=="code") + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) + if (yyextra->docBlockName=="code") { QCString indent; indent.fill(' ',computeIndent(yytext,-1)); @@ -6426,8 +6463,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) REJECT; } } -<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * - if (yyextra->docBlockName=="code") +<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * + if (yyextra->docBlockName=="code") { QCString indent; if (yyextra->nestedComment) // keep * it is part of the code @@ -6442,10 +6479,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } else - { - REJECT; - } - } + { + REJECT; + } + } <DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { QCString pat = substitute(yytext,"*"," "); yyextra->docBlock+=pat; @@ -6462,10 +6499,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(DocBlock); } } -<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special - yyextra->docBlock+=yytext; - } -<DocCopyBlock>"/*"|"*/"|"//" { +<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special + yyextra->docBlock+=yytext; + } +<DocCopyBlock>"/*"|"*/"|"//" { if (yytext[1]=='*') { yyextra->nestedComment=TRUE; @@ -6474,110 +6511,117 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->nestedComment=FALSE; } - yyextra->docBlock+=yytext; - } -<DocCopyBlock>\n { // newline - yyextra->docBlock+=*yytext; + yyextra->docBlock+=yytext; + } +<DocCopyBlock>\n { // newline + yyextra->docBlock+=*yytext; lineCount(yyscanner); - } -<DocCopyBlock>. { // any other character - yyextra->docBlock+=*yytext; - } -<DocCopyBlock><<EOF>> { - warn(yyextra->yyFileName,yyextra->yyLineNr, - "reached end of file while inside a '%s' block!\n" - "The command that should end the block seems to be missing!\n", - yyextra->docBlockName.data()); - yyterminate(); - } + } +<DocCopyBlock>. { // any other character + yyextra->docBlock+=*yytext; + } +<DocCopyBlock><<EOF>> { + warn(yyextra->yyFileName,yyextra->yyLineNr, + "reached end of file while inside a '%s' block!\n" + "The command that should end the block seems to be missing!\n", + yyextra->docBlockName.data()); + yyterminate(); + } /* ------------- Prototype parser -------------- */ -<Prototype>"operator"{B}*"("{B}*")" { - yyextra->current->name+=yytext; - } -<Prototype>"(" { - yyextra->current->args+=*yytext; - yyextra->currentArgumentContext = PrototypeQual; - yyextra->fullArgString = yyextra->current->args.copy(); - yyextra->copyArgString = &yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - } -<Prototype>"("({ID}"::")*({B}*[&*])+ { - yyextra->current->type+=yyextra->current->name+yytext; - yyextra->current->name.resize(0); - BEGIN( PrototypePtr ); - } -<PrototypePtr>{SCOPENAME} { - yyextra->current->name+=yytext; - } -<PrototypePtr>"(" { - yyextra->current->args+=*yytext; - yyextra->currentArgumentContext = PrototypeQual; - yyextra->fullArgString = yyextra->current->args.copy(); - yyextra->copyArgString = &yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - } -<PrototypePtr>")" { - yyextra->current->type+=')'; - BEGIN( Prototype ); - } -<PrototypePtr>. { - yyextra->current->name+=yytext; - } -<PrototypeQual>"{" { - BEGIN( PrototypeSkipLine); - } -<PrototypeQual>{B}*"const"{B}* { - yyextra->current->args += " const "; - yyextra->current->argList.setConstSpecifier(TRUE); - } -<PrototypeQual>{B}*"volatile"{B}* { - yyextra->current->args += " volatile "; - yyextra->current->argList.setVolatileSpecifier(TRUE); - } -<PrototypeQual>{B}*"="{B}*"0"{B}* { - yyextra->current->args += " = 0"; - yyextra->current->virt = Pure; - yyextra->current->argList.setPureSpecifier(TRUE); - } -<PrototypeQual>"throw"{B}*"(" { - yyextra->current->exception = "throw("; - BEGIN(PrototypeExc); - } -<PrototypeExc>")" { - yyextra->current->exception += ')'; - BEGIN(PrototypeQual); - } -<PrototypeExc>. { - yyextra->current->exception += *yytext; - } -<PrototypeQual>. { - yyextra->current->args += *yytext; - } -<Prototype>. { - yyextra->current->name += *yytext; - } -<PrototypeSkipLine>. { - } - - - - -<SkipCxxComment>.*"\\\n" { // line continuation - if (yyextra->insideCS) - { - REJECT; - } - else - { +<Prototype>"operator"{B}*"("{B}*")" { + yyextra->current->name+=yytext; + } +<Prototype>"(" { + yyextra->current->args+=*yytext; + yyextra->currentArgumentContext = PrototypeQual; + yyextra->fullArgString = yyextra->current->args.copy(); + yyextra->copyArgString = &yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + } +<Prototype>"("({ID}"::")*({B}*[&*])+ { + if (yyextra->insidePHP) // reference parameter + { + REJECT; + } + else + { + yyextra->current->type+=yyextra->current->name+yytext; + yyextra->current->name.resize(0); + BEGIN( PrototypePtr ); + } + } +<PrototypePtr>{SCOPENAME} { + yyextra->current->name+=yytext; + } +<PrototypePtr>"(" { + yyextra->current->args+=*yytext; + yyextra->currentArgumentContext = PrototypeQual; + yyextra->fullArgString = yyextra->current->args.copy(); + yyextra->copyArgString = &yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + } +<PrototypePtr>")" { + yyextra->current->type+=')'; + BEGIN( Prototype ); + } +<PrototypePtr>. { + yyextra->current->name+=yytext; + } +<PrototypeQual>"{" { + BEGIN( PrototypeSkipLine); + } +<PrototypeQual>{B}*"const"{B}* { + yyextra->current->args += " const "; + yyextra->current->argList.setConstSpecifier(TRUE); + } +<PrototypeQual>{B}*"volatile"{B}* { + yyextra->current->args += " volatile "; + yyextra->current->argList.setVolatileSpecifier(TRUE); + } +<PrototypeQual>{B}*"="{B}*"0"{B}* { + yyextra->current->args += " = 0"; + yyextra->current->virt = Pure; + yyextra->current->argList.setPureSpecifier(TRUE); + } +<PrototypeQual>"throw"{B}*"(" { + yyextra->current->exception = "throw("; + BEGIN(PrototypeExc); + } +<PrototypeExc>")" { + yyextra->current->exception += ')'; + BEGIN(PrototypeQual); + } +<PrototypeExc>. { + yyextra->current->exception += *yytext; + } +<PrototypeQual>. { + yyextra->current->args += *yytext; + } +<Prototype>. { + yyextra->current->name += *yytext; + } +<PrototypeSkipLine>. { + } + + + + +<SkipCxxComment>.*"\\\n" { // line continuation + if (yyextra->insideCS) + { + REJECT; + } + else + { lineCount(yyscanner); - } - } -<SkipCxxComment>.*/\n { - BEGIN( yyextra->lastCContext ) ; - } + } + } +<SkipCxxComment>.*/\n { + BEGIN( yyextra->lastCContext ) ; + } <SkipComment>[^\*\n]+ /* ------------ Generic rules -------------- */ @@ -6589,59 +6633,59 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( SkipC11Attribute ); } -<*>\n { lineCount(yyscanner); } -<*>\" { - if (yyextra->insideIDL && yyextra->insideCppQuote) - { - BEGIN(EndCppQuote); - } - } -<*>"#" { - if (!yyextra->insidePHP) - REJECT; - yyextra->lastCContext = YY_START ; - BEGIN( SkipCxxComment ) ; - } -<*>\' { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=YY_START; - BEGIN(SkipPHPString); - } - } -<*>\" { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=YY_START; - BEGIN(SkipString); - } - } +<*>\n { lineCount(yyscanner); } +<*>\" { + if (yyextra->insideIDL && yyextra->insideCppQuote) + { + BEGIN(EndCppQuote); + } + } +<*>"#" { + if (!yyextra->insidePHP) + REJECT; + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } +<*>\' { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=YY_START; + BEGIN(SkipPHPString); + } + } +<*>\" { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=YY_START; + BEGIN(SkipString); + } + } <*>\? { - if (yyextra->insideCS && (YY_START != SkipRound)) - { - if (yyextra->current->type.isEmpty()) - { - if (yyextra->current->name.isEmpty()) - yyextra->current->name="?"; - else - yyextra->current->name+="?"; - } - else - { - yyextra->current->type+="?"; - } - } - } + if (yyextra->insideCS && (YY_START != SkipRound)) + { + if (yyextra->current->type.isEmpty()) + { + if (yyextra->current->name.isEmpty()) + yyextra->current->name="?"; + else + yyextra->current->name+="?"; + } + else + { + yyextra->current->type+="?"; + } + } + } <*>. <SkipComment>"//"|"/*" -<*>"/*" { yyextra->lastCContext = YY_START ; - BEGIN( SkipComment ) ; - } -<SkipComment>{B}*"*/" { BEGIN( yyextra->lastCContext ) ; } -<*>"//" { - yyextra->lastCContext = YY_START ; - BEGIN( SkipCxxComment ) ; - } +<*>"/*" { yyextra->lastCContext = YY_START ; + BEGIN( SkipComment ) ; + } +<SkipComment>{B}*"*/" { BEGIN( yyextra->lastCContext ) ; } +<*>"//" { + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } %% //---------------------------------------------------------------------------- @@ -6686,7 +6730,7 @@ static void initParser(yyscan_t yyscanner) static void initEntry(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->insideJava) + if (yyextra->insideJava) { yyextra->protection = (yyextra->current_root->spec & (Entry::Interface|Entry::Enum)) ? Public : Package; } @@ -6710,15 +6754,15 @@ static void lineCount(yyscan_t yyscanner) const char *p; for (p = yytext ; *p ; ++p ) { - if (*p=='\n') + if (*p=='\n') { yyextra->yyLineNr++,yyextra->column=0,yyextra->yyColNr=1; } - else if (*p=='\t') + else if (*p=='\t') { yyextra->column+=tabSize - (yyextra->column%tabSize); } - else + else { yyextra->column++,yyextra->yyColNr++; } @@ -6745,14 +6789,14 @@ static void addType(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; uint tl=yyextra->current->type.length(); - if( tl>0 && !yyextra->current->name.isEmpty() && yyextra->current->type.at(tl-1)!='.') + if( tl>0 && !yyextra->current->name.isEmpty() && yyextra->current->type.at(tl-1)!='.') { yyextra->current->type += ' ' ; } yyextra->current->type += yyextra->current->name ; yyextra->current->name.resize(0) ; tl=yyextra->current->type.length(); - if( tl>0 && !yyextra->current->args.isEmpty() && yyextra->current->type.at(tl-1)!='.') + if( tl>0 && !yyextra->current->args.isEmpty() && yyextra->current->type.at(tl-1)!='.') { yyextra->current->type += ' ' ; } @@ -6793,7 +6837,7 @@ static void setContext(yyscan_t yyscanner) yyextra->language = getLanguageFromFileName(yyextra->yyFileName); yyextra->insideIDL = yyextra->language==SrcLangExt_IDL; yyextra->insideJava = yyextra->language==SrcLangExt_Java; - yyextra->insideCS = yyextra->language==SrcLangExt_CSharp; + yyextra->insideCS = yyextra->language==SrcLangExt_CSharp; yyextra->insideD = yyextra->language==SrcLangExt_D; yyextra->insidePHP = yyextra->language==SrcLangExt_PHP; yyextra->insideObjC = yyextra->language==SrcLangExt_ObjC; @@ -6803,7 +6847,7 @@ static void setContext(yyscan_t yyscanner) //printf("setContext(%s) yyextra->insideIDL=%d yyextra->insideJava=%d yyextra->insideCS=%d " // "yyextra->insideD=%d yyextra->insidePHP=%d yyextra->insideObjC=%d\n", // yyextra->yyFileName.data(),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC - // ); + // ); } //----------------------------------------------------------------------------- @@ -6850,7 +6894,7 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol { static QRegExp re("([^)]*)"); int bi1 = yyextra->current->args.findRev(re); - int bi2 = bi1!=-1 ? yyextra->current->args.findRev(re,bi1-1) : -1; + int bi2 = bi1!=-1 ? yyextra->current->args.findRev(re,bi1-1) : -1; char c; if (bi1!=-1 && bi2!=-1) // found something like "int (*func)(int arg)" { @@ -6887,13 +6931,13 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol i++; if (i!=l) { - yyextra->oldStyleArgType=yyextra->current->args.left(i); - oldStyleArgPtr=yyextra->current->args.mid(i,j-i); - oldStyleArgName=yyextra->current->args.mid(j).stripWhiteSpace(); + yyextra->oldStyleArgType=yyextra->current->args.left(i); + oldStyleArgPtr=yyextra->current->args.mid(i,j-i); + oldStyleArgName=yyextra->current->args.mid(j).stripWhiteSpace(); } else { - oldStyleArgName=yyextra->current->args.copy().stripWhiteSpace(); + oldStyleArgName=yyextra->current->args.copy().stripWhiteSpace(); } } } @@ -6931,7 +6975,7 @@ static void addKnRArgInfo(yyscan_t yyscanner,const QCString &type,const QCString a.type=type.stripWhiteSpace(); if (a.type.left(9)=="register ") // strip keyword { - a.type=a.type.mid(9); + a.type=a.type.mid(9); } a.name=name.stripWhiteSpace(); if (!brief.isEmpty() && !docs.isEmpty()) @@ -6944,7 +6988,7 @@ static void addKnRArgInfo(yyscan_t yyscanner,const QCString &type,const QCString } else { - a.docs=docs; + a.docs=docs; } } } @@ -6980,15 +7024,15 @@ static void startCommentBlock(yyscan_t yyscanner,bool brief) yyextra->current->docLine = yyextra->yyLineNr; } } - + //---------------------------------------------------------------------------- static void newEntry(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->tempEntry==0) // if temp entry is not 0, it holds yyextra->current, - // and yyextra->current is actually replaced by yyextra->previous which was - // already added to yyextra->current_root, so we should not add it again + if (yyextra->tempEntry==0) // if temp entry is not 0, it holds yyextra->current, + // and yyextra->current is actually replaced by yyextra->previous which was + // already added to yyextra->current_root, so we should not add it again // (see bug723314) { yyextra->previous = yyextra->current; @@ -7025,15 +7069,15 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief 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 - yyextra->yyFileName, // file - lineNr, // line of block start - yyextra->docBlockInBody ? FALSE : brief, // isBrief - yyextra->docBlockInBody ? FALSE : yyextra->docBlockAutoBrief, // isJavaDocStyle - yyextra->docBlockInBody, // isInBody - yyextra->protection, + yyextra->thisParser, + yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(), + processedDoc, // text + yyextra->yyFileName, // file + lineNr, // line of block start + yyextra->docBlockInBody ? FALSE : brief, // isBrief + yyextra->docBlockInBody ? FALSE : yyextra->docBlockAutoBrief, // isJavaDocStyle + yyextra->docBlockInBody, // isInBody + yyextra->protection, position, needsEntry, Config_getBool(MARKDOWN_SUPPORT) @@ -7041,7 +7085,7 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief ) { //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); - if (needsEntry) + if (needsEntry) { QCString docFile = yyextra->current->docFile; newEntry(yyscanner); @@ -7085,27 +7129,27 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al) //printf("handleParametersCommentBlock [%s]\n",doc.data()); while (yyextra->commentScanner.parseCommentBlock( - yyextra->thisParser, - yyextra->current.get(), - a.docs, // text - yyextra->yyFileName, // file - yyextra->current->docLine, // line of block start - FALSE, - FALSE, - FALSE, - yyextra->protection, - position, - needsEntry, + yyextra->thisParser, + yyextra->current.get(), + a.docs, // text + yyextra->yyFileName, // file + yyextra->current->docLine, // line of block start + FALSE, + FALSE, + FALSE, + yyextra->protection, + position, + needsEntry, Config_getBool(MARKDOWN_SUPPORT) - ) - ) + ) + ) { - //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position); - if (needsEntry) newEntry(yyscanner); + //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position); + if (needsEntry) newEntry(yyscanner); } if (needsEntry) { - newEntry(yyscanner); + newEntry(yyscanner); } a.docs = yyextra->current->doc; @@ -7138,9 +7182,9 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) yyextra->inputString = ce->program; yyextra->inputPosition = 0; if (ce->section==Entry::ENUM_SEC || (ce->spec&Entry::Enum)) - BEGIN( FindFields ) ; + BEGIN( FindFields ) ; else - BEGIN( FindMembers ) ; + BEGIN( FindMembers ) ; yyextra->current_root = ce; yyextra->yyFileName = ce->fileName; //setContext(); @@ -7164,44 +7208,44 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) if( ce->section==Entry::CLASS_SEC ) // class { if (yyextra->insidePHP || yyextra->insideD || yyextra->insideJS || yyextra->insideIDL || yyextra->insideSlice) - { - yyextra->current->protection = yyextra->protection = Public ; - } - else if (yyextra->insideJava) - { + { + yyextra->current->protection = yyextra->protection = Public ; + } + else if (yyextra->insideJava) + { yyextra->current->protection = yyextra->protection = (ce->spec & (Entry::Interface|Entry::Enum)) ? Public : Package; - } - else if (ce->spec&(Entry::Interface | Entry::Ref | Entry::Value | Entry::Struct | Entry::Union)) - { - if (ce->lang==SrcLangExt_ObjC) - { - yyextra->current->protection = yyextra->protection = Protected ; - } - else - { - yyextra->current->protection = yyextra->protection = Public ; - } - } - else - { + } + else if (ce->spec&(Entry::Interface | Entry::Ref | Entry::Value | Entry::Struct | Entry::Union)) + { + if (ce->lang==SrcLangExt_ObjC) + { + yyextra->current->protection = yyextra->protection = Protected ; + } + else + { + yyextra->current->protection = yyextra->protection = Public ; + } + } + else + { yyextra->current->protection = yyextra->protection = Private ; - } + } } else if (ce->section == Entry::ENUM_SEC ) // enum { - yyextra->current->protection = yyextra->protection = ce->protection; + yyextra->current->protection = yyextra->protection = ce->protection; } else if (!ce->name.isEmpty() && ce->name.at(ni)=='@') // unnamed union or namespace { - if (ce->section == Entry::NAMESPACE_SEC ) // unnamed namespace - { + if (ce->section == Entry::NAMESPACE_SEC ) // unnamed namespace + { yyextra->current->stat = yyextra->stat = TRUE; - } - yyextra->current->protection = yyextra->protection = ce->protection; + } + yyextra->current->protection = yyextra->protection = ce->protection; } else // named struct, union, protocol, category { - yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->protection = yyextra->protection = Public ; } yyextra->mtype = Method; yyextra->virt = Normal; @@ -7212,19 +7256,19 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) //memberGroupInside.resize(0); QCString name = ce->name; yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); - + scannerYYlex(yyscanner); yyextra->lexInit=TRUE; //forceEndGroup(); yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); - + ce->program.resize(0); //if (depthIf>0) //{ - // warn(yyextra->yyFileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!"); + // warn(yyextra->yyFileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!"); //} } parseCompounds(yyscanner,ce); @@ -7247,7 +7291,6 @@ static void parseMain(yyscan_t yyscanner, yyextra->column = 0; scannerYYrestart(0,yyscanner); - //yyextra->anonCount = 0; // don't reset per file //depthIf = 0; yyextra->protection = Public; yyextra->mtype = Method; @@ -7301,7 +7344,7 @@ static void parseMain(yyscan_t yyscanner, parseCompounds(yyscanner,rt); - yyextra->anonNSCount++; + anonNSCount++; // add additional entries that were created during processing for (auto &kv: yyextra->outerScopeEntries) @@ -7319,7 +7362,7 @@ 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()) + if (text.isEmpty()) { warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!"); return; @@ -7332,11 +7375,11 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) const char *orgInputString; int orgInputPosition; YY_BUFFER_STATE orgState; - + // save scanner state orgState = YY_CURRENT_BUFFER; yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner), yyscanner); - orgInputString = yyextra->inputString; + orgInputString = yyextra->inputString; orgInputPosition = yyextra->inputPosition; // set new string @@ -7356,7 +7399,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) YY_BUFFER_STATE tmpState = YY_CURRENT_BUFFER; yy_switch_to_buffer(orgState, yyscanner); yy_delete_buffer(tmpState, yyscanner); - yyextra->inputString = orgInputString; + yyextra->inputString = orgInputString; yyextra->inputPosition = orgInputPosition; @@ -7417,7 +7460,7 @@ bool COutlineParser::needsPreprocessing(const QCString &extension) const QCString fe=extension.lower(); SrcLangExt lang = getLanguageFromFileName(extension); return (SrcLangExt_Cpp == lang) || - !( fe==".java" || fe==".as" || fe==".d" || fe==".php" || + !( fe==".java" || fe==".as" || fe==".d" || fe==".php" || fe==".php4" || fe==".inc" || fe==".phtml"|| fe==".php5" ); } diff --git a/src/scopedtypevariant.h b/src/scopedtypevariant.h new file mode 100644 index 0000000..d544434 --- /dev/null +++ b/src/scopedtypevariant.h @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * 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 SCOPEDTYPEVARIANT_H +#define SCOPEDTYPEVARIANT_H + +#include <utility> +#include <vector> +#include <qcstring.h> +#include "definition.h" + +//! Class representing a local class definition found while +//! generating syntax highlighted code. +class LocalDef +{ + public: + void insertBaseClass(const QCString &name) { m_baseClasses.push_back(name); } + std::vector<QCString> baseClasses() const { return m_baseClasses; } + private: + std::vector<QCString> m_baseClasses; +}; + +//----------------------------------------------------------------------------- + +/*! Variant class for a scoped type. + * + * Variants: + * - Dummy: a type used for hiding a global type. + * - Local: a locally defined type (e.g. found inside a function) + * - Global: a globally defined type (processed by doxygen in an earlier pass). + */ +class ScopedTypeVariant +{ + public: + //! possible variant types + enum Variant + { + Global, + Local, + Dummy + }; + //! default constructor for creating a variant of type Dummy + ScopedTypeVariant() : m_variant(Dummy) + { + m_u.globalDef = 0; + } + //! constructor for creating a variant of type Global + explicit ScopedTypeVariant(const Definition *d) + { + if (d) + { + m_name = d->name(); + m_variant = Global; + m_u.globalDef = d; + } + else + { + m_variant = Dummy; + m_u.globalDef = 0; + } + } + //! constructor for creating a variant of type Local + explicit ScopedTypeVariant(const QCString &name) + { + m_name = name; + m_variant = Local; + m_u.localDef = new LocalDef; + } + //! copy constructor + ScopedTypeVariant(const ScopedTypeVariant &stv) + { + m_variant = stv.m_variant; + m_name = stv.m_name; + if (m_variant==Local) + { + m_u.localDef = new LocalDef(*stv.m_u.localDef); + } + else if (m_variant==Global) + { + m_u.globalDef = stv.m_u.globalDef; + } + } + //! move constructor + ScopedTypeVariant(ScopedTypeVariant &&stv) noexcept : ScopedTypeVariant() + { + swap(*this,stv); + } + //! assignment operator + ScopedTypeVariant &operator=(ScopedTypeVariant stv) + { + swap(*this,stv); + return *this; + } + //! destructor + ~ScopedTypeVariant() + { + if (m_variant==Local) + { + delete m_u.localDef; + } + } + //! swap function + friend void swap(ScopedTypeVariant &first,ScopedTypeVariant &second) + { + using std::swap; // enable ADL + swap(first.m_variant,second.m_variant); + swap(first.m_name,second.m_name); + swap(first.m_u.globalDef,second.m_u.globalDef); + } + //! Turn the variant into a Global type + void setGlobal(const Definition *def) + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Global; + m_name = def->name(); + m_u.globalDef = def; + } + //! Turn the variant into a Local type + LocalDef *setLocal(const QCString &name) + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Local; + m_name = name; + m_u.localDef = new LocalDef; + return m_u.localDef; + } + //! Turn the variant into a Dummy type + void setDummy() + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Dummy; + m_name = ""; + m_u.localDef=0; + } + Variant type() const { return m_variant; } + QCString name() const { return m_name; } + LocalDef *localDef() const { return m_variant==Local ? m_u.localDef : 0; } + const Definition *globalDef() const { return m_variant==Global ? m_u.globalDef : 0; } + + private: + Variant m_variant; + QCString m_name; + union + { + const Definition *globalDef; + LocalDef *localDef; + } m_u; +}; + +//----------------------------------------------------------------------------- + +/*! Represents a stack of variable to class mappings as found in the + * code. Each scope is enclosed in pushScope() and popScope() calls. + * Variables are added by calling addVariables() and one can search + * for variable using findVariable(). + */ +class VariableContext +{ + public: + using Scope = std::unordered_map<std::string,ScopedTypeVariant>; + + void pushScope() + { + m_scopes.push_back(Scope()); + } + void popScope() + { + if (!m_scopes.empty()) + { + m_scopes.pop_back(); + } + } + void clear() + { + m_scopes.clear(); + m_globalScope.clear(); + } + void clearExceptGlobal() + { + m_scopes.clear(); + } + void addVariable(const QCString &name,ScopedTypeVariant stv) + { + Scope *scope = m_scopes.empty() ? &m_globalScope : &m_scopes.back(); + scope->emplace(std::make_pair(name.str(),std::move(stv))); // add it to a list + } + const ScopedTypeVariant *findVariable(const QCString &name) + { + const ScopedTypeVariant *result = 0; + if (name.isEmpty()) return result; + + // search from inner to outer scope + auto it = std::rbegin(m_scopes); + while (it != std::rend(m_scopes)) + { + auto it2 = it->find(name.str()); + if (it2 != std::end(*it)) + { + result = &it2->second; + return result; + } + ++it; + } + // nothing found -> also try the global scope + auto it2 = m_globalScope.find(name.str()); + if (it2 != m_globalScope.end()) + { + result = &it2->second; + } + return result; + } + bool atGlobalScope() const { return m_scopes.empty(); } + + private: + Scope m_globalScope; + std::vector<Scope> m_scopes; +}; + +//----------------------------------------------------------------------------- + +/** Represents the call context */ +class CallContext +{ + public: + struct Ctx + { + Ctx(const QCString &name_,const QCString &type_) : name(name_), type(type_) {} + QCString name; + QCString type; + ScopedTypeVariant stv; + }; + + CallContext() + { + clear(); + } + void setScope(const ScopedTypeVariant &stv) + { + Ctx &ctx = m_stvList.back(); + ctx.stv=std::move(stv); + } + void pushScope(const QCString &name_,const QCString &type_) + { + m_stvList.push_back(Ctx(name_,type_)); + } + void popScope(QCString &name_,QCString &type_) + { + if (m_stvList.size()>1) + { + const Ctx &ctx = m_stvList.back(); + name_ = ctx.name; + type_ = ctx.type; + m_stvList.pop_back(); + } + } + void clear() + { + m_stvList.clear(); + m_stvList.push_back(Ctx("","")); + } + const ScopedTypeVariant getScope() const + { + return m_stvList.back().stv; + } + + private: + std::vector<Ctx> m_stvList; +}; + + +#endif diff --git a/src/searchindex.cpp b/src/searchindex.cpp index ec7f7d6..42601b9 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -37,6 +37,8 @@ #include "filename.h" #include "membername.h" #include "resourcemgr.h" +#include "namespacedef.h" +#include "classdef.h" // file format: (all multi-byte values are stored in big endian format) // 4 byte header @@ -49,41 +51,33 @@ // (4 bytes index to url string + 4 bytes frequency counter) // for each url: a \0 terminated string -const int numIndexEntries = 256*256; +const size_t numIndexEntries = 256*256; //-------------------------------------------------------------------- -IndexWord::IndexWord(const char *word) : m_word(word), m_urls(17) +IndexWord::IndexWord(QCString word) : m_word(word) { - m_urls.setAutoDelete(TRUE); //printf("IndexWord::IndexWord(%s)\n",word); } void IndexWord::addUrlIndex(int idx,bool hiPriority) { //printf("IndexWord::addUrlIndex(%d,%d)\n",idx,hiPriority); - URLInfo *ui = m_urls.find(idx); - if (ui==0) + auto it = m_urls.find(idx); + if (it==m_urls.end()) { //printf("URLInfo::URLInfo(%d)\n",idx); - ui=new URLInfo(idx,0); - m_urls.insert(idx,ui); + it = m_urls.insert(std::make_pair(idx,URLInfo(idx,0))).first; } - ui->freq+=2; - if (hiPriority) ui->freq|=1; // mark as high priority document + it->second.freq+=2; + if (hiPriority) it->second.freq|=1; // mark as high priority document } //-------------------------------------------------------------------- -SearchIndex::SearchIndex() : SearchIndexIntf(Internal), - m_words(328829), m_index(numIndexEntries), m_url2IdMap(10007), m_urls(10007), m_urlIndex(-1) +SearchIndex::SearchIndex() : SearchIndexIntf(Internal) { - int i; - m_words.setAutoDelete(TRUE); - m_url2IdMap.setAutoDelete(TRUE); - m_urls.setAutoDelete(TRUE); - m_index.setAutoDelete(TRUE); - for (i=0;i<numIndexEntries;i++) m_index.insert(i,new QList<IndexWord>); + m_index.resize(numIndexEntries); } void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) @@ -91,7 +85,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is if (ctx==0) return; assert(!isSourceFile || ctx->definitionType()==Definition::TypeFile); //printf("SearchIndex::setCurrentDoc(%s,%s,%s)\n",name,baseName,anchor); - QCString url=isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); + QCString url=isSourceFile ? (toFileDef(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); url+=Config_getString(HTML_FILE_EXTENSION); QCString baseUrl = url; if (anchor) url+=QCString("#")+anchor; @@ -99,7 +93,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is QCString name=ctx->qualifiedName(); if (ctx->definitionType()==Definition::TypeMember) { - const MemberDef *md = dynamic_cast<const MemberDef *>(ctx); + const MemberDef *md = toMemberDef(ctx); name.prepend((md->getLanguage()==SrcLangExt_Fortran ? theTranslator->trSubprogram(TRUE,TRUE) : theTranslator->trMember(TRUE,TRUE))+" "); @@ -116,7 +110,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is { case Definition::TypePage: { - const PageDef *pd = dynamic_cast<const PageDef *>(ctx); + const PageDef *pd = toPageDef(ctx); if (pd->hasTitle()) { name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title(); @@ -129,7 +123,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is break; case Definition::TypeClass: { - const ClassDef *cd = dynamic_cast<const ClassDef *>(ctx); + const ClassDef *cd = toClassDef(ctx); name.prepend(cd->compoundTypeString()+" "); } break; @@ -151,7 +145,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is break; case Definition::TypeGroup: { - const GroupDef *gd = dynamic_cast<const GroupDef *>(ctx); + const GroupDef *gd = toGroupDef(ctx); if (gd->groupTitle()) { name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle(); @@ -167,16 +161,16 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is } } - int *pIndex = m_url2IdMap.find(baseUrl); - if (pIndex==0) + auto it = m_url2IdMap.find(baseUrl.str()); + if (it == m_url2IdMap.end()) { ++m_urlIndex; - m_url2IdMap.insert(baseUrl,new int(m_urlIndex)); - m_urls.insert(m_urlIndex,new URL(name,url)); + m_url2IdMap.insert(std::make_pair(baseUrl.str(),m_urlIndex)); + m_urls.insert(std::make_pair(m_urlIndex,URL(name,url))); } else { - m_urls.insert(*pIndex,new URL(name,url)); + m_urls.insert(std::make_pair(it->second,URL(name,url))); } } @@ -208,17 +202,16 @@ void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse) if (word==0 || word[0]=='\0') return; QCString wStr = QCString(word).lower(); //printf("SearchIndex::addWord(%s,%d) wStr=%s\n",word,hiPriority,wStr.data()); - IndexWord *w = m_words[wStr]; - if (w==0) + int idx=charsToIndex(wStr); + if (idx<0 || idx>=static_cast<int>(m_index.size())) return; + auto it = m_words.find(wStr.str()); + if (it==m_words.end()) { - int idx=charsToIndex(wStr); //fprintf(stderr,"addWord(%s) at index %d\n",word,idx); - if (idx<0) return; - w = new IndexWord(wStr); - m_index[idx]->append(w); - m_words.insert(wStr,w); + m_index[idx].push_back(IndexWord(wStr)); + it = m_words.insert({ wStr.str(), static_cast<int>(m_index[idx].size())-1 }).first; } - w->addUrlIndex(m_urlIndex,hiPriority); + m_index[idx][it->second].addUrlIndex(m_urlIndex,hiPriority); int i; bool found=FALSE; if (!recurse) // the first time we check if we can strip the prefix @@ -244,12 +237,12 @@ void SearchIndex::addWord(const char *word,bool hiPriority) addWord(word,hiPriority,FALSE); } -static void writeInt(QFile &f,int index) +static void writeInt(QFile &f,size_t index) { - f.putch(((uint)index)>>24); - f.putch((((uint)index)>>16)&0xff); - f.putch((((uint)index)>>8)&0xff); - f.putch(((uint)index)&0xff); + f.putch(static_cast<int>(index>>24)); + f.putch(static_cast<int>((index>>16)&0xff)); + f.putch(static_cast<int>((index>>8)&0xff)); + f.putch(static_cast<int>(index&0xff)); } static void writeString(QFile &f,const char *s) @@ -261,21 +254,19 @@ static void writeString(QFile &f,const char *s) void SearchIndex::write(const char *fileName) { - int i; - int size=4; // for the header + size_t i; + size_t size=4; // for the header size+=4*numIndexEntries; // for the index - int wordsOffset = size; + size_t wordsOffset = size; // first pass: compute the size of the wordlist for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - int ws = iw->word().length()+1; + int ws = iw.word().length()+1; size+=ws+4; // word + url info list offset } size+=1; // zero list terminator @@ -283,19 +274,17 @@ void SearchIndex::write(const char *fileName) } // second pass: compute the offsets in the index - int indexOffsets[numIndexEntries]; - int offset=wordsOffset; + size_t indexOffsets[numIndexEntries]; + size_t offset=wordsOffset; for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { indexOffsets[i]=offset; - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - offset+= iw->word().length()+1; + offset+= iw.word().length()+1; offset+=4; // word + offset to url info array } offset+=1; // zero list terminator @@ -305,42 +294,36 @@ void SearchIndex::write(const char *fileName) indexOffsets[i]=0; } } - int padding = size; + size_t padding = size; size = (size+3)&~3; // round up to 4 byte boundary padding = size - padding; - //int statsOffset = size; - //IndexWord *iw; - int *wordStatOffsets = new int[m_words.count()]; + std::vector<size_t> wordStatOffsets(m_words.size()); int count=0; // third pass: compute offset to stats info for each word for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { //printf("wordStatOffsets[%d]=%d\n",count,size); wordStatOffsets[count++] = size; - size+=4+iw->urls().count()*8; // count + (url_index,freq) per url + size+=4 + iw.urls().size() * 8; // count + (url_index,freq) per url } } } - int *urlOffsets = new int[m_urls.count()]; - //int urlsOffset = size; - QIntDictIterator<URL> udi(m_urls); - URL *url; - for (udi.toFirst();(url=udi.current());++udi) + std::vector<size_t> urlOffsets(m_urls.size()); + for (const auto &udi : m_urls) { - urlOffsets[udi.currentKey()]=size; - size+=url->name.length()+1+ - url->url.length()+1; + urlOffsets[udi.first]=size; + size+=udi.second.name.length()+1+ + udi.second.url.length()+1; } + //printf("Total size %x bytes (word=%x stats=%x urls=%x)\n",size,wordsOffset,statsOffset,urlsOffset); QFile f(fileName); if (f.open(IO_WriteOnly)) @@ -356,14 +339,12 @@ void SearchIndex::write(const char *fileName) count=0; for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - writeString(f,iw->word()); + writeString(f,iw.word()); writeInt(f,wordStatOffsets[count++]); } f.putch(0); @@ -374,35 +355,29 @@ void SearchIndex::write(const char *fileName) // write word statistics for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - int numUrls = iw->urls().count(); + size_t numUrls = iw.urls().size(); writeInt(f,numUrls); - QIntDictIterator<URLInfo> uli(iw->urls()); - URLInfo *ui; - for (uli.toFirst();(ui=uli.current());++uli) + for (const auto &ui : iw.urls()) { - writeInt(f,urlOffsets[ui->urlIdx]); - writeInt(f,ui->freq); + writeInt(f,urlOffsets[ui.second.urlIdx]); + writeInt(f,ui.second.freq); } } } } // write urls - for (udi.toFirst();(url=udi.current());++udi) + for (const auto &udi : m_urls) { - writeString(f,url->name); - writeString(f,url->url); + writeString(f,udi.second.name); + writeString(f,udi.second.url); } } - delete[] urlOffsets; - delete[] wordStatOffsets; } @@ -422,29 +397,19 @@ struct SearchDocEntry struct SearchIndexExternal::Private { - Private() : docEntries(12251) {} - SDict<SearchDocEntry> docEntries; + std::map<std::string,SearchDocEntry> docEntries; SearchDocEntry *current = 0; }; -SearchIndexExternal::SearchIndexExternal() : SearchIndexIntf(External) -{ - p = new SearchIndexExternal::Private; - p->docEntries.setAutoDelete(TRUE); - p->current=0; -} - -SearchIndexExternal::~SearchIndexExternal() +SearchIndexExternal::SearchIndexExternal() : SearchIndexIntf(External), p(std::make_unique<Private>()) { - //printf("p->docEntries.count()=%d\n",p->docEntries.count()); - delete p; } static QCString definitionToName(const Definition *ctx) { if (ctx && ctx->definitionType()==Definition::TypeMember) { - const MemberDef *md = dynamic_cast<const MemberDef*>(ctx); + const MemberDef *md = toMemberDef(ctx); if (md->isFunction()) return "function"; else if (md->isSlot()) @@ -475,7 +440,7 @@ static QCString definitionToName(const Definition *ctx) switch(ctx->definitionType()) { case Definition::TypeClass: - return (dynamic_cast<const ClassDef*>(ctx))->compoundTypeString(); + return (toClassDef(ctx))->compoundTypeString(); case Definition::TypeFile: return "file"; case Definition::TypeNamespace: @@ -497,29 +462,28 @@ static QCString definitionToName(const Definition *ctx) void SearchIndexExternal::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) { - QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID)); - QCString baseName = isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); + static QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID)); + QCString baseName = isSourceFile ? (toFileDef(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); QCString url = baseName + Doxygen::htmlFileExtension; if (anchor) url+=QCString("#")+anchor; QCString key = extId+";"+url; - p->current = p->docEntries.find(key); - //printf("setCurrentDoc(url=%s,isSourceFile=%d) current=%p\n",url.data(),isSourceFile,p->current); - if (!p->current) + auto it = p->docEntries.find(key.str()); + if (it == p->docEntries.end()) { - SearchDocEntry *e = new SearchDocEntry; - e->type = isSourceFile ? QCString("source") : definitionToName(ctx); - e->name = ctx->qualifiedName(); + SearchDocEntry e; + e.type = isSourceFile ? QCString("source") : definitionToName(ctx); + e.name = ctx->qualifiedName(); if (ctx->definitionType()==Definition::TypeMember) { - e->args = (dynamic_cast<const MemberDef*>(ctx))->argsString(); + e.args = (toMemberDef(ctx))->argsString(); } - e->extId = extId; - e->url = url; - p->current = e; - p->docEntries.append(key,e); + e.extId = extId; + e.url = url; + it = p->docEntries.insert({key.str(),e}).first; //printf("searchIndexExt %s : %s\n",e->name.data(),e->url.data()); } + p->current = &it->second; } void SearchIndexExternal::addWord(const char *word,bool hiPriority) @@ -539,26 +503,25 @@ void SearchIndexExternal::write(const char *fileName) FTextStream t(&f); t << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl; t << "<add>" << endl; - SDict<SearchDocEntry>::Iterator it(p->docEntries); - SearchDocEntry *doc; - for (it.toFirst();(doc=it.current());++it) + for (auto &kv : p->docEntries) { - doc->normalText.addChar(0); // make sure buffer ends with a 0 terminator - doc->importantText.addChar(0); // make sure buffer ends with a 0 terminator + SearchDocEntry &doc = kv.second; + doc.normalText.addChar(0); // make sure buffer ends with a 0 terminator + doc.importantText.addChar(0); // make sure buffer ends with a 0 terminator t << " <doc>" << endl; - t << " <field name=\"type\">" << doc->type << "</field>" << endl; - t << " <field name=\"name\">" << convertToXML(doc->name) << "</field>" << endl; - if (!doc->args.isEmpty()) + t << " <field name=\"type\">" << doc.type << "</field>" << endl; + t << " <field name=\"name\">" << convertToXML(doc.name) << "</field>" << endl; + if (!doc.args.isEmpty()) { - t << " <field name=\"args\">" << convertToXML(doc->args) << "</field>" << endl; + t << " <field name=\"args\">" << convertToXML(doc.args) << "</field>" << endl; } - if (!doc->extId.isEmpty()) + if (!doc.extId.isEmpty()) { - t << " <field name=\"tag\">" << convertToXML(doc->extId) << "</field>" << endl; + t << " <field name=\"tag\">" << convertToXML(doc.extId) << "</field>" << endl; } - t << " <field name=\"url\">" << convertToXML(doc->url) << "</field>" << endl; - t << " <field name=\"keywords\">" << convertToXML(doc->importantText.get()) << "</field>" << endl; - t << " <field name=\"text\">" << convertToXML(doc->normalText.get()) << "</field>" << endl; + t << " <field name=\"url\">" << convertToXML(doc.url) << "</field>" << endl; + t << " <field name=\"keywords\">" << convertToXML(doc.importantText.get()) << "</field>" << endl; + t << " <field name=\"text\">" << convertToXML(doc.normalText.get()) << "</field>" << endl; t << " </doc>" << endl; } t << "</add>" << endl; @@ -572,14 +535,6 @@ void SearchIndexExternal::write(const char *fileName) //--------------------------------------------------------------------------- // the following part is for the javascript based search engine -#include "memberdef.h" -#include "namespacedef.h" -#include "pagedef.h" -#include "classdef.h" -#include "filedef.h" -#include "language.h" -#include "doxygen.h" -#include "message.h" static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES]; @@ -783,50 +738,46 @@ void createJavaScriptSearchIndex() // add symbols to letter -> symbol list map // index classes - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { uint letter = getUtf8CodeToLower(cd->localName(),0); if (cd->isLinkable() && isId(letter)) { - g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,cd.get()); if (sliceOpt) { if (cd->compoundType()==ClassDef::Interface) { - g_searchIndexInfo[SEARCH_INDEX_INTERFACES].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_INTERFACES].symbolList.append(letter,cd.get()); } else if (cd->compoundType()==ClassDef::Struct) { - g_searchIndexInfo[SEARCH_INDEX_STRUCTS].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_STRUCTS].symbolList.append(letter,cd.get()); } else if (cd->compoundType()==ClassDef::Exception) { - g_searchIndexInfo[SEARCH_INDEX_EXCEPTIONS].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_EXCEPTIONS].symbolList.append(letter,cd.get()); } else // cd->compoundType()==ClassDef::Class { - g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd.get()); } } else // non slice optimisation: group all types under classes { - g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd); + g_searchIndexInfo[SEARCH_INDEX_CLASSES].symbolList.append(letter,cd.get()); } } } // index namespaces - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; - for (;(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { uint letter = getUtf8CodeToLower(nd->name(),0); if (nd->isLinkable() && isId(letter)) { - g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,nd); - g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].symbolList.append(letter,nd); + g_searchIndexInfo[SEARCH_INDEX_ALL].symbolList.append(letter,nd.get()); + g_searchIndexInfo[SEARCH_INDEX_NAMESPACES].symbolList.append(letter,nd.get()); } } @@ -956,7 +907,7 @@ void writeJavaScriptSearchIndex() QCString baseName; baseName.sprintf("%s_%x",g_searchIndexInfo[i].name.data(),p); - QCString fileName = searchDirName + "/"+baseName+".html"; + QCString fileName = searchDirName + "/"+baseName+Doxygen::htmlFileExtension; QCString dataFileName = searchDirName + "/"+baseName+".js"; QFile outFile(fileName); @@ -968,7 +919,8 @@ void writeJavaScriptSearchIndex() t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"" " \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; - t << "<html><head><title></title>" << endl; + t << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl; + t << "<head><title></title>" << endl; t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl; t << "<meta name=\"generator\" content=\"Doxygen " << getDoxygenVersion() << "\"/>" << endl; t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl; @@ -979,18 +931,18 @@ void writeJavaScriptSearchIndex() t << "<div id=\"SRIndex\">" << endl; t << "<div class=\"SRStatus\" id=\"Loading\">" << theTranslator->trLoading() << "</div>" << endl; t << "<div id=\"SRResults\"></div>" << endl; // here the results will be inserted - t << "<script type=\"text/javascript\"><!--" << endl; - t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; + t << "<script type=\"text/javascript\">" << endl; + t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "createResults();" << endl; // this function will insert the results - t << "/* @license-end */\n"; - t << "--></script>" << endl; + t << "/* @license-end */\n"; + t << "</script>" << endl; t << "<div class=\"SRStatus\" id=\"Searching\">" << theTranslator->trSearching() << "</div>" << endl; t << "<div class=\"SRStatus\" id=\"NoMatches\">" << theTranslator->trNoMatches() << "</div>" << endl; - t << "<script type=\"text/javascript\"><!--" << endl; - t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; + t << "<script type=\"text/javascript\">" << endl; + t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "document.getElementById(\"Loading\").style.display=\"none\";" << endl; t << "document.getElementById(\"NoMatches\").style.display=\"none\";" << endl; t << "var searchResults = new SearchResults(\"searchResults\");" << endl; @@ -1001,8 +953,8 @@ void writeJavaScriptSearchIndex() t << " if (elem) elem.focus();" << endl; t << " }" << endl; t << "});" << endl; - t << "/* @license-end */\n"; - t << "--></script>" << endl; + t << "/* @license-end */\n"; + t << "</script>" << endl; t << "</div>" << endl; // SRIndex t << "</body>" << endl; t << "</html>" << endl; @@ -1040,7 +992,7 @@ void writeJavaScriptSearchIndex() if (dl->count()==1) // item with a unique name { - const MemberDef *md = dynamic_cast<const MemberDef*>(d); + const MemberDef *md = toMemberDef(d); QCString anchor = d->anchor(); ti << "'" << externalRef("../",d->getReference(),TRUE) @@ -1092,7 +1044,7 @@ void writeJavaScriptSearchIndex() const Definition *scope = d->getOuterScope(); const Definition *next = di.current(); const Definition *nextScope = 0; - const MemberDef *md = dynamic_cast<const MemberDef*>(d); + const MemberDef *md = toMemberDef(d); if (next) nextScope = next->getOuterScope(); QCString anchor = d->anchor(); @@ -1136,12 +1088,12 @@ void writeJavaScriptSearchIndex() QCString name; if (d->definitionType()==Definition::TypeClass) { - name = convertToXML((dynamic_cast<const ClassDef*>(d))->displayName()); + name = convertToXML((toClassDef(d))->displayName()); found = TRUE; } else if (d->definitionType()==Definition::TypeNamespace) { - name = convertToXML((dynamic_cast<const NamespaceDef*>(d))->displayName()); + name = convertToXML((toNamespaceDef(d))->displayName()); found = TRUE; } else if (scope==0 || scope==Doxygen::globalScope) // in global scope @@ -1268,13 +1220,14 @@ void writeJavaScriptSearchIndex() ResourceMgr::instance().copyResource("search.js",searchDirName); } { - QFile f(searchDirName+"/nomatches.html"); + QFile f(searchDirName+"/nomatches"+Doxygen::htmlFileExtension); if (f.open(IO_WriteOnly)) { FTextStream t(&f); t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " "\"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; - t << "<html><head><title></title>" << endl; + t << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl; + t << "<head><title></title>" << endl; t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl; t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl; t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl; @@ -1316,11 +1269,11 @@ void SearchIndexList::append(const Definition *d) { if (d->definitionType()==Definition::TypeGroup) { - dispName = (dynamic_cast<const GroupDef*>(d))->groupTitle(); + dispName = (toGroupDef(d))->groupTitle(); } else if (d->definitionType()==Definition::TypePage) { - dispName = (dynamic_cast<const PageDef*>(d))->title(); + dispName = (toPageDef(d))->title(); } l=new SearchDefinitionList(searchId(dispName),dispName); SDict< SearchDefinitionList >::append(dispName,l); diff --git a/src/searchindex.h b/src/searchindex.h index 923973c..71c1ce1 100644 --- a/src/searchindex.h +++ b/src/searchindex.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. * @@ -18,11 +18,15 @@ #ifndef _SEARCHINDEX_H #define _SEARCHINDEX_H +#include <memory> +#include <vector> +#include <map> +#include <unordered_map> +#include <string> + #include <qintdict.h> #include <qlist.h> -#include <qdict.h> #include <qintdict.h> -#include <qvector.h> #include "sortdict.h" #include "definition.h" #include "util.h" @@ -40,7 +44,7 @@ void finalizeSearchIndexer(); struct URL { - URL(const char *n,const char *u) : name(n), url(u) {} + URL(QCString n,QCString u) : name(n), url(u) {} QCString name; QCString url; }; @@ -56,14 +60,15 @@ struct URLInfo class IndexWord { public: - IndexWord(const char *word); + using URLInfoMap = std::unordered_map<int,URLInfo>; + IndexWord(QCString word); void addUrlIndex(int,bool); - const QIntDict<URLInfo> &urls() const { return m_urls; } + URLInfoMap urls() const { return m_urls; } QCString word() const { return m_word; } private: QCString m_word; - QIntDict<URLInfo> m_urls; + URLInfoMap m_urls; }; class SearchIndexIntf @@ -84,16 +89,16 @@ class SearchIndex : public SearchIndexIntf { public: SearchIndex(); - void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile); - void addWord(const char *word,bool hiPriority); - void write(const char *file); + void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) override; + void addWord(const char *word,bool hiPriority) override; + void write(const char *file) override; private: void addWord(const char *word,bool hiPrio,bool recurse); - QDict<IndexWord> m_words; - QVector< QList<IndexWord> > m_index; - QDict<int> m_url2IdMap; - QIntDict<URL> m_urls; - int m_urlIndex; + std::unordered_map<std::string,int> m_words; + std::vector< std::vector< IndexWord> > m_index; + std::unordered_map<std::string,int> m_url2IdMap; + std::map<int,URL> m_urls; + int m_urlIndex = -1; }; @@ -102,12 +107,11 @@ class SearchIndexExternal : public SearchIndexIntf struct Private; public: SearchIndexExternal(); - ~SearchIndexExternal(); void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); void write(const char *file); private: - Private *p; + std::unique_ptr<Private> p; }; //------- client side search index ---------------------- diff --git a/src/sqlcode.h b/src/sqlcode.h index 20e20f7..aa465d7 100644 --- a/src/sqlcode.h +++ b/src/sqlcode.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2014 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. * @@ -32,6 +30,8 @@ class Definition; class SQLCodeParser : public CodeParserInterface { public: + SQLCodeParser(); + virtual ~SQLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -48,6 +48,9 @@ class SQLCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/sqlcode.l b/src/sqlcode.l index 58a2fce..74318bb 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2014 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. * @@ -50,7 +50,7 @@ struct sqlcodeYY_state { CodeOutputInterface * code; const char *inputString; //!< the code fragment as text - int inputPosition; //!< read offset during parsing + yy_size_t inputPosition; //!< read offset during parsing int inputLines; //!< number of line in the code fragment int yyLineNr; //!< current line number bool needsTermination; @@ -60,9 +60,9 @@ struct sqlcodeYY_state QCString exampleName; QCString classScope; - FileDef *sourceFileDef; - Definition *currentDefinition; - MemberDef *currentMemberDef; + const FileDef *sourceFileDef; + const Definition *currentDefinition; + const MemberDef *currentMemberDef; bool includeCodeFragment; const char *currentFontClass; }; @@ -71,18 +71,18 @@ struct sqlcodeYY_state static const char *stateToString(int state); #endif -static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); static void startCodeLine(yyscan_t yyscanner); static void endFontClass(yyscan_t yyscanner); static void endCodeLine(yyscan_t yyscanner); static void nextCodeLine(yyscan_t yyscanner); -static void codifyLines(char *text,yyscan_t yyscanner); -static void startFontClass(const char *s,yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); static int countLines(yyscan_t yyscanner); -static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner); +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,yyscanner); +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} @@ -110,7 +110,7 @@ typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE") -literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN") +literalkeyword (?i:"false"|"true"|"NULL"|"UNKNOWN") stringliteral (\"[^"]*\")|('[^']*') number [0-9]+ literals ({literalkeyword}|{stringliteral}|{number}) @@ -126,104 +126,107 @@ commentclose "\*/" %% {literals} { - startFontClass("stringliteral",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } - + {keyword} { - startFontClass("keyword",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {flowkeyword} { - startFontClass("keywordflow",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {typekeyword} { - startFontClass("keywordtype",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {variable} { - startFontClass("preprocessor",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"preprocessor"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {simplecomment} { - startFontClass("comment",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {commentopen} { - startFontClass("comment",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); BEGIN(COMMENT); } <COMMENT>. { - codifyLines(yytext,yyscanner); - + codifyLines(yyscanner,yytext); + } <COMMENT>{nl} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } <COMMENT>{commentclose} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); BEGIN(INITIAL); } - + {idchar} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } {nl} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } +[\x80-\xFF]* { // keep utf8 characters together... + codifyLines(yyscanner,yytext); + } . { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } %% -static void setCurrentDoc(const QCString &anchor, yyscan_t yyscanner) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } /*! start a new line of code, inserting a line number if yyextra->sourceFileDef - * is TRUE. If a definition starts at the current line, then the line + * is true. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ static void startCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->sourceFileDef) - { - Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); - + { + const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { yyextra->currentDefinition = d; @@ -236,14 +239,14 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); - setCurrentDoc(lineAnchor,yyscanner); + setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), 0,yyextra->yyLineNr); - setCurrentDoc(lineAnchor,yyscanner); + setCurrentDoc(yyscanner,lineAnchor); } } else @@ -251,9 +254,9 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - + yyextra->code->startCodeLine(yyextra->sourceFileDef); - + if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -282,42 +285,43 @@ static void nextCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; endCodeLine(yyscanner); - if (yyextra->yyLineNr<yyextra->inputLines) + if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; startCodeLine(yyscanner); } } -static void codifyLines(char *text,yyscan_t yyscanner) +static void codifyLines(yyscan_t yyscanner,const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - char *p=text,*sp=p; + const char *p=text,*sp=p; char c; - bool done=FALSE; - + bool done=false; while (!done) { sp=p; - while ((c=*p++) && c!='\n') { } - if (c=='\n') { yyextra->yyLineNr++; - *(p-1)='\0'; - yyextra->code->codify(sp); + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); nextCodeLine(yyscanner); } else { yyextra->code->codify(sp); - done=TRUE; + done=true; } } } -static void startFontClass(const char *s,yyscan_t yyscanner) +static void startFontClass(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); @@ -332,103 +336,128 @@ static int countLines(yyscan_t yyscanner) const char *p=yyextra->inputString; char c; int count=1; - while ((c=*p)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; } - if (p>yyextra->inputString && *(p-1)!='\n') + if (p>yyextra->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++, - yyextra->needsTermination=TRUE; - } + count++, + yyextra->needsTermination=true; + } return count; } -static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner) +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 inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; yy_size_t c=0; - while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + while( c < max_size && *s ) { - *buf = yyextra->inputString[yyextra->inputPosition++] ; - c++; buf++; + *buf++ = *s++; + c++; } + yyextra->inputPosition += c; return c; } // public interface ----------------------------------------------------------- -static yyscan_t yyscanner; -static struct sqlcodeYY_state sqlcode_extra; - -void parseSqlCode( - CodeOutputInterface &od, - const char * /*className*/, - const QCString &s, - bool exBlock, - const char *exName, - FileDef *fd, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *, - bool,const Definition *searchCtx, - bool /*collectXRefs*/ - ) -{ - if (s.isEmpty()) return; - - sqlcodeYYlex_init_extra(&sqlcode_extra, &yyscanner); - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; +struct SQLCodeParser::Private +{ + yyscan_t yyscanner; + sqlcodeYY_state state; +}; + +SQLCodeParser::SQLCodeParser() : p(std::make_unique<Private>()) +{ + sqlcodeYYlex_init_extra(&p->state, &p->yyscanner); #ifdef FLEX_DEBUG sqlcodeYYset_debug(1,yyscanner); #endif + resetCodeParserState(); +} + +SQLCodeParser::~SQLCodeParser() +{ + sqlcodeYYlex_destroy(p->yyscanner); +} + +void SQLCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} + +void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - - yyextra->code = &od; - yyextra->inputString = s; + if (input.isEmpty()) return; + + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + + yyextra->code = &codeOutIntf; + yyextra->inputString = input; yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; + yyextra->needsTermination = false; yyextra->searchCtx=searchCtx; - + if (startLine!=-1) yyextra->yyLineNr = startLine; else yyextra->yyLineNr = 1; - + if (endLine!=-1) yyextra->inputLines = endLine+1; else yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; - - yyextra->exampleBlock = exBlock; - yyextra->exampleName = exName; - yyextra->sourceFileDef = fd; - - bool cleanupSourceDef = FALSE; - - if (exBlock && fd==0) + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - yyextra->sourceFileDef = createFileDef("",(exName?exName:"generated")); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; } - - if (yyextra->sourceFileDef) + + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001",yyscanner); + setCurrentDoc(yyscanner,"l00001"); } yyextra->includeCodeFragment = inlineFragment; - // Starts line 1 on the output + // Starts line 1 on the output startCodeLine(yyscanner); - sqlcodeYYrestart( yyin,yyscanner ); + sqlcodeYYrestart( 0, yyscanner ); sqlcodeYYlex(yyscanner); @@ -442,45 +471,8 @@ void parseSqlCode( delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } - - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - sqlcodeYYlex_destroy(yyscanner); - return; -} - -void resetSqlCodeParserState() -{ - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->currentDefinition = 0; - yyextra->currentMemberDef = 0; -} - -//--------------------------------------------------------------------------------- -void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt, - bool isExampleBlock, - const char *exampleName, - FileDef *fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - parseSqlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); -} - -void SQLCodeParser::resetCodeParserState() -{ - resetSqlCodeParserState(); + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } //--------------------------------------------------------------------------------- diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 2f72221..97c7337 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -1264,13 +1264,9 @@ I think the hurdles are: inner_refid (unless I'm missing a method that would uniformly return the correct refid for all types). */ -static void writeInnerClasses(const ClassSDict *cl, struct Refid outer_refid) +static void writeInnerClasses(const ClassLinkedRefMap &cl, struct Refid outer_refid) { - if (!cl) return; - - ClassSDict::Iterator cli(*cl); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : cl) { if (!cd->isHidden() && !cd->isAnonymous()) { @@ -1348,22 +1344,17 @@ static void writeInnerDirs(const DirList &dl, struct Refid outer_refid) } } -static void writeInnerNamespaces(const NamespaceSDict *nl, struct Refid outer_refid) +static void writeInnerNamespaces(const NamespaceLinkedRefMap &nl, struct Refid outer_refid) { - if (nl) + for (const auto &nd : nl) { - NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + if (!nd->isHidden() && !nd->isAnonymous()) { - if (!nd->isHidden() && !nd->isAnonymous()) - { - struct Refid inner_refid = insertRefid(nd->getOutputFileBase()); + struct Refid inner_refid = insertRefid(nd->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); } } } @@ -1421,7 +1412,7 @@ QCString getSQLDocBlock(const Definition *scope, fileName, lineNr, const_cast<Definition*>(scope), - dynamic_cast<const MemberDef*>(def), + toMemberDef(def), doc, FALSE, FALSE, @@ -1619,26 +1610,16 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref // + source references // The cross-references in initializers only work when both the src and dst // are defined. - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict!=0) + auto refList = md->getReferencesMembers(); + for (const auto &rmd : refList) { - MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(md,rmd, "inline"); - } + insertMemberReference(md,rmd, "inline"); } // + source referenced by - mdict = md->getReferencedByMembers(); - if (mdict!=0) + auto refByList = md->getReferencedByMembers(); + for (const auto &rmd : refByList) { - MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(rmd,md, "inline"); - } + insertMemberReference(rmd,md, "inline"); } return; } @@ -1856,24 +1837,16 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref // + source references // The cross-references in initializers only work when both the src and dst // are defined. - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict!=0) + auto refList = md->getReferencesMembers(); + for (const auto &refmd : refList) { - MemberSDict::IteratorDict mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(md,rmd, "inline"); - } + insertMemberReference(md,refmd, "inline"); } // + source referenced by - mdict = md->getReferencedByMembers(); - if (mdict!=0) + auto refByList = md->getReferencedByMembers(); + for (const auto &refmd : refByList) { - MemberSDict::IteratorDict mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(rmd,md, "inline"); - } + insertMemberReference(refmd,md, "inline"); } } @@ -2012,41 +1985,31 @@ static void generateSqlite3ForClass(const ClassDef *cd) step(compounddef_insert); // + list of direct super classes - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - const BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) - { - struct Refid base_refid = insertRefid(bcd->classDef->getOutputFileBase()); - struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); - bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); - bindIntParameter(compoundref_insert,":prot",bcd->prot); - bindIntParameter(compoundref_insert,":virt",bcd->virt); - step(compoundref_insert); - } + struct Refid base_refid = insertRefid(bcd.classDef->getOutputFileBase()); + struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd.prot); + bindIntParameter(compoundref_insert,":virt",bcd.virt); + step(compoundref_insert); } // + list of direct sub classes - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - const BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) - { - struct Refid derived_refid = insertRefid(bcd->classDef->getOutputFileBase()); - struct Refid base_refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); - bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); - bindIntParameter(compoundref_insert,":prot",bcd->prot); - bindIntParameter(compoundref_insert,":virt",bcd->virt); - step(compoundref_insert); - } + struct Refid derived_refid = insertRefid(bcd.classDef->getOutputFileBase()); + struct Refid base_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd.prot); + bindIntParameter(compoundref_insert,":virt",bcd.virt); + step(compoundref_insert); } // + list of inner classes - writeInnerClasses(cd->getClassSDict(),refid); + writeInnerClasses(cd->getClasses(),refid); // + template argument list(s) writeTemplateList(cd); @@ -2110,10 +2073,10 @@ static void generateSqlite3ForNamespace(const NamespaceDef *nd) step(compounddef_insert); // + contained class definitions - writeInnerClasses(nd->getClassSDict(),refid); + writeInnerClasses(nd->getClasses(),refid); // + contained namespace definitions - writeInnerNamespaces(nd->getNamespaceSDict(),refid); + writeInnerNamespaces(nd->getNamespaces(),refid); // + member groups if (nd->getMemberGroupSDict()) @@ -2272,16 +2235,10 @@ static void generateSqlite3ForFile(const FileDef *fd) } // + contained class definitions - if (fd->getClassSDict()) - { - writeInnerClasses(fd->getClassSDict(),refid); - } + writeInnerClasses(fd->getClasses(),refid); // + contained namespace definitions - if (fd->getNamespaceSDict()) - { - writeInnerNamespaces(fd->getNamespaceSDict(),refid); - } + writeInnerNamespaces(fd->getNamespaces(),refid); // + member groups if (fd->getMemberGroupSDict()) @@ -2583,21 +2540,17 @@ void generateSqlite3() recordMetadata(); // + classes - ClassSDict::Iterator cli(*Doxygen::classSDict); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + for (const auto &cd : *Doxygen::classLinkedMap) { msg("Generating Sqlite3 output for class %s\n",cd->name().data()); - generateSqlite3ForClass(cd); + generateSqlite3ForClass(cd.get()); } // + namespaces - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { msg("Generating Sqlite3 output for namespace %s\n",nd->name().data()); - generateSqlite3ForNamespace(nd); + generateSqlite3ForNamespace(nd.get()); } // + files diff --git a/src/symbolmap.h b/src/symbolmap.h new file mode 100644 index 0000000..0f837d4 --- /dev/null +++ b/src/symbolmap.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * 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 SYMBOLMAP_H +#define SYMBOLMAP_H + +#include <algorithm> +#include <map> +#include <vector> +#include <string> +#include <utility> + +//! Class implementing a symbol map that maps symbol names to objects. +//! Symbol names do not have to be unique. +//! Supports adding symbols with add(), removing symbols with remove(), and +//! finding symbols with find(). +template<class T> +class SymbolMap +{ + public: + using Ptr = T *; + using Map = std::multimap<std::string,Ptr>; + using iterator = typename Map::iterator; + using const_iterator = typename Map::const_iterator; + + //! Add a symbol \a def into the map under key \a name + void add(const char *name,Ptr def) + { + m_map.insert({std::string(name),def}); + } + + //! Remove a symbol \a def from the map that was stored under key \a name + void remove(const char *name,Ptr def) + { + auto range = find(name); + for (auto it=range.first; it!=range.second; ) + { + if (it->second==def) it = m_map.erase(it); else ++it; + } + } + + //! Find the list of symbols stored under key \a name + //! Returns a pair of iterators pointing to the start and end of the range of matching symbols + std::pair<const_iterator,const_iterator> find(const char *name) const + { + return m_map.equal_range(name ? name : ""); + } + + //! Find the list of symbols stored under key \a name + //! Returns a pair of iterators pointing to the start and end of the range of matching symbols + std::pair<iterator,iterator> find(const char *name) + { + return m_map.equal_range(name ? name : ""); + } + + iterator begin() { return m_map.begin(); } + iterator end() { return m_map.end(); } + const_iterator begin() const { return m_map.cbegin(); } + const_iterator end() const { return m_map.cend(); } + bool empty() const { return m_map.empty(); } + size_t size() const { return m_map.size(); } + + private: + Map m_map; +}; + +#endif diff --git a/src/symbolresolver.cpp b/src/symbolresolver.cpp new file mode 100644 index 0000000..9f80c15 --- /dev/null +++ b/src/symbolresolver.cpp @@ -0,0 +1,1114 @@ +/****************************************************************************** + * + * 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. + * + */ + +#include <unordered_map> +#include <string> +#include <vector> + +#include "symbolresolver.h" +#include "util.h" +#include "doxygen.h" +#include "namespacedef.h" +#include "config.h" +#include "defargs.h" + +static std::mutex g_cacheMutex; + +//-------------------------------------------------------------------------------------- + +/** Helper class representing the stack of items considered while resolving + * the scope. + */ +class AccessStack +{ + /** Element in the stack. */ + struct AccessElem + { + AccessElem(const Definition *d,const FileDef *f,const Definition *i,QCString e = QCString()) : scope(d), fileScope(f), item(i), expScope(e) {} + const Definition *scope; + const FileDef *fileScope; + const Definition *item; + QCString expScope; + }; + public: + void push(const Definition *scope,const FileDef *fileScope,const Definition *item) + { + m_elements.push_back(AccessElem(scope,fileScope,item)); + } + void push(const Definition *scope,const FileDef *fileScope,const Definition *item,const QCString &expScope) + { + m_elements.push_back(AccessElem(scope,fileScope,item,expScope)); + } + void pop() + { + if (!m_elements.empty()) m_elements.pop_back(); + } + bool find(const Definition *scope,const FileDef *fileScope, const Definition *item) + { + auto it = std::find_if(m_elements.begin(),m_elements.end(), + [&](const AccessElem &e) { return e.scope==scope && e.fileScope==fileScope && e.item==item; }); + return it!=m_elements.end(); + } + bool find(const Definition *scope,const FileDef *fileScope, const Definition *item,const QCString &expScope) + { + auto it = std::find_if(m_elements.begin(),m_elements.end(), + [&](const AccessElem &e) { return e.scope==scope && e.fileScope==fileScope && e.item==item && e.expScope==expScope; }); + return it!=m_elements.end(); + } + void clear() + { + m_elements.clear(); + } + + private: + std::vector<AccessElem> m_elements; +}; + +//-------------------------------------------------------------------------------------- + +using VisitedNamespaces = std::unordered_map<std::string,const Definition *>; + +//-------------------------------------------------------------------------------------- + +struct SymbolResolver::Private +{ + public: + Private(const FileDef *f) : m_fileScope(f) {} + void reset() + { + m_resolvedTypedefs.clear(); + resolvedType.resize(0); + typeDef = 0; + templateSpec.resize(0); + } + void setFileScope(const FileDef *fileScope) + { + m_fileScope = fileScope; + } + + QCString resolvedType; + const MemberDef *typeDef = 0; + QCString templateSpec; + + const ClassDef *getResolvedClassRec( + const Definition *scope, // in + const char *n, // in + const MemberDef **pTypeDef, // out + QCString *pTemplSpec, // out + QCString *pResolvedType); // out + + int isAccessibleFrom( AccessStack &accessStack, + const Definition *scope, + const Definition *item); + + int isAccessibleFromWithExpScope( + VisitedNamespaces &visitedNamespaces, + AccessStack &accessStack, + const Definition *scope, + const Definition *item, + const QCString &explicitScopePart); + + private: + void getResolvedSymbol(const Definition *scope, // in + const Definition *d, // in + const QCString &explicitScopePart, // in + const std::unique_ptr<ArgumentList> &actTemplParams, // in + int &minDistance, // input + const ClassDef *&bestMatch, // out + const MemberDef *&bestTypedef, // out + QCString &bestTemplSpec, // out + QCString &bestResolvedType // out + ); + + const ClassDef *newResolveTypedef( + const Definition *scope, // in + const MemberDef *md, // in + const MemberDef **pMemType, // out + QCString *pTemplSpec, // out + QCString *pResolvedType, // out + const std::unique_ptr<ArgumentList> &actTemplParams = std::unique_ptr<ArgumentList>() + ); + + const Definition *followPath(const Definition *start,const QCString &path); + + const Definition *endOfPathIsUsedClass(LinkedRefMap<const ClassDef> cl,const QCString &localName); + + bool accessibleViaUsingNamespace(StringUnorderedSet &visited, + const LinkedRefMap<const NamespaceDef> &nl, + const Definition *item, + const QCString &explicitScopePart=""); + bool accessibleViaUsingClass(const LinkedRefMap<const ClassDef> &cl, + const Definition *item, + const QCString &explicitScopePart="" + ); + QCString substTypedef(const Definition *scope,const QCString &name, + const MemberDef **pTypeDef=0); + + const FileDef *m_fileScope; + std::unordered_map<std::string,const MemberDef*> m_resolvedTypedefs; +}; + + + +const ClassDef *SymbolResolver::Private::getResolvedClassRec( + const Definition *scope, + const char *n, + const MemberDef **pTypeDef, + QCString *pTemplSpec, + QCString *pResolvedType) +{ + if (n==0 || *n=='\0') return 0; + //static int level=0; + //fprintf(stderr,"%d [getResolvedClassRec(%s,%s)\n",level++,scope?scope->name().data():"<global>",n); + QCString name; + QCString explicitScopePart; + QCString strippedTemplateParams; + name=stripTemplateSpecifiersFromScope + (removeRedundantWhiteSpace(n),TRUE, + &strippedTemplateParams); + std::unique_ptr<ArgumentList> actTemplParams; + if (!strippedTemplateParams.isEmpty()) // template part that was stripped + { + actTemplParams = stringToArgumentList(scope->getLanguage(),strippedTemplateParams); + } + + int qualifierIndex = computeQualifiedIndex(name); + //printf("name=%s qualifierIndex=%d\n",name.data(),qualifierIndex); + if (qualifierIndex!=-1) // qualified name + { + // split off the explicit scope part + explicitScopePart=name.left(qualifierIndex); + // todo: improve namespace alias substitution + replaceNamespaceAliases(explicitScopePart,explicitScopePart.length()); + name=name.mid(qualifierIndex+2); + } + + if (name.isEmpty()) + { + //fprintf(stderr,"%d ] empty name\n",--level); + return 0; // empty name + } + + //printf("Looking for symbol %s\n",name.data()); + auto range = Doxygen::symbolMap.find(name); + // 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 (range.first==range.second) + { + range = Doxygen::symbolMap.find(name+"-p"); + if (range.first==range.second) + { + //fprintf(stderr,"%d ] no such symbol!\n",--level); + return 0; + } + } + //printf("found symbol!\n"); + + bool hasUsingStatements = + (m_fileScope && (!m_fileScope->getUsedNamespaces().empty() || + !m_fileScope->getUsedClasses().empty()) + ); + //printf("hasUsingStatements=%d\n",hasUsingStatements); + // Since it is often the case that the same name is searched in the same + // scope over an over again (especially for the linked source code generation) + // we use a cache to collect previous results. This is possible since the + // result of a lookup is deterministic. As the key we use the concatenated + // scope, the name to search for and the explicit scope prefix. The speedup + // achieved by this simple cache can be enormous. + int scopeNameLen = scope->name().length()+1; + int nameLen = name.length()+1; + int explicitPartLen = explicitScopePart.length(); + int fileScopeLen = hasUsingStatements ? 1+m_fileScope->absFilePath().length() : 0; + + // below is a more efficient coding of + // QCString key=scope->name()+"+"+name+"+"+explicitScopePart; + QCString key(scopeNameLen+nameLen+explicitPartLen+fileScopeLen+1); + char *pk=key.rawData(); + qstrcpy(pk,scope->name()); *(pk+scopeNameLen-1)='+'; + pk+=scopeNameLen; + qstrcpy(pk,name); *(pk+nameLen-1)='+'; + pk+=nameLen; + qstrcpy(pk,explicitScopePart); + pk+=explicitPartLen; + + // 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 + // one of them). + if (hasUsingStatements) + { + // below is a more efficient coding of + // key+="+"+m_fileScope->name(); + *pk++='+'; + qstrcpy(pk,m_fileScope->absFilePath()); + pk+=fileScopeLen-1; + } + *pk='\0'; + + LookupInfo *pval = 0; + { + std::lock_guard<std::mutex> lock(g_cacheMutex); + pval=Doxygen::lookupCache->find(key.str()); + //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()); + if (pTemplSpec) *pTemplSpec=pval->templSpec; + if (pTypeDef) *pTypeDef=pval->typeDef; + if (pResolvedType) *pResolvedType=pval->resolvedType; + //fprintf(stderr,"%d ] cachedMatch=%s\n",--level, + // pval->classDef?pval->classDef->name().data():"<none>"); + //if (pTemplSpec) + // printf("templSpec=%s\n",pTemplSpec->data()); + return pval->classDef; + } + else // not found yet; we already add a 0 to avoid the possibility of + // endless recursion. + { + pval = Doxygen::lookupCache->insert(key.str(),LookupInfo()); + } + } + + const ClassDef *bestMatch=0; + const MemberDef *bestTypedef=0; + QCString bestTemplSpec; + QCString bestResolvedType; + int minDistance=10000; // init at "infinite" + + for (auto it=range.first ; it!=range.second; ++it) + { + Definition *d = it->second; + getResolvedSymbol(scope,d,explicitScopePart,actTemplParams, + minDistance,bestMatch,bestTypedef,bestTemplSpec,bestResolvedType); + } + + if (pTypeDef) + { + *pTypeDef = bestTypedef; + } + if (pTemplSpec) + { + *pTemplSpec = bestTemplSpec; + } + if (pResolvedType) + { + *pResolvedType = bestResolvedType; + } + + //printf("getResolvedClassRec: bestMatch=%p pval->resolvedType=%s\n", + // bestMatch,bestResolvedType.data()); + + if (pval) + { + std::lock_guard<std::mutex> lock(g_cacheMutex); + pval->classDef = bestMatch; + pval->typeDef = bestTypedef; + pval->templSpec = bestTemplSpec; + pval->resolvedType = bestResolvedType; + } + //fprintf(stderr,"%d ] bestMatch=%s distance=%d\n",--level, + // bestMatch?bestMatch->name().data():"<none>",minDistance); + //if (pTemplSpec) + // printf("templSpec=%s\n",pTemplSpec->data()); + return bestMatch; +} + +void SymbolResolver::Private::getResolvedSymbol( + const Definition *scope, // in + const Definition *d, // in + const QCString &explicitScopePart, // in + const std::unique_ptr<ArgumentList> &actTemplParams, // in + int &minDistance, // inout + const ClassDef *&bestMatch, // out + const MemberDef *&bestTypedef, // out + QCString &bestTemplSpec, // out + QCString &bestResolvedType // out + ) +{ + //fprintf(stderr,"getResolvedSymbol(%s,%s)\n",scope->name().data(),d->qualifiedName().data()); + // only look at classes and members that are enums or typedefs + if (d->definitionType()==Definition::TypeClass || + (d->definitionType()==Definition::TypeMember && + ((toMemberDef(d))->isTypedef() || + (toMemberDef(d))->isEnumerate()) + ) + ) + { + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + // test accessibility of definition within scope. + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,d,explicitScopePart); + //fprintf(stderr," %s; distance %s (%p) is %d\n",scope->name().data(),d->name().data(),d,distance); + if (distance!=-1) // definition is accessible + { + // see if we are dealing with a class or a typedef + if (d->definitionType()==Definition::TypeClass) // d is a class + { + const ClassDef *cd = toClassDef(d); + //printf("cd=%s\n",cd->name().data()); + if (!cd->isTemplateArgument()) // skip classes that + // 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; + bestTypedef = 0; + bestTemplSpec.resize(0); + bestResolvedType = cd->qualifiedName(); + } + else if (distance==minDistance && + m_fileScope && bestMatch && + !m_fileScope->getUsedNamespaces().empty() && + d->getOuterScope()->definitionType()==Definition::TypeNamespace && + bestMatch->getOuterScope()==Doxygen::globalScope + ) + { + // in case the distance is equal it could be that a class X + // is defined in a namespace and in the global scope. When searched + // in the global scope the distance is 0 in both cases. We have + // to choose one of the definitions: we choose the one in the + // namespace if the fileScope imports namespaces and the definition + // found was in a namespace while the best match so far isn't. + // Just a non-perfect heuristic but it could help in some situations + // (kdecore code is an example). + minDistance=distance; + bestMatch = cd; + bestTypedef = 0; + bestTemplSpec.resize(0); + bestResolvedType = cd->qualifiedName(); + } + } + else + { + //printf(" is a template argument!\n"); + } + } + else if (d->definitionType()==Definition::TypeMember) + { + const MemberDef *md = toMemberDef(d); + //fprintf(stderr," member isTypedef()=%d\n",md->isTypedef()); + if (md->isTypedef()) // d is a typedef + { + QCString args=md->argsString(); + if (args.isEmpty()) // do not expand "typedef t a[4];" + { + //printf(" found typedef!\n"); + + // we found a symbol at this distance, but if it didn't + // resolve to a class, we still have to make sure that + // something at a greater distance does not match, since + // that symbol is hidden by this one. + if (distance<minDistance) + { + QCString spec; + QCString type; + minDistance=distance; + const MemberDef *enumType = 0; + const ClassDef *cd = newResolveTypedef(scope,md,&enumType,&spec,&type,actTemplParams); + if (cd) // type resolves to a class + { + //printf(" bestTypeDef=%p spec=%s type=%s\n",md,spec.data(),type.data()); + bestMatch = cd; + bestTypedef = md; + bestTemplSpec = spec; + bestResolvedType = type; + } + else if (enumType) // type resolves to a member type + { + //printf(" is enum\n"); + bestMatch = 0; + bestTypedef = enumType; + bestTemplSpec = ""; + bestResolvedType = enumType->qualifiedName(); + } + else if (md->isReference()) // external reference + { + bestMatch = 0; + bestTypedef = md; + bestTemplSpec = spec; + bestResolvedType = type; + } + else + { + bestMatch = 0; + bestTypedef = md; + bestTemplSpec.resize(0); + bestResolvedType.resize(0); + //printf(" no match\n"); + } + } + else + { + //printf(" not the best match %d min=%d\n",distance,minDistance); + } + } + else + { + //printf(" not a simple typedef\n") + } + } + else if (md->isEnumerate()) + { + if (distance<minDistance) + { + minDistance=distance; + bestMatch = 0; + bestTypedef = md; + bestTemplSpec = ""; + bestResolvedType = md->qualifiedName(); + } + } + } + } // if definition accessible + else + { + //printf(" Not accessible!\n"); + } + } // if definition is a class or member + //printf(" bestMatch=%p bestResolvedType=%s\n",bestMatch,bestResolvedType.data()); +} + +const ClassDef *SymbolResolver::Private::newResolveTypedef( + const Definition *scope, // in + const MemberDef *md, // in + const MemberDef **pMemType, // out + QCString *pTemplSpec, // out + QCString *pResolvedType, // out + const std::unique_ptr<ArgumentList> &actTemplParams) // in +{ + //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); + bool isCached = md->isTypedefValCached(); // value already cached + if (isCached) + { + //printf("Already cached %s->%s [%s]\n", + // md->name().data(), + // md->getCachedTypedefVal()?md->getCachedTypedefVal()->name().data():"<none>", + // md->getCachedResolvedTypedef()?md->getCachedResolvedTypedef().data():"<none>"); + + if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec(); + if (pResolvedType) *pResolvedType = md->getCachedResolvedTypedef(); + return md->getCachedTypedefVal(); + } + //printf("new typedef\n"); + QCString qname = md->qualifiedName(); + if (m_resolvedTypedefs.find(qname.str())!=m_resolvedTypedefs.end()) + { + return 0; // typedef already done + } + + auto typedef_it = m_resolvedTypedefs.insert({qname.str(),md}).first; // 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); + } + 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)==' ')) + { + ip--; + } + type=type.left(ip+1); + type.stripPrefix("const "); // strip leading "const" + type.stripPrefix("struct "); // strip leading "struct" + type.stripPrefix("union "); // strip leading "union" + int sp=0; + tl=type.length(); // length may have been changed + while (sp<tl && type.at(sp)==' ') sp++; + const MemberDef *memTypeDef = 0; + const ClassDef *result = getResolvedClassRec(md->getOuterScope(),type, + &memTypeDef,0,pResolvedType); + // if type is a typedef then return what it resolves to. + if (memTypeDef && memTypeDef->isTypedef()) + { + result=newResolveTypedef(m_fileScope,memTypeDef,pMemType,pTemplSpec,0); + goto done; + } + else if (memTypeDef && memTypeDef->isEnumerate() && pMemType) + { + *pMemType = memTypeDef; + } + + //printf("type=%s result=%p\n",type.data(),result); + if (result==0) + { + // try unspecialized version if type is template + int si=type.findRev("::"); + int i=type.find('<'); + if (si==-1 && i!=-1) // typedef of a template => try the unspecialized version + { + if (pTemplSpec) *pTemplSpec = type.mid(i); + result = getResolvedClassRec(md->getOuterScope(),type.left(i),0,0,pResolvedType); + //printf("result=%p pRresolvedType=%s sp=%d ip=%d tl=%d\n", + // result,pResolvedType?pResolvedType->data():"<none>",sp,ip,tl); + } + else if (si!=-1) // A::B + { + i=type.find('<',si); + if (i==-1) // Something like A<T>::B => lookup A::B + { + i=type.length(); + } + else // Something like A<T>::B<S> => lookup A::B, spec=<S> + { + if (pTemplSpec) *pTemplSpec = type.mid(i); + } + result = getResolvedClassRec(md->getOuterScope(), + stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0,pResolvedType); + } + + //if (result) ip=si+sp+1; + } + +done: + if (pResolvedType) + { + if (result) + { + *pResolvedType = result->qualifiedName(); + //printf("*pResolvedType=%s\n",pResolvedType->data()); + if (sp>0) pResolvedType->prepend(typedefValue.left(sp)); + if (ip<tl-1) pResolvedType->append(typedefValue.right(tl-ip-1)); + } + else + { + *pResolvedType = typedefValue; + } + } + + // remember computed value for next time + 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); + //printf("==> %s (%s,%d)\n",result->name().data(),result->getDefFileName().data(),result->getDefLine()); + //printf("*pResolvedType=%s\n",pResolvedType?pResolvedType->data():"<none>"); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->cacheTypedefVal(result, + pTemplSpec ? *pTemplSpec : QCString(), + pResolvedType ? *pResolvedType : QCString() + ); + } + } + + m_resolvedTypedefs.erase(typedef_it); // remove from the trace list + + return result; +} + +int SymbolResolver::Private::isAccessibleFromWithExpScope( + VisitedNamespaces &visitedNamespaces, + AccessStack &accessStack, + const Definition *scope, + const Definition *item, + const QCString &explicitScopePart) +{ + if (explicitScopePart.isEmpty()) + { + // handle degenerate case where there is no explicit scope. + return isAccessibleFrom(accessStack,scope,item); + } + + if (accessStack.find(scope,m_fileScope,item,explicitScopePart)) + { + return -1; + } + accessStack.push(scope,m_fileScope,item,explicitScopePart); + + + //printf(" <isAccessibleFromWithExpScope(%s,%s,%s)\n",scope?scope->name().data():"<global>", + // item?item->name().data():"<none>", + // explicitScopePart.data()); + int result=0; // assume we found it + const Definition *newScope = followPath(scope,explicitScopePart); + if (newScope) // explicitScope is inside scope => newScope is the result + { + Definition *itemScope = item->getOuterScope(); + //printf(" scope traversal successful %s<->%s!\n",itemScope->name().data(),newScope->name().data()); + //if (newScope && newScope->definitionType()==Definition::TypeClass) + //{ + // ClassDef *cd = (ClassDef *)newScope; + // printf("---> Class %s: bases=%p\n",cd->name().data(),cd->baseClasses()); + //} + if (itemScope==newScope) // exact match of scopes => distance==0 + { + //printf("> found it\n"); + } + else if (itemScope && newScope && + itemScope->definitionType()==Definition::TypeClass && + newScope->definitionType()==Definition::TypeClass && + (toClassDef(newScope))->isBaseClass(toClassDef(itemScope),TRUE,0) + ) + { + // 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 + // class A { public: class I {} }; + // class B { public: class I {} }; + // will find A::I, so we still prefer a direct match and give this one a distance of 1 + result=1; + + //printf("scope(%s) is base class of newScope(%s)\n", + // scope->name().data(),newScope->name().data()); + } + else + { + int i=-1; + if (newScope->definitionType()==Definition::TypeNamespace) + { + visitedNamespaces.insert({newScope->name().str(),newScope}); + // this part deals with the case where item is a class + // A::B::C but is explicit referenced as A::C, where B is imported + // in A via a using directive. + //printf("newScope is a namespace: %s!\n",newScope->name().data()); + const NamespaceDef *nscope = toNamespaceDef(newScope); + for (const auto &cd : nscope->getUsedClasses()) + { + //printf("Trying for class %s\n",cd->name().data()); + if (cd==item) + { + goto done; + } + } + for (const auto &nd : nscope->getUsedNamespaces()) + { + if (visitedNamespaces.find(nd->name().str())==visitedNamespaces.end()) + { + //printf("Trying for namespace %s\n",nd->name().data()); + i = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,item,nd->name()); + if (i!=-1) + { + //printf("> found via explicit scope of used namespace\n"); + goto done; + } + } + } + } + // repeat for the parent scope + if (scope!=Doxygen::globalScope) + { + i = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope->getOuterScope(),item,explicitScopePart); + } + //printf(" | result=%d\n",i); + result = (i==-1) ? -1 : i+2; + } + } + else // failed to resolve explicitScope + { + //printf(" failed to resolve: scope=%s\n",scope->name().data()); + if (scope->definitionType()==Definition::TypeNamespace) + { + const NamespaceDef *nscope = toNamespaceDef(scope); + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nscope->getUsedNamespaces(),item,explicitScopePart)) + { + //printf("> found in used namespace\n"); + goto done; + } + } + if (scope==Doxygen::globalScope) + { + if (m_fileScope) + { + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,m_fileScope->getUsedNamespaces(),item,explicitScopePart)) + { + //printf("> found in used namespace\n"); + goto done; + } + } + //printf("> not found\n"); + result=-1; + } + else // continue by looking into the parent scope + { + int i=isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope->getOuterScope(),item,explicitScopePart); + //printf("> result=%d\n",i); + result= (i==-1) ? -1 : i+2; + } + } + +done: + //printf(" > result=%d\n",result); + accessStack.pop(); + return result; +} + +const Definition *SymbolResolver::Private::followPath(const Definition *start,const QCString &path) +{ + int is,ps; + int l; + const Definition *current=start; + ps=0; + //printf("followPath: start='%s' path='%s'\n",start?start->name().data():"<none>",path.data()); + // for each part of the explicit scope + while ((is=getScopeFragment(path,ps,&l))!=-1) + { + // try to resolve the part if it is a typedef + const MemberDef *memTypeDef=0; + QCString qualScopePart = substTypedef(current,path.mid(is,l),&memTypeDef); + //printf(" qualScopePart=%s\n",qualScopePart.data()); + if (memTypeDef) + { + const ClassDef *type = newResolveTypedef(m_fileScope,memTypeDef,0,0,0); + if (type) + { + //printf("Found type %s\n",type->name().data()); + return type; + } + } + const Definition *next = current->findInnerCompound(qualScopePart); + //printf("++ Looking for %s inside %s result %s\n", + // qualScopePart.data(), + // current->name().data(), + // next?next->name().data():"<null>"); + if (next==0) // failed to follow the path + { + //printf("==> next==0!\n"); + if (current->definitionType()==Definition::TypeNamespace) + { + next = endOfPathIsUsedClass( + (toNamespaceDef(current))->getUsedClasses(),qualScopePart); + } + else if (current->definitionType()==Definition::TypeFile) + { + next = endOfPathIsUsedClass( + (toFileDef(current))->getUsedClasses(),qualScopePart); + } + current = next; + if (current==0) break; + } + else // continue to follow scope + { + current = next; + //printf("==> current = %p\n",current); + } + ps=is+l; + } + //printf("followPath(start=%s,path=%s) result=%s\n", + // start->name().data(),path.data(),current?current->name().data():"<null>"); + return current; // path could be followed +} + +const Definition *SymbolResolver::Private::endOfPathIsUsedClass(LinkedRefMap<const ClassDef> cl,const QCString &localName) +{ + for (const auto &cd : cl) + { + if (cd->localName()==localName) + { + return cd; + } + } + return 0; +} + +bool SymbolResolver::Private::accessibleViaUsingNamespace(StringUnorderedSet &visited, + const LinkedRefMap<const NamespaceDef> &nl, + const Definition *item, + const QCString &explicitScopePart) +{ + for (const auto &und : nl) // check used namespaces for the class + { + //printf("[Trying via used namespace %s: count=%d/%d\n",und->name().data(), + // count,nl->count()); + const Definition *sc = explicitScopePart.isEmpty() ? und : followPath(und,explicitScopePart); + if (sc && item->getOuterScope()==sc) + { + //printf("] found it\n"); + return true; + } + if (item->getLanguage()==SrcLangExt_Cpp) + { + QCString key=und->name(); + if (!und->getUsedNamespaces().empty() && visited.find(key.str())==visited.end()) + { + visited.insert(key.str()); + + if (accessibleViaUsingNamespace(visited,und->getUsedNamespaces(),item,explicitScopePart)) + { + //printf("] found it via recursion\n"); + return true; + } + + visited.erase(key.str()); + } + } + //printf("] Try via used namespace done\n"); + } + return false; +} + + +bool SymbolResolver::Private::accessibleViaUsingClass(const LinkedRefMap<const ClassDef> &cl, + const Definition *item, + const QCString &explicitScopePart) +{ + for (const auto &ucd : cl) + { + //printf("Trying via used class %s\n",ucd->name().data()); + const Definition *sc = explicitScopePart.isEmpty() ? ucd : followPath(ucd,explicitScopePart); + if (sc && sc==item) return true; + //printf("Try via used class done\n"); + } + return false; +} + +int SymbolResolver::Private::isAccessibleFrom(AccessStack &accessStack, + const Definition *scope, + const Definition *item) +{ + //printf("<isAccessibleFrom(scope=%s,item=%s itemScope=%s)\n", + // scope->name().data(),item->name().data(),item->getOuterScope()->name().data()); + + if (accessStack.find(scope,m_fileScope,item)) + { + return -1; + } + accessStack.push(scope,m_fileScope,item); + + int result=0; // assume we found it + int i; + + Definition *itemScope=item->getOuterScope(); + bool memberAccessibleFromScope = + (item->definitionType()==Definition::TypeMember && // a member + itemScope && itemScope->definitionType()==Definition::TypeClass && // of a class + scope->definitionType()==Definition::TypeClass && // accessible + (toClassDef(scope))->isAccessibleMember(toMemberDef(item)) // from scope + ); + bool nestedClassInsideBaseClass = + (item->definitionType()==Definition::TypeClass && // a nested class + itemScope && itemScope->definitionType()==Definition::TypeClass && // inside a base + scope->definitionType()==Definition::TypeClass && // class of scope + (toClassDef(scope))->isBaseClass(toClassDef(itemScope),TRUE) + ); + + if (itemScope==scope || memberAccessibleFromScope || nestedClassInsideBaseClass) + { + //printf("> found it\n"); + if (nestedClassInsideBaseClass) result++; // penalty for base class to prevent + // this is preferred over nested class in this class + // see bug 686956 + } + else if (scope==Doxygen::globalScope) + { + if (m_fileScope) + { + if (accessibleViaUsingClass(m_fileScope->getUsedClasses(),item)) + { + //printf("> found via used class\n"); + goto done; + } + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,m_fileScope->getUsedNamespaces(),item)) + { + //printf("> found via used namespace\n"); + goto done; + } + } + //printf("> reached global scope\n"); + result=-1; // not found in path to globalScope + } + else // keep searching + { + // check if scope is a namespace, which is using other classes and namespaces + if (scope->definitionType()==Definition::TypeNamespace) + { + const NamespaceDef *nscope = toNamespaceDef(scope); + //printf(" %s is namespace with %d used classes\n",nscope->name().data(),nscope->getUsedClasses()); + if (accessibleViaUsingClass(nscope->getUsedClasses(),item)) + { + //printf("> found via used class\n"); + goto done; + } + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nscope->getUsedNamespaces(),item)) + { + //printf("> found via used namespace\n"); + goto done; + } + } + // repeat for the parent scope + i=isAccessibleFrom(accessStack,scope->getOuterScope(),item); + //printf("> result=%d\n",i); + result= (i==-1) ? -1 : i+2; + } +done: + accessStack.pop(); + return result; +} + +QCString SymbolResolver::Private::substTypedef( + const Definition *scope,const QCString &name, + const MemberDef **pTypeDef) +{ + QCString result=name; + if (name.isEmpty()) return result; + + auto range = Doxygen::symbolMap.find(name); + if (range.first==range.second) + return result; // no matches + + MemberDef *bestMatch=0; + int minDistance=10000; // init at "infinite" + + for (auto it = range.first; it!=range.second; ++it) + { + Definition *d = it->second; + // only look at members + if (d->definitionType()==Definition::TypeMember) + { + // that are also typedefs + MemberDef *md = toMemberDef(d); + if (md->isTypedef()) // d is a typedef + { + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + // test accessibility of typedef within scope. + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,d,""); + if (distance!=-1 && distance<minDistance) + // definition is accessible and a better match + { + minDistance=distance; + bestMatch = md; + } + } + } + } + + 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; +} + +//---------------------------------------------------------------------------------------------- + + +SymbolResolver::SymbolResolver(const FileDef *fileScope) + : p(std::make_unique<Private>(fileScope)) +{ +} + +SymbolResolver::~SymbolResolver() +{ +} + + +const ClassDef *SymbolResolver::resolveClass(const Definition *scope, + const char *name, + bool mayBeUnlinkable, + bool mayBeHidden) +{ + p->reset(); + + if (scope==0 || + (scope->definitionType()!=Definition::TypeClass && + scope->definitionType()!=Definition::TypeNamespace + ) || + (scope->getLanguage()==SrcLangExt_Java && QCString(name).find("::")!=-1) + ) + { + scope=Doxygen::globalScope; + } + //fprintf(stderr,"------------ resolveClass(scope=%s,name=%s,mayUnlinkable=%d)\n", + // scope?scope->name().data():"<global>", + // name, + // mayBeUnlinkable + // ); + const ClassDef *result; + if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) + { + result = getClass(name); + } + else + { + result = p->getResolvedClassRec(scope,name,&p->typeDef,&p->templateSpec,&p->resolvedType); + if (result==0) // for nested classes imported via tag files, the scope may not + // present, so we check the class name directly as well. + // See also bug701314 + { + result = getClass(name); + } + } + if (!mayBeUnlinkable && result && !result->isLinkable()) + { + if (!mayBeHidden || !result->isHidden()) + { + //printf("result was %s\n",result?result->name().data():"<none>"); + result=0; // don't link to artificial/hidden classes unless explicitly allowed + } + } + //fprintf(stderr,"ResolvedClass(%s,%s)=%s\n",scope?scope->name().data():"<global>", + // name,result?result->name().data():"<none>"); + return result; +} + +int SymbolResolver::isAccessibleFrom(const Definition *scope,const Definition *item) +{ + p->reset(); + AccessStack accessStack; + return p->isAccessibleFrom(accessStack,scope,item); +} + +int SymbolResolver::isAccessibleFromWithExpScope(const Definition *scope,const Definition *item, + const QCString &explicitScopePart) +{ + p->reset(); + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + return p->isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,item,explicitScopePart); +} + +void SymbolResolver::setFileScope(const FileDef *fileScope) +{ + p->setFileScope(fileScope); +} + +const MemberDef *SymbolResolver::getTypedef() const +{ + return p->typeDef; +} + +QCString SymbolResolver::getTemplateSpec() const +{ + return p->templateSpec; +} + +QCString SymbolResolver::getResolvedType() const +{ + return p->resolvedType; +} + diff --git a/src/symbolresolver.h b/src/symbolresolver.h new file mode 100644 index 0000000..5536c1e --- /dev/null +++ b/src/symbolresolver.h @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * 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 SYMBOLRESOLVER_H +#define SYMBOLRESOLVER_H + +#include <memory> +#include "qcstring.h" +#include "classdef.h" + +class Definition; +class FileDef; +class MemberDef; + +//! Helper class to find a class definition or check if +//! A symbol is accessible in a given scope. +class SymbolResolver +{ + public: + explicit SymbolResolver(const FileDef *fileScope = 0); + ~SymbolResolver(); + + // actions + + /** Find the class definition matching name within + * the scope set. + * @param scope The scope to search from. + * @param name The name of the symbol. + * @param maybeUnlinkable include unlinkable symbols in the search. + * @param mayBeHidden include hidden symbols in the search. + * @note As a result of this call the getters getTypedef(), + * getTemplateSpec(), and getResolvedType() are set as well. + */ + const ClassDef *resolveClass(const Definition *scope, + const char *name, + bool maybeUnlinkable=false, + bool mayBeHidden=false); + + /** Wrapper around resolveClass that returns a mutable interface to + * the class object or a nullptr if the symbol is immutable. + */ + ClassDefMutable *resolveClassMutable(const Definition *scope, + const char *name, + bool mayBeUnlinkable=false, + bool mayBeHidden=false) + { + return toClassDefMutable(resolveClass(scope,name,mayBeUnlinkable,mayBeHidden)); + } + + /** Checks if symbol \a item is accessible from within \a scope. + * @returns -1 if \a item is not accessible or a number indicating how + * many scope levels up the nearest match was found. + */ + int isAccessibleFrom(const Definition *scope, + const Definition *item); + + /** Check if symbol \a item is accessible from within \a scope, + * where it has to match the \a explicitScopePart. + * @returns -1 if \a item is not accessible or a number indicating how + * many scope levels up the nearest match was found. + */ + int isAccessibleFromWithExpScope(const Definition *scope, + const Definition *item, + const QCString &explicitScopePart + ); + + /** Sets or updates the file scope using when resolving symbols. */ + void setFileScope(const FileDef *fd); + + // getters + + /** In case a call to resolveClass() resolves to a type member (e.g. an enum) + * this method will return it. + */ + const MemberDef *getTypedef() const; + + /** In case a call to resolveClass() points to a template specialization, the + * template part is return via this method. + */ + QCString getTemplateSpec() const; + + /** In case a call to resolveClass() points to a typedef or using declaration. + * The type name it resolved to is returned via this method. + */ + QCString getResolvedType() const; + + private: + struct Private; + std::unique_ptr<Private> p; +}; + +#endif diff --git a/src/tagreader.cpp b/src/tagreader.cpp index 62aadc3..d5f8d5f 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -21,17 +21,13 @@ #include <map> #include <functional> #include <utility> +#include <algorithm> #include <assert.h> #include <stdio.h> #include <stdarg.h> -#include <algorithm> - - -#include <qxml.h> -#include <qfileinfo.h> -#include <qstring.h> +#include "xml.h" #include "entry.h" #include "doxygen.h" #include "util.h" @@ -47,32 +43,32 @@ class TagAnchorInfo { public: - TagAnchorInfo(const QCString &f, - const QCString &l, - const QCString &t=QCString()) + TagAnchorInfo(const std::string &f, + const std::string &l, + const std::string &t=std::string()) : label(l), fileName(f), title(t) {} - QCString label; - QCString fileName; - QCString title; + std::string label; + std::string fileName; + std::string title; }; /** Container for enum values that are scoped within an enum */ class TagEnumValueInfo { public: - QCString name; - QCString file; - QCString anchor; - QCString clangid; + std::string name; + std::string file; + std::string anchor; + std::string clangid; }; /** Container for include info that can be read from a tagfile */ class TagIncludeInfo { public: - QCString id; - QCString name; - QCString text; + std::string id; + std::string name; + std::string text; bool isLocal; bool isImported; }; @@ -81,13 +77,13 @@ class TagIncludeInfo class TagMemberInfo { public: - QCString type; - QCString name; - QCString anchorFile; - QCString anchor; - QCString arglist; - QCString kind; - QCString clangId; + std::string type; + std::string name; + std::string anchorFile; + std::string anchor; + std::string arglist; + std::string kind; + std::string clangId; std::vector<TagAnchorInfo> docAnchors; Protection prot = Public; Specifier virt = Normal; @@ -104,8 +100,8 @@ class TagCompoundInfo virtual ~TagCompoundInfo() {} CompoundType compoundType() const { return m_type; } std::vector<TagMemberInfo> members; - QCString name; - QCString filename; + std::string name; + std::string filename; std::vector<TagAnchorInfo> docAnchors; private: CompoundType m_type; @@ -117,8 +113,8 @@ 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; + std::string clangId; + std::string anchor; std::vector<BaseInfo> bases; StringVector templateArguments; StringVector classList; @@ -139,7 +135,7 @@ class TagNamespaceInfo : public TagCompoundInfo { public: TagNamespaceInfo() :TagCompoundInfo(CompoundType::Namespace) {} - QCString clangId; + std::string clangId; StringVector classList; StringVector namespaceList; static TagNamespaceInfo *get(std::unique_ptr<TagCompoundInfo> &t) @@ -173,7 +169,7 @@ class TagFileInfo : public TagCompoundInfo { public: TagFileInfo() : TagCompoundInfo(CompoundType::File) { } - QCString path; + std::string path; StringVector classList; StringVector namespaceList; std::vector<TagIncludeInfo> includes; @@ -192,7 +188,7 @@ class TagGroupInfo : public TagCompoundInfo { public: TagGroupInfo() : TagCompoundInfo(CompoundType::Group) { } - QCString title; + std::string title; StringVector subgroupList; StringVector classList; StringVector namespaceList; @@ -214,7 +210,7 @@ class TagPageInfo : public TagCompoundInfo { public: TagPageInfo() : TagCompoundInfo(CompoundType::Page) {} - QCString title; + std::string title; static TagPageInfo *get(std::unique_ptr<TagCompoundInfo> &t) { return dynamic_cast<TagPageInfo*>(t.get()); @@ -230,7 +226,7 @@ class TagDirInfo : public TagCompoundInfo { public: TagDirInfo() : TagCompoundInfo(CompoundType::Dir) {} - QCString path; + std::string path; StringVector subdirList; StringVector fileList; static TagDirInfo *get(std::unique_ptr<TagCompoundInfo> &t) @@ -249,75 +245,33 @@ class TagDirInfo : public TagCompoundInfo * memory. The method buildLists() is used to transfer/translate * the structures to the doxygen engine. */ -class TagFileParser : public QXmlDefaultHandler +class TagFileParser { - enum State { Invalid, - InClass, - InFile, - InNamespace, - InGroup, - InPage, - InMember, - InEnumValue, - InPackage, - InDir, - InTempArgList - }; - - struct CompoundFactory - { - 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_tagName(tagName) {} - void setDocumentLocator ( QXmlLocator * locator ) + void setDocumentLocator ( const XMLLocator * locator ) { m_locator = locator; } - void setFileName( const QString &fileName ) - { - m_inputFileName = fileName.utf8(); - } - - void warn(const char *fmt) + void startDocument() { - ::warn(m_inputFileName,m_locator->lineNumber(),"%s", fmt); + m_state = Invalid; } - void warn(const char *fmt,const char *s) + void startElement( const std::string &name, const XMLHandlers::Attributes& attrib ); + void endElement( const std::string &name ); + void characters ( const std::string & ch ) { m_curString+=ch; } + void error( const std::string &fileName,int lineNr,const std::string &msg) { - ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s); + ::warn(fileName.c_str(),lineNr,"%s",msg.c_str()); } - void startCompound( const QXmlAttributes& attrib ) - { - m_curString = ""; - QString kind = attrib.value("kind"); - QString isObjC = attrib.value("objc"); - - auto it = m_compoundFactory.find(kind.utf8().str()); - if (it!=m_compoundFactory.end()) - { - 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_curCompound && - m_curCompound->compoundType()==TagCompoundInfo::CompoundType::Class) - { - TagClassInfo::get(m_curCompound)->isObjC = TRUE; - } - } + void dump(); + void buildLists(const std::shared_ptr<Entry> &root); + void addIncludes(); + void startCompound( const XMLHandlers::Attributes& attrib ); void endCompound() { @@ -338,13 +292,13 @@ class TagFileParser : public QXmlDefaultHandler } } - void startMember( const QXmlAttributes& attrib) + void startMember( const XMLHandlers::Attributes& attrib) { 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(); + m_curMember.kind = XMLHandlers::value(attrib,"kind"); + std::string protStr = XMLHandlers::value(attrib,"protection"); + std::string virtStr = XMLHandlers::value(attrib,"virtualness"); + std::string staticStr = XMLHandlers::value(attrib,"static"); if (protStr=="protected") { m_curMember.prot = Protected; @@ -388,15 +342,15 @@ class TagFileParser : public QXmlDefaultHandler } } - void startEnumValue( const QXmlAttributes& attrib) + void startEnumValue( const XMLHandlers::Attributes& attrib) { if (m_state==InMember) { m_curString = ""; 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_curEnumValue.file = XMLHandlers::value(attrib,"file"); + m_curEnumValue.anchor = XMLHandlers::value(attrib,"anchor"); + m_curEnumValue.clangid = XMLHandlers::value(attrib,"clangid"); m_stateStack.push(m_state); m_state = InEnumValue; } @@ -431,7 +385,7 @@ class TagFileParser : public QXmlDefaultHandler case InMember: case InPackage: case InDir: - if (QString(m_curString).startsWith("autotoc_md")) return; + if (m_curString.rfind("autotoc_md",0)==0) return; break; default: warn("Unexpected tag 'docanchor' found"); @@ -541,15 +495,15 @@ class TagFileParser : public QXmlDefaultHandler } } - void startStringValue(const QXmlAttributes& ) + void startStringValue(const XMLHandlers::Attributes& ) { m_curString = ""; } - void startDocAnchor(const QXmlAttributes& attrib ) + void startDocAnchor(const XMLHandlers::Attributes& attrib ) { - m_fileName = attrib.value("file").utf8(); - m_title = attrib.value("title").utf8(); + m_fileName = XMLHandlers::value(attrib,"file"); + m_title = XMLHandlers::value(attrib,"title"); m_curString = ""; } @@ -587,13 +541,13 @@ class TagFileParser : public QXmlDefaultHandler } } - void startBase(const QXmlAttributes& attrib ) + void startBase(const XMLHandlers::Attributes& attrib ) { m_curString=""; if (m_state==InClass && m_curCompound) { - QString protStr = attrib.value("protection"); - QString virtStr = attrib.value("virtualness"); + std::string protStr = XMLHandlers::value(attrib,"protection"); + std::string virtStr = XMLHandlers::value(attrib,"virtualness"); Protection prot = Public; Specifier virt = Normal; if (protStr=="protected") @@ -628,13 +582,13 @@ class TagFileParser : public QXmlDefaultHandler } } - void startIncludes(const QXmlAttributes& attrib ) + void startIncludes(const XMLHandlers::Attributes& attrib ) { 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_curIncludes.id = XMLHandlers::value(attrib,"id"); + m_curIncludes.name = XMLHandlers::value(attrib,"name"); + m_curIncludes.isLocal = XMLHandlers::value(attrib,"local")=="yes"; + m_curIncludes.isImported = XMLHandlers::value(attrib,"imported")=="yes"; m_curString=""; } @@ -788,7 +742,7 @@ class TagFileParser : public QXmlDefaultHandler } } - void startIgnoreElement(const QXmlAttributes& ) + void startIgnoreElement(const XMLHandlers::Attributes& ) { } @@ -796,134 +750,40 @@ class TagFileParser : public QXmlDefaultHandler { } - bool startDocument() - { - m_state = Invalid; + 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); - 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&, - const QString&name, const QXmlAttributes& attrib ) - { - //printf("startElement '%s'\n",name.data()); - auto it = m_startElementHandlers.find(name.utf8().str()); - if (it!=std::end(m_startElementHandlers)) - { - it->second(attrib); - } - else - { - warn("Unknown tag '%s' found!",name.data()); - } - return TRUE; - } - bool endElement( const QString&, const QString&, const QString& name ) + enum State { Invalid, + InClass, + InFile, + InNamespace, + InGroup, + InPage, + InMember, + InEnumValue, + InPackage, + InDir, + InTempArgList + }; + private: + + void warn(const char *fmt) { - //printf("endElement '%s'\n",name.data()); - auto it = m_endElementHandlers.find(name.utf8().str()); - if (it!=std::end(m_endElementHandlers)) - { - it->second(); - } - else - { - warn("Unknown tag '%s' found!",name.data()); - } - return TRUE; + std::string fileName = m_locator->fileName(); + ::warn(fileName.c_str(),m_locator->lineNr(),"%s", fmt); } - bool characters ( const QString & ch ) + void warn(const char *fmt,const char *s) { - m_curString+=ch.utf8(); - return TRUE; + std::string fileName = m_locator->fileName(); + ::warn(fileName.c_str(),m_locator->lineNr(),fmt,s); } - void dump(); - void buildLists(const std::shared_ptr<Entry> &root); - void addIncludes(); - private: - 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::vector< std::unique_ptr<TagCompoundInfo> > m_tagFileCompounds; std::unique_ptr<TagCompoundInfo> m_curCompound; TagMemberInfo m_curMember; @@ -931,44 +791,149 @@ class TagFileParser : public QXmlDefaultHandler TagIncludeInfo m_curIncludes; std::string m_curString; - QCString m_tagName; - QCString m_fileName; - QCString m_title; + std::string m_tagName; + std::string m_fileName; + std::string m_title; State m_state = Invalid; std::stack<State> m_stateStack; - QXmlLocator *m_locator = nullptr; - QCString m_inputFileName; + const XMLLocator *m_locator = nullptr; }; -/** Error handler for the XML tag file parser. - * - * Basically dumps all fatal error to stderr using err(). - */ -class TagFileErrorHandler : public QXmlErrorHandler +//--------------------------------------------------------------------------------------------------------------- + +struct ElementCallbacks { - public: - virtual ~TagFileErrorHandler() {} - bool warning( const QXmlParseException & ) - { - return FALSE; - } - bool error( const QXmlParseException & ) - { - return FALSE; - } - bool fatalError( const QXmlParseException &exception ) - { - err("Fatal error at line %d column %d: %s\n", - exception.lineNumber(),exception.columnNumber(), - exception.message().data()); - return FALSE; - } - QString errorString() { return ""; } + using StartCallback = std::function<void(TagFileParser&,const XMLHandlers::Attributes&)>; + using EndCallback = std::function<void(TagFileParser&)>; - private: - QString errorMsg; + StartCallback startCb; + EndCallback endCb; +}; + +ElementCallbacks::StartCallback startCb(void (TagFileParser::*fn)(const XMLHandlers::Attributes &)) +{ + return [fn](TagFileParser &parser,const XMLHandlers::Attributes &attr) { (parser.*fn)(attr); }; +} + +ElementCallbacks::EndCallback endCb(void (TagFileParser::*fn)()) +{ + return [fn](TagFileParser &parser) { (parser.*fn)(); }; +} + +static const std::map< std::string, ElementCallbacks > g_elementHandlers = +{ + // name, start element callback, end element callback + { "compound", { startCb(&TagFileParser::startCompound ), endCb(&TagFileParser::endCompound ) } }, + { "member", { startCb(&TagFileParser::startMember ), endCb(&TagFileParser::endMember ) } }, + { "enumvalue", { startCb(&TagFileParser::startEnumValue ), endCb(&TagFileParser::endEnumValue ) } }, + { "name", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endName ) } }, + { "base", { startCb(&TagFileParser::startBase ), endCb(&TagFileParser::endBase ) } }, + { "filename", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endFilename ) } }, + { "includes", { startCb(&TagFileParser::startIncludes ), endCb(&TagFileParser::endIncludes ) } }, + { "path", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endPath ) } }, + { "anchorfile", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endAnchorFile ) } }, + { "anchor", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endAnchor ) } }, + { "clangid", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endClangId ) } }, + { "arglist", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endArglist ) } }, + { "title", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endTitle ) } }, + { "subgroup", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endSubgroup ) } }, + { "class", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endClass ) } }, + { "namespace", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endNamespace ) } }, + { "file", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endFile ) } }, + { "dir", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endDir ) } }, + { "page", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endPage ) } }, + { "docanchor", { startCb(&TagFileParser::startDocAnchor ), endCb(&TagFileParser::endDocAnchor ) } }, + { "tagfile", { startCb(&TagFileParser::startIgnoreElement), endCb(&TagFileParser::endIgnoreElement) } }, + { "templarg", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endTemplateArg ) } }, + { "type", { startCb(&TagFileParser::startStringValue ), endCb(&TagFileParser::endType ) } } +}; + +//--------------------------------------------------------------------------------------------------------------- + +struct CompoundFactory +{ + using CreateFunc = std::function<std::unique_ptr<TagCompoundInfo>()>; + CompoundFactory(TagFileParser::State s,CreateFunc f) : state(s), make_instance(f) {} + TagFileParser::State state; + CreateFunc make_instance; }; +static const std::map< std::string, CompoundFactory > g_compoundFactory = +{ + // kind tag state creation function + { "class", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Class); } } }, + { "struct", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Struct); } } }, + { "union", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Union); } } }, + { "interface", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Interface); } } }, + { "enum", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Enum); } } }, + { "exception", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Exception); } } }, + { "protocol", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Protocol); } } }, + { "category", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Category); } } }, + { "service", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Service); } } }, + { "singleton", { TagFileParser::InClass, []() { return std::make_unique<TagClassInfo>(TagClassInfo::Kind::Singleton); } } }, + { "file", { TagFileParser::InFile, []() { return std::make_unique<TagFileInfo>(); } } }, + { "namespace", { TagFileParser::InNamespace, []() { return std::make_unique<TagNamespaceInfo>(); } } }, + { "group", { TagFileParser::InGroup, []() { return std::make_unique<TagGroupInfo>(); } } }, + { "page", { TagFileParser::InPage, []() { return std::make_unique<TagPageInfo>(); } } }, + { "package", { TagFileParser::InPackage, []() { return std::make_unique<TagPackageInfo>(); } } }, + { "dir", { TagFileParser::InDir, []() { return std::make_unique<TagDirInfo>(); } } } +}; + +//--------------------------------------------------------------------------------------------------------------- + +void TagFileParser::startElement( const std::string &name, const XMLHandlers::Attributes& attrib ) +{ + //printf("startElement '%s'\n",name.data()); + auto it = g_elementHandlers.find(name); + if (it!=std::end(g_elementHandlers)) + { + it->second.startCb(*this,attrib); + } + else + { + warn("Unknown start tag '%s' found!",name.data()); + } +} + +void TagFileParser::endElement( const std::string &name ) +{ + //printf("endElement '%s'\n",name.data()); + auto it = g_elementHandlers.find(name); + if (it!=std::end(g_elementHandlers)) + { + it->second.endCb(*this); + } + else + { + warn("Unknown end tag '%s' found!",name.data()); + } +} + +void TagFileParser::startCompound( const XMLHandlers::Attributes& attrib ) +{ + m_curString = ""; + std::string kind = XMLHandlers::value(attrib,"kind"); + std::string isObjC = XMLHandlers::value(attrib,"objc"); + + auto it = g_compoundFactory.find(kind); + if (it!=g_compoundFactory.end()) + { + m_curCompound = it->second.make_instance(); + m_state = it->second.state; + } + else + { + warn("Unknown compound attribute '%s' found!",kind.c_str()); + m_state = Invalid; + } + + if (isObjC=="yes" && m_curCompound && + m_curCompound->compoundType()==TagCompoundInfo::CompoundType::Class) + { + TagClassInfo::get(m_curCompound)->isObjC = TRUE; + } +} + /*! Dumps the internal structures. For debugging only! */ void TagFileParser::dump() { @@ -1134,13 +1099,13 @@ void TagFileParser::addDocAnchors(const std::shared_ptr<Entry> &e,const std::vec { for (const auto &ta : l) { - if (SectionManager::instance().find(ta.label)==0) + if (SectionManager::instance().find(ta.label.c_str())==0) { //printf("New sectionInfo file=%s anchor=%s\n", // ta->fileName.data(),ta->label.data()); SectionInfo *si=SectionManager::instance().add( - ta.label,ta.fileName,-1,ta.title, - SectionType::Anchor,0,m_tagName); + ta.label.c_str(),ta.fileName.c_str(),-1,ta.title.c_str(), + SectionType::Anchor,0,m_tagName.c_str()); e->anchors.push_back(si); } else @@ -1347,27 +1312,28 @@ void TagFileParser::buildLists(const std::shared_ptr<Entry> &root) const TagFileInfo *tfi = TagFileInfo::get(comp); std::shared_ptr<Entry> fe = std::make_shared<Entry>(); - fe->section = guessSection(tfi->name); - fe->name = tfi->name; + fe->section = guessSection(tfi->name.c_str()); + fe->name = tfi->name.c_str(); 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); + std::string fullName = m_tagName+":"+tfi->path+stripPath(tfi->name).str(); 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) }; + std::string tagid = m_tagName+":"+tfi->path; + std::unique_ptr<FileDef> fd { createFileDef(tagid.c_str(), + tfi->name.c_str(),m_tagName.c_str(), + tfi->filename.c_str()) }; FileName *mn; - if ((mn=Doxygen::inputNameLinkedMap->find(tfi->name))) + if ((mn=Doxygen::inputNameLinkedMap->find(tfi->name.c_str()))) { mn->push_back(std::move(fd)); } else { - mn = Doxygen::inputNameLinkedMap->add(tfi->name,fullName); + mn = Doxygen::inputNameLinkedMap->add(tfi->name.c_str(),fullName.c_str()); mn->push_back(std::move(fd)); } buildMemberList(fe,tfi->members); @@ -1451,7 +1417,7 @@ void TagFileParser::buildLists(const std::shared_ptr<Entry> &root) [&](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)); + (*i)->groups.push_back(Grouping(tgi->name.c_str(),Grouping::GROUPING_INGROUP)); } } } @@ -1465,7 +1431,7 @@ void TagFileParser::buildLists(const std::shared_ptr<Entry> &root) const TagPageInfo *tpi = TagPageInfo::get(comp); std::shared_ptr<Entry> pe = std::make_shared<Entry>(); - bool isIndex = (stripExtensionGeneral(tpi->filename,getFileNameExtension(tpi->filename))=="index"); + bool isIndex = (stripExtensionGeneral(tpi->filename.c_str(),getFileNameExtension(tpi->filename.c_str()))=="index"); pe->section = isIndex ? Entry::MAINPAGEDOC_SEC : Entry::PAGEDOC_SEC; pe->name = tpi->name; pe->args = tpi->title; @@ -1486,7 +1452,7 @@ void TagFileParser::addIncludes() { 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); + FileName *fn = Doxygen::inputNameLinkedMap->find(tfi->name.c_str()); if (fn) { for (const auto &fd : *fn) @@ -1498,7 +1464,7 @@ void TagFileParser::addIncludes() for (const auto &ii : tfi->includes) { //printf("ii->name='%s'\n",ii->name.data()); - FileName *ifn = Doxygen::inputNameLinkedMap->find(ii.name); + FileName *ifn = Doxygen::inputNameLinkedMap->find(ii.name.c_str()); ASSERT(ifn!=0); if (ifn) { @@ -1508,7 +1474,7 @@ void TagFileParser::addIncludes() // ifd->getOutputFileBase().data(),ii->id.data()); if (ifd->getOutputFileBase()==QCString(ii.id)) { - fd->addIncludeDependency(ifd.get(),ii.text,ii.isLocal,ii.isImported); + fd->addIncludeDependency(ifd.get(),ii.text.c_str(),ii.isLocal,ii.isImported); } } } @@ -1522,18 +1488,19 @@ void TagFileParser::addIncludes() void parseTagFile(const std::shared_ptr<Entry> &root,const char *fullName) { - QFileInfo fi(fullName); - if (!fi.exists()) return; - TagFileParser handler( fullName ); // tagName - handler.setFileName(fullName); - TagFileErrorHandler errorHandler; - QFile xmlFile( fullName ); - QXmlInputSource source( xmlFile ); - QXmlSimpleReader reader; - reader.setContentHandler( &handler ); - reader.setErrorHandler( &errorHandler ); - reader.parse( source ); - handler.buildLists(root); - handler.addIncludes(); - //handler.dump(); + TagFileParser tagFileParser(fullName); + QCString inputStr = fileToString(fullName); + XMLHandlers handlers; + // connect the generic events handlers of the XML parser to the specific handlers of the tagFileParser object + handlers.startDocument = [&tagFileParser]() { tagFileParser.startDocument(); }; + handlers.startElement = [&tagFileParser](const std::string &name,const XMLHandlers::Attributes &attrs) { tagFileParser.startElement(name,attrs); }; + handlers.endElement = [&tagFileParser](const std::string &name) { tagFileParser.endElement(name); }; + handlers.characters = [&tagFileParser](const std::string &chars) { tagFileParser.characters(chars); }; + handlers.error = [&tagFileParser](const std::string &fileName,int lineNr,const std::string &msg) { tagFileParser.error(fileName,lineNr,msg); }; + XMLParser parser(handlers); + tagFileParser.setDocumentLocator(&parser); + parser.parse(fullName,inputStr); + tagFileParser.buildLists(root); + tagFileParser.addIncludes(); + //tagFileParser.dump(); } diff --git a/src/template.cpp b/src/template.cpp index 66347c4..58188fe 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -338,7 +338,7 @@ int TemplateList::release() uint TemplateList::count() const { - return p->elems.size(); + return static_cast<uint>(p->elems.size()); } void TemplateList::append(const TemplateVariant &v) diff --git a/src/to_c_cmd.py b/src/to_c_cmd.py deleted file mode 100755 index 52785f1..0000000 --- a/src/to_c_cmd.py +++ /dev/null @@ -1,8 +0,0 @@ -# place " at begin of each line -# escape existing '\' and '"' -# remove \n at the end of the line (sometimes the last line does not have a \n -# so we cannot do a replacement with some other text) -# place an escaped \n and " at the end of each line -import sys -for line in sys.stdin: - sys.stdout.write('"' + line.replace('\\','\\\\').replace('"','\\"').replace('\n','') + '\\n"\n') diff --git a/src/tooltip.cpp b/src/tooltip.cpp index 8cc1f87..f8222d7 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.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,11 @@ * */ -#include <qdict.h> +#include <map> +#include <memory> +#include <unordered_map> +#include <string> +#include <mutex> #include "tooltip.h" #include "definition.h" @@ -23,37 +27,33 @@ #include "doxygen.h" #include "config.h" -class TooltipManager::Private +static std::mutex g_tooltipLock; + +struct TooltipData { - public: - Private() : tooltipInfo(10007) {} - QDict<Definition> tooltipInfo; + std::map<std::string,const Definition*> tooltipInfo; + std::set<std::string> tooltipWritten; }; -TooltipManager *TooltipManager::s_theInstance = 0; - -TooltipManager::TooltipManager() +class TooltipManager::Private { - p = new Private; -} + public: + std::unordered_map<int, std::unique_ptr<TooltipData> > tooltips; + std::unique_ptr<TooltipData> &getTooltipData(int id); +}; -TooltipManager::~TooltipManager() +TooltipManager &TooltipManager::instance() { - delete p; + static TooltipManager s_instance; + return s_instance; } -TooltipManager *TooltipManager::instance() +TooltipManager::TooltipManager() : p(std::make_unique<Private>()) { - if (!s_theInstance) - { - s_theInstance = new TooltipManager; - } - return s_theInstance; } -void TooltipManager::clearTooltips() +TooltipManager::~TooltipManager() { - p->tooltipInfo.clear(); } static QCString escapeId(const char *s) @@ -68,10 +68,22 @@ static QCString escapeId(const char *s) return res; } -void TooltipManager::addTooltip(const Definition *d) +std::unique_ptr<TooltipData> &TooltipManager::Private::getTooltipData(int id) { - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + std::lock_guard<std::mutex> lock(g_tooltipLock); + auto it = tooltips.insert(std::make_pair(id,std::make_unique<TooltipData>())).first; + return it->second; +} + +void TooltipManager::addTooltip(CodeOutputInterface &ol,const Definition *d) +{ + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); if (!sourceTooltips) return; + int outputId = ol.id(); + if (outputId==0) return; + + auto &ttd = p->getTooltipData(outputId); + QCString id = d->getOutputFileBase(); int i=id.findRev('/'); if (i!=-1) @@ -85,48 +97,57 @@ void TooltipManager::addTooltip(const Definition *d) id+="_"+anc; } id = "a" + id; - if (p->tooltipInfo.find(id)==0) - { - p->tooltipInfo.insert(id,d); - } + ttd->tooltipInfo.insert(std::make_pair(id.str(),d)); + //printf("%p: addTooltip(%s) ol=%d\n",this,id.data(),ol.id()); } void TooltipManager::writeTooltips(CodeOutputInterface &ol) { - QDictIterator<Definition> di(p->tooltipInfo); - Definition *d; - for (di.toFirst();(d=di.current());++di) + int outputId = ol.id(); // get unique identifier per output file + if (outputId==0) return; // not set => no HTML output + auto it = p->tooltips.find(outputId); // see if we have tooltips for this file + if (it!=p->tooltips.end()) { - DocLinkInfo docInfo; - docInfo.name = d->qualifiedName(); - docInfo.ref = d->getReference(); - docInfo.url = d->getOutputFileBase(); - docInfo.anchor = d->anchor(); - SourceLinkInfo defInfo; - if (d->getBodyDef() && d->getStartBodyLine()!=-1) - { - defInfo.file = d->getBodyDef()->name(); - defInfo.line = d->getStartBodyLine(); - defInfo.url = d->getSourceFileBase(); - defInfo.anchor = d->getSourceAnchor(); - } - SourceLinkInfo declInfo; // TODO: fill in... - QCString decl; - if (d->definitionType()==Definition::TypeMember) + auto &ttd = it->second; + for (const auto &kv : ttd->tooltipInfo) { - MemberDef *md = dynamic_cast<MemberDef*>(d); - if (!md->isAnonymous()) + if (ttd->tooltipWritten.find(kv.first)==ttd->tooltipWritten.end()) // only write tooltips once { - decl = md->declaration(); + //printf("%p: writeTooltips(%s) ol=%d\n",this,kv.first.c_str(),ol.id()); + const Definition *d = kv.second; + DocLinkInfo docInfo; + docInfo.name = d->qualifiedName(); + docInfo.ref = d->getReference(); + docInfo.url = d->getOutputFileBase(); + docInfo.anchor = d->anchor(); + SourceLinkInfo defInfo; + if (d->getBodyDef() && d->getStartBodyLine()!=-1) + { + defInfo.file = d->getBodyDef()->name(); + defInfo.line = d->getStartBodyLine(); + defInfo.url = d->getSourceFileBase(); + defInfo.anchor = d->getSourceAnchor(); + } + SourceLinkInfo declInfo; // TODO: fill in... + QCString decl; + if (d->definitionType()==Definition::TypeMember) + { + const MemberDef *md = toMemberDef(d); + if (!md->isAnonymous()) + { + decl = md->declaration(); + } + } + ol.writeTooltip(kv.first.c_str(), // id + docInfo, // symName + decl, // decl + d->briefDescriptionAsTooltip(), // desc + defInfo, + declInfo + ); + ttd->tooltipWritten.insert(kv.first); } } - ol.writeTooltip(di.currentKey(), // id - docInfo, // symName - decl, // decl - d->briefDescriptionAsTooltip(), // desc - defInfo, - declInfo - ); } } diff --git a/src/tooltip.h b/src/tooltip.h index 170ea3c..acdacb4 100644 --- a/src/tooltip.h +++ b/src/tooltip.h @@ -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,23 +15,28 @@ #ifndef TOOLTIP_H #define TOOLTIP_H +#include <memory> + class Definition; class CodeOutputInterface; +//! Class that manages the tooltips for a source file class TooltipManager { public: - static TooltipManager *instance(); - void clearTooltips(); - void addTooltip(const Definition *d); + static TooltipManager &instance(); + ~TooltipManager(); + + /** add a tooltip for a given symbol definition */ + void addTooltip(CodeOutputInterface &ol,const Definition *d); + + /** write the list of all collected tooltip to the given outputs */ void writeTooltips(CodeOutputInterface &ol); private: - class Private; - Private *p; TooltipManager(); - ~TooltipManager(); - static TooltipManager *s_theInstance; + class Private; + std::unique_ptr<Private> p; }; #endif diff --git a/src/translator_br.h b/src/translator_br.h index 5be0282..29a0e20 100644 --- a/src/translator_br.h +++ b/src/translator_br.h @@ -267,6 +267,10 @@ class TranslatorBrazilian : public TranslatorAdapter_1_8_19 { return "Aqui estão as estruturas de dados, uniões e suas respectivas descrições:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Aqui estão as classes e suas respectivas descrições:"; + } else { return "Aqui estão as classes, estruturas, uniões e interfaces e suas respectivas descrições:"; diff --git a/src/translator_ca.h b/src/translator_ca.h index a608ff0..7a7e79a 100644 --- a/src/translator_ca.h +++ b/src/translator_ca.h @@ -251,6 +251,10 @@ class TranslatorCatalan : public TranslatorAdapter_1_8_0 { return "Aquestes són les estructures de dades acompanyades amb breus descripcions:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Aquestes són les classes acompanyades amb breus descripcions:"; + } else { return "Aquestes són les classes, estructures, " diff --git a/src/translator_de.h b/src/translator_de.h index 63b0802..be51653 100644 --- a/src/translator_de.h +++ b/src/translator_de.h @@ -348,13 +348,17 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 { if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - return "Hier folgt die Aufzählung aller Datenstrukturen " - "mit einer Kurzbeschreibung:"; + return "Hier folgt die Aufzählung aller Datenstrukturen " + "mit einer Kurzbeschreibung:"; + } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Hier folgt die Aufzählung aller Klassen mit einer Kurzbeschreibung:"; } else { - return "Hier folgt die Aufzählung aller Klassen, Strukturen, " - "Varianten und Schnittstellen mit einer Kurzbeschreibung:"; + return "Hier folgt die Aufzählung aller Klassen, Strukturen, " + "Varianten und Schnittstellen mit einer Kurzbeschreibung:"; } } diff --git a/src/translator_dk.h b/src/translator_dk.h index 2e9f7d0..fa1db9a 100644 --- a/src/translator_dk.h +++ b/src/translator_dk.h @@ -284,6 +284,8 @@ class TranslatorDanish : public TranslatorAdapter_1_8_0 if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { return "Her er datastrukturerne med korte beskrivelser:"; + } else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) { + return "Her er klasserne med korte beskrivelser:"; } else { return "Her er klasserne, datastrukturerne, " "unionerne og grænsefladerne med korte beskrivelser:"; diff --git a/src/translator_eo.h b/src/translator_eo.h index 3ab9f8a..4ae6ee9 100644 --- a/src/translator_eo.h +++ b/src/translator_eo.h @@ -252,6 +252,10 @@ class TranslatorEsperanto : public TranslatorAdapter_1_8_4 { return "Jen datumstrukturoj kun mallongaj priskriboj:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Jen la klasoj kun mallongaj priskriboj:"; + } else { return "Jen la klasoj, strukturoj, kunigoj kaj interfacoj " diff --git a/src/translator_es.h b/src/translator_es.h index e4b35f3..554c487 100644 --- a/src/translator_es.h +++ b/src/translator_es.h @@ -243,6 +243,10 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15 { return "Lista de estructuras con una breve descripción:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Lista de las clases con una breve descripción:"; + } else { return "Lista de las clases, estructuras, " diff --git a/src/translator_fi.h b/src/translator_fi.h index bc6cbd9..dd2d38c 100644 --- a/src/translator_fi.h +++ b/src/translator_fi.h @@ -311,6 +311,11 @@ class TranslatorFinnish : public TranslatorAdapter_1_6_0 { return "Tässä ovat tietueet lyhyen selitteen kanssa:"; // "Here are the data structures with brief descriptions:" } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Tässä ovat luokat " // "Here are the classes + "lyhyen selitteen kanssa:"; // "with brief descriptions:" + } else { return "Tässä ovat luokat, tietueet ja " // "Here are the classes, structs and " diff --git a/src/translator_gr.h b/src/translator_gr.h index c4af814..a0511b7 100644 --- a/src/translator_gr.h +++ b/src/translator_gr.h @@ -247,6 +247,10 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 { return "Ακολουθούν οι δομές δεδομένων με σύντομες περιγραφές:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Ακολουθούν οι κλάσεις με σύντομες περιγραφές:"; + } else { return "Ακολουθούν οι κλάσεις, οι δομές, " diff --git a/src/translator_hu.h b/src/translator_hu.h index f7d9788..ae2e169 100644 --- a/src/translator_hu.h +++ b/src/translator_hu.h @@ -276,6 +276,10 @@ class TranslatorHungarian : public TranslatorAdapter_1_8_15 { return "Az összes adatszerkezet listája rövid leírásokkal:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Az összes osztály listája rövid leírásokkal:"; + } else { return "Az összes osztály, struktúra, unió és interfész " diff --git a/src/translator_id.h b/src/translator_id.h index 05d36ee..4b5626a 100644 --- a/src/translator_id.h +++ b/src/translator_id.h @@ -234,6 +234,10 @@ class TranslatorIndonesian : public TranslatorAdapter_1_8_0 { return "Berikut ini daftar struktur data, dengan penjelasan singkat:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Berikut ini daftar kelas, dengan penjelasan singkat:"; + } else { return "Berikut ini daftar kelas, struct, union, dan interface, dengan penjelasan singkat:"; diff --git a/src/translator_it.h b/src/translator_it.h index f7f3534..4b12dae 100644 --- a/src/translator_it.h +++ b/src/translator_it.h @@ -291,6 +291,10 @@ class TranslatorItalian : public TranslatorAdapter_1_8_15 { return "Queste sono le strutture dati con una loro breve descrizione:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Queste sono le classi con una loro breve descrizione:"; + } else { return "Queste sono le classi, le struct, le union e le interfacce con una loro breve descrizione:"; diff --git a/src/translator_lt.h b/src/translator_lt.h index b491080..1be20d2 100644 --- a/src/translator_lt.h +++ b/src/translator_lt.h @@ -241,6 +241,10 @@ class TranslatorLithuanian : public TranslatorAdapter_1_4_6 { return "Duomenų struktūros su trumpais aprašymais:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Klasės su trumpais aprašymais:"; + } else { return "Klasės, struktūros, " diff --git a/src/translator_lv.h b/src/translator_lv.h index 36cd78a..8dcc45b 100644 --- a/src/translator_lv.h +++ b/src/translator_lv.h @@ -256,6 +256,10 @@ class TranslatorLatvian : public TranslatorAdapter_1_8_4 { return "Šeit ir visas datu struktūras ar īsu aprakstu:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Šeit ir visas klases ar īsu aprakstu:"; + } else { return "Šeit ir visas klases, struktūras, " diff --git a/src/translator_mk.h b/src/translator_mk.h index ea5c3c8..97a55dc 100644 --- a/src/translator_mk.h +++ b/src/translator_mk.h @@ -236,6 +236,10 @@ class TranslatorMacedonian : public TranslatorAdapter_1_6_0 { return "Список на структури со кратки описи:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Список на класи со кратки описи:"; + } else { return "Список на класи, структури, унии и интерфејси " diff --git a/src/translator_nl.h b/src/translator_nl.h index 07e90ae..413d353 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -111,8 +111,22 @@ class TranslatorDutch : public Translator return result; } QCString trCompoundListDescription() - { return "Hieronder volgen de klassen, structs en " - "unions met voor elk een korte beschrijving:"; + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Hieronder volgen de structs " + "met voor elk een korte beschrijving:"; + } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Hieronder volgen de klassen " + "met voor elk een korte beschrijving:"; + } + else + { + return "Hieronder volgen de klassen, structs en " + "unions met voor elk een korte beschrijving:"; + } } QCString trCompoundMembersDescription(bool extractAll) { diff --git a/src/translator_no.h b/src/translator_no.h index 1dc331a..dee96d0 100755 --- a/src/translator_no.h +++ b/src/translator_no.h @@ -255,6 +255,10 @@ class TranslatorNorwegian : public TranslatorAdapter_1_4_6 { return "Her er datastrukturene med korte beskrivelser:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Her er klasser med korte beskrivelser:"; + } else { return "Her er klasser, struct'er, " diff --git a/src/translator_pl.h b/src/translator_pl.h index 096e9b0..86bc72b 100644 --- a/src/translator_pl.h +++ b/src/translator_pl.h @@ -234,6 +234,10 @@ class TranslatorPolish : public TranslatorAdapter_1_8_2 { return "Tutaj znajdują się struktury danych wraz z ich krótkimi opisami:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Tutaj znajdują się klasy wraz z ich krótkimi opisami:"; + } else { return "Tutaj znajdują się klasy, struktury, " diff --git a/src/translator_pt.h b/src/translator_pt.h index 0185aea..3456aad 100644 --- a/src/translator_pt.h +++ b/src/translator_pt.h @@ -267,6 +267,10 @@ class TranslatorPortuguese : public TranslatorAdapter_1_8_19 { return "Lista das estruturas de dados com uma breve descrição:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Lista de classes com uma breve descrição:"; + } else { return "Lista de classes, estruturas, uniões e interfaces com uma breve descrição:"; diff --git a/src/translator_ro.h b/src/translator_ro.h index edb82bf..01765a6 100644 --- a/src/translator_ro.h +++ b/src/translator_ro.h @@ -254,6 +254,10 @@ class TranslatorRomanian : public TranslatorAdapter_1_8_15 { return "Lista structurilor de date, cu scurte descrieri:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Lista claselor, cu scurte descrieri:"; + } else { return "Lista claselor, structurilor, uniunilor şi interfeţelor" diff --git a/src/translator_ru.h b/src/translator_ru.h index aafae90..3e3f7dc 100644 --- a/src/translator_ru.h +++ b/src/translator_ru.h @@ -212,6 +212,10 @@ class TranslatorRussian : public TranslatorAdapter_1_8_15 { return "Структуры данных с их кратким описанием."; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Классы с их кратким описанием."; + } else { return "Классы с их кратким описанием."; diff --git a/src/translator_sc.h b/src/translator_sc.h index 5217948..b8b5b42 100644 --- a/src/translator_sc.h +++ b/src/translator_sc.h @@ -254,6 +254,10 @@ class TranslatorSerbianCyrillic : public TranslatorAdapter_1_6_0 { return "Овде су структуре са кратким описима:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Овде су класе са кратким описима:"; + } else { return "Овде су класе, структуре, " diff --git a/src/translator_sr.h b/src/translator_sr.h index bfd32f6..cb080ea 100644 --- a/src/translator_sr.h +++ b/src/translator_sr.h @@ -235,6 +235,10 @@ class TranslatorSerbian : public TranslatorAdapter_1_6_0 { return "Spisak struktura sa kratkim opisima:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Spisak klasa sa kratkim opisima:"; + } else { return "Spisak klasa, struktura, unija i interfejsa sa kratkim opisima:"; diff --git a/src/translator_sv.h b/src/translator_sv.h index bc63870..853e265 100644 --- a/src/translator_sv.h +++ b/src/translator_sv.h @@ -353,6 +353,10 @@ class TranslatorSwedish : public Translator { return "Här följer datastrukturerna med korta beskrivningar:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Här följer klasserna med korta beskrivningar:"; + } else { return "Här följer klasserna, strukterna, unionerna och " diff --git a/src/translator_ua.h b/src/translator_ua.h index 2c5047c..e24136c 100644 --- a/src/translator_ua.h +++ b/src/translator_ua.h @@ -208,6 +208,10 @@ class TranslatorUkrainian : public TranslatorAdapter_1_8_4 { return "Структури даних з коротким описом." ; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Класи з коротким описом." ; + } else { return "Класи, структури, об'єднання та інтерфейси з коротким описом." ; diff --git a/src/translator_vi.h b/src/translator_vi.h index 50c0a01..272dedd 100644 --- a/src/translator_vi.h +++ b/src/translator_vi.h @@ -270,6 +270,10 @@ class TranslatorVietnamese : public TranslatorAdapter_1_6_0 { return "Đây là cấu trúc cơ sở dữ liệu với mô tả tóm tắt:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Đây là các classes với các mô tả tóm tắt:"; + } else { return "Đây là các classes, structs, " diff --git a/src/translator_za.h b/src/translator_za.h index fdf3e6a..8fc847e 100644 --- a/src/translator_za.h +++ b/src/translator_za.h @@ -235,6 +235,10 @@ class TranslatorAfrikaans : public TranslatorAdapter_1_6_0 { return " Data strukture met kort beskrywings:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Klasse met kort beskrywings:"; + } else { return "Klasse, structs, " diff --git a/src/util.cpp b/src/util.cpp index acc6098..e4916cd 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -31,7 +31,6 @@ #include <qfileinfo.h> #include <qdir.h> #include <qdatetime.h> -#include <qcache.h> #include "util.h" #include "message.h" @@ -68,6 +67,7 @@ #include "membergroup.h" #include "dirdef.h" #include "htmlentity.h" +#include "symbolresolver.h" #define ENABLE_TRACINGSUPPORT 0 @@ -96,6 +96,8 @@ #define REL_PATH_TO_ROOT "../../" +static const char *hex = "0123456789ABCDEF"; + //------------------------------------------------------------------------ // TextGeneratorOLImpl implementation //------------------------------------------------------------------------ @@ -229,7 +231,7 @@ QCString stripAnonymousNamespaceScope(const QCString &s) while ((i=getScopeFragment(s,p,&l))!=-1) { //printf("Scope fragment %s\n",s.mid(i,l).data()); - if (Doxygen::namespaceSDict->find(s.left(i+l))!=0) + if (Doxygen::namespaceLinkedMap->find(s.left(i+l))!=0) { if (s.at(i)!='@') { @@ -430,7 +432,8 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, // tmd->getOuterScope()->name().data(), mContext); if (tmd->isTypedef() /*&& tmd->getOuterScope()==resScope*/) { - int dist=isAccessibleFrom(resScope,0,tmd); + SymbolResolver resolver; + int dist=resolver.isAccessibleFrom(resScope,tmd); if (dist!=-1 && (md==0 || dist<minDist)) { md = tmd; @@ -477,7 +480,7 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, ClassDef *getClass(const char *n) { if (n==0 || n[0]=='\0') return 0; - return Doxygen::classSDict->find(n); + return Doxygen::classLinkedMap->find(n); } NamespaceDef *getResolvedNamespace(const char *name) @@ -498,706 +501,12 @@ NamespaceDef *getResolvedNamespace(const char *name) { warn_uncond("possible recursive namespace alias detected for %s!\n",name); } - return Doxygen::namespaceSDict->find(it->second.data()); + return Doxygen::namespaceLinkedMap->find(it->second.data()); } else { - return Doxygen::namespaceSDict->find(name); - } -} - -static QDict<MemberDef> g_resolvedTypedefs; -static QDict<Definition> g_visitedNamespaces; - -// forward declaration -static const ClassDef *getResolvedClassRec(const Definition *scope, - const FileDef *fileScope, - const char *n, - const MemberDef **pTypeDef, - QCString *pTemplSpec, - QCString *pResolvedType - ); -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope,const Definition *item, - const QCString &explicitScopePart); - -/*! Returns the class representing the value of the typedef represented by \a md - * 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, - const MemberDef *md, - const MemberDef **pMemType, - QCString *pTemplSpec, - QCString *pResolvedType, - const std::unique_ptr<ArgumentList> &actTemplParams) -{ - //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); - bool isCached = md->isTypedefValCached(); // value already cached - if (isCached) - { - //printf("Already cached %s->%s [%s]\n", - // md->name().data(), - // md->getCachedTypedefVal()?md->getCachedTypedefVal()->name().data():"<none>", - // md->getCachedResolvedTypedef()?md->getCachedResolvedTypedef().data():"<none>"); - - if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec(); - if (pResolvedType) *pResolvedType = md->getCachedResolvedTypedef(); - return md->getCachedTypedefVal(); - } - //printf("new typedef\n"); - QCString qname = md->qualifiedName(); - 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); - } - 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)==' ')) - { - ip--; - } - type=type.left(ip+1); - type.stripPrefix("const "); // strip leading "const" - type.stripPrefix("struct "); // strip leading "struct" - type.stripPrefix("union "); // strip leading "union" - int sp=0; - tl=type.length(); // length may have been changed - while (sp<tl && type.at(sp)==' ') sp++; - const MemberDef *memTypeDef = 0; - 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()) - { - result=newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec); - goto done; - } - else if (memTypeDef && memTypeDef->isEnumerate() && pMemType) - { - *pMemType = memTypeDef; - } - - //printf("type=%s result=%p\n",type.data(),result); - if (result==0) - { - // try unspecialized version if type is template - int si=type.findRev("::"); - int i=type.find('<'); - if (si==-1 && i!=-1) // typedef of a template => try the unspecialized version - { - if (pTemplSpec) *pTemplSpec = type.mid(i); - result = getResolvedClassRec(md->getOuterScope(),fileScope, - type.left(i),0,0,pResolvedType); - //printf("result=%p pRresolvedType=%s sp=%d ip=%d tl=%d\n", - // result,pResolvedType?pResolvedType->data():"<none>",sp,ip,tl); - } - else if (si!=-1) // A::B - { - i=type.find('<',si); - if (i==-1) // Something like A<T>::B => lookup A::B - { - i=type.length(); - } - else // Something like A<T>::B<S> => lookup A::B, spec=<S> - { - if (pTemplSpec) *pTemplSpec = type.mid(i); - } - result = getResolvedClassRec(md->getOuterScope(),fileScope, - stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0, - pResolvedType); - } - - //if (result) ip=si+sp+1; - } - -done: - if (pResolvedType) - { - if (result) - { - *pResolvedType=result->qualifiedName(); - //printf("*pResolvedType=%s\n",pResolvedType->data()); - if (sp>0) pResolvedType->prepend(typedefValue.left(sp)); - if (ip<tl-1) pResolvedType->append(typedefValue.right(tl-ip-1)); - } - else - { - *pResolvedType=typedefValue; - } - } - - // remember computed value for next time - 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); - //printf("==> %s (%s,%d)\n",result->name().data(),result->getDefFileName().data(),result->getDefLine()); - //printf("*pResolvedType=%s\n",pResolvedType?pResolvedType->data():"<none>"); - const_cast<MemberDef*>(md)->cacheTypedefVal(result, - pTemplSpec ? *pTemplSpec : QCString(), - pResolvedType ? *pResolvedType : QCString() - ); - } - - g_resolvedTypedefs.remove(qname); // remove from the trace list - - return result; -} - -/*! Substitutes a simple unqualified \a name within \a scope. Returns the - * value of the typedef or \a name if no typedef was found. - */ -static QCString substTypedef(const Definition *scope,const FileDef *fileScope,const QCString &name, - const MemberDef **pTypeDef=0) -{ - QCString result=name; - if (name.isEmpty()) return result; - - // lookup scope fragment in the symbol map - DefinitionIntf *di = Doxygen::symbolMap->find(name); - if (di==0) return result; // no matches - - MemberDef *bestMatch=0; - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // multi symbols - { - // search for the best match - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - int minDistance=10000; // init at "infinite" - for (dli.toFirst();(d=dli.current());++dli) // foreach definition - { - // only look at members - if (d->definitionType()==Definition::TypeMember) - { - // that are also typedefs - MemberDef *md = dynamic_cast<MemberDef *>(d); - if (md->isTypedef()) // d is a typedef - { - // test accessibility of typedef within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); - if (distance!=-1 && distance<minDistance) - // definition is accessible and a better match - { - minDistance=distance; - bestMatch = md; - } - } - } - } - } - else if (di->definitionType()==DefinitionIntf::TypeMember) // single symbol - { - Definition *d = (Definition*)di; - // that are also typedefs - MemberDef *md = dynamic_cast<MemberDef *>(di); - if (md->isTypedef()) // d is a typedef - { - // test accessibility of typedef within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); - if (distance!=-1) // definition is accessible - { - bestMatch = md; - } - } - } - 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; -} - -static const Definition *endOfPathIsUsedClass(const SDict<Definition> *cl,const QCString &localName) -{ - if (cl) - { - SDict<Definition>::Iterator cli(*cl); - Definition *cd; - for (cli.toFirst();(cd=cli.current());++cli) - { - if (cd->localName()==localName) - { - return cd; - } - } - } - return 0; -} - -/*! 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 - * is returned. - */ -static const Definition *followPath(const Definition *start,const FileDef *fileScope,const QCString &path) -{ - int is,ps; - int l; - const Definition *current=start; - ps=0; - //printf("followPath: start='%s' path='%s'\n",start?start->name().data():"<none>",path.data()); - // for each part of the explicit scope - while ((is=getScopeFragment(path,ps,&l))!=-1) - { - // try to resolve the part if it is a typedef - const MemberDef *typeDef=0; - QCString qualScopePart = substTypedef(current,fileScope,path.mid(is,l),&typeDef); - //printf(" qualScopePart=%s\n",qualScopePart.data()); - if (typeDef) - { - const ClassDef *type = newResolveTypedef(fileScope,typeDef); - if (type) - { - //printf("Found type %s\n",type->name().data()); - return type; - } - } - const Definition *next = current->findInnerCompound(qualScopePart); - //printf("++ Looking for %s inside %s result %s\n", - // qualScopePart.data(), - // current->name().data(), - // next?next->name().data():"<null>"); - if (next==0) // failed to follow the path - { - //printf("==> next==0!\n"); - if (current->definitionType()==Definition::TypeNamespace) - { - next = endOfPathIsUsedClass( - (dynamic_cast<const NamespaceDef *>(current))->getUsedClasses(),qualScopePart); - } - else if (current->definitionType()==Definition::TypeFile) - { - next = endOfPathIsUsedClass( - (dynamic_cast<const FileDef *>(current))->getUsedClasses(),qualScopePart); - } - current = next; - if (current==0) break; - } - else // continue to follow scope - { - current = next; - //printf("==> current = %p\n",current); - } - ps=is+l; - } - //printf("followPath(start=%s,path=%s) result=%s\n", - // start->name().data(),path.data(),current?current->name().data():"<null>"); - return current; // path could be followed -} - -bool accessibleViaUsingClass(const SDict<Definition> *cl, - const FileDef *fileScope, - const Definition *item, - const QCString &explicitScopePart="" - ) -{ - //printf("accessibleViaUsingClass(%p)\n",cl); - if (cl) // see if the class was imported via a using statement - { - SDict<Definition>::Iterator cli(*cl); - Definition *ucd; - bool explicitScopePartEmpty = explicitScopePart.isEmpty(); - for (cli.toFirst();(ucd=cli.current());++cli) - { - //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; - //printf("Try via used class done\n"); - } + return Doxygen::namespaceLinkedMap->find(name); } - return FALSE; -} - -bool accessibleViaUsingNamespace(const NamespaceSDict *nl, - const FileDef *fileScope, - const Definition *item, - const QCString &explicitScopePart="") -{ - static QDict<void> visitedDict; - if (nl) // check used namespaces for the class - { - NamespaceSDict::Iterator nli(*nl); - NamespaceDef *und; - int count=0; - for (nli.toFirst();(und=nli.current());++nli,count++) - { - //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) - { - //printf("] found it\n"); - return TRUE; - } - if (item->getLanguage()==SrcLangExt_Cpp) - { - QCString key=und->name(); - if (und->getUsedNamespaces() && visitedDict.find(key)==0) - { - visitedDict.insert(key,(void *)0x08); - - if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart)) - { - //printf("] found it via recursion\n"); - return TRUE; - } - - visitedDict.remove(key); - } - } - //printf("] Try via used namespace done\n"); - } - } - return FALSE; -} - -const int MAX_STACK_SIZE = 1000; - -/** Helper class representing the stack of items considered while resolving - * the scope. - */ -class AccessStack -{ - public: - AccessStack() : m_index(0) {} - void push(const Definition *scope,const FileDef *fileScope,const Definition *item) - { - if (m_index<MAX_STACK_SIZE) - { - m_elements[m_index].scope = scope; - m_elements[m_index].fileScope = fileScope; - m_elements[m_index].item = item; - m_index++; - } - } - void push(const Definition *scope,const FileDef *fileScope,const Definition *item,const QCString &expScope) - { - if (m_index<MAX_STACK_SIZE) - { - m_elements[m_index].scope = scope; - m_elements[m_index].fileScope = fileScope; - m_elements[m_index].item = item; - m_elements[m_index].expScope = expScope; - m_index++; - } - } - void pop() - { - if (m_index>0) m_index--; - } - bool find(const Definition *scope,const FileDef *fileScope, const Definition *item) - { - int i=0; - for (i=0;i<m_index;i++) - { - AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item) - { - return TRUE; - } - } - return FALSE; - } - bool find(const Definition *scope,const FileDef *fileScope, const Definition *item,const QCString &expScope) - { - int i=0; - 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) - { - return TRUE; - } - } - return FALSE; - } - - private: - /** Element in the stack. */ - struct AccessElem - { - const Definition *scope; - const FileDef *fileScope; - const Definition *item; - QCString expScope; - }; - int m_index; - AccessElem m_elements[MAX_STACK_SIZE]; -}; - -/* Returns the "distance" (=number of levels up) from item to scope, or -1 - * if item in not inside scope. - */ -int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item) -{ - //printf("<isAccessibleFrom(scope=%s,item=%s itemScope=%s)\n", - // scope->name().data(),item->name().data(),item->getOuterScope()->name().data()); - - static AccessStack accessStack; - if (accessStack.find(scope,fileScope,item)) - { - return -1; - } - accessStack.push(scope,fileScope,item); - - int result=0; // assume we found it - int i; - - Definition *itemScope=item->getOuterScope(); - 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 = - (item->definitionType()==Definition::TypeClass && // a nested class - 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) - ); - - if (itemScope==scope || memberAccessibleFromScope || nestedClassInsideBaseClass) - { - //printf("> found it\n"); - if (nestedClassInsideBaseClass) result++; // penalty for base class to prevent - // this is preferred over nested class in this class - // see bug 686956 - } - else if (scope==Doxygen::globalScope) - { - if (fileScope) - { - SDict<Definition> *cl = fileScope->getUsedClasses(); - if (accessibleViaUsingClass(cl,fileScope,item)) - { - //printf("> found via used class\n"); - goto done; - } - NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) - { - //printf("> found via used namespace\n"); - goto done; - } - } - //printf("> reached global scope\n"); - result=-1; // not found in path to globalScope - } - else // keep searching - { - // check if scope is a namespace, which is using other classes and namespaces - if (scope->definitionType()==Definition::TypeNamespace) - { - 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)) - { - //printf("> found via used class\n"); - goto done; - } - const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) - { - //printf("> found via used namespace\n"); - goto done; - } - } - // repeat for the parent scope - i=isAccessibleFrom(scope->getOuterScope(),fileScope,item); - //printf("> result=%d\n",i); - result= (i==-1) ? -1 : i+2; - } -done: - accessStack.pop(); - //Doxygen::lookupCache.insert(key,new int(result)); - return result; -} - - -/* Returns the "distance" (=number of levels up) from item to scope, or -1 - * if item in not in this scope. The explicitScopePart limits the search - * to scopes that match \a scope (or its parent scope(s)) plus the explicit part. - * Example: - * - * class A { public: class I {}; }; - * 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 - * (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 - * thus the result is 1. - */ -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope, - const Definition *item,const QCString &explicitScopePart) -{ - if (explicitScopePart.isEmpty()) - { - // handle degenerate case where there is no explicit scope. - return isAccessibleFrom(scope,fileScope,item); - } - - static AccessStack accessStack; - if (accessStack.find(scope,fileScope,item,explicitScopePart)) - { - return -1; - } - accessStack.push(scope,fileScope,item,explicitScopePart); - - - //printf(" <isAccessibleFromWithExpScope(%s,%s,%s)\n",scope?scope->name().data():"<global>", - // item?item->name().data():"<none>", - // explicitScopePart.data()); - int result=0; // assume we found it - const Definition *newScope = followPath(scope,fileScope,explicitScopePart); - if (newScope) // explicitScope is inside scope => newScope is the result - { - Definition *itemScope = item->getOuterScope(); - //printf(" scope traversal successful %s<->%s!\n",itemScope->name().data(),newScope->name().data()); - //if (newScope && newScope->definitionType()==Definition::TypeClass) - //{ - // ClassDef *cd = (ClassDef *)newScope; - // printf("---> Class %s: bases=%p\n",cd->name().data(),cd->baseClasses()); - //} - if (itemScope==newScope) // exact match of scopes => distance==0 - { - //printf("> found it\n"); - } - else if (itemScope && newScope && - itemScope->definitionType()==Definition::TypeClass && - newScope->definitionType()==Definition::TypeClass && - (dynamic_cast<const ClassDef*>(newScope))->isBaseClass(dynamic_cast<const ClassDef*>(itemScope),TRUE,0) - ) - { - // 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 - // class A { public: class I {} }; - // class B { public: class I {} }; - // will find A::I, so we still prefer a direct match and give this one a distance of 1 - result=1; - - //printf("scope(%s) is base class of newScope(%s)\n", - // scope->name().data(),newScope->name().data()); - } - else - { - int i=-1; - if (newScope->definitionType()==Definition::TypeNamespace) - { - g_visitedNamespaces.insert(newScope->name(),newScope); - // this part deals with the case where item is a class - // A::B::C but is explicit referenced as A::C, where B is imported - // in A via a using directive. - //printf("newScope is a namespace: %s!\n",newScope->name().data()); - const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(newScope); - const SDict<Definition> *cl = nscope->getUsedClasses(); - if (cl) - { - SDict<Definition>::Iterator cli(*cl); - const Definition *cd; - for (cli.toFirst();(cd=cli.current());++cli) - { - //printf("Trying for class %s\n",cd->name().data()); - if (cd==item) - { - //printf("> class is used in this scope\n"); - goto done; - } - } - } - const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (nl) - { - NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) - { - if (g_visitedNamespaces.find(nd->name())==0) - { - //printf("Trying for namespace %s\n",nd->name().data()); - i = isAccessibleFromWithExpScope(scope,fileScope,item,nd->name()); - if (i!=-1) - { - //printf("> found via explicit scope of used namespace\n"); - goto done; - } - } - } - } - } - // repeat for the parent scope - if (scope!=Doxygen::globalScope) - { - i = isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope, - item,explicitScopePart); - } - //printf(" | result=%d\n",i); - result = (i==-1) ? -1 : i+2; - } - } - else // failed to resolve explicitScope - { - //printf(" failed to resolve: scope=%s\n",scope->name().data()); - if (scope->definitionType()==Definition::TypeNamespace) - { - const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); - const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) - { - //printf("> found in used namespace\n"); - goto done; - } - } - if (scope==Doxygen::globalScope) - { - if (fileScope) - { - const NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) - { - //printf("> found in used namespace\n"); - goto done; - } - } - //printf("> not found\n"); - result=-1; - } - else // continue by looking into the parent scope - { - int i=isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope, - item,explicitScopePart); - //printf("> result=%d\n",i); - result= (i==-1) ? -1 : i+2; - } - } - -done: - //printf(" > result=%d\n",result); - accessStack.pop(); - //Doxygen::lookupCache.insert(key,new int(result)); - return result; } int computeQualifiedIndex(const QCString &name) @@ -1206,412 +515,6 @@ int computeQualifiedIndex(const QCString &name) return name.findRev("::",i==-1 ? name.length() : i); } -static void getResolvedSymbol(const Definition *scope, - const FileDef *fileScope, - Definition *d, - const QCString &explicitScopePart, - const std::unique_ptr<ArgumentList> &actTemplParams, - int &minDistance, - const ClassDef *&bestMatch, - const MemberDef *&bestTypedef, - QCString &bestTemplSpec, - QCString &bestResolvedType - ) -{ - //printf(" => found type %x name=%s d=%p\n", - // d->definitionType(),d->name().data(),d); - - // 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()) - ) - ) - { - g_visitedNamespaces.clear(); - // test accessibility of definition within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); - //printf(" %s; distance %s (%p) is %d\n",scope->name().data(),d->name().data(),d,distance); - if (distance!=-1) // definition is accessible - { - // see if we are dealing with a class or a typedef - if (d->definitionType()==Definition::TypeClass) // d is a class - { - 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 - // argument - { - //printf("is not a templ arg\n"); - if (distance<minDistance) // found a definition that is "closer" - { - minDistance=distance; - bestMatch = cd; - bestTypedef = 0; - bestTemplSpec.resize(0); - bestResolvedType = cd->qualifiedName(); - } - else if (distance==minDistance && - fileScope && bestMatch && - fileScope->getUsedNamespaces() && - d->getOuterScope()->definitionType()==Definition::TypeNamespace && - bestMatch->getOuterScope()==Doxygen::globalScope - ) - { - // in case the distance is equal it could be that a class X - // is defined in a namespace and in the global scope. When searched - // in the global scope the distance is 0 in both cases. We have - // to choose one of the definitions: we choose the one in the - // namespace if the fileScope imports namespaces and the definition - // found was in a namespace while the best match so far isn't. - // Just a non-perfect heuristic but it could help in some situations - // (kdecore code is an example). - minDistance=distance; - bestMatch = cd; - bestTypedef = 0; - bestTemplSpec.resize(0); - bestResolvedType = cd->qualifiedName(); - } - } - else - { - //printf(" is a template argument!\n"); - } - } - else if (d->definitionType()==Definition::TypeMember) - { - MemberDef *md = dynamic_cast<MemberDef *>(d); - //printf(" member isTypedef()=%d\n",md->isTypedef()); - if (md->isTypedef()) // d is a typedef - { - QCString args=md->argsString(); - if (args.isEmpty()) // do not expand "typedef t a[4];" - { - //printf(" found typedef!\n"); - - // we found a symbol at this distance, but if it didn't - // resolve to a class, we still have to make sure that - // something at a greater distance does not match, since - // that symbol is hidden by this one. - if (distance<minDistance) - { - QCString spec; - QCString type; - minDistance=distance; - const MemberDef *enumType = 0; - const ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type,actTemplParams); - if (cd) // type resolves to a class - { - //printf(" bestTypeDef=%p spec=%s type=%s\n",md,spec.data(),type.data()); - bestMatch = cd; - bestTypedef = md; - bestTemplSpec = spec; - bestResolvedType = type; - } - else if (enumType) // type resolves to a enum - { - //printf(" is enum\n"); - bestMatch = 0; - bestTypedef = enumType; - bestTemplSpec = ""; - bestResolvedType = enumType->qualifiedName(); - } - else if (md->isReference()) // external reference - { - bestMatch = 0; - bestTypedef = md; - bestTemplSpec = spec; - bestResolvedType = type; - } - else - { - bestMatch = 0; - bestTypedef = md; - bestTemplSpec.resize(0); - bestResolvedType.resize(0); - //printf(" no match\n"); - } - } - else - { - //printf(" not the best match %d min=%d\n",distance,minDistance); - } - } - else - { - //printf(" not a simple typedef\n") - } - } - else if (md->isEnumerate()) - { - if (distance<minDistance) - { - minDistance=distance; - bestMatch = 0; - bestTypedef = md; - bestTemplSpec = ""; - bestResolvedType = md->qualifiedName(); - } - } - } - } // if definition accessible - else - { - //printf(" Not accessible!\n"); - } - } // if definition is a class or member - //printf(" bestMatch=%p bestResolvedType=%s\n",bestMatch,bestResolvedType.data()); -} - -/* 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 - * resolving typedefs. - */ -static const ClassDef *getResolvedClassRec(const Definition *scope, - const FileDef *fileScope, - const char *n, - const MemberDef **pTypeDef, - QCString *pTemplSpec, - QCString *pResolvedType - ) -{ - //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); - std::unique_ptr<ArgumentList> actTemplParams; - if (!strippedTemplateParams.isEmpty()) // template part that was stripped - { - actTemplParams = stringToArgumentList(scope->getLanguage(),strippedTemplateParams); - } - - int qualifierIndex = computeQualifiedIndex(name); - //printf("name=%s qualifierIndex=%d\n",name.data(),qualifierIndex); - if (qualifierIndex!=-1) // qualified name - { - // split off the explicit scope part - explicitScopePart=name.left(qualifierIndex); - // todo: improve namespace alias substitution - replaceNamespaceAliases(explicitScopePart,explicitScopePart.length()); - name=name.mid(qualifierIndex+2); - } - - if (name.isEmpty()) - { - //printf("] empty name\n"); - return 0; // empty name - } - - //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 - // stripped from the key used in the symbolMap, so that is not needed here. - if (di==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() && - fileScope->getUsedNamespaces()->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 - // scope over an over again (especially for the linked source code generation) - // we use a cache to collect previous results. This is possible since the - // result of a lookup is deterministic. As the key we use the concatenated - // scope, the name to search for and the explicit scope prefix. The speedup - // achieved by this simple cache can be enormous. - int scopeNameLen = scope->name().length()+1; - int nameLen = name.length()+1; - int explicitPartLen = explicitScopePart.length(); - int fileScopeLen = hasUsingStatements ? 1+fileScope->absFilePath().length() : 0; - - // below is a more efficient coding of - // QCString key=scope->name()+"+"+name+"+"+explicitScopePart; - QCString key(scopeNameLen+nameLen+explicitPartLen+fileScopeLen+1); - char *p=key.rawData(); - qstrcpy(p,scope->name()); *(p+scopeNameLen-1)='+'; - p+=scopeNameLen; - qstrcpy(p,name); *(p+nameLen-1)='+'; - p+=nameLen; - qstrcpy(p,explicitScopePart); - p+=explicitPartLen; - - // 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 - // one of them). - if (hasUsingStatements) - { - // below is a more efficient coding of - // key+="+"+fileScope->name(); - *p++='+'; - qstrcpy(p,fileScope->absFilePath()); - p+=fileScopeLen-1; - } - *p='\0'; - - LookupInfo *pval=Doxygen::lookupCache->find(key); - //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()); - 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) - // printf("templSpec=%s\n",pTemplSpec->data()); - return pval->classDef; - } - else // not found yet; we already add a 0 to avoid the possibility of - // endless recursion. - { - Doxygen::lookupCache->insert(key,new LookupInfo); - } - - const ClassDef *bestMatch=0; - const MemberDef *bestTypedef=0; - QCString bestTemplSpec; - QCString bestResolvedType; - int minDistance=10000; // init at "infinite" - - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // not a unique name - { - //printf(" name is not unique\n"); - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - int count=0; - for (dli.toFirst();(d=dli.current());++dli,++count) // foreach definition - { - getResolvedSymbol(scope,fileScope,d,explicitScopePart,actTemplParams, - minDistance,bestMatch,bestTypedef,bestTemplSpec, - bestResolvedType); - } - } - else // unique name - { - //printf(" name is unique\n"); - Definition *d = (Definition *)di; - getResolvedSymbol(scope,fileScope,d,explicitScopePart,actTemplParams, - minDistance,bestMatch,bestTypedef,bestTemplSpec, - bestResolvedType); - } - - if (pTypeDef) - { - *pTypeDef = bestTypedef; - } - if (pTemplSpec) - { - *pTemplSpec = bestTemplSpec; - } - if (pResolvedType) - { - *pResolvedType = bestResolvedType; - } - //printf("getResolvedClassRec: bestMatch=%p pval->resolvedType=%s\n", - // bestMatch,bestResolvedType.data()); - - pval=Doxygen::lookupCache->find(key); - if (pval) - { - pval->classDef = bestMatch; - pval->typeDef = bestTypedef; - pval->templSpec = bestTemplSpec; - pval->resolvedType = bestResolvedType; - } - else - { - Doxygen::lookupCache->insert(key,new LookupInfo(bestMatch,bestTypedef,bestTemplSpec,bestResolvedType)); - } - //printf("] bestMatch=%s distance=%d\n", - // bestMatch?bestMatch->name().data():"<none>",minDistance); - //if (pTemplSpec) - // printf("templSpec=%s\n",pTemplSpec->data()); - return bestMatch; -} - -/* 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. - */ -const ClassDef *getResolvedClass(const Definition *scope, - const FileDef *fileScope, - const char *n, - const MemberDef **pTypeDef, - QCString *pTemplSpec, - bool mayBeUnlinkable, - bool mayBeHidden, - QCString *pResolvedType - ) -{ - static bool optimizeOutputVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - g_resolvedTypedefs.clear(); - if (scope==0 || - (scope->definitionType()!=Definition::TypeClass && - scope->definitionType()!=Definition::TypeNamespace - ) || - (scope->getLanguage()==SrcLangExt_Java && QCString(n).find("::")!=-1) - ) - { - scope=Doxygen::globalScope; - } - //printf("------------ getResolvedClass(scope=%s,file=%s,name=%s,mayUnlinkable=%d)\n", - // scope?scope->name().data():"<global>", - // fileScope?fileScope->name().data():"<none>", - // n, - // mayBeUnlinkable - // ); - const ClassDef *result; - if (optimizeOutputVhdl) - { - result = getClass(n); - } - else - { - result = getResolvedClassRec(scope,fileScope,n,pTypeDef,pTemplSpec,pResolvedType); - } - if (result==0) // for nested classes imported via tag files, the scope may not - // present, so we check the class name directly as well. - // See also bug701314 - { - result = getClass(n); - } - if (!mayBeUnlinkable && result && !result->isLinkable()) - { - if (!mayBeHidden || !result->isHidden()) - { - //printf("result was %s\n",result?result->name().data():"<none>"); - result=0; // don't link to artificial/hidden classes unless explicitly allowed - } - } - //printf("getResolvedClass(%s,%s)=%s\n",scope?scope->name().data():"<global>", - // n,result?result->name().data():"<none>"); - return result; -} - //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- @@ -1828,7 +731,7 @@ QCString removeRedundantWhiteSpace(const QCString &s) { if (nc != '=') // avoid splitting operator&= - { + { *dst++=' '; } } @@ -2058,8 +961,9 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, const GroupDef *gd=0; //printf("** Match word '%s'\n",matchWord.data()); - const MemberDef *typeDef=0; - cd=getResolvedClass(scope,fileScope,matchWord,&typeDef); + SymbolResolver resolver(fileScope); + cd=resolver.resolveClass(scope,matchWord); + const MemberDef *typeDef = resolver.getTypedef(); if (typeDef) // First look at typedef then class, see bug 584184. { //printf("Found typedef %s\n",typeDef->name().data()); @@ -2263,90 +1167,68 @@ QCString argListToString(const ArgumentList &al,bool useCanonicalType,bool showD 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.trailingReturnType().isEmpty()) result+=al.trailingReturnType(); if (al.pureSpecifier()) result+=" =0"; return removeRedundantWhiteSpace(result); } -QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang) +QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool includeDefault) { QCString result; if (al.empty()) return result; result="<"; - auto it = al.begin(); - while (it!=al.end()) + bool first=true; + for (const auto &a : al) { - Argument a = *it; - if (!a.name.isEmpty()) // add template argument name + if (a.defval.isEmpty() || includeDefault) { - if (a.type.left(4)=="out") // C# covariance + if (!first) result+=", "; + if (!a.name.isEmpty()) // add template argument name { - result+="out "; - } - else if (a.type.left(3)=="in") // C# contravariance - { - result+="in "; - } - if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) - { - result+=a.type+" "; + if (a.type.left(4)=="out") // C# covariance + { + result+="out "; + } + else if (a.type.left(3)=="in") // C# contravariance + { + result+="in "; + } + if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) + { + result+=a.type+" "; + } + result+=a.name; } - result+=a.name; - } - else // extract name from type - { - int i=a.type.length()-1; - while (i>=0 && isId(a.type.at(i))) i--; - if (i>0) + else // extract name from type { - result+=a.type.right(a.type.length()-i-1); - if (a.type.find("...")!=-1) + int i=a.type.length()-1; + while (i>=0 && isId(a.type.at(i))) i--; + if (i>0) + { + result+=a.type.right(a.type.length()-i-1); + if (a.type.find("...")!=-1) + { + result+="..."; + } + } + else // nothing found -> take whole name { - result+="..."; + result+=a.type; } } - else // nothing found -> take whole name + if (!a.typeConstraint.isEmpty() && lang==SrcLangExt_Java) { - result+=a.type; + result+=" extends "; // TODO: now Java specific, C# has where... + result+=a.typeConstraint; } + first=false; } - if (!a.typeConstraint.isEmpty() && lang==SrcLangExt_Java) - { - result+=" extends "; // TODO: now Java specific, C# has where... - result+=a.typeConstraint; - } - ++it; - if (it!=al.end()) result+=", "; } result+=">"; return removeRedundantWhiteSpace(result); } -// compute the HTML anchors for a list of members -void setAnchors(MemberList *ml) -{ - //int count=0; - if (ml==0) return; - MemberListIterator mli(*ml); - MemberDef *md; - for (;(md=mli.current());++mli) - { - if (!md->isReference()) - { - //QCString anchor; - //if (groupId==-1) - // anchor.sprintf("%c%d",id,count++); - //else - // anchor.sprintf("%c%d_%d",id,groupId,count++); - //if (cd) anchor.prepend(escapeCharsInString(cd->name(),FALSE)); - md->setAnchor(); - //printf("setAnchors(): Member %s outputFileBase=%s anchor %s result %s\n", - // md->name().data(),md->getOutputFileBase().data(),anchor.data(),md->anchor().data()); - } - } -} - //---------------------------------------------------------------------------- /*! takes the \a buf of the given length \a len and converts CR LF (DOS) @@ -2622,16 +1504,11 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) return -1; } int m=maxInheritanceDepth; - if (cd->baseClasses()) + for (const auto &bcdi : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcdi; - for (;(bcdi=bcli.current());++bcli) - { - int mc=minClassDistance(bcdi->classDef,bcd,level+1); - if (mc<m) m=mc; - if (m<0) break; - } + int mc=minClassDistance(bcdi.classDef,bcd,level+1); + if (mc<m) m=mc; + if (m<0) break; } return m; } @@ -2652,14 +1529,12 @@ Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd, err("Internal inconsistency: found class %s seem to have a recursive " "inheritance relation! Please send a bug report to doxygen@gmail.com\n",cd->name().data()); } - else if (cd->baseClasses()) + else if (prot!=Private) { - BaseClassListIterator bcli(*cd->baseClasses()); - const BaseClassDef *bcdi; - for (;(bcdi=bcli.current()) && prot!=Private;++bcli) + for (const auto &bcdi : cd->baseClasses()) { - Protection baseProt = classInheritedProtectionLevel(bcdi->classDef,bcd,bcdi->prot,level+1); - if (baseProt==Private) prot=Private; + Protection baseProt = classInheritedProtectionLevel(bcdi.classDef,bcd,bcdi.prot,level+1); + if (baseProt==Private) prot=Private; else if (baseProt==Protected) prot=Protected; } } @@ -2668,14 +1543,12 @@ exit: return prot; } -void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) +void trimBaseClassScope(const BaseClassList &bcl,QCString &s,int level=0) { //printf("trimBaseClassScope level=%d '%s'\n",level,s.data()); - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for (;(bcd=bcli.current());++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; //printf("Trying class %s\n",cd->name().data()); int spos=s.find(cd->name()+"::"); if (spos!=-1) @@ -2685,8 +1558,10 @@ void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) ); } //printf("base class '%s'\n",cd->name().data()); - if (cd->baseClasses()) + if (!cd->baseClasses().empty()) + { trimBaseClassScope(cd->baseClasses(),s,level+1); + } } } @@ -2877,7 +1752,6 @@ static QCString getCanonicalTypeForIdentifier( if (count>10) return word; // oops recursion QCString symName,result,templSpec,tmpName; - //DefinitionList *defList=0; if (tSpec && !tSpec->isEmpty()) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec)); @@ -2889,21 +1763,26 @@ static QCString getCanonicalTypeForIdentifier( { symName=word; } - //printf("getCanonicalTypeForIdentifier(%s,[%s->%s]) start\n", - // word.data(),tSpec?tSpec->data():"<none>",templSpec.data()); - - const ClassDef *cd = 0; - const MemberDef *mType = 0; - QCString ts; - QCString resolvedType; + //printf("getCanonicalTypeForIdentifier(%s d=%s fs=%s ,[%s->%s]) start\n", + // word.data(), + // d ? d->name().data() : "<null>",fs ? fs->name().data() : "<null>", + // tSpec?tSpec->data():"<none>",templSpec.data()); // lookup class / class template instance - cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE,TRUE,&resolvedType); + SymbolResolver resolver(fs); + const ClassDef *cd = resolver.resolveClass(d,word+templSpec,true,true); + const MemberDef *mType = resolver.getTypedef(); + QCString ts = resolver.getTemplateSpec(); + QCString resolvedType = resolver.getResolvedType(); + bool isTemplInst = cd && !templSpec.isEmpty(); if (!cd && !templSpec.isEmpty()) { // class template specialization not known, look up class template - cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE,TRUE,&resolvedType); + cd = resolver.resolveClass(d,word,true,true); + mType = resolver.getTypedef(); + ts = resolver.getTemplateSpec(); + resolvedType = resolver.getResolvedType(); } if (cd && cd->isUsedOnly()) cd=0; // ignore types introduced by usage relations @@ -2983,7 +1862,13 @@ static QCString getCanonicalTypeForIdentifier( //printf("word=%s typeString=%s\n",word.data(),mType->typeString()); if (word!=mType->typeString()) { - result = getCanonicalTypeForIdentifier(d,fs,mType->typeString(),tSpec,count+1); + QCString type = mType->typeString(); + if (type.startsWith("typename ")) + { + type.stripPrefix("typename "); + type = stripTemplateSpecifiersFromScope(type,FALSE); + } + result = getCanonicalTypeForIdentifier(d,fs,type,tSpec,count+1); } else { @@ -3036,7 +1921,6 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr //printf(" i=%d p=%d\n",i,p); if (i>pp) canType += type.mid(pp,i-pp); - QCString ct = getCanonicalTypeForIdentifier(d,fs,word,&templSpec); // in case the ct is empty it means that "word" represents scope "d" @@ -3107,9 +1991,9 @@ static bool matchArgument2( { //printf(">> match argument: %s::'%s|%s' (%s) <-> %s::'%s|%s' (%s)\n", // srcScope ? srcScope->name().data() : "", - // srcA->type.data(),srcA->name.data(),srcA->canType.data(), + // srcA.type.data(),srcA.name.data(),srcA.canType.data(), // dstScope ? dstScope->name().data() : "", - // dstA->type.data(),dstA->name.data(),dstA->canType.data()); + // dstA.type.data(),dstA.name.data(),dstA.canType.data()); //if (srcA->array!=dstA->array) // nomatch for char[] against char //{ @@ -3392,7 +2276,6 @@ static void findMembersWithSpecificName(const MemberName *mn, bool checkStatics, const FileDef *currentFile, bool checkCV, - const char *forceTagFile, QList<MemberDef> &members) { //printf(" Function with global scope name '%s' args='%s'\n", @@ -3421,7 +2304,7 @@ static void findMembersWithSpecificName(const MemberName *mn, Doxygen::globalScope,fd,argList_p.get(), checkCV); } - if (match && (forceTagFile==0 || md->getReference()==forceTagFile)) + if (match) { //printf("Found match!\n"); members.append(md); @@ -3462,8 +2345,7 @@ bool getDefs(const QCString &scName, const GroupDef *&gd, bool forceEmptyScope, const FileDef *currentFile, - bool checkCV, - const char *forceTagFile + bool checkCV ) { fd=0, md=0, cd=0, nd=0, gd=0; @@ -3526,12 +2408,15 @@ bool getDefs(const QCString &scName, className=mScope; } - const MemberDef *tmd=0; - const ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); + SymbolResolver resolver; + const ClassDef *fcd=resolver.resolveClass(Doxygen::globalScope,className); + const MemberDef *tmd=resolver.getTypedef(); + if (fcd==0 && className.find('<')!=-1) // try without template specifiers as well { QCString nameWithoutTemplates = stripTemplateSpecifiersFromScope(className,FALSE); - fcd=getResolvedClass(Doxygen::globalScope,0,nameWithoutTemplates,&tmd); + fcd=resolver.resolveClass(Doxygen::globalScope,nameWithoutTemplates); + tmd=resolver.getTypedef(); } //printf("Trying class scope %s: fcd=%p tmd=%p\n",className.data(),fcd,tmd); // todo: fill in correct fileScope! @@ -3559,7 +2444,7 @@ bool getDefs(const QCString &scName, //printf("match=%d\n",match); if (match) { - ClassDef *mcd=mmd->getClassDef(); + const ClassDef *mcd=mmd->getClassDef(); if (mcd) { int m=minClassDistance(fcd,mcd); @@ -3582,7 +2467,7 @@ bool getDefs(const QCString &scName, MemberDef *mmd = mmd_p.get(); //if (mmd->isLinkable()) //{ - ClassDef *mcd=mmd->getClassDef(); + const ClassDef *mcd=mmd->getClassDef(); //printf(" >Class %s found\n",mcd->name().data()); if (mcd) { @@ -3729,7 +2614,7 @@ bool getDefs(const QCString &scName, } //printf("Trying namespace %s\n",namespaceName.data()); if (!namespaceName.isEmpty() && - (fnd=Doxygen::namespaceSDict->find(namespaceName)) && + (fnd=Doxygen::namespaceLinkedMap->find(namespaceName)) && fnd->isLinkable() ) { @@ -3856,11 +2741,11 @@ bool getDefs(const QCString &scName, { QList<MemberDef> members; // search for matches with strict static checking - findMembersWithSpecificName(mn,args,TRUE,currentFile,checkCV,forceTagFile,members); + findMembersWithSpecificName(mn,args,TRUE,currentFile,checkCV,members); if (members.count()==0) // nothing found { // search again without strict static checking - findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,forceTagFile,members); + findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,members); } //printf("found %d members\n",members.count()); if (members.count()!=1 && args && !qstrcmp(args,"()")) @@ -3976,7 +2861,7 @@ static bool getScopeDefs(const char *docScope,const char *scope, { return TRUE; // class link written => quit } - else if ((nd=Doxygen::namespaceSDict->find(fullName)) && nd->isLinkable()) + else if ((nd=Doxygen::namespaceLinkedMap->find(fullName)) && nd->isLinkable()) { return TRUE; // namespace link written => quit } @@ -4364,7 +3249,7 @@ bool resolveLink(/* in */ const char *scName, // resAnchor=cd->anchor(); // return TRUE; // } - else if ((nd=Doxygen::namespaceSDict->find(linkRef))) + else if ((nd=Doxygen::namespaceLinkedMap->find(linkRef))) { *resContext=nd; return TRUE; @@ -4408,7 +3293,7 @@ bool generateLink(OutputDocInterface &od,const char *clName, compound->definitionType()==Definition::TypeGroup /* is group */ ) { - linkText=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link + linkText=(toGroupDef(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeFile) { @@ -4487,7 +3372,7 @@ struct FindFileCacheElem bool isAmbig; }; -static QCache<FindFileCacheElem> g_findFileDefCache(5000); +static Cache<std::string,FindFileCacheElem> g_findFileDefCache(5000); static std::mutex g_findFileDefMutex; @@ -4504,8 +3389,7 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) QCString key = addr; key+=n; - g_findFileDefCache.setAutoDelete(TRUE); - FindFileCacheElem *cachedResult = g_findFileDefCache.find(key); + FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str()); //printf("key=%s cachedResult=%p\n",key.data(),cachedResult); if (cachedResult) { @@ -4515,7 +3399,7 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) } else { - cachedResult = new FindFileCacheElem(0,FALSE); + cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(0,FALSE)); } QCString name=QDir::cleanDirPath(n).utf8(); @@ -4543,8 +3427,6 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) if (path.isEmpty() || isSamePath) { cachedResult->fileDef = fd.get(); - g_findFileDefCache.insert(key,cachedResult); - //printf("=1 ===> add to cache %p\n",fd); return fd.get(); } } @@ -4563,12 +3445,10 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) lastMatch=fd; } } - //printf(">1 ===> add to cache %p\n",fd); ambig=(count>1); cachedResult->isAmbig = ambig; cachedResult->fileDef = lastMatch; - g_findFileDefCache.insert(key,cachedResult); return lastMatch; } } @@ -4577,8 +3457,6 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) //printf("not found!\n"); } exit: - //printf("0 ===> add to cache %p: %s\n",cachedResult,n); - g_findFileDefCache.insert(key,cachedResult); //delete cachedResult; return 0; } @@ -4654,41 +3532,24 @@ int getPrefixIndex(const QCString &name) //---------------------------------------------------------------------------- -static void initBaseClassHierarchy(BaseClassList *bcl) -{ - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current(); ++bcli) - { - ClassDef *cd=bcli.current()->classDef; - if (cd->baseClasses()==0) // no base classes => new root - { - initBaseClassHierarchy(cd->baseClasses()); - } - cd->setVisited(FALSE); - } -} -//---------------------------------------------------------------------------- - bool classHasVisibleChildren(const ClassDef *cd) { - BaseClassList *bcl; + BaseClassList bcl; if (cd->getLanguage()==SrcLangExt_VHDL) // reverse baseClass/subClass relation { - if (cd->baseClasses()==0) return FALSE; + if (cd->baseClasses().empty()) return FALSE; bcl=cd->baseClasses(); } else { - if (cd->subClasses()==0) return FALSE; + if (cd->subClasses().empty()) return FALSE; bcl=cd->subClasses(); } - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcd : bcl) { - if (bcli.current()->classDef->isVisibleInHierarchy()) + if (bcd.classDef->isVisibleInHierarchy()) { return TRUE; } @@ -4696,49 +3557,91 @@ bool classHasVisibleChildren(const ClassDef *cd) return FALSE; } - //---------------------------------------------------------------------------- -void initClassHierarchy(ClassSDict *cl) +bool hasVisibleRoot(const BaseClassList &bcl) { - ClassSDict::Iterator cli(*cl); - ClassDef *cd; - for ( ; (cd=cli.current()); ++cli) + for (const auto &bcd : bcl) { - cd->setVisited(FALSE); - initBaseClassHierarchy(cd->baseClasses()); + const ClassDef *cd=bcd.classDef; + if (cd->isVisibleInHierarchy()) return TRUE; + hasVisibleRoot(cd->baseClasses()); } + return FALSE; } -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------- -bool hasVisibleRoot(const BaseClassList *bcl) +// copies the next UTF8 character from input stream into buffer ids +// returns the size of the character in bytes (or 0 if it is invalid) +// the character itself will be copied as a UTF-8 encoded string to ids. +int getUtf8Char(const char *input,char ids[MAX_UTF8_CHAR_SIZE],CaseModifier modifier) { - if (bcl) + int inputLen=1; + const unsigned char uc = (unsigned char)*input; + bool validUTF8Char = false; + if (uc <= 0xf7) { - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current(); ++bcli) + const char* pt = input+1; + int l = 0; + if ((uc&0x80)==0x00) { - const ClassDef *cd=bcli.current()->classDef; - if (cd->isVisibleInHierarchy()) return TRUE; - hasVisibleRoot(cd->baseClasses()); + switch (modifier) + { + case CaseModifier::None: ids[0]=*input; break; + case CaseModifier::ToUpper: ids[0]=(char)toupper(*input); break; + case CaseModifier::ToLower: ids[0]=(char)tolower(*input); break; + } + l=1; // 0xxx.xxxx => normal single byte ascii character + } + else + { + ids[ 0 ] = *input; + if ((uc&0xE0)==0xC0) + { + l=2; // 110x.xxxx: >=2 byte character + } + if ((uc&0xF0)==0xE0) + { + l=3; // 1110.xxxx: >=3 byte character + } + if ((uc&0xF8)==0xF0) + { + l=4; // 1111.0xxx: >=4 byte character + } + } + validUTF8Char = l>0; + for (int m=1; m<l && validUTF8Char; ++m) + { + unsigned char ct = (unsigned char)*pt; + if (ct==0 || (ct&0xC0)!=0x80) // invalid unicode character + { + validUTF8Char=false; + } + else + { + ids[ m ] = *pt++; + } + } + if (validUTF8Char) // got a valid unicode character + { + ids[ l ] = 0; + inputLen=l; } } - return FALSE; + return inputLen; } -//---------------------------------------------------------------------- // note that this function is not reentrant due to the use of static growBuf! QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscore) { - static bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); - static bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES); - static GrowBuf growBuf; - growBuf.clear(); + bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); + bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES); if (name==0) return ""; + GrowBuf growBuf; signed char c; - const signed char *p=(const signed char*)name; + const char *p=name; while ((c=*p++)!=0) { switch(c) @@ -4774,54 +3677,25 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor default: if (c<0) { - char ids[5]; - const unsigned char uc = (unsigned char)c; - bool doEscape = TRUE; - if (allowUnicodeNames && uc <= 0xf7) + char ids[MAX_UTF8_CHAR_SIZE]; + bool doEscape = true; + if (allowUnicodeNames) { - const signed char* pt = p; - ids[ 0 ] = c; - int l = 0; - if ((uc&0xE0)==0xC0) - { - l=2; // 11xx.xxxx: >=2 byte character - } - if ((uc&0xF0)==0xE0) - { - l=3; // 111x.xxxx: >=3 byte character - } - if ((uc&0xF8)==0xF0) - { - l=4; // 1111.xxxx: >=4 byte character - } - doEscape = l==0; - for (int m=1; m<l && !doEscape; ++m) - { - unsigned char ct = (unsigned char)*pt; - if (ct==0 || (ct&0xC0)!=0x80) // invalid unicode character - { - doEscape=TRUE; - } - else - { - ids[ m ] = *pt++; - } - } - if ( !doEscape ) // got a valid unicode character + int charLen = getUtf8Char(p-1,ids); + if (charLen>0) { - ids[ l ] = 0; - growBuf.addStr( ids ); - p += l - 1; + growBuf.addStr(ids); + p+=charLen-1; + doEscape = false; } } if (doEscape) // not a valid unicode char or escaping needed { - static char map[] = "0123456789ABCDEF"; unsigned char id = (unsigned char)c; ids[0]='_'; ids[1]='x'; - ids[2]=map[id>>4]; - ids[3]=map[id&0xF]; + ids[2]=hex[id>>4]; + ids[3]=hex[id&0xF]; ids[4]=0; growBuf.addStr(ids); } @@ -5229,10 +4103,8 @@ QCString stripScope(const char *name) /*! Converts a string to a HTML id string */ QCString convertToId(const char *s) { - static const char hex[] = "0123456789ABCDEF"; - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; bool first=TRUE; @@ -5271,9 +4143,8 @@ QCString correctId(QCString s) /*! Converts a string to an XML-encoded string */ QCString convertToXML(const char *s, bool keepEntities) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; while ((c=*p++)) @@ -5323,9 +4194,8 @@ QCString convertToXML(const char *s, bool keepEntities) /*! Converts a string to an DocBook-encoded string */ QCString convertToDocBook(const char *s) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const unsigned char *q; int cnt; const unsigned char *p=(const unsigned char *)s; @@ -5367,13 +4237,18 @@ QCString convertToDocBook(const char *s) break; case '\'': growBuf.addStr("'"); break; case '"': growBuf.addStr("""); break; - case '\007': growBuf.addStr("␇"); break; - case 1: case 2: case 3: case 4: case 5: case 6: case 8: - case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: + case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: + case 11: case 12: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: - break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char) - default: growBuf.addChar(c); break; + growBuf.addStr("$"); + growBuf.addChar(hex[static_cast<uchar>(c)>>4]); + growBuf.addChar(hex[static_cast<uchar>(c)&0xF]); + growBuf.addChar(';'); + break; + default: + growBuf.addChar(c); + break; } } growBuf.addChar(0); @@ -5383,9 +4258,8 @@ QCString convertToDocBook(const char *s) /*! Converts a string to a HTML-encoded string */ QCString convertToHtml(const char *s,bool keepEntities) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; growBuf.addStr(getHtmlDirEmbeddingChar(getTextDirByConfig(s))); const char *p=s; char c; @@ -5421,7 +4295,22 @@ QCString convertToHtml(const char *s,bool keepEntities) break; case '\'': growBuf.addStr("'"); break; case '"': growBuf.addStr("""); break; - default: growBuf.addChar(c); break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) + { + growBuf.addStr("$"); + growBuf.addChar(hex[uc>>4]); + growBuf.addChar(hex[uc&0xF]); + growBuf.addChar(';'); + } + else + { + growBuf.addChar(c); + } + } + break; } } growBuf.addChar(0); @@ -5430,9 +4319,8 @@ QCString convertToHtml(const char *s,bool keepEntities) QCString convertToJSString(const char *s, bool applyTextDir) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; if (applyTextDir) growBuf.addStr(getJsDirEmbeddingChar(getTextDirByConfig(s))); const char *p=s; @@ -5452,9 +4340,8 @@ QCString convertToJSString(const char *s, bool applyTextDir) QCString convertToPSString(const char *s) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; while ((c=*p++)) @@ -5474,7 +4361,7 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing,bool keepSpaces) { QGString result; FTextStream t(&result); - filterLatexString(t,s,insideTabbing,FALSE,FALSE,keepSpaces); + filterLatexString(t,s,insideTabbing,false,false,false,keepSpaces); return result.data(); } @@ -5486,8 +4373,7 @@ QCString convertCharEntitiesToUTF8(const QCString &s) static QRegExp entityPat("&[a-zA-Z]+[0-9]*;"); if (s.length()==0) return result; - static GrowBuf growBuf; - growBuf.clear(); + GrowBuf growBuf; int p,i=0,l; while ((p=entityPat.match(s,i,&l))!=-1) { @@ -5714,7 +4600,7 @@ QCString normalizeNonTemplateArgumentsInString( result += name.mid(p,i-p); QCString n = name.mid(i,l); bool found=FALSE; - for (const Argument formArg : formalArgs) + for (const Argument &formArg : formalArgs) { if (formArg.name == n) { @@ -5725,7 +4611,8 @@ QCString normalizeNonTemplateArgumentsInString( if (!found) { // try to resolve the type - const ClassDef *cd = getResolvedClass(context,0,n); + SymbolResolver resolver; + const ClassDef *cd = resolver.resolveClass(context,n); if (cd) { result+=cd->name(); @@ -6020,7 +4907,9 @@ found: PageDef *addRelatedPage(const char *name,const QCString &ptitle, const QCString &doc, - const char *fileName,int startLine, + const char *fileName, + int docLine, + int startLine, const RefItemVector &sli, GroupDef *gd, const TagInfo *tagInfo, @@ -6030,12 +4919,16 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, { PageDef *pd=0; //printf("addRelatedPage(name=%s gd=%p)\n",name,gd); + QCString title=ptitle.stripWhiteSpace(); if ((pd=Doxygen::pageSDict->find(name)) && !tagInfo) { - if (!xref) warn(fileName,startLine,"multiple use of page label '%s', (other occurrence: %s, line: %d)", - name,pd->docFile().data(),pd->docLine()); + if (!xref && !title.isEmpty() && pd->title()!=title) + { + warn(fileName,startLine,"multiple use of page label '%s', (other occurrence: %s, line: %d)", + name,pd->docFile().data(),pd->getStartBodyLine()); + } // append documentation block to the page. - pd->setDocumentation(doc,fileName,startLine); + pd->setDocumentation(doc,fileName,docLine); //printf("Adding page docs '%s' pi=%p name=%s\n",doc.data(),pd,name); // append (x)refitems to the page. pd->setRefItems(sli); @@ -6048,8 +4941,8 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, else if (baseName.right(Doxygen::htmlFileExtension.length())==Doxygen::htmlFileExtension) baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length()); - QCString title=ptitle.stripWhiteSpace(); - pd=createPageDef(fileName,startLine,baseName,doc,title); + pd=createPageDef(fileName,docLine,baseName,doc,title); + pd->setBodySegment(startLine,startLine,-1); pd->setRefItems(sli); pd->setLanguage(lang); @@ -6071,24 +4964,29 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, // a page name is a label as well! QCString file; + QCString orgFile; + int line = -1; if (gd) { file=gd->getOutputFileBase(); + orgFile=gd->getOutputFileBase(); } else { file=pd->getOutputFileBase(); + orgFile=pd->docFile(); + line = pd->getStartBodyLine(); } const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { 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(orgFile,line,"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(orgFile,line,"multiple use of section label '%s', (first occurrence: %s)",pd->name().data(),si->fileName().data()); } } else @@ -6166,7 +5064,7 @@ void addGroupListToTitle(OutputList &ol,const Definition *d) } void filterLatexString(FTextStream &t,const char *str, - bool insideTabbing,bool insidePre,bool insideItem,bool keepSpaces) + bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces) { if (str==0) return; //if (strlen(str)<2) stackTrace(); @@ -6203,12 +5101,13 @@ void filterLatexString(FTextStream &t,const char *str, case '$': t << "\\$"; break; case '"': t << "\"{}"; break; case '-': t << "-\\/"; break; - case '^': (usedTableLevels()>0) ? t << "\\string^" : t << (char)c; break; + case '^': insideTable ? t << "\\string^" : t << (char)c; break; case '~': t << "\\string~"; break; case ' ': if (keepSpaces) t << "~"; else t << ' '; break; default: - t << (char)c; + if (c<32) t << ' '; // non printable control character + else t << (char)c; break; } } @@ -6297,12 +5196,19 @@ void filterLatexString(FTextStream &t,const char *str, default: //if (!insideTabbing && forceBreaks && c!=' ' && *p!=' ') if (!insideTabbing && - ((c>='A' && c<='Z' && pc!=' ' && pc!='\0' && *p) || (c==':' && pc!=':') || (pc=='.' && isId(c))) + ((c>='A' && c<='Z' && pc!=' ' && !(pc>='A' && pc <= 'Z') && pc!='\0' && *p) || (c==':' && pc!=':') || (pc=='.' && isId(c))) ) { t << "\\+"; } - t << (char)c; + if (c<32) + { + t << ' '; // non-printable control character + } + else + { + t << (char)c; + } } } pc = c; @@ -6340,7 +5246,13 @@ QCString latexEscapeLabelName(const char *s) p++; } tmp[i]=0; - filterLatexString(t,tmp,TRUE); + filterLatexString(t,tmp, + true, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); break; } } @@ -6379,7 +5291,13 @@ QCString latexEscapeIndexChars(const char *s) p++; } tmp[i]=0; - filterLatexString(t,tmp.data(),TRUE); + filterLatexString(t,tmp.data(), + true, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); break; } } @@ -6416,7 +5334,7 @@ QCString latexFilterURL(const char *s) if (s==0) return ""; QGString result; FTextStream t(&result); - const char *p=s; + const signed char *p=(const signed char*)s; char c; while ((c=*p++)) { @@ -6426,7 +5344,15 @@ QCString latexFilterURL(const char *s) case '%': t << "\\%"; break; case '\\': t << "\\\\"; break; default: - t << c; + if (c<0) + { + unsigned char id = (unsigned char)c; + t << "\\%" << hex[id>>4] << hex[id&0xF]; + } + else + { + t << c; + } break; } } @@ -6802,7 +5728,7 @@ QCString getFileNameExtension(QCString fn) //-------------------------------------------------------------------------- -MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, +static MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, const char *n) { if (scope==0 || @@ -6818,8 +5744,8 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, if (name.isEmpty()) return 0; // no name was given - DefinitionIntf *di = Doxygen::symbolMap->find(name); - if (di==0) + auto range = Doxygen::symbolMap.find(name); + if (range.first==range.second) return 0; // could not find any matching symbols // mostly copied from getResolvedClassRec() @@ -6836,40 +5762,21 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, int minDistance = 10000; MemberDef *bestMatch = 0; - if (di->definitionType()==DefinitionIntf::TypeSymbolList) + for (auto it=range.first; it!=range.second; ++it) { - //printf("multiple matches!\n"); - // find the closest closest matching definition - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - for (dli.toFirst();(d=dli.current());++dli) + Definition *d = it->second; + if (d->definitionType()==Definition::TypeMember) { - if (d->definitionType()==Definition::TypeMember) + SymbolResolver resolver(fileScope); + int distance = resolver.isAccessibleFromWithExpScope(scope,d,explicitScopePart); + if (distance!=-1 && distance<minDistance) { - g_visitedNamespaces.clear(); - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); - if (distance!=-1 && distance<minDistance) - { - minDistance = distance; - bestMatch = dynamic_cast<MemberDef *>(d); - //printf("new best match %s distance=%d\n",bestMatch->qualifiedName().data(),distance); - } + minDistance = distance; + bestMatch = toMemberDef(d); + //printf("new best match %s distance=%d\n",bestMatch->qualifiedName().data(),distance); } } } - else if (di->definitionType()==Definition::TypeMember) - { - //printf("unique match!\n"); - Definition *d = (Definition *)di; - g_visitedNamespaces.clear(); - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); - if (distance!=-1 && distance<minDistance) - { - minDistance = distance; - bestMatch = dynamic_cast<MemberDef *>(d); - //printf("new best match %s distance=%d\n",bestMatch->qualifiedName().data(),distance); - } - } return bestMatch; } @@ -7053,8 +5960,7 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, //printf("----- replaceAliasArguments(val=[%s],args=[%s])\n",aliasValue.data(),argList.data()); // first make a list of arguments from the comma separated argument list - QList<QCString> args; - args.setAutoDelete(TRUE); + std::vector<QCString> args; int i,l=(int)argList.length(); int s=0; for (i=0;i<l;i++) @@ -7062,7 +5968,7 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, char c = argList.at(i); if (c==',' && (i==0 || argList.at(i-1)!='\\')) { - args.append(new QCString(argList.mid(s,i-s))); + args.push_back(QCString(argList.mid(s,i-s))); s=i+1; // start of next argument } else if (c=='@' || c=='\\') @@ -7071,68 +5977,58 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, i+=findEndOfCommand(argList.data()+i+1); } } - if (l>s) args.append(new QCString(argList.right(l-s))); + if (l>s) args.push_back(QCString(argList.right(l-s))); //printf("found %d arguments\n",args.count()); // next we look for the positions of the markers and add them to a list - QList<Marker> markerList; - markerList.setAutoDelete(TRUE); + std::vector<Marker> markerList; l = aliasValue.length(); + char pc='\0'; + bool insideMarkerId=false; int markerStart=0; - int markerEnd=0; - for (i=0;i<l;i++) + auto isDigit = [](char c) { return c>='0' && c<='9'; }; + for (i=0;i<=l;i++) { - if (markerStart==0 && aliasValue.at(i)=='\\') // start of a \xx marker + char c = i<l ? aliasValue.at(i) : '\0'; + if (insideMarkerId && !isDigit(c)) // found end of a markerId { - markerStart=i+1; + insideMarkerId = false; + int markerLen = i-markerStart; + markerList.push_back(Marker(markerStart-1, + atoi(aliasValue.mid(markerStart,markerLen)), + markerLen+1)); } - else if (markerStart>0 && aliasValue.at(i)>='0' && aliasValue.at(i)<='9') + if (c=='\\' && (pc=='@' || pc=='\\')) // found escaped backslash { - // read digit that make up the marker number - markerEnd=i+1; + // skip + pc = '\0'; } else { - if (markerStart>0 && markerEnd>markerStart) // end of marker + if (isDigit(c) && pc=='\\') // found start of a markerId { - int markerLen = markerEnd-markerStart; - markerList.append(new Marker(markerStart-1, // include backslash - atoi(aliasValue.mid(markerStart,markerLen)),markerLen+1)); - //printf("found marker at %d with len %d and number %d\n", - // markerStart-1,markerLen+1,atoi(aliasValue.mid(markerStart,markerLen))); + insideMarkerId=true; + markerStart=i; } - markerStart=0; // outside marker - markerEnd=0; + pc = c; } } - if (markerStart>0) - { - markerEnd=l; - } - if (markerStart>0 && markerEnd>markerStart) - { - int markerLen = markerEnd-markerStart; - markerList.append(new Marker(markerStart-1, // include backslash - atoi(aliasValue.mid(markerStart,markerLen)),markerLen+1)); - //printf("found marker at %d with len %d and number %d\n", - // markerStart-1,markerLen+1,atoi(aliasValue.mid(markerStart,markerLen))); - } // then we replace the markers with the corresponding arguments in one pass QCString result; int p=0; - for (i=0;i<(int)markerList.count();i++) + for (i=0;i<(int)markerList.size();i++) { - Marker *m = markerList.at(i); - result+=aliasValue.mid(p,m->pos-p); + const Marker &m = markerList.at(i); + result+=aliasValue.mid(p,m.pos-p); //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 + if (m.number>0 && m.number<=(int)args.size()) // valid number { - result+=expandAliasRec(aliasesProcessed,*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()); } - p=m->pos+m->size; // continue after the marker + p=m.pos+m.size; // continue after the marker } result+=aliasValue.right(l-p); // append remainder //printf("string after replacement of markers: '%s'\n",result.data()); @@ -7649,7 +6545,6 @@ QCString replaceColorMarkers(const char *str) QCString s=str; if (s.isEmpty()) return result; static QRegExp re("##[0-9A-Fa-f][0-9A-Fa-f]"); - static const char hex[] = "0123456789ABCDEF"; static int hue = Config_getInt(HTML_COLORSTYLE_HUE); static int sat = Config_getInt(HTML_COLORSTYLE_SAT); static int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); @@ -7834,7 +6729,10 @@ bool isURL(const QCString &url) { QCString loc_url = url.stripWhiteSpace(); return loc_url.left(5)=="http:" || loc_url.left(6)=="https:" || - loc_url.left(4)=="ftp:" || loc_url.left(5)=="file:"; + loc_url.left(4)=="ftp:" || loc_url.left(5)=="ftps:" || + loc_url.left(5)=="sftp:" || loc_url.left(5)=="file:" || + loc_url.left(5)=="news:" || loc_url.left(4)=="irc:" || + loc_url.left(5)=="ircs:"; } /** Corrects URL \a url according to the relative path \a relPath. * Returns the corrected URL. For absolute URLs no correction will be done. @@ -7991,44 +6889,6 @@ bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile) ); } -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()) && - src->showInCallGraph() - ) - { - dst->addSourceReferencedBy(src); - MemberDef *mdDef = dst->memberDefinition(); - if (mdDef) - { - mdDef->addSourceReferencedBy(src); - } - MemberDef *mdDecl = dst->memberDeclaration(); - if (mdDecl) - { - mdDecl->addSourceReferencedBy(src); - } - } - if ((src->hasReferencesRelation() || src->hasCallGraph()) && - src->showInCallGraph() - ) - { - src->addSourceReferences(dst); - MemberDef *mdDef = src->memberDefinition(); - if (mdDef) - { - mdDef->addSourceReferences(dst); - } - MemberDef *mdDecl = src->memberDeclaration(); - if (mdDecl) - { - mdDecl->addSourceReferences(dst); - } - } -} - //-------------------------------------------------------------------------------------- /*! @brief Get one unicode character as an unsigned integer from utf-8 string @@ -8097,55 +6957,54 @@ uint getUtf8CodeToUpper( const QCString& s, int idx ) } //-------------------------------------------------------------------------------------- +// +bool namespaceHasNestedNamespace(const NamespaceDef *nd) +{ + for (const auto &cnd : nd->getNamespaces()) + { + if (cnd->isLinkableInProject() && !cnd->isAnonymous()) + { + return true; + } + } + return false; +} -bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct) +bool namespaceHasNestedClass(const NamespaceDef *nd,bool filterClasses,ClassDef::CompoundType ct) { - if (nd->getNamespaceSDict()) + //printf(">namespaceHasVisibleChild(%s,includeClasses=%d)\n",nd->name().data(),includeClasses); + for (const auto &cnd : nd->getNamespaces()) { - NamespaceSDict::Iterator cnli(*nd->getNamespaceSDict()); - const NamespaceDef *cnd; - for (cnli.toFirst();(cnd=cnli.current());++cnli) + if (namespaceHasNestedClass(cnd,filterClasses,ct)) { - if (cnd->isLinkableInProject() && !cnd->isAnonymous()) - { - return TRUE; - } - else if (namespaceHasVisibleChild(cnd,includeClasses,filterClasses,ct)) - { - return TRUE; - } + //printf("<namespaceHasVisibleChild(%s,includeClasses=%d): case2\n",nd->name().data(),includeClasses); + return TRUE; } } - if (includeClasses) + + ClassLinkedRefMap list = nd->getClasses(); + if (filterClasses) { - const ClassSDict *d = nd->getClassSDict(); - if (filterClasses) + if (ct == ClassDef::Interface) { - if (ct == ClassDef::Interface) - { - d = nd->getInterfaceSDict(); - } - else if (ct == ClassDef::Struct) - { - d = nd->getStructSDict(); - } - else if (ct == ClassDef::Exception) - { - d = nd->getExceptionSDict(); - } + list = nd->getInterfaces(); + } + else if (ct == ClassDef::Struct) + { + list = nd->getStructs(); } + else if (ct == ClassDef::Exception) + { + list = nd->getExceptions(); + } + } - if (d) + for (const auto &cd : list) + { + if (cd->isLinkableInProject() && cd->templateMaster()==0) { - ClassSDict::Iterator cli(*d); - const ClassDef *cd; - for (;(cd=cli.current());++cli) - { - if (cd->isLinkableInProject() && cd->templateMaster()==0) - { - return TRUE; - } - } + //printf("<namespaceHasVisibleChild(%s,includeClasses=%d): case3\n",nd->name().data(),includeClasses); + return TRUE; } } return FALSE; @@ -8380,7 +7239,7 @@ bool mainPageHasTitle() return Doxygen::mainPage!=0 && Doxygen::mainPage->hasTitle(); } -QCString getDotImageExtension(void) +QCString getDotImageExtension() { QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format @@ -8457,20 +7316,56 @@ void writeLatexSpecialFormulaChars(FTextStream &t) } //------------------------------------------------------ +// simplified way to know if this is fixed form +bool recognizeFixedForm(const char* contents, FortranFormat format) +{ + int column=0; + bool skipLine=FALSE; -static int g_usedTableLevels = 0; + if (format == FortranFormat_Fixed) return TRUE; + if (format == FortranFormat_Free) return FALSE; -void incUsedTableLevels() -{ - g_usedTableLevels++; -} -void decUsedTableLevels() -{ - g_usedTableLevels--; + for(int i=0;;i++) { + column++; + + switch(contents[i]) { + case '\n': + column=0; + skipLine=FALSE; + break; + case ' ': + break; + case '\000': + return FALSE; + case '#': + skipLine=TRUE; + break; + case 'C': + case 'c': + case '*': + if (column==1) return TRUE; + if (skipLine) break; + return FALSE; + case '!': + if (column>1 && column<7) return FALSE; + skipLine=TRUE; + break; + default: + if (skipLine) break; + if (column>=7) return TRUE; + return FALSE; + } + } + return FALSE; } -int usedTableLevels() + +FortranFormat convertFileNameFortranParserCode(QCString fn) { - return g_usedTableLevels; -} + QCString ext = getFileNameExtension(fn); + QCString parserName = Doxygen::parserManager->getParserName(ext.data()); -//------------------------------------------------------ + if (parserName == "fortranfixed") return FortranFormat_Fixed; + else if (parserName == "fortranfree") return FortranFormat_Free; + + return FortranFormat_Unknown; +} @@ -23,6 +23,8 @@ */ #include <memory> +#include <unordered_map> +#include <algorithm> #include <qlist.h> #include <ctype.h> @@ -32,6 +34,7 @@ #include "classdef.h" #include "arguments.h" #include "containers.h" +#include "namespacedef.h" //-------------------------------------------------------------------- @@ -45,8 +48,6 @@ class OutputList; class OutputDocInterface; class MemberDef; class ExampleSDict; -class ClassSDict; -class BaseClassList; class GroupDef; class NamespaceSDict; class ClassList; @@ -135,8 +136,6 @@ void linkifyText(const TextGeneratorIntf &ol, int indentLevel=0 ); -void setAnchors(MemberList *ml); - QCString fileToString(const char *name,bool filter=FALSE,bool isSourceCode=FALSE); QCString dateToString(bool); @@ -151,8 +150,7 @@ bool getDefs(const QCString &scopeName, const GroupDef *&gd, bool forceEmptyScope=FALSE, const FileDef *currentFile=0, - bool checkCV=FALSE, - const char *forceTagFile=0 + bool checkCV=FALSE ); QCString getFileFilter(const char* name,bool isSourceCode); @@ -204,17 +202,16 @@ QCString selectBlock(const QCString& s,const QCString &name,bool which); QCString resolveDefines(const char *n); ClassDef *getClass(const char *key); - -const ClassDef *getResolvedClass(const Definition *scope, - const FileDef *fileScope, - const char *key, - const MemberDef **pTypeDef=0, - QCString *pTemplSpec=0, - bool mayBeUnlinkable=FALSE, - bool mayBeHidden=FALSE, - QCString *pResolvedType=0); +inline ClassDefMutable *getClassMutable(const char *key) +{ + return toClassDefMutable(getClass(key)); +} NamespaceDef *getResolvedNamespace(const char *key); +inline NamespaceDefMutable *getResolvedNamespaceMutable(const char *key) +{ + return toNamespaceDefMutable(getResolvedNamespace(key)); +} FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n, bool &ambig); @@ -232,7 +229,7 @@ QCString removeRedundantWhiteSpace(const QCString &s); QCString argListToString(const ArgumentList &al,bool useCanonicalType=FALSE,bool showDefVals=TRUE); -QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang); +QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool includeDefaults=true); QCString generateMarker(int id); @@ -257,11 +254,10 @@ QCString removeAnonymousScopes(const QCString &s); QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0); -void initClassHierarchy(ClassSDict *cl); - -bool hasVisibleRoot(const BaseClassList *bcl); +bool hasVisibleRoot(const BaseClassList &bcl); bool classHasVisibleChildren(const ClassDef *cd); -bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct); +bool namespaceHasNestedNamespace(const NamespaceDef *nd); +bool namespaceHasNestedClass(const NamespaceDef *nd,bool filterClasses,ClassDef::CompoundType ct); bool classVisibleInIndex(const ClassDef *cd); int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level=0); @@ -311,8 +307,6 @@ QCString substituteTemplateArgumentsInString( const ArgumentList &formalArgs, const std::unique_ptr<ArgumentList> &actualArgs); -//QList<ArgumentList> *copyArgumentLists(const QList<ArgumentList> *srcLists); - QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly=TRUE, QCString *lastScopeStripped=0); @@ -337,7 +331,9 @@ void addRefItem(const RefItemVector &sli, PageDef *addRelatedPage(const char *name, const QCString &ptitle, const QCString &doc, - const char *fileName,int startLine, + const char *fileName, + int docLine, + int startLine, const RefItemVector &sli = RefItemVector(), GroupDef *gd=0, const TagInfo *tagInfo=0, @@ -351,10 +347,11 @@ QCString unescapeCharsInString(const char *s); void addGroupListToTitle(OutputList &ol,const Definition *d); void filterLatexString(FTextStream &t,const char *str, - bool insideTabbing=FALSE, - bool insidePre=FALSE, - bool insideItem=FALSE, - bool keepSpaces=FALSE); + bool insideTabbing, + bool insidePre, + bool insideItem, + bool insideTable, + bool keepSpaces); QCString latexEscapeLabelName(const char *s); QCString latexEscapeIndexChars(const char *s); @@ -375,11 +372,6 @@ QCString stripExtension(const char *fName); void replaceNamespaceAliases(QCString &scope,int i); -int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item); - -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope,const Definition *item, - const QCString &explicitScopePart); - int computeQualifiedIndex(const QCString &name); void addDirPrefix(QCString &fileName); @@ -402,17 +394,8 @@ QCString getFileNameExtension(QCString fn); void initDefaultExtensionMapping(); void addCodeOnlyMappings(); -MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, - const char *n); bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n); -const ClassDef *newResolveTypedef(const FileDef *fileScope, - const MemberDef *md, - const MemberDef **pMemType=0, - QCString *pTemplSpec=0, - QCString *pResolvedType=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); QCString transcodeCharacterStringToUTF8(const QCString &input); @@ -423,8 +406,6 @@ QCString extractAliasArgs(const QCString &args,int pos); int countAliasArguments(const QCString argList); -//QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList); - QCString resolveAliasCmd(const QCString aliasCmd); QCString expandAlias(const QCString &aliasName,const QCString &aliasValue); @@ -474,12 +455,19 @@ bool protectionLevelVisible(Protection prot); QCString stripIndentation(const QCString &s); void stripIndentation(QCString &doc,const int indentationLevel); -QCString getDotImageExtension(void); +QCString getDotImageExtension(); bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile); -void addDocCrossReference(MemberDef *src,MemberDef *dst); - +const int MAX_UTF8_CHAR_LEN = 4; +const int MAX_UTF8_CHAR_SIZE = MAX_UTF8_CHAR_LEN+1; // include 0 terminator +enum class CaseModifier +{ + None, + ToUpper, + ToLower +}; +int getUtf8Char(const char *input,char ids[MAX_UTF8_CHAR_SIZE],CaseModifier modifier=CaseModifier::None); uint getUtf8Code( const QCString& s, int idx ); uint getUtf8CodeToLower( const QCString& s, int idx ); uint getUtf8CodeToUpper( const QCString& s, int idx ); @@ -498,8 +486,7 @@ bool openOutputFile(const char *outFile,QFile &f); void writeExtraLatexPackages(FTextStream &t); void writeLatexSpecialFormulaChars(FTextStream &t); -int usedTableLevels(); -void incUsedTableLevels(); -void decUsedTableLevels(); +bool recognizeFixedForm(const char* contents, FortranFormat format); +FortranFormat convertFileNameFortranParserCode(QCString fn); #endif diff --git a/src/vhdlcode.h b/src/vhdlcode.h index b79e2ab..48c15bb 100644 --- a/src/vhdlcode.h +++ b/src/vhdlcode.h @@ -1,3 +1,17 @@ +/****************************************************************************** + * + * 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 VHDLCODE_H #define VHDLCODE_H @@ -12,7 +26,8 @@ void codeFreeVhdlScanner(); class VHDLCodeParser : public CodeParserInterface { public: - virtual ~VHDLCodeParser() {} + VHDLCodeParser(); + virtual ~VHDLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -28,8 +43,10 @@ class VHDLCodeParser : public CodeParserInterface const Definition *searchCtx=0, bool collectXRefs=TRUE ); - void resetCodeParserState() {} + void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; - -#endif +#endif diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 808e5a2..efb367b 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.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. * @@ -20,12 +20,17 @@ %option never-interactive %option case-insensitive %option prefix="vhdlcodeYY" +%option reentrant +%option extra-type="struct vhdlcodeYY_state *" %top{ #include <stdint.h> } %{ +#include <unordered_set> +#include <string> + /* * includes */ @@ -55,11 +60,11 @@ #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) - + /* ----------------------------------------------------------------- * statics @@ -67,57 +72,70 @@ // ----------------- <vhdl> ---------------------------------- -//static bool isPackBody=FALSE; -//static bool isStartMap; -static bool isFuncProto=FALSE; -static bool isComponent=FALSE; -static bool isPackageBody=FALSE; -static bool isProto = FALSE; -static bool g_startCode = FALSE; -static QCString g_PrevString; -static QCString g_CurrClass; -static QDict<QCString>g_vhdlKeyDict; -static QCString g_tempComp; -static QCString g_PortMapComp; -static MemberDef *g_vhdlMember; -static QCString g_FuncProto; - -//----------------------------------------------------------- - -static CodeOutputInterface * g_code; -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_inputLines; //!< number of line in the code fragment -static int g_yyLineNr; //!< current line number -static bool g_needsTermination; -static const Definition *g_searchCtx; - -static bool g_exampleBlock; -static QCString g_exampleName; -static QCString g_exampleFile; - -static QCString g_classScope; - -static bool g_CurrARCH = FALSE; - -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; -static const char * g_currentFontClass; - -static bool g_lexInit = FALSE; -static int g_braceCount=0; - - -static void writeFont(const char *s,const char* text); -static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName); -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); +struct vhdlcodeYY_state +{ + bool isFuncProto = false; + bool isComponent = false; + bool isPackageBody = false; + bool isProto = false; + bool startCode = false; + QCString prevString; + QCString currClass; + std::unordered_set<std::string> vhdlKeyDict; + QCString tempComp; + QCString PortMapComp; + const MemberDef * vhdlMember = 0; + QCString funcProto; + + CodeOutputInterface * code = 0; + const char * inputString = 0; //!< the code fragment as text + 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 + bool needsTermination = false; + const Definition *searchCtx = 0; + + bool exampleBlock = false; + QCString exampleName; + QCString exampleFile; + + bool currArch = false; + + const FileDef * sourceFileDef = 0; + const Definition * currentDefinition = 0; + const MemberDef * currentMemberDef = 0; + bool includeCodeFragment = false; + const char * currentFontClass = 0; + + bool lexInit = false; + int braceCount = 0; +}; + + +static void writeFont(yyscan_t yyscanner,const char *s,const char* text); +static void generateMemLink(yyscan_t yyscanner,CodeOutputInterface &ol,QCString &clName,QCString& memberName); +static bool writeColoredWord(yyscan_t yyscanner,QCString& word ); +static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, bool typeOnly=false, const char *curr_class=0); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static bool checkVhdlString(yyscan_t yyscanner,QCString &name); +static void addToSearchIndex(yyscan_t yyscanner,const char *text); +static void startCodeLine(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void writeWord(yyscan_t yyscanner,const char *word,const char* curr_class=0,bool classLink=false); +static void codifyLines(yyscan_t yyscanner,const char *text,const char *cl=0,bool classlink=false,bool comment=false); +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, + Definition *d, + const char *text); +static void generateFuncLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef* mdef); +static int countLines(yyscan_t yyscanner); +static void endFontClass(yyscan_t yyscanner); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void appStringLower(QCString& qcs,const char* text); +static void codifyMapLines(yyscan_t yyscanner,const char *text); +static void writeFuncProto(yyscan_t yyscanner); +static void writeProcessProto(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #if USE_STATE2STRING static const char *stateToString(int state); @@ -125,24 +143,818 @@ static const char *stateToString(int state); //------------------------------------------------------------------- -static void setCurrentDoc(const QCString &anchor) +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + + +B [ \t] +BN [ \t\n\r] +STRING ["][^"\n]*["] +NAME [a-z_A-Z][ a-z_A-Z0-9]* +FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]* +ID "$"?[a-z_A-Z][a-z_A-Z0-9]* +SPECSIGN [:;, +*&\/=<>'\t]* +DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")* +ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}* +ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}* + +ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME}{BN}+("is") +PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+ + +END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for") +END2 [^a-zA-Z_]("end"){BN}*[;] +END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;] +END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;] +ENDEFUNC {END3}|{END4}|{END2} + +KEYWORD ("of"|"new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in") +TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration") +FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(") + +ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":=" +ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" +LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" +BITOP "&"|"|"|"^"|"<<"|">>"|"~" +OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} + +PORT {B}*("port"){BN}*("(") +GENERIC {B}*("generic"){BN}*("(") + +BRACEOPEN [(]{1} +BRACECLOSE [)]{1} + +TEXTT {B}*"--"[^\n]* + +MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) +MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1} +MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) +MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1}) + +XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFIG"|"CONFIG_MODE"|"COOL_CLK"|"DATA_GATE"|"DCI_VALUE"|"DISABLE"|"DRIVE"|"DROP_SPEC"|"ENABLE"|"FAST"|"FEEDBACK"|"FILE"|"FLOAT"|"FROM-THRU-TO"|"FROM-TO"|"HBLKNM"|"HU_SET"|"INREG"|"IOB"|"IOBDELAY"|"IOSTANDARD"|"KEEP"|"KEEPER"|"LOC"|"LOCATE"|"LOCK_PINS"|"MAP"|"MAXDELAY"|"MAXPT"|"MAXSKEW"|"NODELAY"|"NOREDUCE"|"OFFSET"|"OPEN_DRAIN"|"OPT_EFFORT"|"OPTIMIZE"|"PERIOD"|"PIN"|"PRIORITY"|"PROHIBIT"|"PULLDOWN"|"PULLUP"|"PWR_MODE"|"REG"|"RLOC"|"RLOC_ORIGIN"|"RLOC_RANGE"|"SAVE NET"|"FLAG"|"SYSTEM_JITTER"|"TEMPERATURE"|"TIMEGRP"|"TIMESPEC"|"VOLTAGE" + +%option noyywrap +%option nounput + +%x Bases +%x ParseType +%x ParseFuncProto +%x ParseComponent +%x ParsePackage +%x ParseProcessProto +%x ClassName +%x PackageName +%x ClassVar +%x ClassesName +%x Map +%x End +%x Body + +%% + +. { + BEGIN(Bases); + } + +<Map>{BRACEOPEN} { + yyextra->braceCount++; + writeFont(yyscanner,"vhdlchar",yytext); + BEGIN(Map); + } + +<Map>[^()\n,--]* { /* write and link a port map lines */ + QCString tt(yytext); + VhdlDocGen::deleteAllChars(tt,','); + QRegExp r("=>"); + QCStringList ql=QCStringList::split(r,tt); + if (ql.count()>=2) + { + unsigned int index=0; + QCString t1=ql[0]; + char cc=t1.at(index); + while (cc==' ' || cc=='\t') + { + char c2[2]; + c2[0]=cc; + c2[1]=0; + yyextra->code->codify(c2); + index++; + if (index>=t1.size()) break; + cc=t1.at(index); + } + + QCString s1=t1; + s1=s1.stripWhiteSpace(); + + // if (!yyextra->PortMapComp.isEmpty()) + generateMemLink(yyscanner,*yyextra->code,yyextra->PortMapComp,s1); + while (index++<t1.size()) + { + cc=t1.at(index); + if (cc==' ' || cc=='\t') + { + char c2[2]; + c2[0]=cc; + c2[1]=0; + yyextra->code->codify(c2); + } + } + codifyLines(yyscanner,"=>"); + index=0; + QCString s2=ql[1]; + t1=s2; + cc=t1.at(index); + while (cc==' ' || cc=='\t') + { + char c2[2]; + c2[0]=cc; + c2[1]=0; + yyextra->code->codify(c2); + index++; + if (index>=t1.size()) break; + cc=t1.at(index); + } + s2=s2.stripWhiteSpace(); + if (!checkVhdlString(yyscanner,s2)) + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,s2); + } + while (index++<t1.size()) + { + if (t1.at(index)==' ') + { + yyextra->code->codify(" "); + } + } + } + else + { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + } + BEGIN(Map); + } + +<Map>"\n"|"," { + codifyLines(yyscanner,yytext); + BEGIN(Map); + } + +<Map>{BRACECLOSE} { + yyextra->braceCount--; + writeFont(yyscanner,"vhdlchar",yytext); + if (yyextra->braceCount==0) + { + BEGIN(Bases); + } + } + +<ParseFuncProto>{NAME} { + QCString tmp(yytext); + tmp=tmp.stripWhiteSpace(); + appStringLower(yyextra->prevString,yytext); + yyextra->vhdlKeyDict.insert(yyextra->prevString.str()); + if (!writeColoredWord(yyscanner,tmp)) + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,tmp); + } + BEGIN(Bases); + } + +<ParseType>{STRING} { + QCString qcs(yytext); + VhdlDocGen::deleteAllChars(qcs,'"'); + VhdlDocGen::deleteAllChars(qcs,' '); + if (VhdlDocGen::isNumber(qcs)) + { + writeFont(yyscanner,"vhdllogic",yytext); + } + else + { + writeFont(yyscanner,"keyword",yytext); + } + } + +<ParseType>"\n" { + yyextra->funcProto.append(yytext); + if (yyextra->isProto) + { + codifyLines(yyscanner,yytext); + } + BEGIN(ParseType); + } + + +<ParseType>{TEXTT} { + yyextra->funcProto.append(yytext); + if (yyextra->isProto) + { + writeFont(yyscanner,"keyword",yytext); + } + BEGIN(ParseType); + } + +<ParseType>{ENDEFUNC} { + QRegExp regg("[\\s]"); + QCString tt(yytext); + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + tt=tt.lower(); + VhdlDocGen::deleteAllChars(tt,';'); + tt.stripWhiteSpace(); + QCStringList ql=QCStringList::split(regg,tt); + int index=ql.findIndex(QCString("if"))+1; + index+=ql.findIndex(QCString("case"))+1; + index+=ql.findIndex(QCString("loop"))+1; + index+=ql.findIndex(QCString("generate"))+1; + if (index==0) + { + BEGIN(Bases); + } + else + { + BEGIN(ParseType); + } + } + +<ParseType>{END1} { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + yyextra->vhdlKeyDict.clear(); + } + +<ParseType>^{B}*("begin "|"begin") { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + yyextra->isFuncProto=false; + } + +<ParseType>{SPECSIGN} { + yyextra->funcProto.append(yytext); + if (yyextra->isProto) + { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + } + } + +<ParseType>["_a-zA-Z0-9]* { + QCString val(yytext); + yyextra->funcProto.append(yytext); + appStringLower(yyextra->prevString,yytext); + + if (yyextra->isFuncProto && yyextra->braceCount==0) + { + yyextra->vhdlKeyDict.insert(yyextra->prevString.str()); + } + + if (yyextra->isProto) + { + if (!writeColoredWord(yyscanner,val)) + { + if (!yyextra->isFuncProto && + yyextra->vhdlKeyDict.find(yyextra->prevString.str())==yyextra->vhdlKeyDict.end()) + { + val=val.stripWhiteSpace(); + if (VhdlDocGen::isNumber(val)) + { + startFontClass(yyscanner,"vhdllogic"); + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + endFontClass(yyscanner); + } + else + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,val); + } + } + else + { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + } + } + } + BEGIN(ParseType); + } + +<ParseType>{BRACEOPEN} { + yyextra->braceCount++; + yyextra->funcProto+='('; + if (yyextra->isProto) + { + writeFont(yyscanner,"vhdlchar",yytext); + } + BEGIN(ParseType); + } + +<ParseType>{BRACECLOSE} { + yyextra->braceCount--; + yyextra->funcProto+=')'; + if (yyextra->isProto) + { + writeFont(yyscanner,"vhdlchar",yytext); + } + if (yyextra->braceCount==0 && !yyextra->isProto)// && !yyextra->isPackageBody) + { + yyextra->isProto=true; + appStringLower(yyextra->prevString,yytext); + writeFuncProto(yyscanner); + BEGIN(Bases); + } + if (yyextra->isPackageBody) + { + BEGIN(ParseType); + } + } + + +<ClassesName>{FUNCNAME} { + appStringLower(yyextra->prevString,yytext); + yyextra->currClass.resize(0); + yyextra->currClass.append(yytext); + yyextra->currClass=yyextra->currClass.stripWhiteSpace(); + + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN(Bases); + } + + +<ParseComponent>{BRACEOPEN} { + yyextra->braceCount++; + yyextra->code->codify(yytext); + } + + +<ParseComponent>{BRACECLOSE} { + yyextra->braceCount--; + yyextra->code->codify(yytext); + if (yyextra->braceCount==0 && !yyextra->isComponent) + { + yyextra->tempComp.resize(0); + BEGIN(Bases); + } + else + { + BEGIN(ParseComponent); + } + } + +<ParseComponent>{B}*"-" { + if (strlen(yytext)>=2) // found text ? + { + writeFont(yyscanner,"keyword",yytext); + } + else + { + writeFont(yyscanner,"vhdlchar",yytext); + } + } + +<ParseComponent>{SPECSIGN} { + codifyLines(yyscanner,yytext); + } + + + +<ParseComponent>"\n"|" " { + codifyLines(yyscanner,yytext); + } + +<ParseComponent>{DIGITSS} { + startFontClass(yyscanner,"vhdllogic"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +<ParseComponent>{PORT} { + codifyLines(yyscanner,yytext); + yyextra->braceCount=1; + yyextra->isComponent=false; + } + +<ParseComponent>{GENERIC} { + codifyLines(yyscanner,yytext); + yyextra->braceCount=1; + } + +<ParseComponent>[_a-zA_Z][_a-zA-Z0-9]* { + QCString temp(yytext); + appStringLower(yyextra->prevString,yytext); + if (!checkVhdlString(yyscanner,temp)) + { + if (!writeColoredWord(yyscanner,yyextra->prevString)) + { + generateMemLink(yyscanner,*yyextra->code,yyextra->tempComp,temp); + } + } + } + +<ParseComponent>{STRING} { + QCString temp(yytext); + if (!checkVhdlString(yyscanner,temp)) + { + codifyLines(yyscanner,yytext); + } + } + + +<ParseProcessProto>[^()]* { + yyextra->funcProto.append(yytext); + } + + + +<ParseProcessProto>{BRACEOPEN} { + yyextra->funcProto.append(yytext); + yyextra->braceCount++; + } + +<ParseProcessProto>{BRACECLOSE} { + yyextra->funcProto.append(yytext); + yyextra->braceCount--; + if (yyextra->braceCount==0) + { + writeProcessProto(yyscanner); + BEGIN(Bases); + } + } + +<ParsePackage>[^:;]* { //found package + QCString temp(yytext); + QCStringList strl=QCStringList::split(".",temp); + if (strl.count()>2) + { + QCString s1=strl[0]; + QCString s2=strl[1]; + QCString s3=strl[2]; + s1.append("."); + s3.prepend("."); + codifyLines(yyscanner,s1.data(),yyextra->currClass.data()); + ClassDef *cd=VhdlDocGen::getPackageName(s2); + if (cd) + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,s2.data()); + } + else + { + codifyLines(yyscanner,s2.data()); + } + codifyLines(yyscanner,s3.data()); + } + else + { + writeFont(yyscanner,"keywordflow",yytext); + } + BEGIN(Bases); + } + +<Bases>{MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map + QCString tt(yytext); + int j=tt.find('.'); + + if (j>0) + { + QCString left=tt.left(j+1); + codifyLines(yyscanner,left.data()); + tt=tt.right(tt.length()-j-1); + left=VhdlDocGen::getIndexWord(tt.data(),0); + if (!left.isEmpty()) + { + if (left.contains('(')) + { + j=left.find('(',false); + QCString name=left.left(j); + generateClassOrGlobalLink(yyscanner,*yyextra->code,name.data()); + yyextra->PortMapComp=name; + name=tt.right(tt.length()-name.length()); + codifyLines(yyscanner,name.data()); + } + else + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,left.data()); + tt.stripPrefix(left.data()); //=tt.right(tt.length()-left.length()-1); + + yyextra->PortMapComp=left; + codifyLines(yyscanner,tt.data()); + } + } + } + else + { + if (tt.contains(':',false)) + { + codifyMapLines(yyscanner,tt.data()); + } + else + { + codifyLines(yyscanner,tt.data()); + } + } + yyextra->braceCount=1; + BEGIN(Map); + } + +<Bases>^{B}*("component"){BN}+{FUNCNAME} { // found component + appStringLower(yyextra->prevString,yytext); + QCString temp=VhdlDocGen::getIndexWord(yytext,1); + temp=temp.stripWhiteSpace(); + VhdlDocGen::deleteAllChars(temp,'\n'); + yyextra->tempComp=temp; + codifyLines(yyscanner,yytext,temp.data(),true); + yyextra->braceCount=0; + yyextra->isComponent=true; + BEGIN(ParseComponent); + } + + + +<Bases>{ARCHITECTURE} { // found architecture + yyextra->PortMapComp.resize(0); + QCString temp = VhdlDocGen::getIndexWord(yytext,3); + yyextra->currArch = true; + temp+="::"; + temp+=VhdlDocGen::getIndexWord(yytext,1); + yyextra->currClass=temp; + VhdlDocGen::deleteAllChars(temp,'\n'); + codifyLines(yyscanner,yytext,temp.data(),true); + yyextra->isPackageBody=false; + } + + +<Bases>^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body + QCString ss(yytext); + QCString temp=VhdlDocGen::getIndexWord(yytext,2); + QCStringList ql=QCStringList::split(temp,ss); + QCString ll=ql[0]; + codifyLines(yyscanner,ll.data(),yyextra->currClass.data()); + temp=temp.stripWhiteSpace(); + temp.prepend("_"); + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp.data()); + yyextra->currClass.resize(0); + yyextra->currClass=temp; + yyextra->isProto=false; + yyextra->isPackageBody=true; + } + +<Bases>{PROCESS} { // found process + yyextra->isFuncProto=true; + yyextra->funcProto.resize(0); + yyextra->funcProto.append(yytext); + yyextra->vhdlKeyDict.clear(); + appStringLower(yyextra->prevString,yytext); + if (yyextra->prevString.contains('(')) + { + yyextra->braceCount=1; + BEGIN(ParseProcessProto); + } + else + { + writeProcessProto(yyscanner); + } + } + +<Bases>("end"){BN}+("process") { // end of process + yyextra->isFuncProto=false; + codifyLines(yyscanner,yytext); + BEGIN(Bases); + } + + +<Bases>^{B}*("begin "|"begin") { + yyextra->isFuncProto=false; + writeFont(yyscanner,"vhdlkeyword",yytext); + } + +<Bases>^{B}*("use"|"library"){BN}+ { //found package or library + writeFont(yyscanner,"vhdlkeyword",yytext); + BEGIN(ParsePackage); + } + + +<Bases>^{B}*("use"){BN}+("configuration")[^\n]* { + codifyLines(yyscanner,yytext); + } + +<Bases>{FUNC} { // found function|procedure + yyextra->vhdlKeyDict.clear(); + yyextra->funcProto.resize(0); + yyextra->isProto=false; + yyextra->funcProto.append(yytext); + yyextra->braceCount=1; + BEGIN(ParseType); + } + +<Bases>^{B}*("entity"|"package"){BN}+ { + appStringLower(yyextra->prevString,yytext); + writeFont(yyscanner,"keywordflow",yytext); + yyextra->isPackageBody=false; + BEGIN(ClassesName); + } + +<Bases>"end"{BN}+"architecture"{BN}+{FUNCNAME} { + codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + yyextra->currArch = false; + } +<Bases>"end"{BN}+{FUNCNAME} { + if (yyextra->currArch) + { + codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + yyextra->currArch = false; + } + else + { + REJECT; + } + } +<Bases>"end" { + appStringLower(yyextra->prevString,yytext); + QCString temp(yytext); + temp=temp.stripWhiteSpace(); + + writeColoredWord(yyscanner,temp); + BEGIN(End); + } +<End>{ID} { + appStringLower(yyextra->prevString,yytext); + QCString temp(yytext); + temp=temp.stripWhiteSpace(); + + if (!writeColoredWord(yyscanner,temp)) + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp.data()); + } + } +<End>";" { + codifyLines(yyscanner,yytext); + BEGIN(Bases); + } +<Bases>{KEYWORD} { // found keyword + QCString qcs(yytext); + if (!writeColoredWord(yyscanner,qcs)) + { + startFontClass(yyscanner,"vhdlchar"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + } + + +<Bases>{ID} { + appStringLower(yyextra->prevString,yytext); + QCString temp(yytext); + temp=temp.stripWhiteSpace(); + + if (!writeColoredWord(yyscanner,temp)) + { + startFontClass(yyscanner,"vhdlchar"); + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp); + endFontClass(yyscanner); + } + } + +<Bases,ParseComponent>{DIGITSS} { + startFontClass(yyscanner,"vhdllogic"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +<Bases>^{B}*("use"){BN}+("entity"|"component")[^\n]* { + codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + } + + +<Bases>{TYPEKW} { + codifyLines(yyscanner,yytext); + if (yyextra->isFuncProto) + { + BEGIN(ParseFuncProto); + } + else + { + BEGIN(Bases); + } + } + +<Bases>{OPERATOR} { + startFontClass(yyscanner,"vhdlchar"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + +<Bases>","|"."|":"|"'"|"("|")" { + startFontClass(yyscanner,"vhdlchar"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + +<Bases>{STRING} { + QCString qcs(yytext); + VhdlDocGen::deleteAllChars(qcs,'"'); + VhdlDocGen::deleteAllChars(qcs,' '); + + if (VhdlDocGen::isNumber(qcs)) + { + writeFont(yyscanner,"vhdllogic",yytext); + } + else + { + writeFont(yyscanner,"keyword",yytext); + } + } + +<Bases>{B}*"#"[^\n]* { + writeFont(yyscanner,"keyword",yytext); + } + +<Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] { + writeWord(yyscanner,yytext); + //codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + } + +<Bases>^{B}*"set_"[^\n]* { + writeWord(yyscanner,yytext); + } + +<*>\n { + codifyLines(yyscanner,yytext); + BEGIN(Bases); + } + +<*>[\x80-\xFF]* { // keep utf8 characters together... + yyextra->code->codify(yytext); + } +<*>. { + yyextra->code->codify(yytext); + } + +<*>\n{TEXTT} { // found normal or special comment on its own line + QCString text(yytext); + int i=text.find("--"); + if (text.mid(i,3)=="--!") // && // hide special comment + { + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + codifyLines(yyscanner,text,0,false,true); + } + else yyextra->yyLineNr++; // skip complete line, but count line + } + else // normal comment + { + codifyLines(yyscanner,text,0,false,true); + } + } +<*>{TEXTT} { // found normal or special comment after something + QCString text(yytext); + int i=text.find("--"); + if (text.mid(i,3)=="--!") + { + // hide special comment + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + codifyLines(yyscanner,text,0,false,true); + } + } + else // normal comment + { + codifyLines(yyscanner,text,0,false,true); + } + } + +%% + +/*@ ---------------------------------------------------------------------------- + */ + +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 inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - if (g_searchCtx) + if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } -static bool checkVhdlString(QCString &name) +static bool checkVhdlString(yyscan_t yyscanner,QCString &name) { - if (name.isEmpty()) return FALSE; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (name.isEmpty()) return false; static QRegExp regg("[\\s\"]"); int len=name.length(); @@ -151,121 +963,123 @@ static bool checkVhdlString(QCString &name) QCStringList qrl=QCStringList::split(regg,name); if (VhdlDocGen::isNumber(qrl[0])) { - g_code->codify("\""); - startFontClass("vhdllogic"); + yyextra->code->codify("\""); + startFontClass(yyscanner,"vhdllogic"); QCString mid=name.mid(1,len-2); //" 1223 " - g_code->codify(mid.data()); - endFontClass(); - g_code->codify("\""); + yyextra->code->codify(mid.data()); + endFontClass(yyscanner); + yyextra->code->codify("\""); } else { - startFontClass("keyword"); - g_code->codify(name.data()); - endFontClass(); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(name.data()); + endFontClass(yyscanner); } - return TRUE; + return true; } if (VhdlDocGen::isNumber(name)) { - startFontClass("vhdllogic"); - g_code->codify(name.data()); - endFontClass(); - return TRUE; + startFontClass(yyscanner,"vhdllogic"); + yyextra->code->codify(name.data()); + endFontClass(yyscanner); + return true; } - return FALSE; + return false; } -static void addToSearchIndex(const char *text) +static void addToSearchIndex(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - Doxygen::searchIndex->addWord(text,FALSE); + yyextra->code->addWord(text,false); } } -/*! start a new line of code, inserting a line number if g_sourceFileDef - * is TRUE. If a definition starts at the current line, then the line +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef + * is true. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ -static void startCodeLine() +static void startCodeLine(yyscan_t yyscanner) { - //if (g_currentFontClass) { g_code->endFontClass(); } - if (g_sourceFileDef) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //if (yyextra->currentFontClass) { yyextra->code->endFontClass(); } + if (yyextra->sourceFileDef) { //QCString lineNumber,lineAnchor; - //lineNumber.sprintf("%05d",g_yyLineNr); - //lineAnchor.sprintf("l%05d",g_yyLineNr); - // if ((g_yyLineNr % 500) == 0) - // fprintf(stderr,"\n starting Line %d:",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) + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + // if ((yyextra->yyLineNr % 500) == 0) + // fprintf(stderr,"\n starting Line %d:",yyextra->yyLineNr); + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("startCodeLine %d d=%s\n", yyextra->yyLineNr,d ? d->name().data() : "<null>"); + if (!yyextra->includeCodeFragment && d) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - if (!g_tempComp.isEmpty() && g_currentMemberDef ) + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + if (!yyextra->tempComp.isEmpty() && yyextra->currentMemberDef ) { - //ClassDef *cf=VhdlDocGen::getClass(g_tempComp.data()); - QCString nn=g_currentMemberDef->name(); - MemberDef* mdeff=VhdlDocGen::findMember(g_tempComp,nn); + //ClassDef *cf=VhdlDocGen::getClass(yyextra->tempComp.data()); + QCString nn=yyextra->currentMemberDef->name(); + MemberDef* mdeff=VhdlDocGen::findMember(yyextra->tempComp,nn); if (mdeff) { - g_currentMemberDef=mdeff; + yyextra->currentMemberDef=mdeff; } } - g_parmType.resize(0); - g_parmName.resize(0); QCString lineAnchor; - lineAnchor.sprintf("l%05d",g_yyLineNr); - if (g_currentMemberDef) + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) { - g_code->writeLineNumber(g_currentMemberDef->getReference(), - g_currentMemberDef->getOutputFileBase(), - g_currentMemberDef->anchor(),g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { - g_code->writeLineNumber(d->getReference(), + yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - g_code->startCodeLine(g_sourceFileDef); - g_startCode=TRUE; - if (g_currentFontClass) + yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->startCode=true; + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void endCodeLine() +static void endCodeLine(yyscan_t yyscanner) { - endFontClass(); - g_code->endCodeLine(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); } -static void nextCodeLine() +static void nextCodeLine(yyscan_t yyscanner) { - if (g_startCode) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->startCode) { - endCodeLine(); // </div> + endCodeLine(yyscanner); // </div> } - const char *fc = g_currentFontClass; - if (g_yyLineNr<g_inputLines) + const char *fc = yyextra->currentFontClass; + if (yyextra->yyLineNr<yyextra->inputLines) { - g_currentFontClass = fc; - startCodeLine(); //<div> + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); //<div> } } @@ -274,10 +1088,11 @@ static void nextCodeLine() * and will be linked. */ -static void writeWord(const char *word,const char* curr_class=0,bool classLink=FALSE) +static void writeWord(yyscan_t yyscanner,const char *word,const char* curr_class,bool classLink) { - bool found=FALSE; - QCString temp; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool found=false; + QCString temp; QCString tclass(curr_class); QCString ttt(word); if (ttt.isEmpty()) return; @@ -288,69 +1103,71 @@ static void writeWord(const char *word,const char* curr_class=0,bool classLink=F { if (found) { - if (!writeColoredWord(temp)) // is it a keyword ? + if (!writeColoredWord(yyscanner,temp)) // is it a keyword ? { //if (VhdlDocGen::findKeyWord(temp)) - // writeFont("vhdlkeyword",temp.data()); - //printf("writeWord: %s\n",temp.data()); + // writeFont(yyscanner,"vhdlkeyword",temp.data()); + //printf("writeWord: %s\n",temp.data()); if (!tclass.isEmpty()) { if (!classLink) - { - generateMemLink(*g_code,tclass,temp); - } + { + generateMemLink(yyscanner,*yyextra->code,tclass,temp); + } else { - generateClassOrGlobalLink(*g_code,temp,FALSE,curr_class); + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp,false,curr_class); + } + } + else + { + if (!checkVhdlString(yyscanner,temp)) + { + yyextra->code->codify(temp.data()); } } - else - { - if (!checkVhdlString(temp)) - g_code->codify(temp.data()); - } } temp.resize(0); - found=FALSE; + found=false; } char cc[2]; cc[0]=c; cc[1]=0; - g_code->codify(cc); + yyextra->code->codify(cc); } else { - found=TRUE; + found=true; temp+=c; } } // for if (!temp.isEmpty()) { - if (!writeColoredWord(temp)) + if (!writeColoredWord(yyscanner,temp)) { if (!tclass.isEmpty()) { if (!classLink) { - generateMemLink(*g_code,tclass,temp); // generateMemLink(*g_code,g_CurrClass,left); + generateMemLink(yyscanner,*yyextra->code,tclass,temp); // generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,left); } else { - generateClassOrGlobalLink(*g_code,temp,FALSE,curr_class); + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp,false,curr_class); } } - else + else { QCString qc(temp.data()); if (VhdlDocGen::isNumber(qc)){ - startFontClass("vhdllogic"); - g_code->codify(temp.data()); - endFontClass(); + startFontClass(yyscanner,"vhdllogic"); + yyextra->code->codify(temp.data()); + endFontClass(yyscanner); } - else - g_code->codify(temp.data()); + else + yyextra->code->codify(temp.data()); } } } @@ -360,64 +1177,68 @@ static void writeWord(const char *word,const char* curr_class=0,bool classLink=F /*! write a code fragment 'text' that may span multiple lines, inserting * line numbers for each line. */ -static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,bool comment=FALSE) +static void codifyLines(yyscan_t yyscanner,const char *text,const char *cl,bool classlink,bool comment) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (text==0) return; - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); const char *p=text,*sp=p; char c; - bool done=FALSE; + bool done=false; while (!done) { sp=p; while ((c=*p++) && c!='\n') {} if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; QCString line = sp; line = line.left((int)(p-sp)-1); - //*(p-1)='\0'; - //g_code->codify(sp); if (comment) { - writeFont("comment",line.data()); + writeFont(yyscanner,"comment",line.data()); } else { - writeWord(line,cl,classlink); + writeWord(yyscanner,line,cl,classlink); } - nextCodeLine(); + nextCodeLine(yyscanner); } else { if (comment) - writeFont("comment",sp); + { + writeFont(yyscanner,"comment",sp); + } else - writeWord(sp,cl,classlink); - done=TRUE; + { + writeWord(yyscanner,sp,cl,classlink); + } + done=true; } } } /*! 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, +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, Definition *d, const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); 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(); } - bool done=FALSE; + bool done=false; char *p=(char *)text; while (!done) { @@ -426,78 +1247,58 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, while ((c=*p++) && c!='\n') {} if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; // printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); - nextCodeLine(); + nextCodeLine(yyscanner); } else { ol.writeCodeLink(ref,file,anchor,sp,tooltip); - done=TRUE; + done=true; } } } -static void setParameterList(const MemberDef *md) -{ - g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; - for (const Argument &a: md->argumentList()) - { - g_parmName = a.name.copy(); - g_parmType = a.type.copy(); - int i = g_parmType.find('*'); - if (i!=-1) g_parmType = g_parmType.left(i); - i = g_parmType.find('&'); - if (i!=-1) g_parmType = g_parmType.left(i); - g_parmType.stripPrefix("const "); - g_parmType=g_parmType.stripWhiteSpace(); - // g_theVarContext.addVariable(g_parmType,g_parmName); - } -} - - /*! writes a link to a function or procedure */ - -static void generateFuncLink(CodeOutputInterface &ol,MemberDef* mdef) +static void generateFuncLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef* mdef) { - //printf("generateFuncLink(FuncName=%s)\n",mdef->name().data()); QCString memberName=mdef->name(); if (mdef && mdef->isLinkable()) // is it a linkable class { - writeMultiLineCodeLink(ol,mdef,mdef->name()); - addToSearchIndex(memberName); + writeMultiLineCodeLink(yyscanner,ol,mdef,mdef->name()); + addToSearchIndex(yyscanner,memberName); return; } - codifyLines(memberName.data()); - addToSearchIndex(memberName); + codifyLines(yyscanner,memberName.data()); + addToSearchIndex(yyscanner,memberName); } // generateFuncLink -static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName) +static void generateMemLink(yyscan_t yyscanner,CodeOutputInterface &ol,QCString &clName,QCString& memberName) { - if (memberName.isEmpty()) return; + if (memberName.isEmpty()) return; if (clName.isEmpty()) { - codifyLines(memberName.data()); + codifyLines(yyscanner,memberName.data()); return; } - + QCString className=clName; MemberDef *md=0; //MemberDef *comp=0; - //bool isLocal=FALSE; + //bool isLocal=false; md=VhdlDocGen::findMember(className,memberName); ClassDef *po=VhdlDocGen::getClass(className.data()); - if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS) + if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS) { QCString temp=className;//.stripPrefix("_"); temp.stripPrefix("_"); @@ -506,17 +1307,17 @@ static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& m if (md && md->isLinkable()) // is it a linkable class { - writeMultiLineCodeLink(ol,md,memberName); - addToSearchIndex(memberName); + writeMultiLineCodeLink(yyscanner,ol,md,memberName); + addToSearchIndex(yyscanner,memberName); return; } // nothing found, just write out the word - codifyLines(memberName.data()); - addToSearchIndex(memberName); + codifyLines(yyscanner,memberName.data()); + addToSearchIndex(yyscanner,memberName); }// generateMemLink -static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool /*typeOnly*/, const char *curr_class) +static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, bool /*typeOnly*/, const char *curr_class) { QCString className=clName; @@ -524,9 +1325,9 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName ClassDef *cd=0; //MemberDef *md=0; - //bool isLocal=FALSE; + //bool isLocal=false; className.stripPrefix("_"); - cd = getClass(className.data()); + cd = getClass(className.data()); if (!cd && curr_class) { if (QCString(curr_class).contains(QRegExp("::"+QCString(clName)+"$"))) cd = getClass(curr_class); @@ -543,14 +1344,14 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName //{ // temp=VhdlDocGen::getClassName(cd); //} - writeMultiLineCodeLink(ol,cd,temp); - addToSearchIndex(className); + writeMultiLineCodeLink(yyscanner,ol,cd,temp); + addToSearchIndex(yyscanner,className); return; } Definition *d = cd->getOuterScope(); if (d && d->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<ClassDef*>(d); + cd = toClassDef(d); } else { @@ -559,55 +1360,59 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName } // nothing found, just write out the word - codifyLines(clName); - addToSearchIndex(clName); + codifyLines(yyscanner,clName); + addToSearchIndex(yyscanner,clName); }// generateClasss or global link /*! counts the number of lines in the input */ -static int countLines() +static int countLines(yyscan_t yyscanner) { - const char *p=g_inputString; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->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>yyextra->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++, + yyextra->needsTermination=true; + } return count; } -static void endFontClass() +static void endFontClass(yyscan_t yyscanner) { - if (g_currentFontClass) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) { - g_code->endFontClass(); - g_currentFontClass=0; + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; } } -static void startFontClass(const char *s) +static void startFontClass(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (s==0) return; - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } -static void writeFont(const char *s,const char* text) +static void writeFont(yyscan_t yyscanner,const char *s,const char* text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (s==0 || text==0) return; - //printf("writeFont(%d,\"%s\")\n",g_yyLineNr,text); - g_code->startFontClass(s); - g_code->codify(text); - g_code->endFontClass(); + //printf("writeFont(yyscanner,%d,\"%s\")\n",yyextra->yyLineNr,text); + yyextra->code->startFontClass(s); + yyextra->code->codify(text); + yyextra->code->endFontClass(); } //---------------------------------------------------------------------------- @@ -616,42 +1421,34 @@ static void appStringLower(QCString& qcs,const char* text) { qcs.resize(0); qcs.append(text); - //qcs=qcs.lower(); qcs=qcs.stripWhiteSpace(); } -//static void appString(QCString& qcs,const char* text) -//{ -// qcs.resize(0); -// qcs.append(text); -//} - -static QCString g_temp; - /* writes and links a port map statement */ -static void codifyMapLines(const char *text) +static void codifyMapLines(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (text==0) return; - g_temp.resize(0); - //bool dot=FALSE; + QCString temp; + //bool dot=false; int wordCounter=0; QCString ctemp; - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); + //printf("codifyMapLines(%d,\"%s\")\n",yyextra->yyLineNr,text); const char *p=text; //,*sp=p; char c; - bool done=FALSE; + bool done=false; while (!done) { //sp=p; while ((c=*p++) && c!='\n' && c!=':' && c != ' ' && c != '(' && c!='\0' && c!='\t') - { + { if (c!=0x9) - g_temp+=c; + temp+=c; } if (c=='\0') return; - if (!g_temp.isEmpty()) wordCounter++; + if (!temp.isEmpty()) wordCounter++; - if (!g_temp.isEmpty()) + if (!temp.isEmpty()) { // different kinds of component instantiations // xxx:yyy (generic/port) map( @@ -659,50 +1456,51 @@ static void codifyMapLines(const char *text) // xxx: entity yyy(zzz) (generic/port) map( if (wordCounter==2 || wordCounter==3) { - QCString q=g_temp.lower(); // consider (upper/lower) cases - if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic") - { - generateMemLink(*g_code,g_CurrClass,g_temp); - } - else - { - g_PortMapComp=g_temp; - generateClassOrGlobalLink(*g_code,g_temp); - } + QCString q=temp.lower(); // consider (upper/lower) cases + if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic") + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp); + } + else + { + yyextra->PortMapComp=temp; + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp); + } } - else + else { - generateMemLink(*g_code,g_CurrClass,g_temp); + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp); } } ctemp.fill(c,1); - codifyLines(ctemp.data()); + codifyLines(yyscanner,ctemp.data()); ctemp.resize(0); - g_temp.resize(0); + temp.resize(0); }//while -}//codifymaplines +}//codifyMapLines /* -* writes a function|procedure prototype and links the function|procedure name +* writes a function|procedure prototype and links the function|procedure name */ -static void writeFuncProto() +static void writeFuncProto(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString name,ret; - VhdlDocGen::parseFuncProto(g_FuncProto,name,ret,FALSE); + VhdlDocGen::parseFuncProto(yyextra->funcProto,name,ret,false); if (name.isEmpty()) { - codifyLines(g_FuncProto.data(),g_CurrClass.data()); + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); return; } - QCStringList qlist=QCStringList::split(name,g_FuncProto); + QCStringList qlist=QCStringList::split(name,yyextra->funcProto); QCString temp=qlist[0]; - codifyLines(temp.data(),g_CurrClass.data()); - g_FuncProto.stripPrefix(temp.data()); + codifyLines(yyscanner,temp.data(),yyextra->currClass.data()); + yyextra->funcProto.stripPrefix(temp.data()); temp.resize(0); - temp=g_CurrClass; - if (isPackageBody) + temp=yyextra->currClass; + if (yyextra->isPackageBody) { temp.stripPrefix("_");// _{package body name} } @@ -710,844 +1508,69 @@ static void writeFuncProto() if (mdef) { - generateFuncLink(*g_code,mdef); - g_FuncProto.stripPrefix(name.data()); - codifyLines(g_FuncProto.data(),g_CurrClass.data()); + generateFuncLink(yyscanner,*yyextra->code,mdef); + yyextra->funcProto.stripPrefix(name.data()); + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); } else { - codifyLines(g_FuncProto.data(),g_CurrClass.data()); + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); } }// writeFuncProto /* writes a process prototype to the output */ - static void writeProcessProto(){ - codifyLines(g_FuncProto.data(),g_CurrClass.data()); - g_vhdlKeyDict.clear(); +static void writeProcessProto(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); + yyextra->vhdlKeyDict.clear(); }// writeProcessProto /* writes a keyword */ -static bool writeColoredWord(QCString& word ) +static bool writeColoredWord(yyscan_t yyscanner,QCString& word ) { QCString qcs=word.lower(); - QCString *ss=VhdlDocGen::findKeyWord(qcs); - if (ss) + const char *ss=VhdlDocGen::findKeyWord(qcs); + if (ss) { - writeFont(ss->data(),word.data()); - return TRUE; + writeFont(yyscanner,ss,word.data()); + return true; } - return FALSE; + return false; } -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +//----------------------------------------------------------------------------------- -static int yyread(char *buf,int max_size) +struct VHDLCodeParser::Private { - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} - - -B [ \t] -BN [ \t\n\r] -STRING ["][^"\n]*["] -NAME [a-z_A-Z][ a-z_A-Z0-9]* -FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]* -ID "$"?[a-z_A-Z][a-z_A-Z0-9]* -SPECSIGN [:;, +*&\/=<>'\t]* -DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")* -ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}* -ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}* - -ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME}{BN}+("is") -PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+ - -END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for") -END2 [^a-zA-Z_]("end"){BN}*[;] -END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;] -END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;] -ENDEFUNC {END3}|{END4}|{END2} - -KEYWORD ("of"|"new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in") -TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration") -FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(") + yyscan_t yyscanner; + vhdlcodeYY_state state; +}; -ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":=" -ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" -LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" -BITOP "&"|"|"|"^"|"<<"|">>"|"~" -OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} - -PORT {B}*("port"){BN}*("(") -GENERIC {B}*("generic"){BN}*("(") - -BRACEOPEN [(]{1} -BRACECLOSE [)]{1} - -TEXTT {B}*"--"[^\n]* - -MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) -MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1} -MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) -MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1}) - -XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFIG"|"CONFIG_MODE"|"COOL_CLK"|"DATA_GATE"|"DCI_VALUE"|"DISABLE"|"DRIVE"|"DROP_SPEC"|"ENABLE"|"FAST"|"FEEDBACK"|"FILE"|"FLOAT"|"FROM-THRU-TO"|"FROM-TO"|"HBLKNM"|"HU_SET"|"INREG"|"IOB"|"IOBDELAY"|"IOSTANDARD"|"KEEP"|"KEEPER"|"LOC"|"LOCATE"|"LOCK_PINS"|"MAP"|"MAXDELAY"|"MAXPT"|"MAXSKEW"|"NODELAY"|"NOREDUCE"|"OFFSET"|"OPEN_DRAIN"|"OPT_EFFORT"|"OPTIMIZE"|"PERIOD"|"PIN"|"PRIORITY"|"PROHIBIT"|"PULLDOWN"|"PULLUP"|"PWR_MODE"|"REG"|"RLOC"|"RLOC_ORIGIN"|"RLOC_RANGE"|"SAVE NET"|"FLAG"|"SYSTEM_JITTER"|"TEMPERATURE"|"TIMEGRP"|"TIMESPEC"|"VOLTAGE" - -%option noyywrap -%option nounput - -%x Bases -%x ParseType -%x ParseFuncProto -%x ParseComponent -%x ParsePackage -%x ParseProcessProto -%x ClassName -%x PackageName -%x ClassVar -%x ClassesName -%x Map -%x End -%x Body - -%% - -. { - BEGIN(Bases); - } - -<Map>{BRACEOPEN} { - g_braceCount++; - writeFont("vhdlchar",vhdlcodeYYtext); - BEGIN(Map); - } - -<Map>[^()\n,--]* { /* write and link a port map lines */ - QCString tt(vhdlcodeYYtext); - VhdlDocGen::deleteAllChars(tt,','); - QRegExp r("=>"); - QCStringList ql=QCStringList::split(r,tt); - if (ql.count()>=2) - { - unsigned int index=0; - QCString t1=ql[0]; - char cc=t1.at(index); - while (cc==' ' || cc=='\t') - { - char c2[2]; - c2[0]=cc; - c2[1]=0; - g_code->codify(c2); - index++; - if (index>=t1.size()) break; - cc=t1.at(index); - } - - QCString s1=t1; - s1=s1.stripWhiteSpace(); - - // if (!g_PortMapComp.isEmpty()) - generateMemLink(*g_code,g_PortMapComp,s1); - while (index++<t1.size()) - { - cc=t1.at(index); - if (cc==' ' || cc=='\t') - { - char c2[2]; - c2[0]=cc; - c2[1]=0; - g_code->codify(c2); - } - } - codifyLines("=>"); - index=0; - QCString s2=ql[1]; - t1=s2; - cc=t1.at(index); - while (cc==' ' || cc=='\t') - { - char c2[2]; - c2[0]=cc; - c2[1]=0; - g_code->codify(c2); - index++; - if (index>=t1.size()) break; - cc=t1.at(index); - } - s2=s2.stripWhiteSpace(); - if (!checkVhdlString(s2)) - generateMemLink(*g_code,g_CurrClass,s2); - while (index++<t1.size()) - { - if (t1.at(index)==' ') - { - g_code->codify(" "); - } - } - } - else - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - } - BEGIN(Map); - } - -<Map>"\n"|"," { - codifyLines(vhdlcodeYYtext); - BEGIN(Map); - } - -<Map>{BRACECLOSE} { - g_braceCount--; - writeFont("vhdlchar",vhdlcodeYYtext); - if (g_braceCount==0) - { - BEGIN(Bases); - } - } - -<ParseFuncProto>{NAME} { - QCString tmp(vhdlcodeYYtext); - tmp=tmp.stripWhiteSpace(); - appStringLower(g_PrevString,vhdlcodeYYtext); - g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data())); - if (!writeColoredWord(tmp)) - { - generateMemLink(*g_code,g_CurrClass,tmp); - } - BEGIN(Bases); - } - -<ParseType>{STRING} { - QCString qcs(vhdlcodeYYtext); - VhdlDocGen::deleteAllChars(qcs,'"'); - VhdlDocGen::deleteAllChars(qcs,' '); - if (VhdlDocGen::isNumber(qcs)) - writeFont("vhdllogic",vhdlcodeYYtext); - else - writeFont("keyword",vhdlcodeYYtext); - } - -<ParseType>"\n" { - g_FuncProto.append(vhdlcodeYYtext); - if (isProto) - { - codifyLines(vhdlcodeYYtext); - } - BEGIN(ParseType); - } - - -<ParseType>{TEXTT} { - g_FuncProto.append(vhdlcodeYYtext); - if (isProto) - { - writeFont("keyword",vhdlcodeYYtext); - } - BEGIN(ParseType); - } - -<ParseType>{ENDEFUNC} { - QRegExp regg("[\\s]"); - QCString tt(vhdlcodeYYtext); - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - tt=tt.lower(); - VhdlDocGen::deleteAllChars(tt,';'); - tt.stripWhiteSpace(); - QCStringList ql=QCStringList::split(regg,tt); - int index=ql.findIndex(QCString("if"))+1; - index+=ql.findIndex(QCString("case"))+1; - index+=ql.findIndex(QCString("loop"))+1; - index+=ql.findIndex(QCString("generate"))+1; - if (index==0) - { - BEGIN(Bases); - } - else - { - BEGIN(ParseType); - } - } - -<ParseType>{END1} { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - g_vhdlKeyDict.clear(); - } - -<ParseType>^{B}*("begin "|"begin") { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - isFuncProto=FALSE; - } - -<ParseType>{SPECSIGN} { - g_FuncProto.append(vhdlcodeYYtext); - if (isProto) - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - } - } - -<ParseType>["_a-zA-Z0-9]* { - QCString val(vhdlcodeYYtext); - g_FuncProto.append(vhdlcodeYYtext); - appStringLower(g_PrevString,vhdlcodeYYtext); - - if (isFuncProto && g_braceCount==0) - { - g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data())); - } - - if (isProto) - { - if (!writeColoredWord(val)) - { - if (!isFuncProto && !g_vhdlKeyDict.find(g_PrevString)) - { - val=val.stripWhiteSpace(); - if (VhdlDocGen::isNumber(val)) - { - startFontClass("vhdllogic"); - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - endFontClass(); - } - else - generateMemLink(*g_code,g_CurrClass,val); - } - else - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - } - } - } - BEGIN(ParseType); - } - -<ParseType>{BRACEOPEN} { - g_braceCount++; - g_FuncProto+='('; - if (isProto) - { - writeFont("vhdlchar",vhdlcodeYYtext); - } - BEGIN(ParseType); - } - -<ParseType>{BRACECLOSE} { - g_braceCount--; - g_FuncProto+=')'; - if (isProto) - { - writeFont("vhdlchar",vhdlcodeYYtext); - } - if (g_braceCount==0 && !isProto)// && !isPackageBody) - { - isProto=TRUE; - appStringLower(g_PrevString,vhdlcodeYYtext); - writeFuncProto(); - BEGIN(Bases); - } - if (isPackageBody) - { - BEGIN(ParseType); - } - } - - -<ClassesName>{FUNCNAME} { - appStringLower(g_PrevString,vhdlcodeYYtext); - g_CurrClass.resize(0); - g_CurrClass.append(vhdlcodeYYtext); - g_CurrClass=g_CurrClass.stripWhiteSpace(); - - generateClassOrGlobalLink(*g_code,vhdlcodeYYtext); - BEGIN(Bases); - } - - -<ParseComponent>{BRACEOPEN} { - g_braceCount++; - g_code->codify(vhdlcodeYYtext); - } - - -<ParseComponent>{BRACECLOSE} { - g_braceCount--; - g_code->codify(vhdlcodeYYtext); - if (g_braceCount==0 && !isComponent) - { - g_tempComp.resize(0); - BEGIN(Bases); - } - else - { - BEGIN(ParseComponent); - } - } - -<ParseComponent>{B}*"-" { - if (strlen(vhdlcodeYYtext)>=2) // found text ? - { - writeFont("keyword",vhdlcodeYYtext); - } - else - { - writeFont("vhdlchar",vhdlcodeYYtext); - } - } - -<ParseComponent>{SPECSIGN} { - codifyLines(vhdlcodeYYtext); - } - - - -<ParseComponent>"\n"|" " { - codifyLines(vhdlcodeYYtext); - } - -<ParseComponent>{DIGITSS} { - startFontClass("vhdllogic"); - codifyLines(vhdlcodeYYtext); - endFontClass(); - } - -<ParseComponent>{PORT} { - codifyLines(vhdlcodeYYtext); - g_braceCount=1; - isComponent=FALSE; - } - -<ParseComponent>{GENERIC} { - codifyLines(vhdlcodeYYtext); - g_braceCount=1; - } - -<ParseComponent>[_a-zA_Z][_a-zA-Z0-9]* { - QCString temp(vhdlcodeYYtext); - appStringLower(g_PrevString,vhdlcodeYYtext); - if (!checkVhdlString(temp)){ - if (!writeColoredWord(g_PrevString)) - { - generateMemLink(*g_code,g_tempComp,temp); - } - } - } - -<ParseComponent>{STRING} { - QCString temp(vhdlcodeYYtext); - if (!checkVhdlString(temp)) - codifyLines(vhdlcodeYYtext); - } - - -<ParseProcessProto>[^()]* { - g_FuncProto.append(vhdlcodeYYtext); - } - - - -<ParseProcessProto>{BRACEOPEN} { - g_FuncProto.append(vhdlcodeYYtext); - g_braceCount++; - } - -<ParseProcessProto>{BRACECLOSE} { - g_FuncProto.append(vhdlcodeYYtext); - g_braceCount--; - if (g_braceCount==0) - { - writeProcessProto(); - BEGIN(Bases); - } - } - -<ParsePackage>[^:;]* { //found package - QCString temp(vhdlcodeYYtext); - QCStringList strl=QCStringList::split(".",temp); - if (strl.count()>2) - { - QCString s1=strl[0]; - QCString s2=strl[1]; - QCString s3=strl[2]; - s1.append("."); - s3.prepend("."); - codifyLines(s1.data(),g_CurrClass.data()); - ClassDef *cd=VhdlDocGen::getPackageName(s2); - if (cd) - { - generateClassOrGlobalLink(*g_code,s2.data()); - } - else - { - codifyLines(s2.data()); - } - codifyLines(s3.data()); - } - else - { - writeFont("keywordflow",vhdlcodeYYtext); - } - BEGIN(Bases); - } - -<Bases>{MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map - QCString tt(vhdlcodeYYtext); - /* - if (tt.contains(':',FALSE)) - { - isStartMap=TRUE; - } - else - { - isStartMap=FALSE; - } - */ - int j=tt.find('.'); - - if (j>0) - { - QCString left=tt.left(j+1); - codifyLines(left.data()); - tt=tt.right(tt.length()-j-1); - left=VhdlDocGen::getIndexWord(tt.data(),0); - if (!left.isEmpty()) - { - if (left.contains('(')) - { - j=left.find('(',FALSE); - QCString name=left.left(j); - generateClassOrGlobalLink(*g_code,name.data()); - g_PortMapComp=name; - name=tt.right(tt.length()-name.length()); - codifyLines(name.data()); - } - else - { - generateClassOrGlobalLink(*g_code,left.data()); - tt.stripPrefix(left.data()); //=tt.right(tt.length()-left.length()-1); - - g_PortMapComp=left; - codifyLines(tt.data()); - } - } - } - else - { - if (tt.contains(':',FALSE)) - codifyMapLines(tt.data()); - else - codifyLines(tt.data()); - } - g_braceCount=1; - BEGIN(Map); - } - -<Bases>^{B}*("component"){BN}+{FUNCNAME} { // found component - appStringLower(g_PrevString,vhdlcodeYYtext); - // writeFont("keywordflow",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data()); - // writeFont("vhdlkeyword"," "); - QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); - temp=temp.stripWhiteSpace(); - VhdlDocGen::deleteAllChars(temp,'\n'); - g_tempComp=temp; - codifyLines(vhdlcodeYYtext,temp.data(),TRUE); - g_braceCount=0; - - //if (getClass(temp.data())) - // generateClassOrGlobalLink(*g_code,temp.data()); - //else - // generateMemLink(*g_code,g_CurrClass,temp); - - isComponent=TRUE; - BEGIN(ParseComponent); - } - - - -<Bases>{ARCHITECTURE} { // found architecture - g_PortMapComp.resize(0); - // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data()); - // writeFont("vhdlkeyword"," "); - // writeFont("vhdlchar",VhdlDocGen::getIndexWord(vhdlcodeYYtext,1).data()); - // writeFont("vhdlkeyword"," "); - // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,2).data()); - // writeFont("vhdlkeyword"," "); - //QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); - //temp=temp.stripWhiteSpace(); - //temp+=("-"); - //temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,3); - QCString temp = VhdlDocGen::getIndexWord(vhdlcodeYYtext,3); - g_CurrARCH = TRUE; - temp+="::"; - temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); - g_CurrClass=temp; - VhdlDocGen::deleteAllChars(temp,'\n'); - codifyLines(vhdlcodeYYtext,temp.data(),TRUE); - //generateClassOrGlobalLink(*g_code,temp.data()); - isPackageBody=FALSE; - } - - -<Bases>^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body - QCString ss(vhdlcodeYYtext); - QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,2); - QCStringList ql=QCStringList::split(temp,ss); - QCString ll=ql[0]; - codifyLines(ll.data(),g_CurrClass.data()); - temp=temp.stripWhiteSpace(); - temp.prepend("_"); - generateClassOrGlobalLink(*g_code,temp.data()); - g_CurrClass.resize(0); - g_CurrClass=temp; - isProto=FALSE; - isPackageBody=TRUE; - // BEGIN(ClassesName); - } - -<Bases>{PROCESS} { // found process - isFuncProto=TRUE; - g_FuncProto.resize(0); - g_FuncProto.append(vhdlcodeYYtext); - g_vhdlKeyDict.clear(); - appStringLower(g_PrevString,vhdlcodeYYtext); - if (g_PrevString.contains('(')) - { - g_braceCount=1; - BEGIN(ParseProcessProto); - } - else - { - writeProcessProto(); - } - } - -<Bases>("end"){BN}+("process") { // end of process - isFuncProto=FALSE; - codifyLines(vhdlcodeYYtext); - BEGIN(Bases); - } - - -<Bases>^{B}*("begin "|"begin") { - isFuncProto=FALSE; - writeFont("vhdlkeyword",vhdlcodeYYtext); - } - -<Bases>^{B}*("use"|"library"){BN}+ { //found package or library - writeFont("vhdlkeyword",vhdlcodeYYtext); - BEGIN(ParsePackage); - } - - -<Bases>^{B}*("use"){BN}+("configuration")[^\n]* { - codifyLines(vhdlcodeYYtext); - } - - - -<Bases>{FUNC} { // found function|procedure - g_vhdlKeyDict.clear(); - g_FuncProto.resize(0); - isProto=FALSE; - g_FuncProto.append(vhdlcodeYYtext); - g_braceCount=1; - BEGIN(ParseType); - } - - - -<Bases>^{B}*("entity"|"package"){BN}+ { - appStringLower(g_PrevString,vhdlcodeYYtext); - writeFont("keywordflow",vhdlcodeYYtext); - isPackageBody=FALSE; - BEGIN(ClassesName); - } - - -<Bases>"end"{BN}+"architecture"{BN}+{FUNCNAME} { - codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - g_CurrARCH = FALSE; - } -<Bases>"end"{BN}+{FUNCNAME} { - if (g_CurrARCH) - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - g_CurrARCH = FALSE; - } - else - REJECT; - } -<Bases>"end" { - appStringLower(g_PrevString,vhdlcodeYYtext); - QCString temp(vhdlcodeYYtext); - temp=temp.stripWhiteSpace(); - - writeColoredWord(temp); - BEGIN(End); - } -<End>{ID} { - appStringLower(g_PrevString,vhdlcodeYYtext); - QCString temp(vhdlcodeYYtext); - temp=temp.stripWhiteSpace(); - - if (!writeColoredWord(temp)) - { - generateClassOrGlobalLink(*g_code,temp.data()); - } - } -<End>";" { - codifyLines(vhdlcodeYYtext); - BEGIN(Bases); - } -<Bases>{KEYWORD} { // found keyword - QCString qcs(vhdlcodeYYtext); - if (!writeColoredWord(qcs)) - { - startFontClass("vhdlchar"); - g_code->codify(vhdlcodeYYtext); - endFontClass(); - } - } - - -<Bases>{ID} { - appStringLower(g_PrevString,vhdlcodeYYtext); - QCString temp(vhdlcodeYYtext); - temp=temp.stripWhiteSpace(); - - if (!writeColoredWord(temp)) - { - startFontClass("vhdlchar"); - generateMemLink(*g_code,g_CurrClass,temp); - endFontClass(); - } - } - -<Bases,ParseComponent>{DIGITSS} { - startFontClass("vhdllogic"); - codifyLines(vhdlcodeYYtext); - endFontClass(); - } - -<Bases>^{B}*("use"){BN}+("entity"|"component")[^\n]* { - codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - } - - -<Bases>{TYPEKW} { - codifyLines(vhdlcodeYYtext); - if (isFuncProto) - { - BEGIN(ParseFuncProto); - } - else - { - BEGIN(Bases); - } - } - -<Bases>{OPERATOR} { - startFontClass("vhdlchar"); - g_code->codify(vhdlcodeYYtext); - endFontClass(); - } - -<Bases>","|"."|":"|"'"|"("|")" { - startFontClass("vhdlchar"); - g_code->codify(vhdlcodeYYtext); - endFontClass(); - } - -<Bases>{STRING} { - QCString qcs(vhdlcodeYYtext); - VhdlDocGen::deleteAllChars(qcs,'"'); - VhdlDocGen::deleteAllChars(qcs,' '); - - if (VhdlDocGen::isNumber(qcs)) - writeFont("vhdllogic",vhdlcodeYYtext); - else - writeFont("keyword",vhdlcodeYYtext); - } - -<Bases>{B}*"#"[^\n]* { - writeFont("keyword",vhdlcodeYYtext); - } - -<Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] { - writeWord(yytext); - //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - } - -<Bases>^{B}*"set_"[^\n]* { - writeWord(yytext); - } - -<*>\n { - codifyLines(vhdlcodeYYtext); - BEGIN(Bases); - } - -<*>. { - g_code->codify(vhdlcodeYYtext); - } - -<*>\n{TEXTT} { // found normal or special comment on its own line - QCString text(vhdlcodeYYtext); - int i=text.find("--"); - if (text.mid(i,3)=="--!") // && // hide special comment - { - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - codifyLines(text,0,FALSE,TRUE); - } - else g_yyLineNr++; // skip complete line, but count line - } - else // normal comment - { - codifyLines(text,0,FALSE,TRUE); - } - } -<*>{TEXTT} { // found normal or special comment after something - QCString text(vhdlcodeYYtext); - int i=text.find("--"); - if (text.mid(i,3)=="--!") - { - // hide special comment - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - codifyLines(text,0,FALSE,TRUE); - } - } - else // normal comment - { - codifyLines(text,0,FALSE,TRUE); - } - } - -%% +VHDLCodeParser::VHDLCodeParser() : p(std::make_unique<Private>()) +{ + vhdlcodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + vhdlcodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); +} -/*@ ---------------------------------------------------------------------------- - */ +VHDLCodeParser::~VHDLCodeParser() +{ + vhdlcodeYYlex_destroy(p->yyscanner); +} -static void resetVhdlCodeParserState() +void VHDLCodeParser::resetCodeParserState() { - g_vhdlKeyDict.setAutoDelete(TRUE); - g_vhdlKeyDict.clear(); + p->state.vhdlKeyDict.clear(); } void VHDLCodeParser::parseCode(CodeOutputInterface &od, const char *className, - const QCString &s, + const QCString &s, SrcLangExt, bool exBlock, const char *exName, @@ -1560,96 +1583,84 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, const Definition *searchCtx, bool /* collectXRefs */) { + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); + printlex(yy_flex_debug, true, __FILE__, fd ? fd->fileName().data(): NULL); if (memberDef) { const ClassDef *dd=memberDef->getClassDef(); - if (dd) g_CurrClass=dd->name(); + if (dd) yyextra->currClass=dd->name(); } - resetVhdlCodeParserState(); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx = searchCtx; + resetCodeParserState(); + yyextra->code = &od; + yyextra->inputString = s; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = false; + yyextra->searchCtx = searchCtx; if (startLine!=-1) - g_yyLineNr = startLine; + yyextra->yyLineNr = startLine; else - g_yyLineNr = 1; + yyextra->yyLineNr = 1; if (endLine!=-1) - g_inputLines = endLine+1; + yyextra->inputLines = endLine+1; else - g_inputLines = g_yyLineNr + countLines() - 1; + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; - // g_theCallContext.clear(); - g_classScope = className; - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; - bool cleanupSourceDef = FALSE; + // yyextra->theCallContext.clear(); + yyextra->exampleBlock = exBlock; + yyextra->exampleName = exName; + yyextra->sourceFileDef = fd; + bool cleanupSourceDef = false; if (exBlock && fd==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",exName); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",exName); + cleanupSourceDef = true; } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_currentDefinition = 0; - g_currentMemberDef = 0; - g_vhdlMember=0; - if (!g_exampleName.isEmpty()) + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->vhdlMember=0; + if (!yyextra->exampleName.isEmpty()) { - g_exampleFile = convertNameToFile(g_exampleName+"-example"); + yyextra->exampleFile = convertNameToFile(yyextra->exampleName+"-example"); } - g_includeCodeFragment = inlineFragment; - startCodeLine(); - // g_type.resize(0); - // g_name.resize(0); - // g_args.resize(0); - g_parmName.resize(0); - g_parmType.resize(0); - if(!g_lexInit) - VhdlDocGen::init(); - if (memberDef) + yyextra->includeCodeFragment = inlineFragment; + startCodeLine(yyscanner); + if (!yyextra->lexInit) { - setParameterList(memberDef); + VhdlDocGen::init(); + yyextra->lexInit=true; } - /*int iLine=*/countLines(); - vhdlcodeYYrestart( vhdlcodeYYin ); + /*int iLine=*/countLines(yyscanner); + vhdlcodeYYrestart( 0, yyscanner ); BEGIN( Bases ); - vhdlcodeYYlex(); - g_lexInit=TRUE; - if (g_needsTermination) + vhdlcodeYYlex(yyscanner); + if (yyextra->needsTermination) { - endCodeLine(); + endCodeLine(yyscanner); } if (cleanupSourceDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } - g_startCode=FALSE; - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); -} + yyextra->startCode=false; -void codeFreeVhdlScanner() -{ -#if defined(YY_FLEX_SUBMINOR_VERSION) - if (g_lexInit) - { - vhdlcodeYYlex_destroy(); - } -#endif + // write the tooltips + TooltipManager::instance().writeTooltips(od); + + printlex(yy_flex_debug, false, __FILE__, fd ? fd->fileName().data(): NULL); } #if USE_STATE2STRING diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 8e311b7..dd208aa 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -55,6 +55,7 @@ #include "filename.h" #include "membergroup.h" #include "memberdef.h" +#include "membername.h" #include "plantuml.h" #include "vhdljjparser.h" #include "VhdlParser.h" @@ -63,14 +64,9 @@ //#define DEBUGFLOW #define theTranslator_vhdlType theTranslator->trVhdlType -static QDict<QCString> g_vhdlKeyDict0(17,FALSE); -static QDict<QCString> g_vhdlKeyDict1(17,FALSE); -static QDict<QCString> g_vhdlKeyDict2(17,FALSE); -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 addInstance(ClassDef* entity, ClassDef* arch, ClassDef *inst, +static void addInstance(ClassDefMutable* entity, ClassDefMutable* arch, ClassDefMutable *inst, const std::shared_ptr<Entry> &cur); //---------- create svg ------------------------------------------------------------- @@ -178,10 +174,8 @@ static void createSVG() // Brief descriptions for entities are shown too. void VhdlDocGen::writeOverview() { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; bool found=FALSE; - for ( ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ENTITYCLASS ) { @@ -205,14 +199,14 @@ void VhdlDocGen::writeOverview() startDot(t); - for (cli.toFirst() ; (cd=cli.current()) ; ++cli ) + for (const auto &cd : *Doxygen::classLinkedMap) { if ((VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS ) { continue; } - QList<MemberDef>* port= getPorts(cd); + QList<MemberDef>* port= getPorts(cd.get()); if (port==0) { continue; @@ -225,30 +219,23 @@ void VhdlDocGen::writeOverview() } startTable(t,cd->name()); - writeClassToDot(t,cd); + writeClassToDot(t,cd.get()); writeTable(port,t); endTable(t); - // writeVhdlPortToolTip(t,port,cd); - writeVhdlEntityToolTip(t,cd); + writeVhdlEntityToolTip(t,cd.get()); delete port; - BaseClassList *bl=cd->baseClasses(); - if (bl) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*bl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - ClassDef *bClass=bcd->classDef; - QCString dotn=cd->name()+":"; - dotn+=cd->name(); - QCString csc=bClass->name()+":"; - csc+=bClass->name(); - // fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data()); - writeVhdlDotLink(t,dotn,csc,0); - } - }// if bl + ClassDef *bClass=bcd.classDef; + QCString dotn=cd->name()+":"; + dotn+=cd->name(); + QCString csc=bClass->name()+":"; + csc+=bClass->name(); + // fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data()); + writeVhdlDotLink(t,dotn,csc,0); + } }// for endDot(t); @@ -567,11 +554,8 @@ VhdlDocGen::~VhdlDocGen() { } -void VhdlDocGen::init() -{ - // vhdl keywords included VHDL 2008 -const char* g_vhdlKeyWordMap0[] = +static const std::set< std::string > g_vhdlKeyWordSet0 = { "abs","access","after","alias","all","and","architecture","array","assert","assume","assume_guarantee","attribute", "begin","block","body","buffer","bus", @@ -592,100 +576,57 @@ const char* g_vhdlKeyWordMap0[] = "unaffected","units","until","use", "variable","vmode","vprop","vunit", "wait","when","while","with", - "xor","xnor", - 0 + "xor","xnor" }; // type -const char* g_vhdlKeyWordMap1[] = +static const std::set< std::string> g_vhdlKeyWordSet1 = { "natural","unsigned","signed","string","boolean", "bit","bit_vector","character", "std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer", - "real","float","ufixed","sfixed","time","positive",0 + "real","float","ufixed","sfixed","time","positive" }; // logic -const char* g_vhdlKeyWordMap2[] = +static const std::set< std::string > g_vhdlKeyWordSet2 = { - "abs","and","or","not","mod", "xor","rem","xnor","ror","rol","sla", - "sll",0 + "abs","and","or","not","mod","xor","rem","xnor","ror","rol","sla","sll" }; // predefined attributes -const char* g_vhdlKeyWordMap3[] = +static const std::set< std::string > g_vhdlKeyWordSet3 = { -"base","left","right","high","low","ascending", -"image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low", -"range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event", -"active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name",0 + "base","left","right","high","low","ascending", + "image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low", + "range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event", + "active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name" }; - int j=0; - g_vhdlKeyDict0.setAutoDelete(TRUE); - g_vhdlKeyDict1.setAutoDelete(TRUE); - g_vhdlKeyDict2.setAutoDelete(TRUE); - g_vhdlKeyDict3.setAutoDelete(TRUE); - - while (g_vhdlKeyWordMap0[j]) - { - g_vhdlKeyDict0.insert(g_vhdlKeyWordMap0[j], - new QCString(g_vhdlKeyWordMap0[j])); - j++; - } - - j=0; - while (g_vhdlKeyWordMap1[j]) - { - g_vhdlKeyDict1.insert(g_vhdlKeyWordMap1[j], - new QCString(g_vhdlKeyWordMap1[j])); - j++; - } - - j=0; - while (g_vhdlKeyWordMap2[j]) - { - g_vhdlKeyDict2.insert(g_vhdlKeyWordMap2[j], - new QCString(g_vhdlKeyWordMap2[j])); - j++; - } - - j=0; - while (g_vhdlKeyWordMap3[j]) - { - g_vhdlKeyDict3.insert(g_vhdlKeyWordMap3[j], - new QCString(g_vhdlKeyWordMap3[j])); - j++; - } - -}// buildKeyMap +void VhdlDocGen::init() +{ +} /*! * returns the color of a keyword */ - -QCString* VhdlDocGen::findKeyWord(const QCString& tmp) +const char* VhdlDocGen::findKeyWord(const QCString& kw) { - static QCString vhdlkeyword("vhdlkeyword"); - static QCString vhdltype("keywordtype"); - static QCString vhdllogic("vhdllogic"); - static QCString preprocessor("keywordflow"); + std::string word=kw.lower().str(); - QCString word=tmp.lower(); + if (word.empty()) return 0; - if (word.isEmpty() || word.at(0)=='\0') return 0; + if (g_vhdlKeyWordSet0.find(word)!=g_vhdlKeyWordSet0.end()) + return "keywordflow"; - if (g_vhdlKeyDict0.find(word)) - return &preprocessor; + if (g_vhdlKeyWordSet1.find(word)!=g_vhdlKeyWordSet1.end()) + return "keywordtype"; - if (g_vhdlKeyDict1.find(word)) - return &vhdltype; + if (g_vhdlKeyWordSet2.find(word)!=g_vhdlKeyWordSet2.end()) + return "vhdllogic"; - if (g_vhdlKeyDict2.find(word)) - return &vhdllogic; - - if (g_vhdlKeyDict3.find(word)) - return &vhdlkeyword; + if (g_vhdlKeyWordSet3.find(word)!=g_vhdlKeyWordSet3.end()) + return "vhdlkeyword"; return 0; } @@ -693,21 +634,12 @@ QCString* VhdlDocGen::findKeyWord(const QCString& tmp) ClassDef *VhdlDocGen::getClass(const char *name) { if (name==0 || name[0]=='\0') return 0; - - ClassDef *cd=0; - QCString temp(name); - //temp=temp.lower(); - temp=temp.stripWhiteSpace(); - cd= Doxygen::classSDict->find(temp.data()); - return cd; + return Doxygen::classLinkedMap->find(QCString(name).stripWhiteSpace()); } ClassDef* VhdlDocGen::getPackageName(const QCString & name) { - ClassDef* cd=0; - cd=getClass(name); - - return cd; + return getClass(name); } static QMap<QCString,MemberDef*> varMap; @@ -1039,12 +971,10 @@ void VhdlDocGen::writeInlineClassLink(const ClassDef* cd ,OutputList& ol) */ void VhdlDocGen::findAllArchitectures(QList<QCString>& qll,const ClassDef *cd) { - ClassDef *citer; - ClassSDict::Iterator cli(*Doxygen::classSDict); - for ( ; (citer=cli.current()) ; ++cli ) + for (const auto &citer : *Doxygen::classLinkedMap) { QCString jj=citer->className(); - if (cd != citer && jj.contains('-')!=-1) + if (cd != citer.get() && jj.contains('-')!=-1) { QCStringList ql=QCStringList::split("-",jj); QCString temp=ql[1]; @@ -1057,13 +987,10 @@ void VhdlDocGen::findAllArchitectures(QList<QCString>& qll,const ClassDef *cd) }// for }//findAllArchitectures -ClassDef* VhdlDocGen::findArchitecture(const ClassDef *cd) +const ClassDef* VhdlDocGen::findArchitecture(const ClassDef *cd) { - ClassDef *citer; QCString nn=cd->name(); - ClassSDict::Iterator cli(*Doxygen::classSDict); - - for ( ; (citer=cli.current()) ; ++cli ) + for (const auto &citer : *Doxygen::classLinkedMap) { QCString jj=citer->name(); QCStringList ql=QCStringList::split(":",jj); @@ -1071,7 +998,7 @@ ClassDef* VhdlDocGen::findArchitecture(const ClassDef *cd) { if (ql[0]==nn ) { - return citer; + return citer.get(); } } } @@ -1272,7 +1199,6 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD QRegExp reg("[\\[\\]\\.\\/\\:\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]"); QCString qcs = s; qcs+=QCString(" ");// parsing the last sign - QCString *ss; QCString find=qcs; QCString temp=qcs; char buf[2]; @@ -1289,7 +1215,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD { find=find.left(j); buf[0]=temp[j]; - ss=VhdlDocGen::findKeyWord(find); + const char *ss=VhdlDocGen::findKeyWord(find); bool k=isNumber(find); // is this a number if (k) { @@ -1299,7 +1225,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD } else if (j != 0 && ss) { - startFonts(find,ss->data(),ol); + startFonts(find,ss,ol); } else { @@ -1435,11 +1361,11 @@ void VhdlDocGen::writeProcedureProto(OutputList& ol,const ArgumentList &al,const nn+=": "; QCString defval = arg.defval; - QCString *str=VhdlDocGen::findKeyWord(defval); + const char *str=VhdlDocGen::findKeyWord(defval); defval+=" "; if (str) { - startFonts(defval,str->data(),ol); + startFonts(defval,str,ol); } else { @@ -1500,7 +1426,7 @@ void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList &al,const } if (!att.isEmpty()) { - QCString *str=VhdlDocGen::findKeyWord(att); + const char *str=VhdlDocGen::findKeyWord(att); att+=" "; if (str) VhdlDocGen::formatString(att,ol,mdef); @@ -1514,7 +1440,7 @@ void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList &al,const QCString w=ss.stripWhiteSpace();//.upper(); startFonts(nn,"vhdlchar",ol); startFonts("in ","stringliteral",ol); - QCString *str=VhdlDocGen::findKeyWord(ss); + const char *str=VhdlDocGen::findKeyWord(ss); if (str) VhdlDocGen::formatString(w,ol,mdef); else @@ -1717,7 +1643,7 @@ void VhdlDocGen::writeVhdlDeclarations(const MemberList* ml, } -void VhdlDocGen::correctMemberProperties(MemberDef *md) +void VhdlDocGen::correctMemberProperties(MemberDefMutable *md) { if (qstrcmp(md->argsString(),"package")==0) { @@ -1767,7 +1693,7 @@ void VhdlDocGen::correctMemberProperties(MemberDef *md) /* writes a vhdl type documentation */ bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definition *d, OutputList &ol) { - const ClassDef *cd=dynamic_cast<const ClassDef*>(d); + const ClassDef *cd=toClassDef(d); bool hasParams = FALSE; if (cd==0) return hasParams; @@ -1849,7 +1775,7 @@ bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definit return hasParams; } -void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile) +void VhdlDocGen::writeTagFile(MemberDefMutable *mdef,FTextStream &tagFile) { tagFile << " <member kind=\""; if (VhdlDocGen::isGeneric(mdef)) tagFile << "generic"; @@ -1893,7 +1819,7 @@ void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile) /* writes a vhdl type declaration */ -void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, +void VhdlDocGen::writeVHDLDeclaration(const MemberDefMutable* mdef,OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool /*inGroup*/) { @@ -2203,24 +2129,28 @@ void VhdlDocGen::writePlainVHDLDeclarations( pack.setAutoDelete(TRUE); bool first=TRUE; - MemberDef *md; + MemberDef *imd; MemberListIterator mli(*mlist); - for ( ; (md=mli.current()); ++mli ) + for ( ; (imd=mli.current()); ++mli ) { - int mems=md->getMemberSpecifiers(); - if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlDocGen::LIBRARY) ) - { - if (first) { ol.startMemberList();first=FALSE; } - VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE); - } //if - else if (md->isBriefSectionVisible() && (mems==specifier)) + MemberDefMutable *md = toMemberDefMutable(imd); + if (md) { - if (!pack.find(md->name().data())) + int mems=md->getMemberSpecifiers(); + if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlDocGen::LIBRARY) ) { - if (first) ol.startMemberList(),first=FALSE; + if (first) { ol.startMemberList();first=FALSE; } VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE); - pack.append(md->name().data(),new QCString(md->name().data())); - } + } //if + else if (md->isBriefSectionVisible() && (mems==specifier)) + { + if (!pack.find(md->name().data())) + { + if (first) ol.startMemberList(),first=FALSE; + VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE); + pack.append(md->name().data(),new QCString(md->name().data())); + } + } //if } //if } //for if (!first) ol.endMemberList(); @@ -2354,9 +2284,9 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& -void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname) +void VhdlDocGen::writeSource(const MemberDefMutable *mdef,OutputList& ol,const QCString & cname) { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".vhd"); + auto intf = Doxygen::parserManager->getCodeParser(".vhd"); // pIntf->resetCodeParserState(); QCString codeFragment=mdef->documentation(); @@ -2381,8 +2311,8 @@ void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString codeFragment.prepend("\n"); ol.pushGeneratorState(); - ol.startCodeFragment(); - intf.parseCode( ol, // codeOutIntf + ol.startCodeFragment("DoxyCode"); + intf->parseCode( ol, // codeOutIntf 0, // scope codeFragment, // input SrcLangExt_VHDL, // lang @@ -2396,7 +2326,7 @@ void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString TRUE // show line numbers ); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); ol.popGeneratorState(); if (cname.isEmpty()) return; @@ -2632,21 +2562,18 @@ QCString VhdlDocGen::parseForBinding(QCString & entity,QCString & arch) - // find class with upper/lower letters - ClassDef* VhdlDocGen::findVhdlClass(const char *className ) +// find class with upper/lower letters +ClassDef* VhdlDocGen::findVhdlClass(const char *className ) +{ + for (const auto &cd : *Doxygen::classLinkedMap) { - - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) - { - if (qstricmp(className,cd->name().data())==0) - { - return cd; - } - } - return 0; + if (qstricmp(className,cd->name().data())==0) + { + return cd.get(); + } } + return 0; +} /* @@ -2684,10 +2611,10 @@ void VhdlDocGen::computeVhdlComponentRelations() entity=cur->type; } - ClassDef *classEntity= VhdlDocGen::findVhdlClass(entity.data());//Doxygen::classSDict->find(entity); + ClassDefMutable *classEntity= toClassDefMutable(VhdlDocGen::findVhdlClass(entity.data())); inst=VhdlDocGen::getIndexWord(cur->args.data(),0); - ClassDef *cd=Doxygen::classSDict->find(inst); - ClassDef *ar=Doxygen::classSDict->find(cur->args); + ClassDefMutable *cd=toClassDefMutable(Doxygen::classLinkedMap->find(inst)); + ClassDefMutable *ar=toClassDefMutable(Doxygen::classLinkedMap->find(cur->args)); if (cd==0) { @@ -2702,8 +2629,8 @@ void VhdlDocGen::computeVhdlComponentRelations() } -static void addInstance(ClassDef* classEntity, ClassDef* ar, - ClassDef *cd , const std::shared_ptr<Entry> &cur) +static void addInstance(ClassDefMutable* classEntity, ClassDefMutable* ar, + ClassDefMutable *cd , const std::shared_ptr<Entry> &cur) { QCString bName,n1; @@ -2739,14 +2666,14 @@ static void addInstance(ClassDef* classEntity, ClassDef* ar, ferr: QCString uu=cur->name; - MemberDef *md=createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( ar->getDefFileName(), cur->startLine,cur->startColumn, n1,uu,uu, 0, Public, Normal, cur->stat,Member, MemberType_Variable, ArgumentList(), ArgumentList(), - ""); + "") }; if (ar->getOutputFileBase()) { @@ -2774,27 +2701,29 @@ ferr: //label.replace(epr,":"); //info+=label; //fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data()); - ar->insertMember(md); + ar->insertMember(md.get()); + MemberName *mn = Doxygen::functionNameLinkedMap->add(uu); + mn->push_back(std::move(md)); } -void VhdlDocGen::writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDef *mdef) +void VhdlDocGen::writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDefMutable *mdef) { - 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(); + int i=mdef->name().find('~'); + if (i>0) + { + //sets the real record member name + const_cast<MemberDefMutable*>(mdef)->setName(mdef->name().left(i).data()); + } + writeLink(mdef,ol); + ol.startBold(); + ol.insertMemberAlign(); + if (!ltype.isEmpty()){ + VhdlDocGen::formatString(ltype,ol,mdef); + } + ol.endBold(); } @@ -2843,24 +2772,20 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int return FALSE; } - if (cd->subClasses()) + for (const auto &bcd :cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - for ( ; bcli.current() && !found ; ++bcli) + const ClassDef *ccd=bcd.classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + //printf("isSubClass() subclass %s\n",ccd->name().data()); + if (ccd==scd) { - const ClassDef *ccd=bcli.current()->classDef; - if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); - //printf("isSubClass() subclass %s\n",ccd->name().data()); - if (ccd==scd) - { - found=TRUE; - } - else + found=TRUE; + } + else + { + if (level <256) { - if (level <256) - { - found=ccd->isBaseClass(scd,followInstances,level+1); - } + found=ccd->isBaseClass(scd,followInstances,level+1); } } } @@ -2869,35 +2794,33 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent) { - if (cd->baseClasses()) + BaseClassList bcl = cd->baseClasses(); + for (auto &bcd : bcl) { - BaseClassListIterator bcli(*cd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ClassDef *ccd = bcd.classDef; + if (ccd==ent) { - ClassDef *ccd=bcli.current()->classDef; - if (ccd==ent) + QCString n = bcd.usedName; + int i = n.find('('); + if(i<0) { - QCString n = bcli.current()->usedName; - int i = n.find('('); - if(i<0) - { - bcli.current()->usedName.append("(2)"); - return; - } - static QRegExp reg("[0-9]+"); - QCString s=n.left(i); - QCString r=n.right(n.length()-i); - QCString t=r; - VhdlDocGen::deleteAllChars(r,')'); - VhdlDocGen::deleteAllChars(r,'('); - r.setNum(r.toInt()+1); - t.replace(reg,r.data()); - s.append(t.data()); - bcli.current()->usedName=s; - bcli.current()->templSpecifiers=t; + bcd.usedName.append("(2)"); + return; } - } - } + static QRegExp reg("[0-9]+"); + QCString s=n.left(i); + QCString r=n.right(n.length()-i); + QCString t=r; + VhdlDocGen::deleteAllChars(r,')'); + VhdlDocGen::deleteAllChars(r,'('); + r.setNum(r.toInt()+1); + t.replace(reg,r.data()); + s.append(t.data()); + bcd.usedName=s; + bcd.templSpecifiers=t; + } + } + cd->updateBaseClasses(bcl); } diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h index 5442f88..22751c5 100644 --- a/src/vhdldocgen.h +++ b/src/vhdldocgen.h @@ -31,6 +31,7 @@ class Entry; class ClassDef; class MemberList; class MemberDef; +class MemberDefMutable; class FTextStream; class OutputList; class Definition; @@ -129,7 +130,7 @@ class VhdlDocGen static void computeVhdlComponentRelations(); - static QCString* findKeyWord(const QCString& word); + static const char* findKeyWord(const QCString& word); static ClassDef* getPackageName(const QCString& name); static MemberDef* findMember(const QCString& className, @@ -144,7 +145,7 @@ class VhdlDocGen static QCString getClassTitle(const ClassDef*); static void writeInlineClassLink(const ClassDef*, OutputList &ol); - static void writeTagFile(MemberDef *mdef,FTextStream &tagFile); + static void writeTagFile(MemberDefMutable *mdef,FTextStream &tagFile); static bool isConstraint(const MemberDef *mdef); static bool isConfig(const MemberDef *mdef); @@ -190,7 +191,7 @@ class VhdlDocGen static void writeVhdlDeclarations(const MemberList*,OutputList&,const GroupDef*,const ClassDef*,const FileDef*,const NamespaceDef*); - static void writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, + static void writeVHDLDeclaration(const MemberDefMutable* mdef,OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool inGroup); @@ -214,12 +215,12 @@ class VhdlDocGen static void parseUCF(const char* input,Entry* entity,QCString f,bool vendor); - static ClassDef* findArchitecture(const ClassDef *cd); - static ClassDef* findArchitecture(QCString identifier, QCString entity_name); + static const ClassDef* findArchitecture(const ClassDef *cd); + //static const ClassDef* findArchitecture(QCString identifier, QCString entity_name); - static void correctMemberProperties(MemberDef *md); + static void correctMemberProperties(MemberDefMutable *md); - static void writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname); + static void writeSource(const MemberDefMutable *mdef,OutputList& ol,const QCString & cname); static QCString parseForConfig(QCString & entity,QCString & arch); static QCString parseForBinding(QCString & entity,QCString & arch); @@ -252,7 +253,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 writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDef *mdef); + static void writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol,const MemberDefMutable *mdef); }; //------------------------------------------------------------------------------------------------------------------- diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 7c83d52..4ca4bbe 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -114,7 +114,10 @@ void VHDLOutlineParser::Private::parseVhdlfile(const char *fileName, 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; + delete tokenManager; + delete stream; } VHDLOutlineParser::VHDLOutlineParser() : p(std::make_unique<Private>()) diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 0000000..add95f1 --- /dev/null +++ b/src/xml.h @@ -0,0 +1,74 @@ +#ifndef XML_H +#define XML_H + +#include <memory> +#include <functional> +#include <string> +#include <unordered_map> + +/*! @brief Event handlers that can installed by the client and called while parsing a XML document. + */ +class XMLHandlers +{ + public: + using Attributes = std::unordered_map<std::string,std::string>; + using StartDocType = void(); + using EndDocType = void(); + using StartElementType = void(const std::string &,const Attributes &); + using EndElementType = void(const std::string &); + using ErrorType = void(const std::string,int,const std::string &); + using CharsType = void(const std::string &); + + std::function<StartDocType> startDocument; /**< handler invoked at the start of the document */ + std::function<EndDocType> endDocument; /**< handler invoked at the end of the document */ + std::function<StartElementType> startElement; /**< handler invoked when an opening tag has been found */ + std::function<EndElementType> endElement; /**< handler invoked when a closing tag has been found */ + std::function<CharsType> characters; /**< handler invoked when content between tags has been found */ + std::function<ErrorType> error; /**< handler invoked when the parser encounters an error */ + + static std::string value(const Attributes &attrib,const std::string &key) + { + auto it = attrib.find(key); + if (it!=attrib.end()) + { + return it->second; + } + return ""; + } +}; + +class XMLLocator +{ + public: + virtual ~XMLLocator() {} + virtual int lineNr() const = 0; + virtual std::string fileName() const = 0; +}; + +/*! Very basic SAX style parser to parse XML documents. */ +class XMLParser : public XMLLocator +{ + public: + /*! Creates an instance of the parser object. Different instances can run on different + * threads without interference. + * + * @param handlers The event handlers passed by the client. + */ + XMLParser(const XMLHandlers &handlers); + /*! Destructor */ + ~XMLParser(); + + /*! Parses a file gives the contents of the file as a string. + * @param fileName the name of the file, used for error reporting. + * @param inputString the contents of the file as a zero terminated UTF-8 string. + */ + void parse(const char *fileName,const char *inputString); + + private: + virtual int lineNr() const override; + virtual std::string fileName() const override; + struct Private; + std::unique_ptr<Private> p; +}; + +#endif diff --git a/src/xml.l b/src/xml.l new file mode 100644 index 0000000..ace35d5 --- /dev/null +++ b/src/xml.l @@ -0,0 +1,484 @@ +/****************************************************************************** + * + * 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. + * + */ +/****************************************************************************** + * Minimal flex based parser for XML + ******************************************************************************/ + +%option never-interactive +%option prefix="xmlYY" +%option reentrant +%option extra-type="struct xmlYY_state *" +%option 8bit noyywrap +%top{ +#include <stdint.h> +} + +%{ + +#include <ctype.h> +#include <vector> +#include <stdio.h> +#include "xml.h" +#include "message.h" + +#define YY_NEVER_INTERACTIVE 1 +#define YY_NO_INPUT 1 +#define YY_NO_UNISTD_H 1 + +struct xmlYY_state +{ + std::string fileName; + int lineNr = 1; + const char * inputString = 0; //!< the code fragment as text + yy_size_t inputPosition = 0; //!< read offset during parsing + std::string name; + bool isEnd = false; + bool selfClose = false; + std::string data; + std::string attrValue; + std::string attrName; + XMLHandlers::Attributes attrs; + XMLHandlers handlers; + int cdataContext; + int commentContext; + char stringChar; + std::vector<std::string> xpath; +}; + +#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 void initElement(yyscan_t yyscanner); +static void addCharacters(yyscan_t yyscanner); +static void addElement(yyscan_t yyscanner); +static void addAttribute(yyscan_t yyscanner); +static void countLines(yyscan_t yyscanner, const char *txt,yy_size_t len); +static void reportError(yyscan_t yyscanner, const std::string &msg); +static std::string processData(yyscan_t yyscanner,const char *txt,yy_size_t len); + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +NL (\r\n|\r|\n) +SP [ \t\r\n]+ +OPEN {SP}?"<" +OPENSPECIAL {SP}?"<?" +CLOSE ">"{NL}? +CLOSESPECIAL "?>"{NL}? +NAMESTART [:A-Za-z\200-\377_] +NAMECHAR [:A-Za-z\200-\377_0-9.-] +NAME {NAMESTART}{NAMECHAR}* +ESC "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";" +COLON ":" +PCDATA [^<]+ +COMMENT {OPEN}"!--" +COMMENTEND "--"{CLOSE} +STRING \"([^"&]|{ESC})*\"|\'([^'&]|{ESC})*\' +DOCTYPE {SP}?"<!DOCTYPE"{SP} +CDATA {SP}?"<![CDATA[" +ENDCDATA "]]>" + +%option noyywrap + +%s Initial +%s Content +%s CDataSection +%s Element +%s Attributes +%s AttributeValue +%s AttrValueStr +%s Prolog +%s Comment + +%% + +<Initial>{ + {SP} { countLines(yyscanner,yytext,yyleng); } + {DOCTYPE} { countLines(yyscanner,yytext,yyleng); } + {OPENSPECIAL} { countLines(yyscanner,yytext,yyleng); BEGIN(Prolog); } + {OPEN} { countLines(yyscanner,yytext,yyleng); + initElement(yyscanner); + BEGIN(Element); } + {COMMENT} { yyextra->commentContext = YY_START; + BEGIN(Comment); + } +} +<Content>{ + {CDATA} { countLines(yyscanner,yytext,yyleng); + yyextra->cdataContext = YY_START; + BEGIN(CDataSection); + } + {PCDATA} { yyextra->data += processData(yyscanner,yytext,yyleng); } + {OPEN} { countLines(yyscanner,yytext,yyleng); + addCharacters(yyscanner); + initElement(yyscanner); + BEGIN(Element); + } + {COMMENT} { yyextra->commentContext = YY_START; + countLines(yyscanner,yytext,yyleng); + BEGIN(Comment); + } +} +<Element>{ + "/" { yyextra->isEnd = true; } + {NAME} { yyextra->name = yytext; + BEGIN(Attributes); } + {CLOSE} { addElement(yyscanner); + countLines(yyscanner,yytext,yyleng); + yyextra->data = ""; + BEGIN(Content); + } + {SP} { countLines(yyscanner,yytext,yyleng); } +} +<Attributes>{ + "/" { yyextra->selfClose = true; } + {NAME} { yyextra->attrName = yytext; } + "=" { BEGIN(AttributeValue); } + {CLOSE} { addElement(yyscanner); + countLines(yyscanner,yytext,yyleng); + yyextra->data = ""; + BEGIN(Content); + } + {SP} { countLines(yyscanner,yytext,yyleng); } +} +<AttributeValue>{ + {SP} { countLines(yyscanner,yytext,yyleng); } + ['"] { yyextra->stringChar = *yytext; + yyextra->attrValue = ""; + BEGIN(AttrValueStr); + } + . { std::string msg = std::string("Missing attribute value. Unexpected character `")+yytext+"` found"; + reportError(yyscanner,msg); + unput(*yytext); + BEGIN(Attributes); + } +} +<AttrValueStr>{ + [^'"\n]+ { yyextra->attrValue += processData(yyscanner,yytext,yyleng); } + ['"] { if (*yytext==yyextra->stringChar) + { + addAttribute(yyscanner); + BEGIN(Attributes); + } + else + { + yyextra->attrValue += processData(yyscanner,yytext,yyleng); + } + } + \n { yyextra->lineNr++; yyextra->attrValue+=' '; } +} +<CDataSection>{ + {ENDCDATA} { BEGIN(yyextra->cdataContext); } + [^]\n]+ { yyextra->data += yytext; } + \n { yyextra->data += yytext; + yyextra->lineNr++; + } + . { yyextra->data += yytext; } +} +<Prolog>{ + {CLOSESPECIAL} { countLines(yyscanner,yytext,yyleng); + BEGIN(Initial); + } + [^?\n]+ { } + \n { yyextra->lineNr++; } + . { } +} +<Comment>{ + {COMMENTEND} { countLines(yyscanner,yytext,yyleng); + BEGIN(yyextra->commentContext); + } + [^\n-]+ { } + \n { yyextra->lineNr++; } + . { } +} +\n { yyextra->lineNr++; } +. { std::string msg = "Unexpected character `"; + msg+=yytext; + msg+="` found"; + reportError(yyscanner,msg); + } + +%% + +//---------------------------------------------------------------------------------------- + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void countLines(yyscan_t yyscanner, const char *txt,yy_size_t len) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + for (yy_size_t i=0;i<len;i++) + { + if (txt[i]=='\n') yyextra->lineNr++; + } +} + +static void initElement(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->isEnd = false; // true => </tag> + yyextra->selfClose = false; // true => <tag/> + yyextra->name = ""; + yyextra->attrs.clear(); +} + +static void checkAndUpdatePath(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->xpath.empty()) + { + std::string msg = "found closing tag '"+yyextra->name+"' without matching opening tag"; + reportError(yyscanner,msg); + } + else + { + std::string expectedTagName = yyextra->xpath.back(); + if (expectedTagName!=yyextra->name) + { + std::string msg = "Found closing tag '"+yyextra->name+"' that does not match the opening tag '"+expectedTagName+"' at the same level"; + reportError(yyscanner,msg); + } + else // matching end tag + { + yyextra->xpath.pop_back(); + } + } +} + +static void addElement(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->isEnd) + { + yyextra->xpath.push_back(yyextra->name); + if (yyextra->handlers.startElement) + { + yyextra->handlers.startElement(yyextra->name,yyextra->attrs); + } + if (yy_flex_debug) + { + fprintf(stderr,"%d: startElement(%s,attr=[",yyextra->lineNr,yyextra->name.data()); + for (auto attr : yyextra->attrs) + { + fprintf(stderr,"%s='%s' ",attr.first.c_str(),attr.second.c_str()); + } + fprintf(stderr,"])\n"); + } + } + if (yyextra->isEnd || yyextra->selfClose) + { + if (yy_flex_debug) + { + fprintf(stderr,"%d: endElement(%s)\n",yyextra->lineNr,yyextra->name.data()); + } + checkAndUpdatePath(yyscanner); + if (yyextra->handlers.endElement) + { + yyextra->handlers.endElement(yyextra->name); + } + } +} + +static std::string trimSpaces(const std::string &str) +{ + const int l = static_cast<int>(str.length()); + int s=0, e=l-1; + while (s<l && isspace(str.at(s))) s++; + while (e>s && isspace(str.at(e))) e--; + return str.substr(s,1+e-s); +} + +static void addCharacters(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + std::string data = trimSpaces(yyextra->data); + if (yyextra->handlers.characters) + { + yyextra->handlers.characters(data); + } + if (!data.empty()) + { + if (yy_flex_debug) + { + fprintf(stderr,"characters(%s)\n",data.c_str()); + } + } +} + +static void addAttribute(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->attrs.insert(std::make_pair(yyextra->attrName,yyextra->attrValue)); +} + +static void reportError(yyscan_t yyscanner,const std::string &msg) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yy_flex_debug) + { + fprintf(stderr,"%s:%d: Error '%s'\n",yyextra->fileName.c_str(),yyextra->lineNr,msg.c_str()); + } + if (yyextra->handlers.error) + { + yyextra->handlers.error(yyextra->fileName,yyextra->lineNr,msg); + } +} + +static const char *entities_enc[] = { "amp", "quot", "gt", "lt", "apos" }; +static const char entities_dec[] = { '&', '"', '>', '<', '\'' }; +static const int num_entities = 5; + +// replace character entities such as & in txt and return the string where entities +// are replaced +static std::string processData(yyscan_t yyscanner,const char *txt,yy_size_t len) +{ + std::string result; + result.reserve(len); + for (yy_size_t i=0; i<len; i++) + { + char c = txt[i]; + if (c=='&') + { + const int maxEntityLen = 10; + char entity[maxEntityLen+1]; + entity[maxEntityLen]='\0'; + for (yy_size_t j=0; j<maxEntityLen && i+j+1<len; j++) + { + if (txt[i+j+1]!=';') + { + entity[j]=txt[i+j+1]; + } + else + { + entity[j]=0; + break; + } + } + bool found=false; + for (int e=0; !found && e<num_entities; e++) + { + if (strcmp(entity,entities_enc[e])==0) + { + result+=entities_dec[e]; + i+=strlen(entities_enc[e])+1; + found=true; + } + } + if (!found) + { + std::string msg = std::string("Invalid character entity '&") + entity + ";' found\n"; + reportError(yyscanner,msg); + } + } + else + { + result+=c; + } + } + return result; +} + +//-------------------------------------------------------------- + +struct XMLParser::Private +{ + yyscan_t yyscanner; + struct xmlYY_state xmlYY_extra; +}; + +XMLParser::XMLParser(const XMLHandlers &handlers) : p(new Private) +{ + xmlYYlex_init_extra(&p->xmlYY_extra,&p->yyscanner); + p->xmlYY_extra.handlers = handlers; +} + +XMLParser::~XMLParser() +{ + xmlYYlex_destroy(p->yyscanner); +} + +void XMLParser::parse(const char *fileName,const char *inputStr) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + +#ifdef FLEX_DEBUG + xmlYYset_debug(1,p->yyscanner); +#endif + + if (inputStr==nullptr || inputStr[0]=='\0') return; // empty input + + printlex(yy_flex_debug, true, __FILE__, fileName); + + BEGIN(Initial); + yyextra->fileName = fileName; + yyextra->lineNr = 1; + yyextra->inputString = inputStr; + yyextra->inputPosition = 0; + + xmlYYrestart( 0, yyscanner ); + + if (yyextra->handlers.startDocument) + { + yyextra->handlers.startDocument(); + } + xmlYYlex(yyscanner); + if (yyextra->handlers.endDocument) + { + yyextra->handlers.endDocument(); + } + + if (!yyextra->xpath.empty()) + { + std::string tagName = yyextra->xpath.back(); + std::string msg = "End of file reached while expecting closing tag '"+tagName+"'"; + reportError(yyscanner,msg); + } + + printlex(yy_flex_debug, false, __FILE__, fileName); +} + +int XMLParser::lineNr() const +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + return yyextra->lineNr; +} + +std::string XMLParser::fileName() const +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + return yyextra->fileName; +} + +#if USE_STATE2STRING +#include "xml.l.h" +#endif diff --git a/src/xmlcode.h b/src/xmlcode.h index 4cada9b..5a35506 100644 --- a/src/xmlcode.h +++ b/src/xmlcode.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2014 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. * @@ -32,6 +30,8 @@ class Definition; class XMLCodeParser : public CodeParserInterface { public: + XMLCodeParser(); + virtual ~XMLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -48,6 +48,9 @@ class XMLCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/xmlcode.l b/src/xmlcode.l index b583bf5..c7322cb 100644 --- a/src/xmlcode.l +++ b/src/xmlcode.l @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2014 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,6 +19,11 @@ %option never-interactive %option prefix="xmlcodeYY" +%option reentrant +%option extra-type="struct xmlcodeYY_state *" +%option noyy_top_state +%option nounput +%option noyywrap %top{ #include <stdint.h> } @@ -44,401 +49,430 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 -static CodeOutputInterface * g_code; -static QCString g_curClassName; -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_inputLines; //!< number of line in the code fragment -static int g_yyLineNr; //!< current line number -static bool g_needsTermination; -static const Definition *g_searchCtx; - -static bool g_exampleBlock; -static QCString g_exampleName; -static QCString g_exampleFile; - -static QCString g_type; -static QCString g_name; -static QCString g_args; -static QCString g_classScope; - -static QCString g_CurrScope; - -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; -static const char * g_currentFontClass; +struct xmlcodeYY_state +{ + CodeOutputInterface * code; + QCString curClassName; + QCString parmType; + QCString parmName; + const char * inputString = 0; //!< the code fragment as text + 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 + bool needsTermination = false; + const Definition *searchCtx = 0; + + bool exampleBlock = false; + QCString exampleName; + QCString exampleFile; + + QCString type; + QCString name; + QCString args; + QCString classScope; + + QCString CurrScope; + + const FileDef * sourceFileDef = 0; + const Definition * currentDefinition = 0; + const MemberDef * currentMemberDef = 0; + bool includeCodeFragment = false; + const char * currentFontClass = 0; +}; #if USE_STATE2STRING static const char *stateToString(int state); #endif -static void codify(const char* text) -{ - g_code->codify(text); +static void codify(yyscan_t yyscanner,const char* text); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static void startCodeLine(yyscan_t yyscanner); +static void endFontClass(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); +static int countLines(yyscan_t yyscanner); +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(yyscanner,buf,max_size); + +%} + +nl (\r\n|\r|\n) +ws [ \t]+ +open "<" +close ">" +namestart [A-Za-z\200-\377_] +namechar [:A-Za-z\200-\377_0-9.-] +esc "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";" +name {namestart}{namechar}* +comment {open}"!--"([^-]|"-"[^-])*"--"{close} +data "random string" +string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\' + +%option noyywrap +%option nounput + +%% + +<INITIAL>{ws} { + codifyLines(yyscanner,yytext); + } +<INITIAL>"/" { + endFontClass(yyscanner); + codify(yyscanner,yytext); + } +<INITIAL>"=" { + endFontClass(yyscanner); + codify(yyscanner,yytext); + } +<INITIAL>{close} { + endFontClass(yyscanner); + codify(yyscanner,yytext); + } +<INITIAL>{name} { + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } +<INITIAL>{string} { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +{open}{ws}?{name} { + // Write the < in a different color + char openBracket[] = { yytext[0], '\0' }; + codify(yyscanner,openBracket); + + // Then write the rest + yytext++; + startFontClass(yyscanner,"keywordtype"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + + BEGIN(INITIAL); + } +{open}{ws}?"/"{name} { + // Write the "</" in a different color + char closeBracket[] = { yytext[0], yytext[1], '\0' }; + endFontClass(yyscanner); + codify(yyscanner,closeBracket); + + // Then write the rest + yytext++; // skip the '<' + yytext++; // skip the '/' + startFontClass(yyscanner,"keywordtype"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + + BEGIN(INITIAL); + } +{comment} { + // Strip off the extra '!' + // yytext++; // < + // *yytext = '<'; // replace '!' with '<' + + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +{nl} { + codifyLines(yyscanner,yytext); + } + +. { + //printf("!ERROR(%c)\n", *yytext); + codifyLines(yyscanner,yytext); + } + +%% + +//---------------------------------------------------------------------------------------- + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void codify(yyscan_t yyscanner,const char* text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->code->codify(text); } -static void setCurrentDoc(const QCString &anchor) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - if (g_searchCtx) + if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } -/*! start a new line of code, inserting a line number if g_sourceFileDef - * is TRUE. If a definition starts at the current line, then the line +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef + * is true. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ -static void startCodeLine() +static void startCodeLine(yyscan_t yyscanner) { - if (g_sourceFileDef) - { - Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); - - if (!g_includeCodeFragment && d && d->isLinkableInProject()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef) + { + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - //g_insideBody = FALSE; - g_classScope = d->name().copy(); + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + //yyextra->insideBody = false; + yyextra->classScope = d->name().copy(); QCString lineAnchor; - lineAnchor.sprintf("l%05d",g_yyLineNr); - if (g_currentMemberDef) + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) { - g_code->writeLineNumber(g_currentMemberDef->getReference(), - g_currentMemberDef->getOutputFileBase(), - g_currentMemberDef->anchor(),g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } else { - g_code->writeLineNumber(d->getReference(), + yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - - g_code->startCodeLine(g_sourceFileDef); - - if (g_currentFontClass) + + yyextra->code->startCodeLine(yyextra->sourceFileDef); + + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void endFontClass() +static void endFontClass(yyscan_t yyscanner) { - if (g_currentFontClass) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) { - g_code->endFontClass(); - g_currentFontClass=0; + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; } } -static void endCodeLine() +static void endCodeLine(yyscan_t yyscanner) { - endFontClass(); - g_code->endCodeLine(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); } -static void nextCodeLine() +static void nextCodeLine(yyscan_t yyscanner) { - const char *fc = g_currentFontClass; - endCodeLine(); - if (g_yyLineNr<g_inputLines) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) { - g_currentFontClass = fc; - startCodeLine(); + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); } } -static void codifyLines(char *text) +static void codifyLines(yyscan_t yyscanner,const char *text) { - char *p=text,*sp=p; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=text,*sp=p; char c; - bool done=FALSE; - + bool done=false; while (!done) { sp=p; - while ((c=*p++) && c!='\n') { } - if (c=='\n') { - g_yyLineNr++; - *(p-1)='\0'; - g_code->codify(sp); - nextCodeLine(); + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); - done=TRUE; + yyextra->code->codify(sp); + done=true; } } } -static void startFontClass(const char *s) +static void startFontClass(yyscan_t yyscanner,const char *s) { - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } /*! counts the number of lines in the input */ -static int countLines() +static int countLines(yyscan_t yyscanner) { - const char *p=g_inputString; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->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>yyextra->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++, + yyextra->needsTermination=true; + } return count; } -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +//---------------------------------------------------------------------------------------- -static int yyread(char *buf,int max_size) +struct XMLCodeParser::Private { - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} + yyscan_t yyscanner; + xmlcodeYY_state state; +}; -nl (\r\n|\r|\n) -ws [ \t]+ -open "<" -close ">" -namestart [A-Za-z\200-\377_] -namechar [:A-Za-z\200-\377_0-9.-] -esc "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";" -name {namestart}{namechar}* -comment {open}"!--"([^-]|"-"[^-])*"--"{close} -data "random string" -string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\' - -%option noyywrap -%option nounput +XMLCodeParser::XMLCodeParser() : p(std::make_unique<Private>()) +{ + xmlcodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + xmlcodeYYset_debug(1,yyscanner); +#endif + resetCodeParserState(); +} -%% +XMLCodeParser::~XMLCodeParser() +{ + xmlcodeYYlex_destroy(p->yyscanner); +} -<INITIAL>{ws} { - codifyLines(yytext); - } -<INITIAL>"/" { - endFontClass(); - codify(yytext); - } -<INITIAL>"=" { - endFontClass(); - codify(yytext); - } -<INITIAL>{close} { - endFontClass(); - codify(yytext); - } -<INITIAL>{name} { - startFontClass("keyword"); - codify(yytext); - endFontClass(); - } -<INITIAL>{string} { - startFontClass("stringliteral"); - codifyLines(yytext); - endFontClass(); - } - -{open}{ws}?{name} { - // Write the < in a different color - char openBracket[] = { yytext[0], '\0' }; - codify(openBracket); - - // Then write the rest - yytext++; - startFontClass("keywordtype"); - codify(yytext); - endFontClass(); - - BEGIN(INITIAL); - } -{open}{ws}?"/"{name} { - // Write the "</" in a different color - char closeBracket[] = { yytext[0], yytext[1], '\0' }; - endFontClass(); - codify(closeBracket); - - // Then write the rest - yytext++; // skip the '<' - yytext++; // skip the '/' - startFontClass("keywordtype"); - codify(yytext); - endFontClass(); +void XMLCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} - BEGIN(INITIAL); - } -{comment} { - // Strip off the extra '!' - // yytext++; // < - // *yytext = '<'; // replace '!' with '<' +void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } -{nl} { - codifyLines(yytext); - } + if (input.isEmpty()) return; -. { - //printf("!ERROR(%c)\n", *yytext); - codifyLines(yytext); - } + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); -%% + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = false; + yyextra->searchCtx = searchCtx; -void parseXmlCode( - CodeOutputInterface &od, - const char * /*className*/, - const QCString &s, - bool exBlock, - const char *exName, - FileDef *fd, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *, - bool,const Definition *searchCtx, - bool /*collectXRefs*/ - ) -{ - if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx=searchCtx; - if (startLine!=-1) - g_yyLineNr = startLine; + yyextra->yyLineNr = startLine; else - g_yyLineNr = 1; - + yyextra->yyLineNr = 1; + if (endLine!=-1) - g_inputLines = endLine+1; + yyextra->inputLines = endLine+1; else - g_inputLines = g_yyLineNr + countLines() - 1; - - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; - - bool cleanupSourceDef = FALSE; - - if (exBlock && fd==0) + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",(exName?exName:"generated")); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; } - - if (g_sourceFileDef) + + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_includeCodeFragment = inlineFragment; - // Starts line 1 on the output - startCodeLine(); + yyextra->includeCodeFragment = inlineFragment; + // Starts line 1 on the output + startCodeLine(yyscanner); - xmlcodeYYrestart( xmlcodeYYin ); + xmlcodeYYrestart( 0, yyscanner ); - xmlcodeYYlex(); + xmlcodeYYlex(yyscanner); - if (g_needsTermination) + if (yyextra->needsTermination) { - endCodeLine(); + endCodeLine(yyscanner); } if (cleanupSourceDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } - - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - return; -} - -void resetXmlCodeParserState() -{ - g_currentDefinition = 0; - g_currentMemberDef = 0; -} - -//---------------------------------------------------------------------------- -void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt, - bool isExampleBlock, - const char *exampleName, - FileDef *fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - parseXmlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } -void XMLCodeParser::resetCodeParserState() -{ - resetXmlCodeParserState(); -} #if USE_STATE2STRING #include "xmlcode.l.h" diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 045f87c..73aac7c 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -252,9 +252,8 @@ void XmlDocVisitor::visit(DocVerbatim *s) m_t << " filename=\"" << lang << "\">"; else m_t << ">"; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); m_t << "</programlisting>"; break; case DocVerbatim::Verbatim: @@ -332,8 +331,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -351,8 +349,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::Include: m_t << "<programlisting filename=\"" << inc->file() << "\">"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -411,8 +408,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::Snippet: m_t << "<programlisting filename=\"" << inc->file() << "\">"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -426,8 +422,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -480,17 +475,16 @@ void XmlDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(), - op->text(),langExt,op->isExample(), - op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(), + op->text(),langExt,op->isExample(), + op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 19f1553..8ffaca2 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -226,6 +226,7 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf FTextStream &m_t; }; +//------------------------------------------------------------------------------------------- /** Generator for producing XML formatted source code. */ void XMLCodeGenerator::codify(const char *text) @@ -340,6 +341,18 @@ void XMLCodeGenerator::finish() if (m_insideCodeLine) endCodeLine(); } +void XMLCodeGenerator::startCodeFragment(const char *) +{ + m_t << " <programlisting>" << endl; +} + +void XMLCodeGenerator::endCodeFragment(const char *) +{ + m_t << " </programlisting>" << endl; +} + +//------------------------------------------------------------------------------------------- + static void writeTemplateArgumentList(FTextStream &t, const ArgumentList &al, const Definition *scope, @@ -420,11 +433,12 @@ static void writeXMLDocBlock(FTextStream &t, void writeXMLCodeBlock(FTextStream &t,FileDef *fd) { - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension()); - intf.resetCodeParserState(); + intf->resetCodeParserState(); XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t); - intf.parseCode(*xmlGen, // codeOutIntf + xmlGen->startCodeFragment("DoxyCode"); + intf->parseCode(*xmlGen, // codeOutIntf 0, // scopeName fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)), langExt, // lang @@ -437,6 +451,7 @@ void writeXMLCodeBlock(FTextStream &t,FileDef *fd) 0, // memberDef TRUE // showLineNumbers ); + xmlGen->endCodeFragment("DoxyCode"); xmlGen->finish(); delete xmlGen; } @@ -467,6 +482,7 @@ static void writeMemberReference(FTextStream &t,const Definition *def,const Memb static void stripQualifiers(QCString &typeStr) { bool done=FALSE; + typeStr.stripPrefix("friend "); while (!done) { if (typeStr.stripPrefix("static ")); @@ -834,7 +850,15 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } } - if (isFunc) //function + if (md->isFriendClass()) // for friend classes we show a link to the class as a "parameter" + { + t << " <param>" << endl; + t << " <type>"; + linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->name()); + t << "</type>" << endl; + t << " </param>" << endl; + } + else if (isFunc) //function { const ArgumentList &declAl = md->declArgumentList(); const ArgumentList &defAl = md->argumentList(); @@ -1006,23 +1030,15 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict) + auto refList = md->getReferencesMembers(); + for (const auto &refmd : refList) { - MemberSDict::Iterator mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - writeMemberReference(t,def,rmd,"references"); - } + writeMemberReference(t,def,refmd,"references"); } - mdict = md->getReferencedByMembers(); - if (mdict) + auto refByList = md->getReferencedByMembers(); + for (const auto &refmd : refByList) { - MemberSDict::Iterator mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - writeMemberReference(t,def,rmd,"referencedby"); - } + writeMemberReference(t,def,refmd,"referencedby"); } t << " </memberdef>" << endl; @@ -1117,45 +1133,35 @@ static void writeListOfAllMembers(const ClassDef *cd,FTextStream &t) t << " </listofallmembers>" << endl; } -static void writeInnerClasses(const ClassSDict *cl,FTextStream &t) +static void writeInnerClasses(const ClassLinkedRefMap &cl,FTextStream &t) { - if (cl) + for (const auto &cd : cl) { - ClassSDict::Iterator cli(*cl); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) + if (!cd->isHidden() && !cd->isAnonymous()) { - if (!cd->isHidden() && !cd->isAnonymous()) + t << " <innerclass refid=\"" << classOutputFileBase(cd) + << "\" prot=\""; + switch(cd->protection()) { - t << " <innerclass refid=\"" << classOutputFileBase(cd) - << "\" prot=\""; - switch(cd->protection()) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: t << "package"; break; - } - t << "\">" << convertToXML(cd->name()) << "</innerclass>" << endl; + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; } + t << "\">" << convertToXML(cd->name()) << "</innerclass>" << endl; } } } -static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t) +static void writeInnerNamespaces(const NamespaceLinkedRefMap &nl,FTextStream &t) { - if (nl) + for (const auto &nd : nl) { - NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + if (!nd->isHidden() && !nd->isAnonymous()) { - if (!nd->isHidden() && !nd->isAnonymous()) - { - t << " <innernamespace refid=\"" << nd->getOutputFileBase() - << "\"" << (nd->isInline() ? " inline=\"yes\"" : "") - << ">" << convertToXML(nd->name()) << "</innernamespace>" << endl; - } + t << " <innernamespace refid=\"" << nd->getOutputFileBase() + << "\"" << (nd->isInline() ? " inline=\"yes\"" : "") + << ">" << convertToXML(nd->name()) << "</innernamespace>" << endl; } } } @@ -1279,73 +1285,63 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) t << " <compoundname>"; writeXMLString(t,cd->name()); t << "</compoundname>" << endl; - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " <basecompoundref "; + if (bcd.classDef->isLinkable()) { - t << " <basecompoundref "; - if (bcd->classDef->isLinkable()) - { - t << "refid=\"" << classOutputFileBase(bcd->classDef) << "\" "; - } - t << "prot=\""; - switch (bcd->prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: ASSERT(0); break; - } - t << "\" virt=\""; - switch(bcd->virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t <<"pure-virtual"; break; - } - t << "\">"; - if (!bcd->templSpecifiers.isEmpty()) - { - t << convertToXML( - insertTemplateSpecifierInScope( - bcd->classDef->name(),bcd->templSpecifiers) - ); - } - else - { - t << convertToXML(bcd->classDef->displayName()); - } - t << "</basecompoundref>" << endl; + t << "refid=\"" << classOutputFileBase(bcd.classDef) << "\" "; + } + t << "prot=\""; + switch (bcd.prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; + } + t << "\" virt=\""; + switch(bcd.virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t <<"pure-virtual"; break; } + t << "\">"; + if (!bcd.templSpecifiers.isEmpty()) + { + t << convertToXML( + insertTemplateSpecifierInScope( + bcd.classDef->name(),bcd.templSpecifiers) + ); + } + else + { + t << convertToXML(bcd.classDef->displayName()); + } + t << "</basecompoundref>" << endl; } - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " <derivedcompoundref refid=\"" + << classOutputFileBase(bcd.classDef) + << "\" prot=\""; + switch (bcd.prot) { - t << " <derivedcompoundref refid=\"" - << classOutputFileBase(bcd->classDef) - << "\" prot=\""; - switch (bcd->prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: ASSERT(0); break; - } - t << "\" virt=\""; - switch(bcd->virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t << "pure-virtual"; break; - } - t << "\">" << convertToXML(bcd->classDef->displayName()) - << "</derivedcompoundref>" << endl; + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; + } + t << "\" virt=\""; + switch (bcd.virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; } + t << "\">" << convertToXML(bcd.classDef->displayName()) + << "</derivedcompoundref>" << endl; } IncludeInfo *ii=cd->includeInfo(); @@ -1366,7 +1362,7 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) } } - writeInnerClasses(cd->getClassSDict(),t); + writeInnerClasses(cd->getClasses(),t); writeTemplateList(cd,t); if (cd->getMemberGroupSDict()) @@ -1470,8 +1466,8 @@ static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti) writeXMLString(t,nd->name()); t << "</compoundname>" << endl; - writeInnerClasses(nd->getClassSDict(),t); - writeInnerNamespaces(nd->getNamespaceSDict(),t); + writeInnerClasses(nd->getClasses(),t); + writeInnerNamespaces(nd->getNamespaces(),t); if (nd->getMemberGroupSDict()) { @@ -1601,14 +1597,8 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) t << " </invincdepgraph>" << endl; } - if (fd->getClassSDict()) - { - writeInnerClasses(fd->getClassSDict(),t); - } - if (fd->getNamespaceSDict()) - { - writeInnerNamespaces(fd->getNamespaceSDict(),t); - } + writeInnerClasses(fd->getClasses(),t); + writeInnerNamespaces(fd->getNamespaces(),t); if (fd->getMemberGroupSDict()) { @@ -1639,9 +1629,7 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) t << " </detaileddescription>" << endl; if (Config_getBool(XML_PROGRAMLISTING)) { - t << " <programlisting>" << endl; writeXMLCodeBlock(t,fd); - t << " </programlisting>" << endl; } t << " <location file=\"" << convertToXML(stripFromPath(fd->getDefFileName())) << "\"/>" << endl; t << " </compounddef>" << endl; @@ -1970,29 +1958,14 @@ void generateXML() t << "xml:lang=\"" << theTranslator->trISOLang() << "\""; t << ">" << endl; + for (const auto &cd : *Doxygen::classLinkedMap) { - ClassSDict::Iterator cli(*Doxygen::classSDict); - const ClassDef *cd; - for (cli.toFirst();(cd=cli.current());++cli) - { - generateXMLForClass(cd,t); - } + generateXMLForClass(cd.get(),t); } - //{ - // ClassSDict::Iterator cli(Doxygen::hiddenClasses); - // ClassDef *cd; - // for (cli.toFirst();(cd=cli.current());++cli) - // { - // msg("Generating XML output for class %s\n",cd->name().data()); - // generateXMLForClass(cd,t); - // } - //} - NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + for (const auto &nd : *Doxygen::namespaceLinkedMap) { msg("Generating XML output for namespace %s\n",nd->name().data()); - generateXMLForNamespace(nd,t); + generateXMLForNamespace(nd.get(),t); } for (const auto &fn : *Doxygen::inputNameLinkedMap) { diff --git a/src/xmlgen.h b/src/xmlgen.h index 4458b9f..27bb10b 100644 --- a/src/xmlgen.h +++ b/src/xmlgen.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. * @@ -41,6 +39,8 @@ class XMLCodeGenerator : public CodeOutputInterface const char *anchorId,int l); void setCurrentDoc(const Definition *,const char *,bool){} void addWord(const char *,bool){} + void startCodeFragment(const char *); + void endCodeFragment(const char *); void finish(); diff --git a/src/layout_default.xml b/templates/general/layout_default.xml index 373bb20..373bb20 100644 --- a/src/layout_default.xml +++ b/templates/general/layout_default.xml diff --git a/templates/html/doxygen.css b/templates/html/doxygen.css index 141d418..5898d87 100644 --- a/templates/html/doxygen.css +++ b/templates/html/doxygen.css @@ -103,30 +103,96 @@ caption { } span.legend { - font-size: 70%; - text-align: center; + font-size: 70%; + text-align: center; } h3.version { - font-size: 90%; - text-align: center; + font-size: 90%; + text-align: center; } -div.qindex, div.navtab{ - background-color: ##ee; - border: 1px solid ##b0; - text-align: center; +div.navtab { + border-right: 1px solid ##b0; + padding-right: 15px; + text-align: right; + line-height: 110%; +} + +div.navtab table { + border-spacing: 0; +} + +td.navtab { + padding-right: 6px; + padding-left: 6px; +} +td.navtabHL { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL a, td.navtabHL a:visited { + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +a.navtab { + font-weight: bold; } -div.qindex, div.navpath { +div.qindex{ + text-align: center; width: 100%; line-height: 140%; + font-size: 130%; + color: #A0A0A0; } -div.navtab { - margin-right: 15px; +dt.alphachar{ + font-size: 180%; + font-weight: bold; +} + +.alphachar a{ + color: black; +} + +.alphachar a:hover, .alphachar a:visited{ + text-decoration: none; } +.classindex dl { + padding: 25px; + column-count:1 +} + +.classindex dd { + display:inline-block; + margin-left: 50px; + width: 90%; + line-height: 1.15em; +} + +.classindex dl.odd { + background-color: ##F9; +} + +@media(min-width: 1120px) { + .classindex dl { + column-count:2 + } +} + +@media(min-width: 1320px) { + .classindex dl { + column-count:3 + } +} + + /* @group Link Styling */ a { @@ -143,17 +209,6 @@ a:hover { text-decoration: underline; } -a.qindex { - font-weight: bold; -} - -a.qindexHL { - font-weight: bold; - background-color: ##AA; - color: ##ff; - border: 1px double ##98; -} - .contents a.qindexHL:visited { color: ##ff; } @@ -1426,6 +1481,12 @@ div.toc li.level4 { margin-left: 45px; } +span.emoji { + /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html + * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; + */ +} + .PageDocRTL-title div.toc li.level1 { margin-left: 0 !important; margin-right: 0; diff --git a/templates/html/footer.html b/templates/html/footer.html index 1cb1529..2fd7aee 100644 --- a/templates/html/footer.html +++ b/templates/html/footer.html @@ -3,13 +3,13 @@ <div id="nav-path" class="navpath"><!-- id is needed for treeview function! --> <ul> $navpath - <li class="footer">$generatedby <a href="http://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion </li> + <li class="footer">$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion </li> </ul> </div> <!--END GENERATE_TREEVIEW--> <!--BEGIN !GENERATE_TREEVIEW--> <hr class="footer"/><address class="footer"><small> -$generatedby <a href="http://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion +$generatedby <a href="https://www.doxygen.org/index.html"><img class="footer" src="$relpath^doxygen.svg" width="104" height="31" alt="doxygen"/></a> $doxygenversion </small></address> <!--END !GENERATE_TREEVIEW--> </body> diff --git a/templates/html/htmlbase.tpl b/templates/html/htmlbase.tpl index 362de31..f021ddd 100644 --- a/templates/html/htmlbase.tpl +++ b/templates/html/htmlbase.tpl @@ -228,7 +228,7 @@ $(document).ready(function(){initNavTree('{{ page.fileName }}{% if page_postfix {% else %} {{ tr.generatedBy }} {% endif %} - <a href="http://www.doxygen.org/index.html"><img class="footer" src="{{ page.relPath }}doxygen.svg" width="104" height="31" alt="doxygen"/></a> {{ doxygen.version }} </li> + <a href="https://www.doxygen.org/index.html"><img class="footer" src="{{ page.relPath }}doxygen.svg" width="104" height="31" alt="doxygen"/></a> {{ doxygen.version }} </li> </ul> </div> {% else %} @@ -238,7 +238,7 @@ $(document).ready(function(){initNavTree('{{ page.fileName }}{% if page_postfix {% else %} {{ tr.generatedBy }} {% endif %} - <a href="http://www.doxygen.org/index.html"><img class="footer" src="{{ page.relPath }}doxygen.svg" width="104" height="31" alt="doxygen"/></a> + <a href="https://www.doxygen.org/index.html"><img class="footer" src="{{ page.relPath }}doxygen.svg" width="104" height="31" alt="doxygen"/></a> {{ doxygen.version }} </small></address> {% endif %} diff --git a/templates/html/htmlsearchresult.tpl b/templates/html/htmlsearchresult.tpl index 4e15414..139faf2 100644 --- a/templates/html/htmlsearchresult.tpl +++ b/templates/html/htmlsearchresult.tpl @@ -11,14 +11,14 @@ <div id="SRIndex"> <div class="SRStatus" id="Loading">{{ tr.loading }}</div> <div id="SRResults"></div> -<script type="text/javascript"><!-- +<script type="text/javascript"> /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */ createResults(); /* @license-end */ ---></script> +</script> <div class="SRStatus" id="Searching">{{ tr.searching }}</div> <div class="SRStatus" id="NoMatches">{{ tr.noMatches }}</div> -<script type="text/javascript"><!-- +<script type="text/javascript"> /* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */ document.getElementById("Loading").style.display="none"; document.getElementById("NoMatches").style.display="none"; @@ -31,7 +31,7 @@ window.addEventListener("message", function(event) { } }); /* @license-end */ ---></script> +</script> </div> </body> </html> diff --git a/templates/html/search.css b/templates/html/search.css index 8af75a7..254b5e7 100644 --- a/templates/html/search.css +++ b/templates/html/search.css @@ -216,7 +216,7 @@ span.SRScope { display: none; } -DIV.searchresults { +div.searchresults { margin-left: 10px; margin-right: 10px; } diff --git a/templates/html/search.js b/templates/html/search.js index 92b6094..fb226f7 100644 --- a/templates/html/search.js +++ b/templates/html/search.js @@ -80,9 +80,10 @@ function getYPos(item) storing this instance. Is needed to be able to set timeouts. resultPath - path to use for external files */ -function SearchBox(name, resultsPath, inFrame, label) +function SearchBox(name, resultsPath, inFrame, label, extension) { if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); } + if (!extension || extension == "") { extension = ".html"; } // ---------- Instance variables this.name = name; @@ -97,6 +98,7 @@ function SearchBox(name, resultsPath, inFrame, label) this.searchActive = false; this.insideFrame = inFrame; this.searchLabel = label; + this.extension = extension; // ----------- DOM Elements @@ -347,13 +349,13 @@ function SearchBox(name, resultsPath, inFrame, label) if (idx!=-1) { var hexCode=idx.toString(16); - resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; + resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + this.extension; resultsPageWithSearch = resultsPage+'?'+escape(searchValue); hasResultsPage = true; } else // nothing available for this search term { - resultsPage = this.resultsPath + '/nomatches.html'; + resultsPage = this.resultsPath + '/nomatches' + this.extension; resultsPageWithSearch = resultsPage; hasResultsPage = false; } @@ -439,12 +441,12 @@ function SearchResults(name) while (element && element!=parentElement) { - if (element.nodeName == 'DIV' && element.className == 'SRChildren') + if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren') { return element; } - if (element.nodeName == 'DIV' && element.hasChildNodes()) + if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes()) { element = element.firstChild; } diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty index 78a5254..8f59bcc 100644 --- a/templates/latex/doxygen.sty +++ b/templates/latex/doxygen.sty @@ -13,6 +13,7 @@ \RequirePackage{tabu_doxygen} \RequirePackage{fancyvrb} \RequirePackage{tabularx} +\RequirePackage{multicol} \RequirePackage{multirow} \RequirePackage{hanging} \RequirePackage{ifpdf} @@ -186,9 +187,8 @@ % (only if caption is specified) \newenvironment{DoxyImage}{% \begin{figure}[H]% - \begin{center}% + \centering% }{% - \end{center}% \end{figure}% } @@ -571,6 +571,6 @@ % Define caption that is also suitable in a table \makeatletter \def\doxyfigcaption{% -\refstepcounter{figure}% +\H@refstepcounter{figure}% \@dblarg{\@caption{figure}}} \makeatother diff --git a/testing/012/citelist.xml b/testing/012/citelist.xml index 1bef226..f5addb1 100644 --- a/testing/012/citelist.xml +++ b/testing/012/citelist.xml @@ -12,14 +12,14 @@ <term><anchor id="citelist_1CITEREF_Be09"/>[1]</term> </varlistentry> <listitem> - <para>P.<nonbreakablespace/>Belotti. <ulink url="http://doi.org/10.1007/978-1-4614-1927-3_5">Disjunctive cuts for non-convex MINLP</ulink>. In <ulink url="#CITEREF_LeLe12">Lee and Leyffer</ulink> <ulink url="#CITEREF_LeLe12">[4]</ulink>, pages 117<ndash/>144.</para> + <para>P.<nonbreakablespace/>Belotti. <ulink url="https://link.springer.com/10.1007/978-1-4614-1927-3_5">Disjunctive cuts for non-convex MINLP</ulink>. In <ulink url="#CITEREF_LeLe12">Lee and Leyffer</ulink> <ulink url="#CITEREF_LeLe12">[4]</ulink>, pages 117<ndash/>144.</para> <para/> </listitem> <varlistentry> <term><anchor id="citelist_1CITEREF_BertholdHeinzVigerske2009"/>[2]</term> </varlistentry> <listitem> - <para>T.<nonbreakablespace/>Berthold, S.<nonbreakablespace/>Heinz, and S.<nonbreakablespace/>Vigerske. <ulink url="http://doi.org/10.1007/978-1-4614-1927-3_15">Extending a CIP framework to solve MIQCPs</ulink>. In <ulink url="#CITEREF_LeLe12">Lee and Leyffer</ulink> <ulink url="#CITEREF_LeLe12">[4]</ulink>, pages 427<ndash/>444.</para> + <para>T.<nonbreakablespace/>Berthold, S.<nonbreakablespace/>Heinz, and S.<nonbreakablespace/>Vigerske. <ulink url="https://link.springer.com/10.1007/978-1-4614-1927-3_15">Extending a CIP framework to solve MIQCPs</ulink>. In <ulink url="#CITEREF_LeLe12">Lee and Leyffer</ulink> <ulink url="#CITEREF_LeLe12">[4]</ulink>, pages 427<ndash/>444.</para> <para/> </listitem> <varlistentry> @@ -33,7 +33,7 @@ <term><anchor id="citelist_1CITEREF_LeLe12"/>[4]</term> </varlistentry> <listitem> - <para>Jon Lee and Sven Leyffer, editors. <ulink url="http://doi.org/10.1007/978-1-4614-1927-3"><emphasis>Mixed Integer Nonlinear Programming</emphasis></ulink>, volume 154 of <emphasis>The IMA Volumes in Mathematics and its Applications</emphasis>. Springer, 2012.</para> + <para>Jon Lee and Sven Leyffer, editors. <ulink url="https://link.springer.com/10.1007/978-1-4614-1927-3"><emphasis>Mixed Integer Nonlinear Programming</emphasis></ulink>, volume 154 of <emphasis>The IMA Volumes in Mathematics and its Applications</emphasis>. Springer, 2012.</para> <para/> </listitem> </variablelist> diff --git a/testing/031/indexpage.xml b/testing/031/indexpage.xml index b6631b0..fc030f6 100644 --- a/testing/031/indexpage.xml +++ b/testing/031/indexpage.xml @@ -11,43 +11,43 @@ <image type="docbook" name="sample.png"/> More text.</para> <para>SVG image with caption:<linebreak/> -<image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.svg">A caption</image> +<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg">A caption</image> </para> <para>PNG image with caption:<linebreak/> -<image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.png">A caption</image> +<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png">A caption</image> </para> <para>SVG image without caption:<linebreak/> -<image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.svg"/> +<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg"/> </para> <para>PNG image without caption:<linebreak/> -<image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.png"/> +<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png"/> </para> <para>Inline SVG image with caption:<linebreak/> -This image is inline <image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.svg" inline="yes">MIT license</image> +This image is inline <image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg" inline="yes">MIT license</image> within the text.</para> <para>Inline PNG image with caption:<linebreak/> -This image is inline <image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.png" inline="yes">MIT license</image> +This image is inline <image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png" inline="yes">MIT license</image> within the text.</para> <para>Markdown style linked SVG image:<linebreak/> -<ulink url="http://opensource.org/licenses/MIT"><image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.svg" inline="yes"/></ulink></para> +<ulink url="https://opensource.org/licenses/MIT"><image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg" inline="yes"/></ulink></para> <para>Markdown style linked PNG image:<linebreak/> -<ulink url="http://opensource.org/licenses/MIT"><image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.png" inline="yes"/></ulink></para> +<ulink url="https://opensource.org/licenses/MIT"><image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png" inline="yes"/></ulink></para> <para>HTML style linked SVG image:<linebreak/> -<ulink url="http://opensource.org/licenses/MIT"><image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.svg" inline="yes"/></ulink></para> +<ulink url="https://opensource.org/licenses/MIT"><image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg" inline="yes"/></ulink></para> <para>HTML style linked PNG image:<linebreak/> -<ulink url="http://opensource.org/licenses/MIT"><image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.png" inline="yes"/></ulink></para> +<ulink url="https://opensource.org/licenses/MIT"><image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png" inline="yes"/></ulink></para> <para>HTML style unlinked SVG image:<linebreak/> -<image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.svg" inline="yes"/> +<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.svg" inline="yes"/> </para> <para>HTML style unlinked PNG image:<linebreak/> -<image type="html" name="http://img.shields.io/badge/license-MIT-brightgreen.png" inline="yes"/> +<image type="html" name="https://raster.shields.io/badge/license-MIT-brightgreen.png" inline="yes"/> </para> <para>Some markdown image tests<linebreak/> -<image type="html" name="https://img.shields.io/badge/docs-Doxygen-blue.svg?foo&bar" inline="yes"/> - <ulink url="http://www.doxygen.nl?foo&bar">Some normal link</ulink></para> +<image type="html" name="https://raster.shields.io/badge/docs-Doxygen-blue.svg?foo&bar" inline="yes"/> + <ulink url="https://www.doxygen.nl/index.html?foo&bar">Some normal link</ulink></para> <para> - <image type="html" name="https://img.shields.io/badge/docs-Doxygen-blue.svg?foo&bar" inline="yes"/> - <ulink url="http://www.doxygen.nl?foo&bar">Some normal link</ulink> + <image type="html" name="https://raster.shields.io/badge/docs-Doxygen-blue.svg?foo&bar" inline="yes"/> + <ulink url="https://www.doxygen.nl/index.html?foo&bar">Some normal link</ulink> </para> </detaileddescription> </compounddef> diff --git a/testing/031_image.dox b/testing/031_image.dox index e451592..4a67116 100644 --- a/testing/031_image.dox +++ b/testing/031_image.dox @@ -9,51 +9,51 @@ Some text. More text. SVG image with caption:\n -\image html http://img.shields.io/badge/license-MIT-brightgreen.svg "A caption" +\image html https://raster.shields.io/badge/license-MIT-brightgreen.svg "A caption" PNG image with caption:\n -\image html http://img.shields.io/badge/license-MIT-brightgreen.png "A caption" +\image html https://raster.shields.io/badge/license-MIT-brightgreen.png "A caption" SVG image without caption:\n -\image html http://img.shields.io/badge/license-MIT-brightgreen.svg +\image html https://raster.shields.io/badge/license-MIT-brightgreen.svg PNG image without caption:\n -\image html http://img.shields.io/badge/license-MIT-brightgreen.png +\image html https://raster.shields.io/badge/license-MIT-brightgreen.png Inline SVG image with caption:\n -This image is inline \image{inline} html http://img.shields.io/badge/license-MIT-brightgreen.svg "MIT license" within the text. +This image is inline \image{inline} html https://raster.shields.io/badge/license-MIT-brightgreen.svg "MIT license" within the text. Inline PNG image with caption:\n This image is inline -\image{inline} html http://img.shields.io/badge/license-MIT-brightgreen.png "MIT license" +\image{inline} html https://raster.shields.io/badge/license-MIT-brightgreen.png "MIT license" within the text. Markdown style linked SVG image:\n -[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT) +[![MIT license](https://raster.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) Markdown style linked PNG image:\n -[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.png)](http://opensource.org/licenses/MIT) +[![MIT license](https://raster.shields.io/badge/license-MIT-brightgreen.png)](https://opensource.org/licenses/MIT) HTML style linked SVG image:\n -<a href="http://opensource.org/licenses/MIT"> -<img src="http://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT license"> +<a href="https://opensource.org/licenses/MIT"> +<img src="https://raster.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT license"> </a> HTML style linked PNG image:\n -<a href="http://opensource.org/licenses/MIT"> -<img src="http://img.shields.io/badge/license-MIT-brightgreen.png" alt="MIT license"> +<a href="https://opensource.org/licenses/MIT"> +<img src="https://raster.shields.io/badge/license-MIT-brightgreen.png" alt="MIT license"> </a> HTML style unlinked SVG image:\n -<img src="http://img.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT license"/> +<img src="https://raster.shields.io/badge/license-MIT-brightgreen.svg" alt="MIT license"/> HTML style unlinked PNG image:\n -<img src="http://img.shields.io/badge/license-MIT-brightgreen.png" alt="MIT license"/> +<img src="https://raster.shields.io/badge/license-MIT-brightgreen.png" alt="MIT license"/> Some markdown image tests\n -![Some SVG image](https://img.shields.io/badge/docs-Doxygen-blue.svg?foo&bar) -[Some normal link](http://www.doxygen.nl?foo&bar) +![Some SVG image](https://raster.shields.io/badge/docs-Doxygen-blue.svg?foo&bar) +[Some normal link](https://www.doxygen.nl/index.html?foo&bar) -![Some SVG image](https://img.shields.io/badge/docs-Doxygen-blue.svg?foo&bar) -[Some normal link](http://www.doxygen.nl?foo&bar) +![Some SVG image](https://raster.shields.io/badge/docs-Doxygen-blue.svg?foo&bar) +[Some normal link](https://www.doxygen.nl/index.html?foo&bar) */ diff --git a/testing/050/indexpage.xml b/testing/050/indexpage.xml index 88ec74c..1987274 100644 --- a/testing/050/indexpage.xml +++ b/testing/050/indexpage.xml @@ -19,7 +19,7 @@ title = {Extending a {CIP} framework to solve {MIQCP}s}, crossref = {LeLe12}, pages = {427--444}, - url = {http://doi.org/10.1007/978-1-4614-1927-3_15} + url = {https://link.springer.com/10.1007/978-1-4614-1927-3_15} } @Book{ LeLe12, title = {Mixed Integer Nonlinear Programming}, @@ -29,7 +29,7 @@ editor = {Jon Lee and Sven Leyffer}, volume = {154}, series = {The IMA Volumes in Mathematics and its Applications}, - url = {http://doi.org/10.1007/978-1-4614-1927-3}, + url = {https://link.springer.com/10.1007/978-1-4614-1927-3}, issn = {978-1-4614-1926-6} } @InCollection{ Be09, @@ -37,7 +37,7 @@ title = {Disjunctive cuts for non-convex {MINLP}}, crossref = {LeLe12}, pages = {117--144}, - url = {http://doi.org/10.1007/978-1-4614-1927-3_5} + url = {https://link.springer.com/10.1007/978-1-4614-1927-3_5} } </verbatim> More text after the verbatim section. </para> </detaileddescription> diff --git a/testing/057/namespacelibrary.xml b/testing/057/namespacelibrary.xml new file mode 100644 index 0000000..5321ad7 --- /dev/null +++ b/testing/057/namespacelibrary.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US"> + <compounddef id="namespacelibrary" kind="namespace" language="C++"> + <compoundname>library</compoundname> + <innerclass refid="classlibrary_1_1v2_1_1foo" prot="public">library::foo</innerclass> + <innernamespace refid="namespacelibrary_1_1v2_1_1_n_s">library::NS</innernamespace> + <innernamespace refid="namespacelibrary_1_1v1">library::v1</innernamespace> + <innernamespace refid="namespacelibrary_1_1v2" inline="yes">library::v2</innernamespace> + <sectiondef kind="func"> + <memberdef kind="function" id="namespacelibrary_1_1v2_1aba9375172f5b36e1f4fda9b1dec39d90" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual"> + <type>void</type> + <definition>void library::v2::func</definition> + <argsstring>()</argsstring> + <name>func</name> + <briefdescription> + <para>a method </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="057_inlinenamespace.cpp" line="33" column="14" declfile="057_inlinenamespace.cpp" declline="33" declcolumn="14"/> + </memberdef> + </sectiondef> + <briefdescription> + <para>the main namespace </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <location file="057_inlinenamespace.cpp" line="7" column="1"/> + </compounddef> +</doxygen> diff --git a/testing/057/namespacelibrary_1_1v1.xml b/testing/057/namespacelibrary_1_1v1.xml new file mode 100644 index 0000000..9a01e02 --- /dev/null +++ b/testing/057/namespacelibrary_1_1v1.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US"> + <compounddef id="namespacelibrary_1_1v1" kind="namespace" language="C++"> + <compoundname>library::v1</compoundname> + <innerclass refid="classlibrary_1_1v1_1_1foo" prot="public">library::v1::foo</innerclass> + <innernamespace refid="namespacelibrary_1_1v1_1_1_n_s">library::v1::NS</innernamespace> + <sectiondef kind="func"> + <memberdef kind="function" id="namespacelibrary_1_1v1_1a2257981298fec15f79c54c28880ac15c" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual"> + <type>void</type> + <definition>void library::v1::func</definition> + <argsstring>()</argsstring> + <name>func</name> + <briefdescription> + <para>a method </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="057_inlinenamespace.cpp" line="19" column="14" declfile="057_inlinenamespace.cpp" declline="19" declcolumn="14"/> + </memberdef> + </sectiondef> + <briefdescription> + <para>the first namespace </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <location file="057_inlinenamespace.cpp" line="10" column="5"/> + </compounddef> +</doxygen> diff --git a/testing/057/namespacelibrary_1_1v2.xml b/testing/057/namespacelibrary_1_1v2.xml new file mode 100644 index 0000000..fd848fd --- /dev/null +++ b/testing/057/namespacelibrary_1_1v2.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version="" xml:lang="en-US"> + <compounddef id="namespacelibrary_1_1v2" kind="namespace" inline="yes" language="C++"> + <compoundname>library::v2</compoundname> + <innerclass refid="classlibrary_1_1v2_1_1foo" prot="public">library::v2::foo</innerclass> + <innernamespace refid="namespacelibrary_1_1v2_1_1_n_s">library::v2::NS</innernamespace> + <sectiondef kind="func"> + <memberdef kind="function" id="namespacelibrary_1_1v2_1aba9375172f5b36e1f4fda9b1dec39d90" prot="public" static="no" const="no" explicit="no" inline="no" virt="non-virtual"> + <type>void</type> + <definition>void library::v2::func</definition> + <argsstring>()</argsstring> + <name>func</name> + <briefdescription> + <para>a method </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="057_inlinenamespace.cpp" line="33" column="14" declfile="057_inlinenamespace.cpp" declline="33" declcolumn="14"/> + </memberdef> + </sectiondef> + <briefdescription> + <para>the inline namespace </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <location file="057_inlinenamespace.cpp" line="24" column="12"/> + </compounddef> +</doxygen> diff --git a/testing/057_inlinenamespace.cpp b/testing/057_inlinenamespace.cpp new file mode 100644 index 0000000..337c4b1 --- /dev/null +++ b/testing/057_inlinenamespace.cpp @@ -0,0 +1,37 @@ +// objective: test inline namespaces +// check: namespacelibrary.xml +// check: namespacelibrary_1_1v1.xml +// check: namespacelibrary_1_1v2.xml + +/// the main namespace +namespace library +{ + /// the first namespace + namespace v1 + { + /// the class + class foo { + public: + /// member of the class + void member(); + }; + /// a method + void func(); + /// a namespace + namespace NS {} + } + /// the inline namespace + inline namespace v2 + { + /// the class + class foo { + public: + /// member of the class + void member(); + }; + /// a method + void func(); + /// a namespace + namespace NS {} + } +} diff --git a/testing/073/073__typed__enum_8cpp.xml b/testing/073/073__typed__enum_8cpp.xml index 7e68f3e..9d6947e 100644 --- a/testing/073/073__typed__enum_8cpp.xml +++ b/testing/073/073__typed__enum_8cpp.xml @@ -15,6 +15,102 @@ </inbodydescription> <location file="073_typed_enum.cpp" line="7" column="1" bodyfile="073_typed_enum.cpp" bodystart="7" bodyend="7"/> </memberdef> + <memberdef kind="enum" id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5" prot="public" static="no" strong="yes"> + <type>unsigned char</type> + <name>Mem</name> + <enumvalue id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5a2ad9d63b69c4a10a5cc9cad923133bc4" prot="public"> + <name>Bottom</name> + <initializer>= 0</initializer> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <enumvalue id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5ac946366be0e03f425017b1a97b4a7fbb" prot="public"> + <name>NotMem</name> + <initializer>= 1U << 0</initializer> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <enumvalue id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5a165d3d525f6d0cbd55e42cc3058cafcc" prot="public"> + <name>Ptr</name> + <initializer>= 1U << 1</initializer> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <enumvalue id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5abd34ea97de15a451a2117e2e4cd49c12" prot="public"> + <name>Lval</name> + <initializer>= 1U << 2</initializer> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <enumvalue id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5adba5553473d129a7985fb532dc249ff4" prot="public"> + <name>Mem</name> + <initializer>= Ptr | Lval</initializer> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <enumvalue id="073__typed__enum_8cpp_1a2890437f40d5bcd72710a06cd6a934f5aa4ffdcf0dc1f31b9acaf295d75b51d00" prot="public"> + <name>Top</name> + <initializer>= NotMem | Mem</initializer> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <briefdescription> + <para>Strongly types enum when values that has the same name as the enum. </para> + </briefdescription> + <detaileddescription> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="073_typed_enum.cpp" line="10" column="1" bodyfile="073_typed_enum.cpp" bodystart="10" bodyend="17"/> + </memberdef> + <memberdef kind="enum" id="073__typed__enum_8cpp_1a06fc87d81c62e9abb8790b6e5713c55b" prot="public" static="no" strong="no"> + <type/> + <name>@0</name> + <enumvalue id="073__typed__enum_8cpp_1a06fc87d81c62e9abb8790b6e5713c55ba52c998ad250c15a855ff5559e6d0d1d6" prot="public"> + <name>Unnamed1</name> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="073_typed_enum.cpp" line="19" column="1" bodyfile="073_typed_enum.cpp" bodystart="19" bodyend="21"/> + </memberdef> + <memberdef kind="enum" id="073__typed__enum_8cpp_1adf764cbdea00d65edcd07bb9953ad2b7" prot="public" static="no" strong="no"> + <type/> + <name>@1</name> + <enumvalue id="073__typed__enum_8cpp_1adf764cbdea00d65edcd07bb9953ad2b7a7b130af0c5cb18bfee8c60994fe1d5ee" prot="public"> + <name>Unnamed2</name> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + </enumvalue> + <briefdescription> + </briefdescription> + <detaileddescription> + </detaileddescription> + <inbodydescription> + </inbodydescription> + <location file="073_typed_enum.cpp" line="23" column="1" bodyfile="073_typed_enum.cpp" bodystart="23" bodyend="25"/> + </memberdef> </sectiondef> <briefdescription> </briefdescription> diff --git a/testing/073_typed_enum.cpp b/testing/073_typed_enum.cpp index 0818463..7248c96 100644 --- a/testing/073_typed_enum.cpp +++ b/testing/073_typed_enum.cpp @@ -5,3 +5,21 @@ /** @brief A strongly-typed enum */ enum class E: unsigned short {}; + +/** @brief Strongly types enum when values that has the same name as the enum */ +enum class Mem : unsigned char { + Bottom = 0, + NotMem = 1U << 0, + Ptr = 1U << 1, + Lval = 1U << 2, + Mem = Ptr | Lval, + Top = NotMem | Mem, +}; + +enum { + Unnamed1 +}; + +enum { + Unnamed2 +}; diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index b354e78..fd6912e 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -1,7 +1,7 @@ # run all tests sequentially (keep for backward compatibility) add_custom_target(tests COMMENT "Running doxygen tests..." - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/testing/runtests.py --doxygen ${PROJECT_BINARY_DIR}/bin/doxygen --inputdir ${CMAKE_SOURCE_DIR}/testing --outputdir ${PROJECT_BINARY_DIR}/testing + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/testing/runtests.py --doxygen ${PROJECT_BINARY_DIR}/bin/doxygen --inputdir ${PROJECT_SOURCE_DIR}/testing --outputdir ${PROJECT_BINARY_DIR}/testing DEPENDS doxygen ) @@ -19,6 +19,6 @@ foreach(TEST_FILE ${TEST_FILES}) string(REGEX REPLACE "^.*/([0-9][0-9][0-9]*).*$" "\\1" TEST_ID "${TEST_FILE}") # add a test target for each test add_test(NAME ${TEST_NAME} - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/testing/runtests.py --id ${TEST_ID} --doxygen $<TARGET_FILE:doxygen> --inputdir ${CMAKE_SOURCE_DIR}/testing --outputdir ${PROJECT_BINARY_DIR}/testing + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/testing/runtests.py --id ${TEST_ID} --doxygen $<TARGET_FILE:doxygen> --inputdir ${PROJECT_SOURCE_DIR}/testing --outputdir ${PROJECT_BINARY_DIR}/testing ) endforeach() diff --git a/testing/README.txt b/testing/README.txt index 39b2345..30e593d 100644 --- a/testing/README.txt +++ b/testing/README.txt @@ -1,5 +1,5 @@ Doxygen regression test suite -============================ +============================= This directory contains a set of regression tests. Each test consists of a file starting with a 3 digit number and a corresponding directory whose name @@ -9,32 +9,44 @@ result is the same, there is no regression and the test passes. If there is a difference the test fails and the difference (in diff -u format) will be shown. It is also possible to see whether or not the test can be built to a xhtml set of files (and tested against a DTD), it is also possible to create a pdf file -for each test to see if the LaTeX / pdf generation is possible. +for each test to see if the LaTeX / pdf generation is possible, similar for +rtf and docbook output. The runtest.py script responsible for running the tests takes a number of optional parameters: - --updateref update the reference data for a test + --updateref update the reference files. Should be used in + combination with -id to update the reference file(s) + for the given test --doxygen [DOXYGEN] path/name of the doxygen executable --xmllint [XMLLINT] path/name of the xmllint executable - --id IDS [IDS ...] id of the test to perform + --id IDS [IDS ...] run test with number n only (the option can be + specified to run test with number n only (the option + can be specified multiple times --start_id START_ID run tests starting with number n --end_id END_ID run tests ending with number n - --all perform all tests + --all can be used in combination with -updateref to update + the reference files for all tests. --inputdir [INPUTDIR] input directory containing the tests --outputdir [OUTPUTDIR] output directory to write the doxygen output to --noredir disable redirection of doxygen warnings + --pool [POOL] pool size of multiprocess tests --xml create xml output and check --rtf create rtf output --docbook create docbook output and check with xmllint --xhtml create xhtml output and check with xmllint + --xmlxsd create xml output and check with xmllint against xsd --pdf create LaTeX output and create pdf from it --subdirs use the configuration parameter CREATE_SUBDIRS=YES + --clang use CLANG_ASSISTED_PARSING, works only when doxygen + has been compiled with "use_libclang" --keep keep result directories - --cfg CFGS [CFGS ...] run test with extra doxygen configuration settings + --cfg CFGS [CFGS ...] + run test with extra doxygen configuration settings (the option may be specified multiple times -In case neither --xml, --pdf, --rtf, --docbook or --xhtml is used the default is set to --xml. +In case neither --xml, --xmlxsd, --pdf, --rtf, --docbook or --xhtml is used the +default is set to --xml. The runtest.pl has the following dependencies on 3rd party tools: - python to run the script diff --git a/testing/runtests.py b/testing/runtests.py index 6b3e54e..fde252d 100755 --- a/testing/runtests.py +++ b/testing/runtests.py @@ -35,6 +35,26 @@ def xpopen(cmd, cmd1="",encoding='utf-8-sig', getStderr=False): proc = subprocess.Popen(shlex.split(cmd),stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding=encoding) # Python 3 with encoding return proc.stdout.read() +def clean_header(errmsg): + # messages (due to the usage of more) have a contents like: + # :::::::::::: + # <file name> + # :::::::::::: + # we want to skip these + msg = errmsg.split('\n') + rtnmsg = "" + cnt = -1 + for o in msg: + if (o): + if (cnt == -1): + if o.startswith(":::::::"): + cnt = 3 + if (cnt > 0): + cnt-=1 + else: + rtnmsg+=0 + return rtnmsg + class Tester: def __init__(self,args,test): self.args = args @@ -118,6 +138,7 @@ class Tester: print('INPUT=%s/%s' % (self.args.inputdir,self.test), file=f) print('STRIP_FROM_PATH=%s' % self.args.inputdir, file=f) print('EXAMPLE_PATH=%s' % self.args.inputdir, file=f) + print('WARN_LOGFILE=%s/warnings.log' % self.test_out, file=f) if 'config' in self.config: for option in self.config['config']: print(option, file=f) @@ -162,7 +183,7 @@ class Tester: # run doxygen if (sys.platform == 'win32'): - redir=' > nul:' + redir=' > nul: 2>&1' else: redir=' 2> /dev/null > /dev/null' @@ -279,6 +300,8 @@ class Tester: msg += ('Failed to run %s with schema %s for files: %s' % (self.args.xmllint,index_xsd,index_xml),) failed_xmlxsd=True if xmllint_out: + xmllint_out = clean_header(xmllint_out) + if xmllint_out: msg += (xmllint_out,) failed_xmlxsd=True # @@ -305,6 +328,8 @@ class Tester: msg += ('Failed to run %s with schema %s for files: %s' % (self.args.xmllint,compound_xsd,compound_xml),) failed_xmlxsd=True if xmllint_out: + xmllint_out = clean_header(xmllint_out) + if xmllint_out: msg += (xmllint_out,) failed_xmlxsd=True @@ -337,6 +362,8 @@ class Tester: xmllint_out = xpopen(exe_string,exe_string1,getStderr=True) xmllint_out = self.cleanup_xmllint_docbook(xmllint_out) if xmllint_out: + xmllint_out = clean_header(xmllint_out) + if xmllint_out: msg += (xmllint_out,) failed_docbook=True elif not self.args.keep: @@ -360,6 +387,8 @@ class Tester: xmllint_out = xpopen(exe_string,exe_string1,getStderr=True) xmllint_out = self.cleanup_xmllint(xmllint_out) if xmllint_out: + xmllint_out = clean_header(xmllint_out) + if xmllint_out: msg += (xmllint_out,) failed_html=True elif not self.args.keep: @@ -400,7 +429,12 @@ class Tester: elif not self.args.keep: shutil.rmtree(latex_output,ignore_errors=True) - if failed_xml or failed_html or failed_latex or failed_docbook or failed_rtf or failed_xmlxsd: + warnings = xopen(self.test_out + "/warnings.log",'r',encoding='ISO-8859-1').read() + failed_warn = len(warnings)!=0 + if failed_warn: + msg += (warnings,) + + if failed_warn or failed_xml or failed_html or failed_latex or failed_docbook or failed_rtf or failed_xmlxsd: testmgr.ok(False,self.test_name,msg) return False @@ -475,6 +509,7 @@ class TestManager: shutil.copytree(self.args.inputdir+"/dtd", "dtd") def split_and_keep(s,sep): + s = s.replace('"','') # add token separator s = s.replace(sep,'\0'+sep) # add token separator s = s.split('\0') # split by null delimiter s = [x.strip() for x in filter(None,s)] # strip and remove empty elements diff --git a/testing/sample.bib b/testing/sample.bib index c20175d..a012565 100644 --- a/testing/sample.bib +++ b/testing/sample.bib @@ -10,7 +10,7 @@ title = {Extending a {CIP} framework to solve {MIQCP}s}, crossref = {LeLe12}, pages = {427--444}, - url = {http://doi.org/10.1007/978-1-4614-1927-3_15} + url = {https://link.springer.com/10.1007/978-1-4614-1927-3_15} } @Book{ LeLe12, title = {Mixed Integer Nonlinear Programming}, @@ -20,7 +20,7 @@ editor = {Jon Lee and Sven Leyffer}, volume = {154}, series = {The IMA Volumes in Mathematics and its Applications}, - url = {http://doi.org/10.1007/978-1-4614-1927-3}, + url = {https://link.springer.com/10.1007/978-1-4614-1927-3}, issn = {978-1-4614-1926-6} } @InCollection{ Be09, @@ -28,5 +28,5 @@ title = {Disjunctive cuts for non-convex {MINLP}}, crossref = {LeLe12}, pages = {117--144}, - url = {http://doi.org/10.1007/978-1-4614-1927-3_5} + url = {https://link.springer.com/10.1007/978-1-4614-1927-3_5} } diff --git a/testing/testsqlite3.py b/testing/testsqlite3.py index b4227b4..1d94f70 100755 --- a/testing/testsqlite3.py +++ b/testing/testsqlite3.py @@ -13,7 +13,7 @@ g_conn=None val=[] def print_unprocessed_attributes(node): for key in node.attrib: - print "WARNING: '%s' has unprocessed attr '%s'" % (node.tag,key) + print("WARNING: '%s' has unprocessed attr '%s'" % (node.tag,key)) def extract_attribute(node,attribute,pnl): if not attribute in node.attrib: @@ -69,7 +69,7 @@ def process_memberdef(node): extract_element(node,chld,q) for chld in node.getchildren(): - print "WARNING: '%s' has unprocessed child elem '%s'" % (node.tag,chld.tag) + print("WARNING: '%s' has unprocessed child elem '%s'" % (node.tag,chld.tag)) extract_attribute(node,"kind",q) extract_attribute(node,"prot",q) @@ -90,12 +90,12 @@ def process_memberdef(node): r=[] try: r = g_conn.execute(query,val).fetchall() - except sqlite3.OperationalError,e: - print "SQL_ERROR:%s"%e + except(sqlite3.OperationalError,e): + print("SQL_ERROR:%s"%e) del val[:] if not len(r) > 0: - print "TEST_ERROR: Member not found in SQL DB" + print("TEST_ERROR: Member not found in SQL DB") def load_xml(name): @@ -104,7 +104,7 @@ def load_xml(name): for event, elem in context: if event == "end" and elem.tag == "memberdef": process_memberdef(elem) - print "\n== Unprocessed XML ==" + print("\n== Unprocessed XML ==") # ET.dump(root) diff --git a/vhdlparser/CMakeLists.txt b/vhdlparser/CMakeLists.txt index 53983f5..b610f5c 100644 --- a/vhdlparser/CMakeLists.txt +++ b/vhdlparser/CMakeLists.txt @@ -21,21 +21,28 @@ if (JAVACC_FOUND) else() add_custom_command( - COMMAND ${JAVACC_EXECUTABLE} ${JAVACC_FLAGS} -OUTPUT_DIRECTORY=${CMAKE_SOURCE_DIR}/vhdlparser ${CMAKE_SOURCE_DIR}/vhdlparser/vhdlparser.jj - DEPENDS ${CMAKE_SOURCE_DIR}/vhdlparser/vhdlparser.jj - OUTPUT ${CMAKE_SOURCE_DIR}/vhdlparser/CharStream.cc ${CMAKE_SOURCE_DIR}/vhdlparser/CharStream.h ${CMAKE_SOURCE_DIR}/vhdlparser/ErrorHandler.h ${CMAKE_SOURCE_DIR}/vhdlparser/ParseException.cc ${CMAKE_SOURCE_DIR}/vhdlparser/ParseException.h ${CMAKE_SOURCE_DIR}/vhdlparser/Token.cc ${CMAKE_SOURCE_DIR}/vhdlparser/Token.h ${CMAKE_SOURCE_DIR}/vhdlparser/TokenManager.h ${CMAKE_SOURCE_DIR}/vhdlparser/TokenMgrError.cc ${CMAKE_SOURCE_DIR}/vhdlparser/TokenMgrError.h ${CMAKE_SOURCE_DIR}/vhdlparser/VhdlParser.cc ${CMAKE_SOURCE_DIR}/vhdlparser/VhdlParser.h ${CMAKE_SOURCE_DIR}/vhdlparser/VhdlParserConstants.h ${CMAKE_SOURCE_DIR}/vhdlparser/VhdlParserTokenManager.cc ${CMAKE_SOURCE_DIR}/vhdlparser/VhdlParserTokenManager.h + COMMAND ${JAVACC_EXECUTABLE} ${JAVACC_FLAGS} -OUTPUT_DIRECTORY=${PROJECT_SOURCE_DIR}/vhdlparser ${PROJECT_SOURCE_DIR}/vhdlparser/vhdlparser.jj + DEPENDS ${PROJECT_SOURCE_DIR}/vhdlparser/vhdlparser.jj + OUTPUT ${PROJECT_SOURCE_DIR}/vhdlparser/CharStream.cc ${PROJECT_SOURCE_DIR}/vhdlparser/CharStream.h ${PROJECT_SOURCE_DIR}/vhdlparser/ErrorHandler.h ${PROJECT_SOURCE_DIR}/vhdlparser/ParseException.cc ${PROJECT_SOURCE_DIR}/vhdlparser/ParseException.h ${PROJECT_SOURCE_DIR}/vhdlparser/Token.cc ${PROJECT_SOURCE_DIR}/vhdlparser/Token.h ${PROJECT_SOURCE_DIR}/vhdlparser/TokenManager.h ${PROJECT_SOURCE_DIR}/vhdlparser/TokenMgrError.cc ${PROJECT_SOURCE_DIR}/vhdlparser/TokenMgrError.h ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParser.cc ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParser.h ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParserConstants.h ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParserTokenManager.cc ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParserTokenManager.h ) endif() endif() -include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/qtools ${GENERATED_SRC}) +add_custom_command( + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/vhdlparser/vhdl_adj.py ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParser.cc ${GENERATED_SRC}/VhdlParser_adj.cc + DEPENDS ${PROJECT_SOURCE_DIR}/vhdlparser/VhdlParser.cc ${PROJECT_SOURCE_DIR}/vhdlparser/vhdl_adj.py + OUTPUT ${GENERATED_SRC}/VhdlParser_adj.cc +) +set_source_files_properties(${GENERATED_SRC}/VhdlParser_adj.cc PROPERTIES GENERATED 1) + +include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/qtools ${PROJECT_SOURCE_DIR}/vhdlparser ${GENERATED_SRC}) add_library(vhdlparser STATIC CharStream.cc ParseException.cc Token.cc TokenMgrError.cc -VhdlParser.cc +${GENERATED_SRC}/VhdlParser_adj.cc VhdlParserTokenManager.cc ) add_dependencies(vhdlparser diff --git a/vhdlparser/VhdlParser.cc b/vhdlparser/VhdlParser.cc index 3c0fe35..e039b33 100644 --- a/vhdlparser/VhdlParser.cc +++ b/vhdlparser/VhdlParser.cc @@ -4541,7 +4541,7 @@ assert(false); } -QCString VhdlParser::instantiation_unit() {QCString s,s1,s2;Token *tok; +QCString VhdlParser::instantiation_unit() {QCString s,s1,s2; switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { case COMPONENT_T: case BASIC_IDENTIFIER: diff --git a/vhdlparser/vhdl_adj.py b/vhdlparser/vhdl_adj.py new file mode 100644 index 0000000..a431970 --- /dev/null +++ b/vhdlparser/vhdl_adj.py @@ -0,0 +1,25 @@ +#!/usr/bin/python +# python script to generate configoptions.cpp and config.doc from config.xml +# +# 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. + +import sys + +def main(): + inputFile = open(sys.argv[1], 'r') + outputFile = open(sys.argv[2], 'w') + for line in inputFile: + outputFile.write(line.replace("assert(false);","assert(false);return \"\";")) + +if __name__ == '__main__': + main() + diff --git a/vhdlparser/vhdlparser.jj b/vhdlparser/vhdlparser.jj index 177b5f4..e263289 100755 --- a/vhdlparser/vhdlparser.jj +++ b/vhdlparser/vhdlparser.jj @@ -1404,7 +1404,7 @@ QCString index_subtype_definition() : {QCString s;} s=type_mark() <RANGE_T> <BOX_T> { return s+" range <> ";} } -QCString instantiation_unit() : {QCString s,s1,s2;Token *tok;} +QCString instantiation_unit() : {QCString s,s1,s2;} { [ <COMPONENT_T> ] s=identifier() {s1="component "; return s; } | <ENTITY_T> [LOOKAHEAD(2)<BASIC_IDENTIFIER> <DOT_T>] s2=name() {s="entity|"+s2;} [ <LPAREN_T> s1=identifier() <RPAREN_T> {s+="(";s+=s1;s+=")" ;}] { return s;} |