diff options
66 files changed, 4220 insertions, 684 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index dcd426b..2621844 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ # Documents produced by Doxygen are derivative works derived from the # input used in their production; they are not affected by this license. -cmake_minimum_required(VERSION 3.1.3) +cmake_minimum_required(VERSION 3.2) project(doxygen) option(build_wizard "Build the GUI frontend for doxygen." OFF) @@ -26,6 +26,8 @@ option(win_static "Link with /MT in stead of /MD on windows" OFF) option(english_only "Only compile in support for the English language" OFF) option(force_qt4 "Forces doxywizard to build using Qt4 even if Qt5 is installed" OFF) +SET(enlarge_lex_buffers "262144" CACHE INTERNAL "Sets the lex input and read buffere to the specified size") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set(TOP "${CMAKE_SOURCE_DIR}") include(version) @@ -46,6 +48,11 @@ if (use_libclang) endif() endif() +# use C++11 standard for compiling (libclang option requires it) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + if (CMAKE_SYSTEM MATCHES "Darwin") set(CMAKE_CXX_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_CXX_FLAGS}") set(CMAKE_C_FLAGS "-Wno-deprecated-register -mmacosx-version-min=${MACOS_VERSION_MIN} ${CMAKE_C_FLAGS}") @@ -83,6 +90,9 @@ find_program(DOT NAMES dot) find_package(PythonInterp REQUIRED) find_package(FLEX REQUIRED) find_package(BISON REQUIRED) +if (BISON_VERSION VERSION_LESS 2.7) + message(SEND_ERROR "Doxygen requires at least bison version 2.7 (installed: ${BISON_VERSION})") +endif() find_package(Threads) if (sqlite3) @@ -145,6 +155,7 @@ endif() add_subdirectory(libmd5) add_subdirectory(liblodepng) add_subdirectory(libmscgen) +add_subdirectory(libversion) add_subdirectory(qtools) add_subdirectory(vhdlparser) add_subdirectory(src) diff --git a/addon/doxyapp/CMakeLists.txt b/addon/doxyapp/CMakeLists.txt index 3312f1a..f205664 100644 --- a/addon/doxyapp/CMakeLists.txt +++ b/addon/doxyapp/CMakeLists.txt @@ -2,6 +2,7 @@ find_package(Iconv) include_directories( ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/libversion ${GENERATED_SRC} ${CMAKE_SOURCE_DIR}/qtools ${ICONV_INCLUDE_DIR} @@ -22,6 +23,7 @@ qtools md5 lodepng mscgen +version doxycfg vhdlparser ${ICONV_LIBRARIES} diff --git a/addon/doxyapp/doxyapp.cpp b/addon/doxyapp/doxyapp.cpp index dd092ed..c18f907 100644 --- a/addon/doxyapp/doxyapp.cpp +++ b/addon/doxyapp/doxyapp.cpp @@ -261,6 +261,8 @@ int main(int argc,char **argv) // setup the non-default configuration options + checkConfiguration(); + adjustConfiguration(); // we need a place to put intermediate files Config_getString(OUTPUT_DIRECTORY)="/tmp/doxygen"; // disable html output @@ -281,14 +283,13 @@ int main(int argc,char **argv) // Extract source browse information, needed // to make doxygen gather the cross reference info Config_getBool(SOURCE_BROWSER)=TRUE; + // In case of a directory take all files on directory and its subdirectories + Config_getBool(RECURSIVE)=TRUE; // set the input + Config_getList(INPUT).clear(); Config_getList(INPUT).append(argv[1]); - // check and finialize the configuration - checkConfiguration(); - adjustConfiguration(); - // parse the files parseInput(); diff --git a/addon/doxyparse/CMakeLists.txt b/addon/doxyparse/CMakeLists.txt index 7741dab..e76f031 100644 --- a/addon/doxyparse/CMakeLists.txt +++ b/addon/doxyparse/CMakeLists.txt @@ -2,6 +2,7 @@ find_package(Iconv) include_directories( ${CMAKE_SOURCE_DIR}/src + ${CMAKE_SOURCE_DIR}/libversion ${GENERATED_SRC} ${CMAKE_SOURCE_DIR}/qtools ${ICONV_INCLUDE_DIR} @@ -22,6 +23,7 @@ qtools md5 lodepng mscgen +version doxycfg vhdlparser ${ICONV_LIBRARIES} diff --git a/addon/doxysearch/doxysearch.cpp b/addon/doxysearch/doxysearch.cpp index ac5740b..98adab4 100644 --- a/addon/doxysearch/doxysearch.cpp +++ b/addon/doxysearch/doxysearch.cpp @@ -374,7 +374,11 @@ int main(int argc,char **argv) parser.set_default_op(Xapian::Query::OP_AND); parser.set_stemming_strategy(Xapian::QueryParser::STEM_ALL); Xapian::termcount max_expansion=100; +#if (XAPIAN_MAJOR_VERSION==1) && (XAPIAN_MINOR_VERSION==2) + parser.set_max_wildcard_expansion(max_expansion); +#else parser.set_max_expansion(max_expansion,Xapian::Query::WILDCARD_LIMIT_MOST_FREQUENT); +#endif Xapian::Query query=parser.parse_query(searchFor, Xapian::QueryParser::FLAG_DEFAULT | Xapian::QueryParser::FLAG_WILDCARD | diff --git a/addon/doxywizard/CMakeLists.txt b/addon/doxywizard/CMakeLists.txt index a89864d..9aba4e4 100644 --- a/addon/doxywizard/CMakeLists.txt +++ b/addon/doxywizard/CMakeLists.txt @@ -30,6 +30,7 @@ endif() include_directories( . + ${CMAKE_SOURCE_DIR}/libversion ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/qtools ${GENERATED_SRC} @@ -57,8 +58,10 @@ CONTENT "#ifndef SETTINGS_H set_source_files_properties(${GENERATED_SRC_WIZARD}/settings.h PROPERTIES GENERATED 1) # generate version.cpp -file(GENERATE OUTPUT ${GENERATED_SRC_WIZARD}/version.cpp - CONTENT "char versionString[]=\"${VERSION}\";" +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 + OUTPUT ${GENERATED_SRC_WIZARD}/version.cpp ) set_source_files_properties(${GENERATED_SRC_WIZARD}/version.cpp PROPERTIES GENERATED 1) @@ -93,7 +96,6 @@ inputstring.cpp inputint.cpp inputstrlist.cpp ${GENERATED_SRC_WIZARD}/settings.h -${GENERATED_SRC_WIZARD}/version.cpp ${GENERATED_SRC_WIZARD}/config_doxyw.cpp ${GENERATED_SRC_WIZARD}/configdoc.cpp ${doxywizard_MOC} @@ -102,9 +104,9 @@ doxywizard.rc ) if(Qt5Core_FOUND) - target_link_libraries(doxywizard Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Xml) + target_link_libraries(doxywizard Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Xml version) else() - target_link_libraries(doxywizard ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY}) + target_link_libraries(doxywizard ${QT_LIBRARIES} ${QT_QTMAIN_LIBRARY} version) endif() install(TARGETS doxywizard DESTINATION bin) diff --git a/addon/doxywizard/doxywizard.cpp b/addon/doxywizard/doxywizard.cpp index 56378ed..02e8cd0 100755 --- a/addon/doxywizard/doxywizard.cpp +++ b/addon/doxywizard/doxywizard.cpp @@ -216,7 +216,7 @@ void MainWindow::about() QString msg; QTextStream t(&msg,QIODevice::WriteOnly); t << QString::fromLatin1("<qt><center>A tool to configure and run doxygen version ")+ - QString::fromLatin1(versionString)+ + QString::fromLatin1(getVersion())+ QString::fromLatin1(" on your source files.</center><p><br>" "<center>Written by<br> Dimitri van Heesch<br>© 2000-2015</center><p>" "</qt>"); diff --git a/addon/doxywizard/expert.cpp b/addon/doxywizard/expert.cpp index 44dea78..c875d8d 100644 --- a/addon/doxywizard/expert.cpp +++ b/addon/doxywizard/expert.cpp @@ -781,7 +781,7 @@ void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec, bool Expert::writeConfig(QTextStream &t,bool brief) { // write global header - t << "# Doxyfile " << versionString << endl << endl; + t << "# Doxyfile " << getVersion() << endl << endl; if (!brief) { t << convertToComment(m_header); diff --git a/cmake/doxygen_version.cmake b/cmake/doxygen_version.cmake new file mode 100644 index 0000000..2433889 --- /dev/null +++ b/cmake/doxygen_version.cmake @@ -0,0 +1,96 @@ +# doxygen_version.cmake +# + +# This file defines the functions and targets needed to monitor +# doxygen VERSION file. +# +# The behavior of this script can be modified by defining any of these variables: +# +# PRE_CONFIGURE_DOXYGEN_VERSION_FILE (REQUIRED) +# -- The path to the file that'll be configured. +# +# POST_CONFIGURE_DOXYGEN_VERSION_FILE (REQUIRED) +# -- The path to the configured PRE_CONFIGURE_DOXYGEN_VERSION_FILE. +# +# DOXY_STATE_FILE (OPTIONAL) +# -- The path to the file used to store the doxygen version information. +# +# This file is based on git_watcher.cmake + +# Short hand for converting paths to absolute. +macro(PATH_TO_ABSOLUTE var_name) + get_filename_component(${var_name} "${${var_name}}" ABSOLUTE) +endmacro() + +# Check that a required variable is set. +macro(CHECK_REQUIRED_VARIABLE var_name) + if(NOT DEFINED ${var_name}) + message(FATAL_ERROR "The \"${var_name}\" variable must be defined.") + endif() + PATH_TO_ABSOLUTE(${var_name}) +endmacro() + +# Check that an optional variable is set, or, set it to a default value. +macro(CHECK_OPTIONAL_VARIABLE var_name default_value) + if(NOT DEFINED ${var_name}) + set(${var_name} ${default_value}) + endif() + PATH_TO_ABSOLUTE(${var_name}) +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") + +# Function: DoxygenStateChangedAction +# Description: this function is executed when the +# doxygen version file has changed. +function(DoxygenStateChangedAction _state_as_list) + # Set variables by index, then configure the file w/ these variables defined. + LIST(GET _state_as_list 0 DOXYGEN_VERSION) + configure_file("${PRE_CONFIGURE_DOXYGEN_VERSION_FILE}" "${POST_CONFIGURE_DOXYGEN_VERSION_FILE}" @ONLY) +endfunction() + + + +# Function: SetupDoxyMonitoring +# Description: this function sets up custom commands that make the build system +# check the doxygen version file before every build. If it has +# changed, then a file is configured. +function(SetupDoxyMonitoring) + add_custom_target(check_doxygen_version + ALL + DEPENDS ${PRE_CONFIGURE_DOXYGEN_VERSION_FILE} + BYPRODUCTS ${POST_CONFIGURE_DOXYGEN_VERSION_FILE} + COMMENT "Checking the doxygen version for changes..." + COMMAND + ${CMAKE_COMMAND} + -D_BUILD_TIME_CHECK_DOXY=TRUE + -DDOXY_STATE_FILE=${DOXY_STATE_FILE} + -DPRE_CONFIGURE_DOXYGEN_VERSION_FILE=${PRE_CONFIGURE_DOXYGEN_VERSION_FILE} + -DPOST_CONFIGURE_DOXYGEN_VERSION_FILE=${POST_CONFIGURE_DOXYGEN_VERSION_FILE} + -P "${CMAKE_CURRENT_LIST_FILE}") +endfunction() + + + +# Function: Main +# Description: primary entry-point to the script. Functions are selected based +# on whether it's configure or build time. +function(Main) + file(STRINGS "${DOXY_STATE_FILE}" DOXYGEN_VERSION) + if(_BUILD_TIME_CHECK_DOXY) + # Check if the doxygen version file has changed. + # If so, run the change action. + if(${DOXY_STATE_FILE} IS_NEWER_THAN ${POST_CONFIGURE_DOXYGEN_VERSION_FILE}) + DoxygenStateChangedAction("${DOXYGEN_VERSION}") + endif() + else() + # >> Executes at configure time. + SetupDoxyMonitoring() + DoxygenStateChangedAction("${DOXYGEN_VERSION}") + endif() +endfunction() + +# And off we go... +Main() diff --git a/cmake/git_watcher.cmake b/cmake/git_watcher.cmake new file mode 100644 index 0000000..6447b86 --- /dev/null +++ b/cmake/git_watcher.cmake @@ -0,0 +1,213 @@ +# git_watcher.cmake +# +# License: MIT +# Source: https://raw.githubusercontent.com/andrew-hardin/cmake-git-version-tracking/master/git_watcher.cmake + + +# This file defines the functions and targets needed to monitor +# the state of a git repo. If the state changes (e.g. a commit is made), +# then a file gets reconfigured. +# +# The behavior of this script can be modified by defining any of these variables: +# +# PRE_CONFIGURE_GIT_VERSION_FILE (REQUIRED) +# -- The path to the file that'll be configured. +# +# POST_CONFIGURE_GIT_VERSION_FILE (REQUIRED) +# -- The path to the configured PRE_CONFIGURE_GIT_VERSION_FILE. +# +# GIT_STATE_FILE (OPTIONAL) +# -- The path to the file used to store the previous build's git state. +# Defaults to the current binary directory. +# +# GIT_WORKING_DIR (OPTIONAL) +# -- The directory from which git commands will be run. +# Defaults to the directory with the top level CMakeLists.txt. +# +# GIT_EXECUTABLE (OPTIONAL) +# -- The path to the git executable. It'll automatically be set if the +# user doesn't supply a path. +# +# Script design: +# - This script was designed similar to a Python application +# with a Main() function. I wanted to keep it compact to +# simplify "copy + paste" usage. +# +# - This script is made to operate in two CMake contexts: +# 1. Configure time context (when build files are created). +# 2. Build time context (called via CMake -P) +# If you see something odd (e.g. the NOT DEFINED clauses), +# consider that it can run in one of two contexts. + +# Short hand for converting paths to absolute. +macro(PATH_TO_ABSOLUTE var_name) + get_filename_component(${var_name} "${${var_name}}" ABSOLUTE) +endmacro() + +# Check that a required variable is set. +macro(CHECK_REQUIRED_VARIABLE var_name) + if(NOT DEFINED ${var_name}) + message(FATAL_ERROR "The \"${var_name}\" variable must be defined.") + endif() + PATH_TO_ABSOLUTE(${var_name}) +endmacro() + +# Check that an optional variable is set, or, set it to a default value. +macro(CHECK_OPTIONAL_VARIABLE var_name default_value) + if(NOT DEFINED ${var_name}) + set(${var_name} ${default_value}) + endif() + PATH_TO_ABSOLUTE(${var_name}) +endmacro() + +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 the optional git variable. +# If it's not set, we'll try to find it using the CMake packaging system. +if(NOT DEFINED GIT_EXECUTABLE) + find_package(Git QUIET REQUIRED) +endif() +CHECK_REQUIRED_VARIABLE(GIT_EXECUTABLE) + + + +# Function: GitStateChangedAction +# Description: this function is executed when the state of the git +# repo changes (e.g. a commit is made). +function(GitStateChangedAction _state_as_list) + # Set variables by index, then configure the file w/ these variables defined. + LIST(GET _state_as_list 0 GIT_RETRIEVED_STATE) + LIST(GET _state_as_list 1 GIT_HEAD_SHA1) + LIST(GET _state_as_list 2 GIT_IS_DIRTY) + configure_file("${PRE_CONFIGURE_GIT_VERSION_FILE}" "${POST_CONFIGURE_GIT_VERSION_FILE}" @ONLY) +endfunction() + + + +# Function: GetGitState +# Description: gets the current state of the git repo. +# Args: +# _working_dir (in) string; the directory from which git commands will be executed. +# _state (out) list; a collection of variables representing the state of the +# repository (e.g. commit SHA). +function(GetGitState _working_dir _state) + + # Get the hash for HEAD. + set(_success "true") + execute_process(COMMAND + "${GIT_EXECUTABLE}" rev-parse --verify HEAD + WORKING_DIRECTORY "${_working_dir}" + RESULT_VARIABLE res + OUTPUT_VARIABLE _hashvar + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(_success "false") + set(_hashvar "GIT-NOTFOUND") + endif() + + # Get whether or not the working tree is dirty. + execute_process(COMMAND + "${GIT_EXECUTABLE}" status --porcelain + WORKING_DIRECTORY "${_working_dir}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(_success "false") + set(_dirty "false") + else() + if(NOT "${out}" STREQUAL "") + set(_dirty "true") + else() + set(_dirty "false") + endif() + endif() + + # Return a list of our variables to the parent scope. + set(${_state} ${_success} ${_hashvar} ${_dirty} PARENT_SCOPE) +endfunction() + + + +# Function: CheckGit +# Description: check if the git repo has changed. If so, update the state file. +# Args: +# _working_dir (in) string; the directory from which git commands will be ran. +# _state_changed (out) bool; whether or no the state of the repo has changed. +# _state (out) list; the repository state as a list (e.g. commit SHA). +function(CheckGit _working_dir _state_changed _state) + + # Get the current state of the repo. + GetGitState("${_working_dir}" state) + + # Set the output _state variable. + # (Passing by reference in CMake is awkward...) + set(${_state} ${state} PARENT_SCOPE) + + # Check if the state has changed compared to the backup on disk. + if(EXISTS "${GIT_STATE_FILE}") + file(READ "${GIT_STATE_FILE}" OLD_HEAD_CONTENTS) + if(OLD_HEAD_CONTENTS STREQUAL "${state}") + # State didn't change. + set(${_state_changed} "false" PARENT_SCOPE) + return() + endif() + endif() + + # The state has changed. + # We need to update the state file on disk. + # Future builds will compare their state to this file. + file(WRITE "${GIT_STATE_FILE}" "${state}") + set(${_state_changed} "true" PARENT_SCOPE) +endfunction() + + + +# Function: SetupGitMonitoring +# Description: this function sets up custom commands that make the build system +# check the state of git before every build. If the state has +# changed, then a file is configured. +function(SetupGitMonitoring) + add_custom_target(check_git_repository + ALL + DEPENDS ${PRE_CONFIGURE_GIT_VERSION_FILE} + BYPRODUCTS ${POST_CONFIGURE_GIT_VERSION_FILE} + COMMENT "Checking the git repository for changes..." + COMMAND + ${CMAKE_COMMAND} + -D_BUILD_TIME_CHECK_GIT=TRUE + -DGIT_WORKING_DIR=${GIT_WORKING_DIR} + -DGIT_EXECUTABLE=${GIT_EXECUTABLE} + -DGIT_STATE_FILE=${GIT_STATE_FILE} + -DPRE_CONFIGURE_GIT_VERSION_FILE=${PRE_CONFIGURE_GIT_VERSION_FILE} + -DPOST_CONFIGURE_GIT_VERSION_FILE=${POST_CONFIGURE_GIT_VERSION_FILE} + -P "${CMAKE_CURRENT_LIST_FILE}") +endfunction() + + + +# Function: Main +# Description: primary entry-point to the script. Functions are selected based +# on whether it's configure or build time. +function(Main) + if(_BUILD_TIME_CHECK_GIT) + # Check if the repo has changed. + # If so, run the change action. + CheckGit("${GIT_WORKING_DIR}" did_change state) + if(did_change) + GitStateChangedAction("${state}") + endif() + else() + # >> Executes at configure time. + SetupGitMonitoring() + endif() +endfunction() + +# And off we go... +Main() diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex index bf269d2..078bdea 100644 --- a/doc/doxygen_manual.tex +++ b/doc/doxygen_manual.tex @@ -14,6 +14,14 @@ \batchmode \documentclass{book} +%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package +\usepackage{ifthen} +\ifx\requestedLaTeXdate\undefined +\usepackage{array} +\else +\usepackage{array}[=2016-10-06] +\fi +%% \usepackage[a4paper,left=2.5cm,right=2.5cm,top=2.5cm,bottom=2.5cm]{geometry} \usepackage{makeidx} \usepackage{natbib} @@ -23,7 +31,7 @@ \usepackage{geometry} \usepackage{listings} \usepackage{color} -\usepackage{ifthen} +%%\usepackage{ifthen} %% moved to top due to workaround for LaTex 2019 version and unmaintained tabu package \usepackage[table]{xcolor} \PassOptionsToPackage{warn}{textcomp} \usepackage{textcomp} diff --git a/doc/faq.doc b/doc/faq.doc index 88a1275..0ba9450 100644 --- a/doc/faq.doc +++ b/doc/faq.doc @@ -235,6 +235,13 @@ 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 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: +``` +-Denlarge_lex_buffers=<size> +``` +where `<size>` is the new size of the input (`YY_BUF_SIZE`) and read (`YY_READ_BUF_SIZE`) buffer. +In case this option is not given the default value of 262144 (i.e. 256K) will be used. + \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 diff --git a/doc/install.doc b/doc/install.doc index 18ea44e..b711cd4 100644 --- a/doc/install.doc +++ b/doc/install.doc @@ -201,7 +201,7 @@ tar zxvf doxygen-x.y.z.src.tar.gz \endverbatim to unpack the sources (you can obtain \c tar from e.g. http://gnuwin32.sourceforge.net/packages.html). Alternatively you can use an unpack program, like 7-Zip (see https://www.7-zip.org/) -or use the build in unpack feature of modern Windows systems). +or use the built-in unpack feature of modern Windows systems). Now your environment is setup to generate the required project files for \c doxygen. diff --git a/doc/trouble.doc b/doc/trouble.doc index c490ae1..cb50399 100644 --- a/doc/trouble.doc +++ b/doc/trouble.doc @@ -20,7 +20,7 @@ <ul> <li>Doxygen is <em>not</em> a real compiler, it is only a lexical scanner. This means that it can and will not detect errors in your source code. -<li>Doxygen has a build in preprocessor, but this works slightly different than +<li>Doxygen has a built-in preprocessor, but this works slightly different than the C preprocessor. Doxygen assumes a header file is properly guarded against multiple inclusion, and that each include file is standalone (i.e. it could be placed at the top of a source file without causing compiler errors). As long as this is diff --git a/libversion/CMakeLists.txt b/libversion/CMakeLists.txt new file mode 100644 index 0000000..1a430fd --- /dev/null +++ b/libversion/CMakeLists.txt @@ -0,0 +1,27 @@ +# 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(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(POST_CONFIGURE_GIT_VERSION_FILE "${GENERATED_SRC}/gitversion.cpp") + +include(${CMAKE_SOURCE_DIR}/cmake/git_watcher.cmake) +include(${CMAKE_SOURCE_DIR}/cmake/doxygen_version.cmake) + +include_directories( + . +) + +add_library(version STATIC + ${POST_CONFIGURE_DOXYGEN_VERSION_FILE} + ${POST_CONFIGURE_GIT_VERSION_FILE} +) + +add_dependencies( version check_git_repository ) +add_dependencies( version check_doxygen_version ) + +set_source_files_properties(${POST_CONFIGURE_GIT_VERSION_FILE} PROPERTIES GENERATED 1) +set_source_files_properties(${POST_CONFIGURE_DOXYGEN_VERSION_FILE} PROPERTIES GENERATED 1) diff --git a/libversion/doxyversion.cpp.in b/libversion/doxyversion.cpp.in new file mode 100644 index 0000000..11bca8d --- /dev/null +++ b/libversion/doxyversion.cpp.in @@ -0,0 +1,7 @@ +#include "version.h" + +char *getVersion(void) +{ + static char versionString[] = "@DOXYGEN_VERSION@"; + return versionString; +} diff --git a/libversion/gitversion.cpp.in b/libversion/gitversion.cpp.in new file mode 100644 index 0000000..164b50b --- /dev/null +++ b/libversion/gitversion.cpp.in @@ -0,0 +1,16 @@ +#include <string.h> +#include <version.h> + +/* - On some systems git is not installed or + * installed on a place where FindGit.cmake cannot find it + * - No git information is present (no .git directory) + * in those cases clear the gitVersionString (would have string GIT-NOTFOUND). + */ +char *getGitVersion(void) +{ + static char gitVersionString[100]; + strcpy(gitVersionString,"@GIT_HEAD_SHA1@"); + strcat(gitVersionString,!strcmp("@GIT_IS_DIRTY@","true")?"*":""); + if (!strcmp("@GIT_HEAD_SHA1@", "GIT-NOTFOUND")) gitVersionString[0] = '\0'; + return gitVersionString; +} diff --git a/addon/doxywizard/version.h b/libversion/version.h index 16bf9df..a656e74 100644 --- a/addon/doxywizard/version.h +++ b/libversion/version.h @@ -17,7 +17,6 @@ #ifndef VERSION_H #define VERSION_H - -extern char versionString[]; - +char *getVersion(void); +char *getGitVersion(void); #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc79194..06e0e44 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/libmd5 ${CMAKE_SOURCE_DIR}/liblodepng ${CMAKE_SOURCE_DIR}/libmscgen + ${CMAKE_SOURCE_DIR}/libversion ${CMAKE_SOURCE_DIR}/vhdlparser ${CMAKE_SOURCE_DIR}/src ${CLANG_INCLUDEDIR} @@ -16,7 +17,7 @@ file(MAKE_DIRECTORY ${GENERATED_SRC}) file(GLOB LANGUAGE_FILES "${CMAKE_SOURCE_DIR}/src/translator_??.h") # instead of increasebuffer.py -add_definitions(-DYY_BUF_SIZE=262144 -DYY_READ_BUF_SIZE=262144) +add_definitions(-DYY_BUF_SIZE=${enlarge_lex_buffers} -DYY_READ_BUF_SIZE=${enlarge_lex_buffers}) # generate settings.h file(GENERATE OUTPUT ${GENERATED_SRC}/settings.h @@ -32,12 +33,6 @@ CONTENT "#ifndef SETTINGS_H set_source_files_properties(${GENERATED_SRC}/settings.h PROPERTIES GENERATED 1) -# generate version.cpp -file(GENERATE OUTPUT ${GENERATED_SRC}/version.cpp - CONTENT "char versionString[]=\"${VERSION}\";" -) -set_source_files_properties(${GENERATED_SRC}/version.cpp PROPERTIES GENERATED 1) - # configvalues.h add_custom_command( COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/configgen.py -maph ${CMAKE_SOURCE_DIR}/src/config.xml > ${GENERATED_SRC}/configvalues.h @@ -142,7 +137,6 @@ add_library(_doxygen STATIC ${GENERATED_SRC}/lang_cfg.h ${GENERATED_SRC}/settings.h ${GENERATED_SRC}/layout_default.xml.h - ${GENERATED_SRC}/version.cpp ${GENERATED_SRC}/ce_parse.h ${GENERATED_SRC}/configvalues.h ${GENERATED_SRC}/resources.cpp @@ -254,6 +248,7 @@ add_library(_doxygen STATIC xmlgen.cpp docbookvisitor.cpp docbookgen.cpp + docgroup.cpp ) add_executable(doxygen main.cpp) @@ -285,6 +280,7 @@ target_link_libraries(doxygen md5 lodepng mscgen + version vhdlparser ${SQLITE3_LIBRARIES} ${ICONV_LIBRARIES} diff --git a/src/classdef.cpp b/src/classdef.cpp index a7f24ed..a7b59c1 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -3330,7 +3330,7 @@ void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCStri //printf("addTypeContraint(%s,%s)\n",type.data(),typeConstraint.data()); static bool hideUndocRelation = Config_getBool(HIDE_UNDOC_RELATIONS); if (typeConstraint.isEmpty() || type.isEmpty()) return; - ClassDef *cd = getResolvedClass(this,getFileDef(),typeConstraint); + ClassDef *cd = const_cast<ClassDef*>(getResolvedClass(this,getFileDef(),typeConstraint)); if (cd==0 && !hideUndocRelation) { cd = new ClassDefImpl(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class); @@ -139,9 +139,9 @@ struct ObjCCallCtx QCString methodName; QCString objectTypeOrName; QGString comment; - ClassDef *objectType; - MemberDef *objectVar; - MemberDef *method; + const ClassDef *objectType; + const MemberDef *objectVar; + const MemberDef *method; QCString format; int lexState; int braceCount; @@ -252,7 +252,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name) 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(); - ClassDef *varType; + const ClassDef *varType; int i=0; if ( (varType=g_codeClassSDict->find(ltype)) || // look for class definitions inside the code block @@ -338,15 +338,15 @@ class CallContext public: struct Ctx { - Ctx() : name(g_name), type(g_type), d(0) {} + Ctx(QCString _name, QCString _type) : name(_name), type(_type), d(0) {} QCString name; QCString type; const Definition *d; }; - CallContext() + CallContext() { - m_defList.append(new Ctx); + m_defList.append(new Ctx("","")); m_defList.setAutoDelete(TRUE); } virtual ~CallContext() {} @@ -359,12 +359,12 @@ class CallContext ctx->d=d; } } - void pushScope() + void pushScope(QCString _name, QCString _type) { - m_defList.append(new Ctx); + m_defList.append(new Ctx(_name,_type)); DBG_CTX((stderr,"** Push call context %d\n",m_defList.count())); } - void popScope() + void popScope(QCString &_name, QCString &_type) { if (m_defList.count()>1) { @@ -372,8 +372,8 @@ class CallContext Ctx *ctx = m_defList.getLast(); if (ctx) { - g_name = ctx->name; - g_type = ctx->type; + _name = ctx->name; + _type = ctx->type; } m_defList.removeLast(); } @@ -386,7 +386,7 @@ class CallContext { DBG_CTX((stderr,"** Clear call context\n")); m_defList.clear(); - m_defList.append(new Ctx); + m_defList.append(new Ctx("","")); } const Definition *getScope() const { @@ -695,7 +695,7 @@ static void setParameterList(const MemberDef *md) } } -static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) +static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) { int pos=0; QCString type = s; @@ -704,7 +704,7 @@ static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) while (extractClassNameFromType(type,pos,className,templSpec)!=-1) { QCString clName=className+templSpec; - ClassDef *cd=0; + const ClassDef *cd=0; if (!g_classScope.isEmpty()) { cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName); @@ -843,7 +843,7 @@ static void updateCallContextForSmartPointer() MemberDef *md; if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer())) { - ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope()); + const ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope()); if (ncd) { g_theCallContext.setScope(ncd); @@ -961,8 +961,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName { className = substitute(className,".","::"); // for PHP namespaces } - ClassDef *cd=0,*lcd=0; - MemberDef *md=0; + const ClassDef *cd=0,*lcd=0; + const MemberDef *md=0; bool isLocal=FALSE; //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); @@ -1033,7 +1033,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName anchor.sprintf("_a%d",g_anchorCount); //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(), // g_exampleFile.data()); - if (cd->addExample(anchor,g_exampleName,g_exampleFile)) + if (const_cast<ClassDef*>(cd)->addExample(anchor,g_exampleName,g_exampleFile)) { ol.writeCodeAnchor(anchor); g_anchorCount++; @@ -1050,7 +1050,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } } } @@ -1092,8 +1092,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName } text+=getLanguageSpecificSeparator(md->getLanguage()); text+=clName; - md->setName(text); - md->setLocalName(text); + const_cast<MemberDef*>(md)->setName(text); + const_cast<MemberDef*>(md)->setLocalName(text); } else // normal reference { @@ -1103,7 +1103,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName addToSearchIndex(clName); if (g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } return; } @@ -1139,7 +1139,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const } } - ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); + const ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); g_theCallContext.setScope(typeClass); @@ -1220,7 +1220,7 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName, if (varName.isEmpty()) return; // look for the variable in the current context - ClassDef *vcd = g_theVarContext.findVariable(varName); + const ClassDef *vcd = g_theVarContext.findVariable(varName); if (vcd) { if (vcd!=VariableContext::dummyContext) @@ -1265,14 +1265,14 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName, if (vmn) { MemberNameIterator vmni(*vmn); - MemberDef *vmd; + const MemberDef *vmd; for (;(vmd=vmni.current());++vmni) { if (/*(vmd->isVariable() || vmd->isFunction()) && */ vmd->getClassDef()==jcd) { //printf("Found variable type=%s\n",vmd->typeString()); - ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); + const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); if (mcd && mcd->isLinkable()) { if (generateClassMemberLink(ol,mcd,memName)) return; @@ -1286,14 +1286,14 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName, { //printf("There is a variable with name `%s'\n",varName); MemberNameIterator vmni(*vmn); - MemberDef *vmd; + const MemberDef *vmd; for (;(vmd=vmni.current());++vmni) { if (/*(vmd->isVariable() || vmd->isFunction()) && */ vmd->getClassDef()==vcd) { //printf("Found variable type=%s\n",vmd->typeString()); - ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); + const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); if (mcd && mcd->isLinkable()) { if (generateClassMemberLink(ol,mcd,memName)) return; @@ -1561,7 +1561,7 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx) writeMultiLineCodeLink(*g_code,ctx->method,pName->data()); if (g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,ctx->method); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(ctx->method)); } } else @@ -1640,7 +1640,7 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx) writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data()); if (g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,ctx->objectVar); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(ctx->objectVar)); } } else if (ctx->objectType && @@ -1648,12 +1648,12 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx) ctx->objectType->isLinkable() ) // object is class name { - ClassDef *cd = ctx->objectType; + const ClassDef *cd = ctx->objectType; writeMultiLineCodeLink(*g_code,cd,pObject->data()); } else // object still needs to be resolved { - ClassDef *cd = getResolvedClass(g_currentDefinition, + const ClassDef *cd = getResolvedClass(g_currentDefinition, g_sourceFileDef, *pObject); if (cd && cd->isLinkable()) { @@ -2302,12 +2302,11 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" char *s=g_curClassBases.first(); while (s) { - ClassDef *bcd; - bcd=g_codeClassSDict->find(s); + const ClassDef *bcd=g_codeClassSDict->find(s); if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s); if (bcd && bcd!=ncd) { - ncd->insertBaseClass(bcd,s,Public,Normal); + ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal); } s=g_curClassBases.next(); } @@ -2510,7 +2509,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <Body>"*"{B}*")" { // end of cast? g_code->codify(yytext); - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_bracketCount--; g_parmType = g_name; BEGIN(FuncCall); @@ -2520,7 +2519,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_name.resize(0);g_type.resize(0); if (*yytext==')') { - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_bracketCount--; BEGIN(FuncCall); } @@ -2852,7 +2851,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } else if (*yytext=='[') { - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); } g_args.resize(0); g_parmType.resize(0); @@ -2878,7 +2877,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <ObjCMemberCall>"[" { g_code->codify(yytext); - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); } <ObjCMemberCall2>{ID}":"? { g_name+=yytext; @@ -2900,7 +2899,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" BEGIN(ObjCMemberCall3); } <ObjCMemberCall2,ObjCMemberCall3>"]" { - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_code->codify(yytext); BEGIN(Body); } @@ -2990,7 +2989,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; } <Body>"]" { - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_code->codify(yytext); // TODO: nested arrays like: a[b[0]->func()]->func() g_name = g_saveName.copy(); @@ -3093,7 +3092,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_parmType.resize(0);g_parmName.resize(0); g_code->codify(yytext); g_bracketCount++; - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); if (YY_START==FuncCall && !g_insideBody) { g_theVarContext.pushScope(); @@ -3127,7 +3126,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_parmName.resize(0); g_theVarContext.addVariable(g_parmType,g_parmName); } - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_inForEachExpression = FALSE; //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). g_code->codify(yytext); @@ -3184,7 +3183,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_theVarContext.pushScope(); } g_theVarContext.addVariable(g_parmType,g_parmName); - //g_theCallContext.popScope(); + //g_theCallContext.popScope(g_name, g_type); g_parmType.resize(0);g_parmName.resize(0); int index = g_name.findRev("::"); DBG_CTX((stderr,"g_name=%s\n",g_name.data())); @@ -3192,7 +3191,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" { QCString scope = g_name.left(index); if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::"); - ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope); + const ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope); if (cd) { setClassScope(cd->name()); @@ -3644,11 +3643,11 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <*>"("|"[" { g_code->codify(yytext); - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); } <*>")"|"]" { g_code->codify(yytext); - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); } <*>\n { g_yyColNr++; diff --git a/src/commentcnv.l b/src/commentcnv.l index 0ea5ff7..031b6f5 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -266,7 +266,7 @@ void replaceComment(int offset); else { g_pythonDocString = TRUE; - g_nestingCount=0; + g_nestingCount=1; g_commentStack.clear(); /* to be on the save side */ copyToOutput(yytext,(int)yyleng); BEGIN(CComment); @@ -281,7 +281,7 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Fortran doesn't have an end comment g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -298,7 +298,7 @@ void replaceComment(int offset); if (isFixedForm && (g_col == 0)) { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Fortran doesn't have an end comment g_commentStack.clear(); /* to be on the safe side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -404,7 +404,7 @@ void replaceComment(int offset); REJECT; } g_specialComment=(int)yyleng==3; - g_nestingCount=0; + g_nestingCount=1; g_commentStack.clear(); /* to be on the save side */ copyToOutput(yytext,(int)yyleng); BEGIN(CComment); @@ -418,7 +418,7 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Python doesn't have an end comment for # g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -433,7 +433,7 @@ void replaceComment(int offset); { g_vhdl = TRUE; copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // VHDL doesn't have an end comment g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -447,7 +447,7 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Fortran doesn't have an end comment g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -680,13 +680,14 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); + g_nestingCount--; if (g_nestingCount<=0) { BEGIN(Scan); } else { - g_nestingCount--; + //g_nestingCount--; delete g_commentStack.pop(); } } @@ -1119,7 +1120,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) } tmp += ")"; warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. " - "Nesting level %d %s",g_nestingCount+1,tmp.data()); // add one for "normal" expected end of comment + "Nesting level %d %s",g_nestingCount,tmp.data()); } g_commentStack.clear(); g_nestingCount = 0; diff --git a/src/commentscan.h b/src/commentscan.h index 75cd99f..7d2189f 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -85,13 +85,5 @@ bool parseCommentBlock(ParserInterface *parser, bool &newEntryNeeded ); -void groupEnterFile(const char *file,int line); -void groupLeaveFile(const char *file,int line); -void groupLeaveCompound(const char *file,int line,const char *name); -void groupEnterCompound(const char *file,int line,const char *name); -void openGroup(Entry *e,const char *file,int line); -void closeGroup(Entry *,const char *file,int line,bool foundInline=FALSE); -void initGroupInfo(Entry *e); - #endif diff --git a/src/commentscan.l b/src/commentscan.l index 665360c..a52821c 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -386,11 +386,6 @@ class GuardedSection bool m_parentVisible; }; -void openGroup(Entry *e,const char *file,int line); -void closeGroup(Entry *e,const char *file,int line,bool foundInline=FALSE); -void initGroupInfo(Entry *e); -static void groupAddDocs(Entry *e); - /* ----------------------------------------------------------------- * * statics @@ -451,21 +446,11 @@ static bool g_insideParBlock; //----------------------------------------------------------------------------- -static QStack<Grouping> g_autoGroupStack; -static int g_memberGroupId = DOX_NOGROUP; -static QCString g_memberGroupHeader; -static QCString g_memberGroupDocs; -static QCString g_memberGroupRelates; -static QCString g_compoundName; - -static int g_openCount = 0; -//----------------------------------------------------------------------------- - static void initParser() { g_sectionLabel.resize(0); g_sectionTitle.resize(0); - g_memberGroupHeader.resize(0); + Doxygen::docGroup.clearHeader(); g_insideParBlock = FALSE; } @@ -1219,12 +1204,12 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } <Comment>{B}*{CMD}"{" { // begin of a group //langParser->handleGroupStartCommand(g_memberGroupHeader); - openGroup(current,yyFileName,yyLineNr); + Doxygen::docGroup.open(current,yyFileName,yyLineNr); } <Comment>{B}*{CMD}"}" { // end of a group //langParser->handleGroupEndCommand(); - closeGroup(current,yyFileName,yyLineNr,TRUE); - g_memberGroupHeader.resize(0); + Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE); + Doxygen::docGroup.clearHeader(); parseMore=TRUE; needNewEntry = TRUE; #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33)) @@ -1905,17 +1890,20 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput('\n'); } <FormatBlock>"/*" { // start of a C-comment - g_commentCount++; + if (!(blockName=="code" || blockName=="verbatim")) g_commentCount++; addOutput(yytext); } <FormatBlock>"*/" { // end of a C-comment addOutput(yytext); - g_commentCount--; - if (g_commentCount<0 && blockName!="verbatim") - { - warn(yyFileName,yyLineNr, + if (!(blockName=="code" || blockName=="verbatim")) + { + g_commentCount--; + if (g_commentCount<0) + { + warn(yyFileName,yyLineNr, "found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data()); - } + } + } } <FormatBlock>. { addOutput(*yytext); @@ -2130,10 +2118,10 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <NameParam>{LC} { // line continuation yyLineNr++; addOutput('\n'); - g_memberGroupHeader+=' '; + Doxygen::docGroup.appendHeader(' '); } <NameParam>. { // ignore other stuff - g_memberGroupHeader+=*yytext; + Doxygen::docGroup.appendHeader(*yytext); current->name+=*yytext; } @@ -2553,11 +2541,11 @@ static bool handleName(const QCString &, const QCStringList &) bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC); if (!stop) { - g_memberGroupHeader.resize(0); + Doxygen::docGroup.clearHeader(); BEGIN( NameParam ); - if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group + if (!Doxygen::docGroup.isEmpty()) // end of previous member group { - closeGroup(current,yyFileName,yyLineNr,TRUE); + Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE); } } return stop; @@ -3205,9 +3193,9 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, } if (current->section==Entry::MEMBERGRP_SEC && - g_memberGroupId==DOX_NOGROUP) // @name section but no group started yet + Doxygen::docGroup.isEmpty()) // @name section but no group started yet { - openGroup(current,yyFileName,yyLineNr); + Doxygen::docGroup.open(current,yyFileName,yyLineNr,true); } Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\noutput=[\n" @@ -3221,7 +3209,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, checkFormula(); prot = protection; - groupAddDocs(curEntry); + Doxygen::docGroup.addDocs(curEntry); newEntryNeeded = needNewEntry; @@ -3240,196 +3228,6 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, return parseMore; } -//--------------------------------------------------------------------------- - -void groupEnterFile(const char *fileName,int) -{ - g_openCount = 0; - g_autoGroupStack.setAutoDelete(TRUE); - g_autoGroupStack.clear(); - g_memberGroupId = DOX_NOGROUP; - g_memberGroupDocs.resize(0); - g_memberGroupRelates.resize(0); - g_compoundName=fileName; -} - -void groupLeaveFile(const char *fileName,int line) -{ - //if (g_memberGroupId!=DOX_NOGROUP) - //{ - // warn(fileName,line,"end of file while inside a member group\n"); - //} - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - if (!g_autoGroupStack.isEmpty()) - { - warn(fileName,line,"end of file while inside a group"); - } - else if (g_openCount > 0) // < 0 is already handled on close call - { - warn(fileName,line,"end of file with unbalanced grouping commands"); - } -} - -void groupEnterCompound(const char *fileName,int line,const char *name) -{ - if (g_memberGroupId!=DOX_NOGROUP) - { - warn(fileName,line,"try to put compound %s inside a member group\n",name); - } - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - g_compoundName = name; - int i = g_compoundName.find('('); - if (i!=-1) - { - g_compoundName=g_compoundName.left(i); // strip category (Obj-C) - } - if (g_compoundName.isEmpty()) - { - g_compoundName=fileName; - } - //printf("groupEnterCompound(%s)\n",name); -} - -void groupLeaveCompound(const char *,int,const char * /*name*/) -{ - //printf("groupLeaveCompound(%s)\n",name); - //if (g_memberGroupId!=DOX_NOGROUP) - //{ - // warn(fileName,line,"end of compound %s while inside a member group\n",name); - //} - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - g_compoundName.resize(0); -} - -static int findExistingGroup(int &groupId,const MemberGroupInfo *info) -{ - //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data()); - QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict); - MemberGroupInfo *mi; - for (di.toFirst();(mi=di.current());++di) - { - if (g_compoundName==mi->compoundName && // same file or scope - !mi->header.isEmpty() && // not a nameless group - qstricmp(mi->header,info->header)==0 // same header name - ) - { - //printf("Found it!\n"); - return (int)di.currentKey(); // put the item in this group - } - } - groupId++; // start new group - return groupId; -} - -void openGroup(Entry *e,const char *,int) -{ - g_openCount++; - //printf("==> openGroup(name=%s,sec=%x) g_autoGroupStack=%d\n", - // e->name.data(),e->section,g_autoGroupStack.count()); - if (e->section==Entry::GROUPDOC_SEC) // auto group - { - g_autoGroupStack.push(new Grouping(e->name,e->groupingPri())); - } - else // start of a member group - { - //printf(" membergroup id=%d %s\n",g_memberGroupId,g_memberGroupHeader.data()); - if (g_memberGroupId==DOX_NOGROUP) // no group started yet - { - static int curGroupId=0; - - MemberGroupInfo *info = new MemberGroupInfo; - info->header = g_memberGroupHeader.stripWhiteSpace(); - info->compoundName = g_compoundName; - g_memberGroupId = findExistingGroup(curGroupId,info); - //printf(" use membergroup %d\n",g_memberGroupId); - Doxygen::memGrpInfoDict.insert(g_memberGroupId,info); - - g_memberGroupRelates = e->relates; - e->mGrpId = g_memberGroupId; - } - } -} - -void closeGroup(Entry *e,const char *fileName,int line,bool foundInline) -{ - g_openCount--; - if (g_openCount < 0) - { - warn(fileName,line,"unbalanced grouping commands"); - } - //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) g_autoGroupStack=%d\n", - // e->name.data(),e->section,fileName,line,g_autoGroupStack.count()); - if (g_memberGroupId!=DOX_NOGROUP) // end of member group - { - MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId); - if (info) // known group - { - info->doc = g_memberGroupDocs; - info->docFile = fileName; - info->docLine = line; - } - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - if (!foundInline) e->mGrpId=DOX_NOGROUP; - //printf("new group id=%d\n",g_memberGroupId); - } - else if (!g_autoGroupStack.isEmpty()) // end of auto group - { - Grouping *grp = g_autoGroupStack.pop(); - // see bug577005: we should not remove the last group for e - if (!foundInline) e->groups->removeLast(); - //printf("Removing %s e=%p\n",grp->groupname.data(),e); - delete grp; - if (!foundInline) initGroupInfo(e); - } -} - -void initGroupInfo(Entry *e) -{ - //printf("==> initGroup(id=%d,related=%s,e=%p)\n",g_memberGroupId, - // g_memberGroupRelates.data(),e); - e->mGrpId = g_memberGroupId; - e->relates = g_memberGroupRelates; - if (!g_autoGroupStack.isEmpty()) - { - //printf("Appending group %s to %s: count=%d entry=%p\n", - // g_autoGroupStack.top()->groupname.data(), - // e->name.data(),e->groups->count(),e); - e->groups->append(new Grouping(*g_autoGroupStack.top())); - } -} - -static void groupAddDocs(Entry *e) -{ - if (e->section==Entry::MEMBERGRP_SEC) - { - g_memberGroupDocs=e->brief.stripWhiteSpace(); - e->doc = stripLeadingAndTrailingEmptyLines(e->doc,e->docLine); - if (!g_memberGroupDocs.isEmpty() && !e->doc.isEmpty()) - { - g_memberGroupDocs+="\n\n"; - } - g_memberGroupDocs+=e->doc; - MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId); - if (info) - { - info->doc = g_memberGroupDocs; - info->docFile = e->docFile; - info->docLine = e->docLine; - info->setRefItems(e->sli); - } - e->doc.resize(0); - e->brief.resize(0); - } -} - static void handleGuard(const QCString &expr) { CondParser prs; diff --git a/src/configgen.py b/src/configgen.py index ca2a5d1..dbba264 100755 --- a/src/configgen.py +++ b/src/configgen.py @@ -717,6 +717,10 @@ def main(): print("") print("void ConfigValues::init()") print("{") + print(" static bool first = TRUE;") + print(" if (!first) return;") + print(" first = FALSE;") + print("") for n in elem.childNodes: if n.nodeType == Node.ELEMENT_NODE: if (n.nodeName == "group"): diff --git a/src/configimpl.l b/src/configimpl.l index bc08cbf..72c826d 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -943,7 +943,7 @@ void ConfigImpl::writeTemplate(FTextStream &t,bool sl,bool upd) { t << takeStartComment() << endl; } - t << "# Doxyfile " << versionString << endl << endl; + t << "# Doxyfile " << getVersion() << endl << endl; if (!sl) { t << convertToComment(m_header,""); @@ -964,7 +964,12 @@ void ConfigImpl::writeTemplate(FTextStream &t,bool sl,bool upd) void ConfigImpl::compareDoxyfile(FTextStream &t) { - t << "# Difference with default Doxyfile " << versionString << endl; + t << "# Difference with default Doxyfile " << getVersion(); + if (strlen(getGitVersion())) + { + t << " (" << getGitVersion() << ")"; + } + t << endl; QListIterator<ConfigOption> it = iterator(); ConfigOption *option; for (;(option=it.current());++it) diff --git a/src/context.cpp b/src/context.cpp index 66206b1..49c9afa 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -380,7 +380,7 @@ class DoxygenContext::Private public: TemplateVariant version() const { - return versionString; + return getVersion(); } TemplateVariant date() const { diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 937d268..1901454 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -636,152 +636,152 @@ DB_VIS_C case DocSimpleSect::See: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << "</title>" << endl; } break; case DocSimpleSect::Return: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trReturns()<< ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trReturns()<< "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << "</title>" << endl; } break; case DocSimpleSect::Author: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << "</title>" << endl; } break; case DocSimpleSect::Authors: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << "</title>" << endl; } break; case DocSimpleSect::Version: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trVersion() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trVersion() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << "</title>" << endl; } break; case DocSimpleSect::Since: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trSince() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trSince() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << "</title>" << endl; } break; case DocSimpleSect::Date: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trDate() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trDate() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << "</title>" << endl; } break; case DocSimpleSect::Note: if (m_insidePre) { - m_t << "<note><title>" << theTranslator->trNote() << ": </title>" << endl; + m_t << "<note><title>" << theTranslator->trNote() << "</title>" << endl; } else { - m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << ": </title>" << endl; + m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << "</title>" << endl; } break; case DocSimpleSect::Warning: if (m_insidePre) { - m_t << "<warning><title>" << theTranslator->trWarning() << ": </title>" << endl; + m_t << "<warning><title>" << theTranslator->trWarning() << "</title>" << endl; } else { - m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << ": </title>" << endl; + m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << "</title>" << endl; } break; case DocSimpleSect::Pre: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trPrecondition() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trPrecondition() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << "</title>" << endl; } break; case DocSimpleSect::Post: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trPostcondition() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trPostcondition() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << "</title>" << endl; } break; case DocSimpleSect::Copyright: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trCopyright() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trCopyright() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << "</title>" << endl; } break; case DocSimpleSect::Invar: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trInvariant() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trInvariant() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << "</title>" << endl; } break; case DocSimpleSect::Remark: // <remark> is miising the <title> possibility if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trRemarks() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trRemarks() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << "</title>" << endl; } break; case DocSimpleSect::Attention: if (m_insidePre) { - m_t << "<caution><title>" << theTranslator->trAttention() << ": </title>" << endl; + m_t << "<caution><title>" << theTranslator->trAttention() << "</title>" << endl; } else { - m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << ": </title>" << endl; + m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << "</title>" << endl; } break; case DocSimpleSect::User: diff --git a/src/docgroup.cpp b/src/docgroup.cpp new file mode 100644 index 0000000..2dcca70 --- /dev/null +++ b/src/docgroup.cpp @@ -0,0 +1,212 @@ +#include "doxygen.h" +#include "util.h" +#include "entry.h" +#include "message.h" +#include "docgroup.h" + + +void DocGroup::enterFile(const char *fileName,int) +{ + m_openCount = 0; + m_autoGroupStack.setAutoDelete(TRUE); + m_autoGroupStack.clear(); + m_memberGroupId = DOX_NOGROUP; + m_memberGroupDocs.resize(0); + m_memberGroupRelates.resize(0); + m_compoundName=fileName; +} + +void DocGroup::leaveFile(const char *fileName,int line) +{ + //if (m_memberGroupId!=DOX_NOGROUP) + //{ + // warn(fileName,line,"end of file while inside a member group\n"); + //} + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + if (!m_autoGroupStack.isEmpty()) + { + warn(fileName,line,"end of file while inside a group"); + } + else if (m_openCount > 0) // < 0 is already handled on close call + { + warn(fileName,line,"end of file with unbalanced grouping commands"); + } +} + +void DocGroup::enterCompound(const char *fileName,int line,const char *name) +{ + if (m_memberGroupId!=DOX_NOGROUP) + { + warn(fileName,line,"try to put compound %s inside a member group\n",name); + } + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + m_compoundName = name; + int i = m_compoundName.find('('); + if (i!=-1) + { + m_compoundName=m_compoundName.left(i); // strip category (Obj-C) + } + if (m_compoundName.isEmpty()) + { + m_compoundName=fileName; + } + //printf("groupEnterCompound(%s)\n",name); +} + +void DocGroup::leaveCompound(const char *,int,const char * /*name*/) +{ + //printf("groupLeaveCompound(%s)\n",name); + //if (m_memberGroupId!=DOX_NOGROUP) + //{ + // warn(fileName,line,"end of compound %s while inside a member group\n",name); + //} + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + m_compoundName.resize(0); +} + +int DocGroup::findExistingGroup(int &groupId,const MemberGroupInfo *info) +{ + //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data()); + QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict); + MemberGroupInfo *mi; + for (di.toFirst();(mi=di.current());++di) + { + if (m_compoundName==mi->compoundName && // same file or scope + !mi->header.isEmpty() && // not a nameless group + qstricmp(mi->header,info->header)==0 // same header name + ) + { + //printf("Found it!\n"); + return (int)di.currentKey(); // put the item in this group + } + } + groupId++; // start new group + return groupId; +} + +void DocGroup::open(Entry *e,const char *,int, bool implicit) +{ + if (!implicit) m_openCount++; + //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%d\n", + // e->name.data(),e->section,m_autoGroupStack.count()); + if (e->section==Entry::GROUPDOC_SEC) // auto group + { + m_autoGroupStack.push(new Grouping(e->name,e->groupingPri())); + } + else // start of a member group + { + //printf(" membergroup id=%d %s\n",m_memberGroupId,m_memberGroupHeader.data()); + if (m_memberGroupId==DOX_NOGROUP) // no group started yet + { + static int curGroupId=0; + + MemberGroupInfo *info = new MemberGroupInfo; + info->header = m_memberGroupHeader.stripWhiteSpace(); + info->compoundName = m_compoundName; + m_memberGroupId = findExistingGroup(curGroupId,info); + //printf(" use membergroup %d\n",m_memberGroupId); + Doxygen::memGrpInfoDict.insert(m_memberGroupId,info); + + m_memberGroupRelates = e->relates; + e->mGrpId = m_memberGroupId; + } + } +} + +void DocGroup::close(Entry *e,const char *fileName,int line,bool foundInline) +{ + if (m_openCount < 1) + { + warn(fileName,line,"unbalanced grouping commands"); + } + else + { + m_openCount--; + } + //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%d\n", + // e->name.data(),e->section,fileName,line,m_autoGroupStack.count()); + if (m_memberGroupId!=DOX_NOGROUP) // end of member group + { + MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(m_memberGroupId); + if (info) // known group + { + info->doc = m_memberGroupDocs; + info->docFile = fileName; + info->docLine = line; + } + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + if (!foundInline) e->mGrpId=DOX_NOGROUP; + //printf("new group id=%d\n",m_memberGroupId); + } + else if (!m_autoGroupStack.isEmpty()) // end of auto group + { + Grouping *grp = m_autoGroupStack.pop(); + // see bug577005: we should not remove the last group for e + if (!foundInline) e->groups->removeLast(); + //printf("Removing %s e=%p\n",grp->groupname.data(),e); + delete grp; + if (!foundInline) initGroupInfo(e); + } +} + +void DocGroup::initGroupInfo(Entry *e) +{ + //printf("==> initGroup(id=%d,related=%s,e=%p)\n",m_memberGroupId, + // m_memberGroupRelates.data(),e); + e->mGrpId = m_memberGroupId; + e->relates = m_memberGroupRelates; + if (!m_autoGroupStack.isEmpty()) + { + //printf("Appending group %s to %s: count=%d entry=%p\n", + // m_autoGroupStack.top()->groupname.data(), + // e->name.data(),e->groups->count(),e); + e->groups->append(new Grouping(*m_autoGroupStack.top())); + } +} + +void DocGroup::addDocs(Entry *e) +{ + if (e->section==Entry::MEMBERGRP_SEC) + { + m_memberGroupDocs=e->brief.stripWhiteSpace(); + e->doc = stripLeadingAndTrailingEmptyLines(e->doc,e->docLine); + if (!m_memberGroupDocs.isEmpty() && !e->doc.isEmpty()) + { + m_memberGroupDocs+="\n\n"; + } + m_memberGroupDocs+=e->doc; + MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(m_memberGroupId); + if (info) + { + info->doc = m_memberGroupDocs; + info->docFile = e->docFile; + info->docLine = e->docLine; + info->setRefItems(e->sli); + } + e->doc.resize(0); + e->brief.resize(0); + } +} + +bool DocGroup::isEmpty() const +{ + return (m_memberGroupId==DOX_NOGROUP); +} + +void DocGroup::clearHeader() +{ + m_memberGroupHeader.resize(0); +} + +void DocGroup::appendHeader(const char text) +{ + m_memberGroupHeader += text; +} diff --git a/src/docgroup.h b/src/docgroup.h new file mode 100644 index 0000000..4ce9af9 --- /dev/null +++ b/src/docgroup.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * 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 + * 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 DOCGROUP_H +#define DOCGROUP_H + +#include <qstack.h> +#include <qstring.h> +#include "membergroup.h" + +class Entry; + +class DocGroup +{ + public: + DocGroup() {}; + + public: + void enterFile(const char *fileName,int); + void leaveFile(const char *fileName,int line); + void enterCompound(const char *fileName,int line,const char *name); + void leaveCompound(const char *,int,const char * /*name*/); + void open(Entry *e,const char *,int,bool implicit=false); + void close(Entry *e,const char *fileName,int line,bool foundInline); + void initGroupInfo(Entry *e); + bool isEmpty() const; + void clearHeader(); + void appendHeader(const char); + void addDocs(Entry *e); + + private: + int findExistingGroup(int &groupId,const MemberGroupInfo *info); + int m_openCount; + QCString m_memberGroupHeader; + int m_memberGroupId; + QCString m_memberGroupRelates; + QCString m_memberGroupDocs; + QStack<Grouping> m_autoGroupStack; + QCString m_compoundName; +}; + +#endif diff --git a/src/docparser.cpp b/src/docparser.cpp index f097d04..be0d60b 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -816,8 +816,8 @@ 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", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return tok; } while ((tok=doctokenizerYYlex()) && @@ -852,7 +852,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, break; } } - DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(cmdName),tok)); + DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok)); return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST ) ? tok : RetVal_OK; } @@ -1162,7 +1162,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,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(tokenName)); return 0; } @@ -1182,7 +1182,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,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(g_token->name)); return 0; } @@ -2681,8 +2681,9 @@ DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocDotFile::parse() +bool DocDotFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_DOTFILE,this,m_children,m_width,m_height); bool ambig; @@ -2694,6 +2695,7 @@ void DocDotFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2707,6 +2709,7 @@ void DocDotFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found " "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name)); } + return ok; } DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) : @@ -2715,8 +2718,9 @@ DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocMscFile::parse() +bool DocMscFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_MSCFILE,this,m_children,m_width,m_height); bool ambig; @@ -2728,6 +2732,7 @@ void DocMscFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2741,6 +2746,7 @@ void DocMscFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found " "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name)); } + return ok; } //--------------------------------------------------------------------------- @@ -2751,8 +2757,9 @@ DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocDiaFile::parse() +bool DocDiaFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_DIAFILE,this,m_children,m_width,m_height); bool ambig; @@ -2764,6 +2771,7 @@ void DocDiaFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2777,6 +2785,7 @@ void DocDiaFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found " "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name)); } + return ok; } //--------------------------------------------------------------------------- @@ -4549,8 +4558,8 @@ int DocParamList::parse(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); retval=0; goto endparamlist; } @@ -4588,7 +4597,7 @@ int DocParamList::parse(const QCString &cmdName) if (tok==0) /* premature end of comment block */ { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s",qPrint(cmdName)); + "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; } @@ -4786,7 +4795,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,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint("cite")); return; } @@ -4818,7 +4827,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,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint("emoji")); return; } @@ -4865,12 +4874,13 @@ int DocPara::handleXRefItem() void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t) { - DBG(("handleIncludeOperator(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; + DBG(("handleIncludeOperator(%s)\n",qPrint(saveCmdName))); int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStatePattern(); @@ -4879,13 +4889,13 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s", qPrint(cmdName)); + "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", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName); @@ -4951,7 +4961,7 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command with option", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command with option", qPrint(saveCmdName)); return; } @@ -4959,7 +4969,7 @@ void DocPara::handleImage(const QCString &cmdName) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -4974,7 +4984,7 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5009,11 +5019,12 @@ void DocPara::handleImage(const QCString &cmdName) template<class T> void DocPara::handleFile(const QCString &cmdName) { + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateFile(); @@ -5022,13 +5033,19 @@ void DocPara::handleFile(const QCString &cmdName) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } QCString name = g_token->name; T *df = new T(this,name,g_context); - m_children.append(df); - df->parse(); + if (df->parse()) + { + m_children.append(df); + } + else + { + delete df; + } } void DocPara::handleVhdlFlow() @@ -5040,11 +5057,12 @@ void DocPara::handleVhdlFlow() void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) { + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateLink(); @@ -5052,7 +5070,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } doctokenizerYYsetStatePara(); @@ -5067,12 +5085,13 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) void DocPara::handleRef(const QCString &cmdName) { - DBG(("handleRef(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; + DBG(("handleRef(%s)\n",qPrint(saveCmdName))); int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateRef(); @@ -5081,7 +5100,7 @@ void DocPara::handleRef(const QCString &cmdName) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); goto endref; } ref = new DocRef(this,g_token->name,g_context); @@ -5094,6 +5113,7 @@ endref: void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) { DBG(("handleInclude(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); bool isBlock = false; if (tok==TK_WORD && g_token->name=="{") @@ -5134,8 +5154,8 @@ 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", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateFile(); @@ -5144,13 +5164,13 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s",qPrint(cmdName)); + "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", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } QCString fileName = g_token->name; @@ -5164,7 +5184,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } blockId = "["+g_token->name+"]"; @@ -5198,25 +5218,26 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) void DocPara::handleSection(const QCString &cmdName) { + QCString saveCmdName = cmdName; // get the argument of the section command. int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"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 " - "argument of command %s\n", qPrint(cmdName)); + "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", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } g_token->sectionId = g_token->name; @@ -6791,54 +6812,55 @@ int DocSection::parse() //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel); - if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1) + while (true) { - // then parse any number of nested sections - while (retval==RetVal_Subsection) // more sections follow + if (retval==RetVal_Subsection && m_level<=Doxygen::subpageNestingLevel+1) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + // then parse any number of nested sections + while (retval==RetVal_Subsection) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + break; } - } - else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2) - { - // then parse any number of nested sections - while (retval==RetVal_Subsubsection) // more sections follow + else if (retval==RetVal_Subsubsection && m_level<=Doxygen::subpageNestingLevel+2) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + if ((m_level<=1+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); + // then parse any number of nested sections + while (retval==RetVal_Subsubsection) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + if (!(m_level<Doxygen::subpageNestingLevel+2 && retval == RetVal_Subsection)) break; } - } - else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3)) - { - // then parse any number of nested sections - while (retval==RetVal_Paragraph) // more sections follow + else if (retval==RetVal_Paragraph && m_level<=QMIN(5,Doxygen::subpageNestingLevel+3)) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + if ((m_level<=2+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); + // then parse any number of nested sections + while (retval==RetVal_Paragraph) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break; + } + else + { + break; } - } - else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) || - (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph) - ) - { - int level = (retval==RetVal_Subsubsection) ? 3 : 4; - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected %s " - "command found inside %s!", - sectionLevelToName[level],sectionLevelToName[m_level]); - retval=0; // stop parsing - } - else - { } INTERNAL_ASSERT(retval==0 || @@ -6992,21 +7014,72 @@ void DocRoot::parse() { delete par; } - if (retval==TK_LISTITEM) + if (retval==RetVal_Paragraph) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + if (!QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + while (retval==RetVal_Paragraph) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid paragraph id `%s'; ignoring paragraph",qPrint(g_token->sectionId)); + retval = 0; + } + } } - else if (retval==RetVal_Subsection) + if (retval==RetVal_Subsubsection) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + if (!(QString(g_token->sectionId).startsWith("autotoc_md"))) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + while (retval==RetVal_Subsubsection) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsubsection id `%s'; ignoring subsubsection",qPrint(g_token->sectionId)); + retval = 0; + } + } } - else if (retval==RetVal_Subsubsection) + if (retval==RetVal_Subsection) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + if (!(QString(g_token->sectionId).startsWith("autotoc_md"))) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + while (retval==RetVal_Subsection) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsection id `%s'; ignoring subsection",qPrint(g_token->sectionId)); + retval = 0; + } + } } - else if (retval==RetVal_Paragraph) + if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); } if (retval==RetVal_Internal) { diff --git a/src/docparser.h b/src/docparser.h index 2cc607e..cab1589 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -798,7 +798,7 @@ class DocDotFile : public CompAccept<DocDotFile> { public: DocDotFile(DocNode *parent,const QCString &name,const QCString &context); - void parse(); + bool parse(); Kind kind() const { return Kind_DotFile; } QCString name() const { return m_name; } QCString file() const { return m_file; } @@ -821,7 +821,7 @@ class DocMscFile : public CompAccept<DocMscFile> { public: DocMscFile(DocNode *parent,const QCString &name,const QCString &context); - void parse(); + bool parse(); Kind kind() const { return Kind_MscFile; } QCString name() const { return m_name; } QCString file() const { return m_file; } @@ -844,7 +844,7 @@ class DocDiaFile : public CompAccept<DocDiaFile> { public: DocDiaFile(DocNode *parent,const QCString &name,const QCString &context); - void parse(); + bool parse(); Kind kind() const { return Kind_DiaFile; } QCString name() const { return m_name; } QCString file() const { return m_file; } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index c7fce01..6f59411 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -174,6 +174,7 @@ QCString Doxygen::spaces; bool Doxygen::generatingXmlOutput = FALSE; bool Doxygen::markdownSupport = TRUE; GenericsSDict *Doxygen::genericsDict; +DocGroup Doxygen::docGroup; // locally accessible globals static QDict<Entry> g_classEntries(1009); @@ -2069,7 +2070,7 @@ static void findUsingDeclarations(Entry *root) // vector -> std::vector if (usingCd==0) { - usingCd = getResolvedClass(nd,fd,name); // try via resolving (see also bug757509) + usingCd = const_cast<ClassDef*>(getResolvedClass(nd,fd,name)); // try via resolving (see also bug757509) } if (usingCd==0) { @@ -2135,7 +2136,7 @@ static void findUsingDeclImports(Entry *root) { QCString scope=root->name.left(i); QCString memName=root->name.right(root->name.length()-i-2); - ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter + const ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter if (bcd) { //printf("found class %s memName=%s\n",bcd->name().data(),memName.data()); @@ -2327,7 +2328,8 @@ static MemberDef *addVariableToClass( { //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n", // md->getClassDef(),cd,root->type.data(),md->typeString()); - if (md->getClassDef()==cd && + if (!md->isAlias() && + md->getClassDef()==cd && removeRedundantWhiteSpace(root->type)==md->typeString()) // member already in the scope { @@ -2555,7 +2557,7 @@ static MemberDef *addVariableToFile( MemberDef *md; for (mni.toFirst();(md=mni.current());++mni) { - if ( + if (!md->isAlias() && ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() && root->fileName==md->getFileDef()->absFilePath() ) // both variable names in the same file @@ -4228,11 +4230,11 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co FileDef *fd=cd->getFileDef(); if (context && cd!=context) { - result = getResolvedClass(context,0,name,0,0,TRUE,TRUE); + result = const_cast<ClassDef*>(getResolvedClass(context,0,name,0,0,TRUE,TRUE)); } if (result==0) { - result = getResolvedClass(cd,fd,name,0,0,TRUE,TRUE); + result = const_cast<ClassDef*>(getResolvedClass(cd,fd,name,0,0,TRUE,TRUE)); } if (result==0) // try direct class, needed for namespaced classes imported via tag files (see bug624095) { @@ -4300,7 +4302,7 @@ static void findUsedClassesForClass(Entry *root, while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1) { // find the type (if any) that matches usedClassName - ClassDef *typeCd = getResolvedClass(masterCd, + const ClassDef *typeCd = getResolvedClass(masterCd, masterCd->getFileDef(), usedClassName, 0,0, @@ -4701,16 +4703,17 @@ static bool findClassRelation( //baseClassName=stripTemplateSpecifiersFromScope // (removeRedundantWhiteSpace(baseClassName),TRUE, // &stripped); - MemberDef *baseClassTypeDef=0; + const MemberDef *baseClassTypeDef=0; QCString templSpec; - ClassDef *baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, + ClassDef *baseClass=const_cast<ClassDef*>( + getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, cd->getFileDef(), baseClassName, &baseClassTypeDef, &templSpec, mode==Undocumented, TRUE - ); + )); //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", @@ -4761,14 +4764,15 @@ static bool findClassRelation( { templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i)); baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e); - baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), - baseClassName, - &baseClassTypeDef, - 0, //&templSpec, - mode==Undocumented, - TRUE - ); + baseClass=const_cast<ClassDef*>( + getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, + cd->getFileDef(), + baseClassName, + &baseClassTypeDef, + 0, //&templSpec, + mode==Undocumented, + TRUE + )); //printf("baseClass=%p -> baseClass=%s templSpec=%s\n", // baseClass,baseClassName.data(),templSpec.data()); } @@ -4797,14 +4801,15 @@ static bool findClassRelation( QCString tmpTemplSpec; // replace any namespace aliases replaceNamespaceAliases(baseClassName,si); - baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, + baseClass=const_cast<ClassDef*>( + getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, cd->getFileDef(), baseClassName, &baseClassTypeDef, &tmpTemplSpec, mode==Undocumented, TRUE - ); + )); found=baseClass!=0 && baseClass!=cd; if (found) templSpec = tmpTemplSpec; } @@ -5476,10 +5481,10 @@ static void addMemberDocs(Entry *root, // find a class definition given the scope name and (optionally) a // template list specifier -static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, +static const ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, const char *scopeName) { - ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE); + const ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE); return tcd; } @@ -7330,7 +7335,7 @@ static void addEnumValuesToEnums(Entry *root) MemberDef *md; for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list { - if (md->isEnumerate() && root->children()) + if (!md->isAlias() && md->isEnumerate() && root->children()) { //printf(" enum with %d children\n",root->children()->count()); EntryListIterator eli(*root->children()); // for each enum value @@ -8518,7 +8523,7 @@ static void flushCachedTemplateRelations() { if (fmd->isTypedefValCached()) { - ClassDef *cd = fmd->getCachedTypedefVal(); + const ClassDef *cd = fmd->getCachedTypedefVal(); if (cd->isTemplate()) fmd->invalidateTypedefValCache(); } } @@ -8532,7 +8537,7 @@ static void flushCachedTemplateRelations() { if (fmd->isTypedefValCached()) { - ClassDef *cd = fmd->getCachedTypedefVal(); + const ClassDef *cd = fmd->getCachedTypedefVal(); if (cd->isTemplate()) fmd->invalidateTypedefValCache(); } } @@ -10122,9 +10127,9 @@ static void devUsage() //---------------------------------------------------------------------------- // print the usage of doxygen -static void usage(const char *name) +static void usage(const char *name,const char *versionString) { - msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-2015\n\n",versionString); + msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-2019\n\n",versionString); msg("You can use doxygen in a number of ways:\n\n"); msg("1) Use doxygen to generate a template configuration file:\n"); msg(" %s [-s] -g [configName]\n\n",name); @@ -10146,7 +10151,7 @@ static void usage(const char *name) msg(" RTF: %s -e rtf extensionsFile\n\n",name); msg("7) Use doxygen to compare the used configuration file with the template configuration file\n"); msg(" %s -x [configFile]\n\n",name); - msg("8) Use doxygen to show a list of build in emoji.\n"); + msg("8) Use doxygen to show a list of built-in emojis.\n"); msg(" %s -f emoji outputFileName\n\n",name); msg(" If - is used for outputFileName doxygen will write to standard output.\n\n"); msg("If -s is specified the comments of the configuration items in the config file will be omitted.\n"); @@ -10341,6 +10346,16 @@ static int computeIdealCacheParam(uint v) void readConfiguration(int argc, char **argv) { + QCString versionString; + if (strlen(getGitVersion())>0) + { + versionString = QCString(getVersion())+" ("+getGitVersion()+")"; + } + else + { + versionString = getVersion(); + } + /************************************************************************** * Handle arguments * **************************************************************************/ @@ -10584,26 +10599,26 @@ void readConfiguration(int argc, char **argv) g_dumpSymbolMap = TRUE; break; case 'v': - msg("%s\n",versionString); + msg("%s\n",versionString.data()); cleanUpDoxygen(); exit(0); break; case '-': if (qstrcmp(&argv[optind][2],"help")==0) { - usage(argv[0]); + usage(argv[0],versionString); exit(0); } else if (qstrcmp(&argv[optind][2],"version")==0) { - msg("%s\n",versionString); + msg("%s\n",versionString.data()); cleanUpDoxygen(); exit(0); } else { err("Unknown option \"-%s\"\n",&argv[optind][1]); - usage(argv[0]); + usage(argv[0],versionString); exit(1); } break; @@ -10619,12 +10634,12 @@ void readConfiguration(int argc, char **argv) break; case 'h': case '?': - usage(argv[0]); + usage(argv[0],versionString); exit(0); break; default: err("Unknown option \"-%c\"\n",argv[optind][1]); - usage(argv[0]); + usage(argv[0],versionString); exit(1); } optind++; @@ -10654,7 +10669,7 @@ void readConfiguration(int argc, char **argv) else { err("Doxyfile not found and no input file specified!\n"); - usage(argv[0]); + usage(argv[0],versionString); exit(1); } } @@ -10668,7 +10683,7 @@ void readConfiguration(int argc, char **argv) else { err("configuration file %s not found!\n",argv[optind]); - usage(argv[0]); + usage(argv[0],versionString); exit(1); } } @@ -11270,9 +11285,7 @@ void parseInput() if (layoutFile.open(IO_ReadOnly)) { msg("Parsing layout file %s...\n",layoutFileName.data()); - QTextStream t(&layoutFile); - t.setEncoding(QTextStream::Latin1); - LayoutDocManager::instance().parse(t,layoutFileName); + LayoutDocManager::instance().parse(layoutFileName); } else if (!defaultLayoutUsed) { diff --git a/src/doxygen.h b/src/doxygen.h index 4ff8a56..c8eee7c 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -27,6 +27,7 @@ #include "membergroup.h" #include "dirdef.h" #include "memberlist.h" +#include "docgroup.h" class RefList; class PageSList; @@ -76,10 +77,10 @@ class StringDict : public QDict<QCString> struct LookupInfo { LookupInfo() : classDef(0), typeDef(0) {} - LookupInfo(ClassDef *cd,MemberDef *td,QCString ts,QCString rt) + LookupInfo(const ClassDef *cd,const MemberDef *td,QCString ts,QCString rt) : classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {} - ClassDef *classDef; - MemberDef *typeDef; + const ClassDef *classDef; + const MemberDef *typeDef; QCString templSpec; QCString resolvedType; }; @@ -150,6 +151,7 @@ class Doxygen static bool generatingXmlOutput; static bool markdownSupport; static GenericsSDict *genericsDict; + static DocGroup docGroup; }; void initDoxygen(); diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 0ad03e3..1076e68 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -2304,7 +2304,7 @@ static void initEntry() current->virt = virt; current->stat = gstat; current->lang = SrcLangExt_Fortran; - initGroupInfo(current); + Doxygen::docGroup.initGroupInfo(current); } /** @@ -2712,7 +2712,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra global_scope = rt; startScope(rt); // implies current_root = rt initParser(); - groupEnterFile(yyFileName,yyLineNr); + Doxygen::docGroup.enterFile(yyFileName,yyLineNr); current = new Entry; current->lang = SrcLangExt_Fortran; @@ -2729,7 +2729,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra } fortranscannerYYlex(); - groupLeaveFile(yyFileName,yyLineNr); + Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); if (global_scope && global_scope != (Entry *) -1) endScope(current_root, TRUE); // TRUE - global root diff --git a/src/ftvhelp.h b/src/ftvhelp.h index 4c3f986..9bcaa5b 100644 --- a/src/ftvhelp.h +++ b/src/ftvhelp.h @@ -73,7 +73,7 @@ class FTVHelp : public IndexIntf }; #define JAVASCRIPT_LICENSE_TEXT \ - "/*\n@ @licstart The following is the entire license notice for the\n" \ + "/*\n@licstart The following is the entire license notice for the\n" \ "JavaScript code in this file.\n\nCopyright (C) 1997-2019 by Dimitri van Heesch\n\n" \ "This program is free software; you can redistribute it and/or modify\n" \ "it under the terms of version 2 of the GNU General Public License as published by\n" \ diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index b3abd09..402b4e4 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -878,7 +878,7 @@ void HtmlGenerator::writeSearchData(const char *dir) { searchCss = mgr.getAsString("search.css"); } - searchCss = substitute(replaceColorMarkers(searchCss),"$doxygenversion",versionString); + searchCss = substitute(replaceColorMarkers(searchCss),"$doxygenversion",getVersion()); t << searchCss; Doxygen::indexList->addStyleSheetFile("search/search.css"); } @@ -887,20 +887,20 @@ void HtmlGenerator::writeSearchData(const char *dir) void HtmlGenerator::writeStyleSheetFile(QFile &file) { FTextStream t(&file); - t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",versionString)); + t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",getVersion())); } void HtmlGenerator::writeHeaderFile(QFile &file, const char * /*cssname*/) { FTextStream t(&file); - t << "<!-- HTML header for doxygen " << versionString << "-->" << endl; + t << "<!-- HTML header for doxygen " << getVersion() << "-->" << endl; t << ResourceMgr::instance().getAsString("header.html"); } void HtmlGenerator::writeFooterFile(QFile &file) { FTextStream t(&file); - t << "<!-- HTML footer for doxygen " << versionString << "-->" << endl; + t << "<!-- HTML footer for doxygen " << getVersion() << "-->" << endl; t << ResourceMgr::instance().getAsString("footer.html"); } @@ -925,7 +925,7 @@ void HtmlGenerator::startFile(const char *name,const char *, t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title)),relPath); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " - << versionString << " -->" << endl; + << getVersion() << " -->" << endl; //static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); static bool searchEngine = Config_getBool(SEARCHENGINE); if (searchEngine /*&& !generateTreeView*/) @@ -990,7 +990,7 @@ QCString HtmlGenerator::writeLogoAsString(const char *path) "<img class=\"footer\" src=\""; result += path; result += "doxygen.png\" alt=\"doxygen\"/></a> "; - result += versionString; + result += getVersion(); result += " "; return result; } @@ -1043,7 +1043,7 @@ void HtmlGenerator::writeStyleInfo(int part) //t << "H1 { text-align: center; border-width: thin none thin none;" << endl; //t << " border-style : double; border-color : blue; padding-left : 1em; padding-right : 1em }" << endl; - t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",versionString)); + t << replaceColorMarkers(substitute(ResourceMgr::instance().getAsString("doxygen.css"),"$doxygenversion",getVersion())); endPlainFile(); Doxygen::indexList->addStyleSheetFile("doxygen.css"); } @@ -2461,7 +2461,7 @@ void HtmlGenerator::writeSearchPage() t << substituteHtmlKeywords(g_header,"Search",""); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " - << versionString << " -->" << endl; + << getVersion() << " -->" << endl; t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" @@ -2515,7 +2515,7 @@ void HtmlGenerator::writeExternalSearchPage() t << substituteHtmlKeywords(g_header,"Search",""); t << "<!-- " << theTranslator->trGeneratedBy() << " Doxygen " - << versionString << " -->" << endl; + << getVersion() << " -->" << endl; t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 182583f..e6c6861 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -485,7 +485,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) if (Config_getBool(LATEX_BATCHMODE)) t << "\\batchmode\n"; - // to overcome problems wit too many open files + // to overcome problems with too many open files t << "\\let\\mypdfximage\\pdfximage" "\\def\\pdfximage{\\immediate\\mypdfximage}"; @@ -497,6 +497,14 @@ static void writeDefaultHeaderPart1(FTextStream &t) documentClass = "book"; t << "\\documentclass[twoside]{" << documentClass << "}\n" "\n"; + t << "%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package\n" + "\\usepackage{ifthen}\n" + "\\ifx\\requestedLaTeXdate\\undefined\n" + "\\usepackage{array}\n" + "\\else\n" + "\\usepackage{array}[=2016-10-06]\n" + "\\fi\n" + "%%\n"; // Load required packages t << "% Packages required by doxygen\n" @@ -768,7 +776,7 @@ static void writeDefaultHeaderPart3(FTextStream &t) { // part 3 // Finalize project number - t << " Doxygen " << versionString << "}\\\\\n"; + t << " Doxygen " << getVersion() << "}\\\\\n"; if (Config_getBool(LATEX_TIMESTAMP)) t << "\\vspace*{0.5cm}\n" "{\\small " << dateToString(TRUE) << "}\\\\\n"; @@ -837,7 +845,7 @@ static void writeDefaultFooter(FTextStream &t) void LatexGenerator::writeHeaderFile(QFile &f) { FTextStream t(&f); - t << "% Latex header for doxygen " << versionString << endl; + t << "% Latex header for doxygen " << getVersion() << endl; writeDefaultHeaderPart1(t); t << "Your title here"; writeDefaultHeaderPart2(t); @@ -848,14 +856,14 @@ void LatexGenerator::writeHeaderFile(QFile &f) void LatexGenerator::writeFooterFile(QFile &f) { FTextStream t(&f); - t << "% Latex footer for doxygen " << versionString << endl; + t << "% Latex footer for doxygen " << getVersion() << endl; writeDefaultFooter(t); } void LatexGenerator::writeStyleSheetFile(QFile &f) { FTextStream t(&f); - t << "% stylesheet for doxygen " << versionString << endl; + t << "% stylesheet for doxygen " << getVersion() << endl; writeDefaultStyleSheet(t); } @@ -1329,6 +1337,15 @@ void LatexGenerator::writeStyleInfo(int part) startPlainFile("doxygen.sty"); writeDefaultStyleSheet(t); endPlainFile(); + + // workaround for the problem caused by change in LaTeX in version 2019 + // in the unmaintained tabu package + startPlainFile("tabu_doxygen.sty"); + t << ResourceMgr::instance().getAsString("tabu_doxygen.sty"); + endPlainFile(); + startPlainFile("longtable_doxygen.sty"); + t << ResourceMgr::instance().getAsString("longtable_doxygen.sty"); + endPlainFile(); } void LatexGenerator::newParagraph() diff --git a/src/layout.cpp b/src/layout.cpp index a5df6f4..30c41f9 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -1538,10 +1538,11 @@ void LayoutDocManager::clear(LayoutDocManager::LayoutPart p) d->docEntries[(int)p].clear(); } -void LayoutDocManager::parse(QTextStream &t,const char *fileName) +void LayoutDocManager::parse(const char *fileName) { LayoutErrorHandler errorHandler(fileName); - QXmlInputSource source( t ); + QXmlInputSource source; + source.setData(fileToString(fileName)); QXmlSimpleReader reader; reader.setContentHandler( &LayoutParser::instance() ); reader.setErrorHandler( &errorHandler ); @@ -1560,7 +1561,7 @@ void writeDefaultLayoutFile(const char *fileName) return; } QTextStream t(&f); - t << substitute(layout_default,"$doxygenversion",versionString); + t << substitute(layout_default,"$doxygenversion",getVersion()); } //---------------------------------------------------------------------------------- diff --git a/src/layout.h b/src/layout.h index b25aa4e..b1facf5 100644 --- a/src/layout.h +++ b/src/layout.h @@ -201,7 +201,7 @@ class LayoutDocManager LayoutNavEntry *rootNavEntry() const; /** Parses a user provided layout */ - void parse(QTextStream &t,const char *fileName); + void parse(const char *fileName); void init(); private: void addEntry(LayoutPart p,LayoutDocEntry*e); diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index b13f7e4..9f5a45b 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -571,7 +571,7 @@ void ManDocVisitor::visitPre(DocSimpleSect *s) // special case 1: user defined title if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) { - m_t << ":\\fP" << endl; + m_t << "\\fP" << endl; m_t << ".RS 4" << endl; } } @@ -944,7 +944,7 @@ void ManDocVisitor::visitPre(DocParamSect *s) default: ASSERT(0); } - m_t << ":\\fP" << endl; + m_t << "\\fP" << endl; m_t << ".RS 4" << endl; } diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 15da899..4dca53f 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -220,7 +220,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual QCString getScopeString() const; virtual ClassDef *getClassDefOfAnonymousType() const; virtual bool isTypedefValCached() const; - virtual ClassDef *getCachedTypedefVal() const; + virtual const ClassDef *getCachedTypedefVal() const; virtual QCString getCachedTypedefTemplSpec() const; virtual QCString getCachedResolvedTypedef() const; virtual MemberDef *memberDefinition() const; @@ -295,7 +295,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void addListReference(Definition *d); virtual void setDocsForDefinition(bool b); virtual void setGroupAlias(const MemberDef *md); - virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType); + virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType); virtual void invalidateTypedefValCache(); virtual void invalidateCachedArgumentTypes(); virtual void setMemberDefinition(MemberDef *md); @@ -693,7 +693,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { return getMdAlias()->getClassDefOfAnonymousType(); } virtual bool isTypedefValCached() const { return getMdAlias()->isTypedefValCached(); } - virtual ClassDef *getCachedTypedefVal() const + virtual const ClassDef *getCachedTypedefVal() const { return getMdAlias()->getCachedTypedefVal(); } virtual QCString getCachedTypedefTemplSpec() const { return getMdAlias()->getCachedTypedefTemplSpec(); } @@ -802,7 +802,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef virtual void addListReference(Definition *d) {} virtual void setDocsForDefinition(bool b) {} virtual void setGroupAlias(const MemberDef *md) {} - virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType) {} + virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) {} virtual void invalidateTypedefValCache() {} virtual void invalidateCachedArgumentTypes() {} virtual void setMemberDefinition(MemberDef *md) {} @@ -1364,7 +1364,7 @@ class MemberDefImpl::IMPL MemberDef *groupMember; bool isTypedefValCached; - ClassDef *cachedTypedefValue; + const ClassDef *cachedTypedefValue; QCString cachedTypedefTemplSpec; QCString cachedResolvedType; @@ -5626,7 +5626,7 @@ bool MemberDefImpl::isTypedefValCached() const return m_impl->isTypedefValCached; } -ClassDef *MemberDefImpl::getCachedTypedefVal() const +const ClassDef *MemberDefImpl::getCachedTypedefVal() const { return m_impl->cachedTypedefValue; } @@ -5908,7 +5908,7 @@ QCString MemberDefImpl::enumBaseType() const } -void MemberDefImpl::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType) +void MemberDefImpl::cacheTypedefVal(const ClassDef*val, const QCString & templSpec, const QCString &resolvedType) { m_impl->isTypedefValCached=TRUE; m_impl->cachedTypedefValue=val; diff --git a/src/memberdef.h b/src/memberdef.h index a742117..af4fb0a 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -248,7 +248,7 @@ class MemberDef : virtual public Definition // cached typedef functions virtual bool isTypedefValCached() const = 0; - virtual ClassDef *getCachedTypedefVal() const = 0; + virtual const ClassDef *getCachedTypedefVal() const = 0; virtual QCString getCachedTypedefTemplSpec() const = 0; virtual QCString getCachedResolvedTypedef() const = 0; @@ -357,7 +357,7 @@ class MemberDef : virtual public Definition virtual void setDocsForDefinition(bool b) = 0; virtual void setGroupAlias(const MemberDef *md) = 0; - virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType) = 0; + virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) = 0; virtual void invalidateTypedefValCache() = 0; virtual void invalidateCachedArgumentTypes() = 0; diff --git a/src/outputgen.h b/src/outputgen.h index e302f42..322f4b7 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -150,7 +150,7 @@ class BaseOutputDocInterface : public CodeOutputInterface Examples }; - virtual bool parseText(const QCString &s) { return s.isEmpty(); } + virtual void parseText(const QCString &s) {} /*! Start of a bullet list: e.g. \c \<ul\> in html. startItemListItem() is * Used for the bullet items. diff --git a/src/outputlist.cpp b/src/outputlist.cpp index 0306f94..daf3270 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -128,14 +128,14 @@ void OutputList::popGeneratorState() } } -bool OutputList::generateDoc(const char *fileName,int startLine, +void OutputList::generateDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef * md, const QCString &docStr,bool indexWords, bool isExample,const char *exampleName, bool singleLine,bool linkFromIndex) { int count=0; - if (docStr.isEmpty()) return TRUE; + if (docStr.isEmpty()) return; QListIterator<OutputGenerator> it(m_outputs); OutputGenerator *og; @@ -143,20 +143,17 @@ bool OutputList::generateDoc(const char *fileName,int startLine, { if (og->isEnabled()) count++; } - if (count==0) return TRUE; // no output formats enabled. + // we want to validate irrespective of the number of output formats + // specified as: + // - when only XML format there should be warnings as well (XML has its own write routines) + // - no formats there should be warnings as well DocRoot *root=0; root = validatingParseDoc(fileName,startLine, ctx,md,docStr,indexWords,isExample,exampleName, singleLine,linkFromIndex); - - writeDoc(root,ctx,md); - - bool isEmpty = root->isEmpty(); - + if (count>0) writeDoc(root,ctx,md); delete root; - - return isEmpty; } void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md) @@ -172,7 +169,7 @@ void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *m VhdlDocGen::setFlowMember(0); } -bool OutputList::parseText(const QCString &textStr) +void OutputList::parseText(const QCString &textStr) { int count=0; QListIterator<OutputGenerator> it(m_outputs); @@ -181,20 +178,22 @@ bool OutputList::parseText(const QCString &textStr) { if (og->isEnabled()) count++; } - if (count==0) return TRUE; // no output formats enabled. + // we want to validate irrespective of the number of output formats + // specified as: + // - when only XML format there should be warnings as well (XML has its own write routines) + // - no formats there should be warnings as well DocText *root = validatingParseText(textStr); - for (it.toFirst();(og=it.current());++it) + if (count>0) { - if (og->isEnabled()) og->writeDoc(root,0,0); + for (it.toFirst();(og=it.current());++it) + { + if (og->isEnabled()) og->writeDoc(root,0,0); + } } - bool isEmpty = root->isEmpty(); - delete root; - - return isEmpty; } diff --git a/src/outputlist.h b/src/outputlist.h index 35d68a8..2a83020 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -74,13 +74,12 @@ class OutputList : public OutputDocInterface // OutputDocInterface implementation ////////////////////////////////////////////////// - bool generateDoc(const char *fileName,int startLine, + void generateDoc(const char *fileName,int startLine, const Definition *ctx,const MemberDef *md,const QCString &docStr, bool indexWords,bool isExample,const char *exampleName=0, bool singleLine=FALSE,bool linkFromIndex=FALSE); void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md); - bool parseText(const QCString &textStr); - + void parseText(const QCString &textStr); void startIndexSection(IndexSections is) { forall(&OutputGenerator::startIndexSection,is); } diff --git a/src/pycode.l b/src/pycode.l index 1a87bca..010d188 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -162,7 +162,7 @@ void PyVariableContext::addVariable(const QCString &type,const QCString &name) QCString lname = name.simplifyWhiteSpace(); Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - ClassDef *varType; + 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 @@ -212,7 +212,7 @@ class PyCallContext Ctx() : name(g_name), type(g_type), cd(0) {} QCString name; QCString type; - ClassDef *cd; + const ClassDef *cd; }; PyCallContext() @@ -223,7 +223,7 @@ class PyCallContext virtual ~PyCallContext() {} - void setClass(ClassDef *cd) + void setClass(const ClassDef *cd) { Ctx *ctx = m_classList.getLast(); if (ctx) @@ -259,7 +259,7 @@ class PyCallContext m_classList.append(new Ctx); } - ClassDef *getClass() const + const ClassDef *getClass() const { Ctx *ctx = m_classList.getLast(); @@ -320,7 +320,7 @@ static void addToSearchIndex(const char *text) } -static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) +static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) { int pos=0; QCString type = s; @@ -330,7 +330,7 @@ static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) { QCString clName=className+templSpec; - ClassDef *cd=0; + const ClassDef *cd=0; if (!g_classScope.isEmpty()) { cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName); @@ -616,8 +616,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data())); - ClassDef *cd=0,*lcd=0; /** Class def that we may find */ - MemberDef *md=0; /** Member def that we may find */ + const ClassDef *cd=0,*lcd=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 @@ -669,7 +669,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } } } @@ -1091,7 +1091,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT char *s=g_curClassBases.first(); while (s) { - ClassDef *baseDefToAdd=g_codeClassSDict[s]; + const ClassDef *baseDefToAdd=g_codeClassSDict[s]; // Try to find class in global // scope @@ -1102,7 +1102,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT if (baseDefToAdd && baseDefToAdd!=classDefToAdd) { - classDefToAdd->insertBaseClass(baseDefToAdd,s,Public,Normal); + classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal); } s=g_curClassBases.next(); diff --git a/src/pyscanner.l b/src/pyscanner.l index fe94e64..3f98f3a 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -143,7 +143,7 @@ static void initEntry() current->stat = gstat; current->lang = SrcLangExt_Python; current->setParent(current_root); - initGroupInfo(current); + Doxygen::docGroup.initGroupInfo(current); gstat = FALSE; } @@ -1772,14 +1772,14 @@ static void parseCompounds(Entry *rt) current = new Entry; initEntry(); - groupEnterCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,ce->name); pyscannerYYlex() ; g_lexInit=TRUE; delete current; current=0; ce->program.resize(0); - groupLeaveCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,ce->name); } parseCompounds(ce); @@ -1839,7 +1839,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) initParser(); current = new Entry; - groupEnterFile(yyFileName,yyLineNr); + Doxygen::docGroup.enterFile(yyFileName,yyLineNr); current->reset(); initEntry(); @@ -1848,7 +1848,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) pyscannerYYlex(); g_lexInit=TRUE; - groupLeaveFile(yyFileName,yyLineNr); + Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); current_root->program.resize(0); delete current; current=0; diff --git a/src/resourcemgr.cpp b/src/resourcemgr.cpp index ab7422a..8cb831e 100644 --- a/src/resourcemgr.cpp +++ b/src/resourcemgr.cpp @@ -144,7 +144,7 @@ bool ResourceMgr::copyResourceAs(const char *name,const char *targetDir,const ch } else { - t << substitute(buf,"$doxygenversion",versionString); + t << substitute(buf,"$doxygenversion",getVersion()); } return TRUE; } diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index c4bcf24..4e89193 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -784,7 +784,6 @@ void RTFDocVisitor::visitPre(DocSimpleSect *s) // special case 1: user defined title if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) { - m_t << ":"; m_t << "\\par"; m_t << "}"; // end bold incIndentLevel(); @@ -1379,7 +1378,6 @@ void RTFDocVisitor::visitPre(DocParamSect *s) default: ASSERT(0); } - m_t << ":"; m_t << "\\par"; m_t << "}" << endl; bool useTable = s->type()==DocParamSect::Param || diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 2f24ca7..948d4cf 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -102,7 +102,7 @@ RTFGenerator::~RTFGenerator() void RTFGenerator::writeStyleSheetFile(QFile &file) { FTextStream t(&file); - t << "# Generated by doxygen " << versionString << "\n\n"; + t << "# Generated by doxygen " << getVersion() << "\n\n"; t << "# This file describes styles used for generating RTF output.\n"; t << "# All text after a hash (#) is considered a comment and will be ignored.\n"; t << "# Remove a hash to activate a line.\n\n"; @@ -119,7 +119,7 @@ void RTFGenerator::writeStyleSheetFile(QFile &file) void RTFGenerator::writeExtensionsFile(QFile &file) { FTextStream t(&file); - t << "# Generated by doxygen " << versionString << "\n\n"; + t << "# Generated by doxygen " << getVersion() << "\n\n"; t << "# This file describes extensions used for generating RTF output.\n"; t << "# All text after a hash (#) is considered a comment and will be ignored.\n"; t << "# Remove a hash to activate a line.\n\n"; diff --git a/src/scanner.l b/src/scanner.l index 42058d8..5ecf261 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -247,7 +247,7 @@ static void initEntry() // //printf("Appending group %s\n",autoGroupStack.top()->groupname.data()); // current->groups->append(new Grouping(*autoGroupStack.top())); //} - initGroupInfo(current); + Doxygen::docGroup.initGroupInfo(current); isTypedef=FALSE; } @@ -2849,17 +2849,17 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } -<FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") { +<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { //handleGroupStartCommand(current->name); if (previous && previous->section==Entry::GROUPDOC_SEC) { // link open command to the group defined in the previous entry - openGroup(previous,yyFileName,yyLineNr); + Doxygen::docGroup.open(previous,yyFileName,yyLineNr); } else { // link open command to the current entry - openGroup(current,yyFileName,yyLineNr); + Doxygen::docGroup.open(current,yyFileName,yyLineNr); } //current = tmp; initEntry(); @@ -2901,9 +2901,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } } -<FindMembers,FindFields,ReadInitializer>"//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}"[^*]*"*/" { +<FindMembers,FindFields,ReadInitializer>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { bool insideEnum = YY_START==FindFields || (YY_START==ReadInitializer && lastInitializerContext==FindFields); // see bug746226 - closeGroup(current,yyFileName,yyLineNr,insideEnum); + Doxygen::docGroup.close(current,yyFileName,yyLineNr,insideEnum); } <FindMembers>"=" { // in PHP code this could also be due to "<?=" current->bodyLine = yyLineNr; @@ -7207,13 +7207,13 @@ static void parseCompounds(Entry *rt) //memberGroupId = DOX_NOGROUP; //memberGroupRelates.resize(0); //memberGroupInside.resize(0); - groupEnterCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,ce->name); scannerYYlex() ; g_lexInit=TRUE; //forceEndGroup(); - groupLeaveCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,ce->name); delete current; current=0; ce->program.resize(0); @@ -7273,7 +7273,7 @@ static void parseMain(const char *fileName, current_root = rt ; initParser(); - groupEnterFile(yyFileName,yyLineNr); + Doxygen::docGroup.enterFile(yyFileName,yyLineNr); current = new Entry; //printf("current=%p current_root=%p\n",current,current_root); int sec=guessSection(yyFileName); @@ -7305,7 +7305,7 @@ static void parseMain(const char *fileName, } //forceEndGroup(); - groupLeaveFile(yyFileName,yyLineNr); + Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); //if (depthIf>0) //{ diff --git a/src/searchindex.cpp b/src/searchindex.cpp index babefe9..b21d587 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -956,6 +956,7 @@ void createJavascriptSearchIndex() void writeJavascriptSearchIndex() { int i; + int cnt = 0; // write index files QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search"; @@ -983,7 +984,7 @@ void writeJavascriptSearchIndex() " \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; t << "<html><head><title></title>" << endl; t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl; - t << "<meta name=\"generator\" content=\"Doxygen " << versionString << "\"/>" << endl; + t << "<meta name=\"generator\" content=\"Doxygen " << getVersion() << "\"/>" << endl; t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl; t << "<script type=\"text/javascript\" src=\"" << baseName << ".js\"></script>" << endl; t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl; @@ -1043,7 +1044,7 @@ void writeJavascriptSearchIndex() } firstEntry=FALSE; - ti << " ['" << dl->id() << "',['" << convertToXML(dl->name()) << "',["; + ti << " ['" << dl->id() << "_" << cnt++ << "',['" << convertToXML(dl->name()) << "',["; if (dl->count()==1) // item with a unique name { diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 5a8e81d..012a0c0 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -924,7 +924,7 @@ static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type= static void recordMetadata() { - bindTextParameter(meta_insert,":doxygen_version",versionString); + bindTextParameter(meta_insert,":doxygen_version",getVersion()); bindTextParameter(meta_insert,":schema_version","0.2.0"); //TODO: this should be a constant somewhere; not sure where bindTextParameter(meta_insert,":generated_at",dateToString(TRUE), FALSE); bindTextParameter(meta_insert,":generated_on",dateToString(FALSE), FALSE); diff --git a/src/tclscanner.l b/src/tclscanner.l index df52201..9ec512a 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -486,7 +486,7 @@ Entry* tcl_entry_new() // myEntry->stat = FALSE; myEntry->fileName = tcl.file_name; myEntry->lang = SrcLangExt_Tcl; - initGroupInfo(myEntry); + Doxygen::docGroup.initGroupInfo(myEntry); // collect entries if (!tcl.code) { @@ -2950,7 +2950,7 @@ tcl_inf("%s\n",fileName); printlex(yy_flex_debug, TRUE, __FILE__, fileName); msg("Parsing %s...\n",fileName); - groupEnterFile(fileName,yylineno); + Doxygen::docGroup.enterFile(fileName,yylineno); tcl_init(); tcl.code = NULL; @@ -2958,7 +2958,7 @@ tcl_inf("%s\n",fileName); tcl.this_parser = this; tcl.entry_main = root; /* toplevel entry */ tcl_parse("",""); - groupLeaveFile(tcl.file_name,yylineno); + Doxygen::docGroup.leaveFile(tcl.file_name,yylineno); root->program.resize(0); myFile.close(); printlex(yy_flex_debug, FALSE, __FILE__, fileName); diff --git a/src/util.cpp b/src/util.cpp index 7107e83..695a52c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -518,10 +518,10 @@ static QDict<MemberDef> g_resolvedTypedefs; static QDict<Definition> g_visitedNamespaces; // forward declaration -static ClassDef *getResolvedClassRec(const Definition *scope, +static const ClassDef *getResolvedClassRec(const Definition *scope, const FileDef *fileScope, const char *n, - MemberDef **pTypeDef, + const MemberDef **pTypeDef, QCString *pTemplSpec, QCString *pResolvedType ); @@ -535,10 +535,12 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop * * Example: typedef int T; will return 0, since "int" is not a class. */ -ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, - MemberDef **pMemType,QCString *pTemplSpec, - QCString *pResolvedType, - ArgumentList *actTemplParams) +const ClassDef *newResolveTypedef(const FileDef *fileScope, + const MemberDef *md, + const MemberDef **pMemType, + QCString *pTemplSpec, + QCString *pResolvedType, + ArgumentList *actTemplParams) { //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); bool isCached = md->isTypedefValCached(); // value already cached @@ -581,8 +583,8 @@ ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, int sp=0; tl=type.length(); // length may have been changed while (sp<tl && type.at(sp)==' ') sp++; - MemberDef *memTypeDef = 0; - ClassDef *result = getResolvedClassRec(md->getOuterScope(), + 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()) @@ -652,7 +654,7 @@ done: //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>"); - md->cacheTypedefVal(result, + const_cast<MemberDef*>(md)->cacheTypedefVal(result, pTemplSpec ? *pTemplSpec : QCString(), pResolvedType ? *pResolvedType : QCString() ); @@ -667,7 +669,7 @@ done: * value of the typedef or \a name if no typedef was found. */ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,const QCString &name, - MemberDef **pTypeDef=0) + const MemberDef **pTypeDef=0) { QCString result=name; if (name.isEmpty()) return result; @@ -763,12 +765,12 @@ static const Definition *followPath(const Definition *start,const FileDef *fileS while ((is=getScopeFragment(path,ps,&l))!=-1) { // try to resolve the part if it is a typedef - MemberDef *typeDef=0; + const MemberDef *typeDef=0; QCString qualScopePart = substTypedef(current,fileScope,path.mid(is,l),&typeDef); //printf(" qualScopePart=%s\n",qualScopePart.data()); if (typeDef) { - ClassDef *type = newResolveTypedef(fileScope,typeDef); + const ClassDef *type = newResolveTypedef(fileScope,typeDef); if (type) { //printf("Found type %s\n",type->name().data()); @@ -1218,8 +1220,8 @@ static void getResolvedSymbol(const Definition *scope, const QCString &explicitScopePart, ArgumentList *actTemplParams, int &minDistance, - ClassDef *&bestMatch, - MemberDef *&bestTypedef, + const ClassDef *&bestMatch, + const MemberDef *&bestTypedef, QCString &bestTemplSpec, QCString &bestResolvedType ) @@ -1306,8 +1308,8 @@ static void getResolvedSymbol(const Definition *scope, QCString spec; QCString type; minDistance=distance; - MemberDef *enumType = 0; - ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type,actTemplParams); + 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()); @@ -1377,10 +1379,10 @@ static void getResolvedSymbol(const Definition *scope, * match against the input name. Can recursively call itself when * resolving typedefs. */ -static ClassDef *getResolvedClassRec(const Definition *scope, +static const ClassDef *getResolvedClassRec(const Definition *scope, const FileDef *fileScope, const char *n, - MemberDef **pTypeDef, + const MemberDef **pTypeDef, QCString *pTemplSpec, QCString *pResolvedType ) @@ -1499,8 +1501,8 @@ static ClassDef *getResolvedClassRec(const Definition *scope, Doxygen::lookupCache->insert(key,new LookupInfo); } - ClassDef *bestMatch=0; - MemberDef *bestTypedef=0; + const ClassDef *bestMatch=0; + const MemberDef *bestTypedef=0; QCString bestTemplSpec; QCString bestResolvedType; int minDistance=10000; // init at "infinite" @@ -1566,10 +1568,10 @@ static ClassDef *getResolvedClassRec(const Definition *scope, * Loops through scope and each of its parent scopes looking for a * match against the input name. */ -ClassDef *getResolvedClass(const Definition *scope, +const ClassDef *getResolvedClass(const Definition *scope, const FileDef *fileScope, const char *n, - MemberDef **pTypeDef, + const MemberDef **pTypeDef, QCString *pTemplSpec, bool mayBeUnlinkable, bool mayBeHidden, @@ -1593,7 +1595,7 @@ ClassDef *getResolvedClass(const Definition *scope, // n, // mayBeUnlinkable // ); - ClassDef *result; + const ClassDef *result; if (optimizeOutputVhdl) { result = getClass(n); @@ -2032,12 +2034,17 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, int floatingIndex=0; if (strLen==0) return; // read a word from the text string - while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1 && - (newIndex==0 || !(txtStr.at(newIndex-1)>='0' && txtStr.at(newIndex-1)<='9')) // avoid matching part of hex numbers - ) + while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1) { - // add non-word part to the result floatingIndex+=newIndex-skipIndex+matchLen; + if (newIndex>0 && txtStr.at(newIndex-1)=='0') // ignore hex numbers (match x00 in 0x00) + { + out.writeString(txtStr.mid(skipIndex,newIndex+matchLen-skipIndex),keepSpaces); + skipIndex=index=newIndex+matchLen; + continue; + } + + // add non-word part to the result bool insideString=FALSE; int i; for (i=index;i<newIndex;i++) @@ -2088,7 +2095,7 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, const GroupDef *gd=0; //printf("** Match word '%s'\n",matchWord.data()); - MemberDef *typeDef=0; + const MemberDef *typeDef=0; cd=getResolvedClass(scope,fileScope,matchWord,&typeDef); if (typeDef) // First look at typedef then class, see bug 584184. { @@ -3496,8 +3503,8 @@ static QCString getCanonicalTypeForIdentifier( //printf("getCanonicalTypeForIdentifier(%s,[%s->%s]) start\n", // word.data(),tSpec?tSpec->data():"<none>",templSpec.data()); - ClassDef *cd = 0; - MemberDef *mType = 0; + const ClassDef *cd = 0; + const MemberDef *mType = 0; QCString ts; QCString resolvedType; @@ -4130,8 +4137,8 @@ bool getDefs(const QCString &scName, className=mScope; } - MemberDef *tmd=0; - ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); + const MemberDef *tmd=0; + const ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); if (fcd==0 && className.find('<')!=-1) // try without template specifiers as well { QCString nameWithoutTemplates = stripTemplateSpecifiersFromScope(className,FALSE); @@ -5330,7 +5337,7 @@ QCString substituteKeywords(const QCString &s,const char *title, result = substitute(result,"$datetime",dateToString(TRUE)); result = substitute(result,"$date",dateToString(FALSE)); result = substitute(result,"$year",yearToString()); - result = substitute(result,"$doxygenversion",versionString); + result = substitute(result,"$doxygenversion",getVersion()); result = substitute(result,"$projectname",projName); result = substitute(result,"$projectnumber",projNum); result = substitute(result,"$projectbrief",projBrief); @@ -6361,7 +6368,7 @@ QCString normalizeNonTemplateArgumentsInString( if (!found) { // try to resolve the type - ClassDef *cd = getResolvedClass(context,0,n); + const ClassDef *cd = getResolvedClass(context,0,n); if (cd) { result+=cd->name(); @@ -7418,20 +7425,16 @@ void addCodeOnlyMappings() SrcLangExt getLanguageFromFileName(const QCString& fileName) { - int i = fileName.findRev('.'); - if (i!=-1) // name has an extension - { - QCString extStr=fileName.right(fileName.length()-i).lower(); - if (!extStr.isEmpty()) // non-empty extension + QFileInfo fi(fileName); + QCString extName = fi.extension().lower().data(); + if (extName.isEmpty()) extName=".no_extension"; + if (extName.at(0)!='.') extName.prepend("."); + int *pVal=g_extLookup.find(extName.data()); + if (pVal) // listed extension { - int *pVal=g_extLookup.find(extStr); - if (pVal) // listed extension - { - //printf("getLanguageFromFileName(%s)=%x\n",extStr.data(),*pVal); - return (SrcLangExt)*pVal; - } + //printf("getLanguageFromFileName(%s)=%x\n",fi.extension().data(),*pVal); + return (SrcLangExt)*pVal; } - } //printf("getLanguageFromFileName(%s) not found!\n",fileName.data()); return SrcLangExt_Cpp; // not listed => assume C-ish language. } @@ -206,10 +206,10 @@ QCString resolveDefines(const char *n); ClassDef *getClass(const char *key); -ClassDef *getResolvedClass(const Definition *scope, +const ClassDef *getResolvedClass(const Definition *scope, const FileDef *fileScope, const char *key, - MemberDef **pTypeDef=0, + const MemberDef **pTypeDef=0, QCString *pTemplSpec=0, bool mayBeUnlinkable=FALSE, bool mayBeHidden=FALSE, @@ -397,10 +397,12 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, const char *n); bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n); -ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, - MemberDef **pMemType=0,QCString *pTemplSpec=0, - QCString *pResolvedType=0, - ArgumentList *actTemplParams=0); +const ClassDef *newResolveTypedef(const FileDef *fileScope, + const MemberDef *md, + const MemberDef **pMemType=0, + QCString *pTemplSpec=0, + QCString *pResolvedType=0, + ArgumentList *actTemplParams=0); QCString parseCommentAsText(const Definition *scope,const MemberDef *member,const QCString &doc,const QCString &fileName,int lineNr); diff --git a/src/version.h b/src/version.h deleted file mode 100644 index 16bf9df..0000000 --- a/src/version.h +++ /dev/null @@ -1,23 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#ifndef VERSION_H -#define VERSION_H - -extern char versionString[]; - -#endif diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 4a312bd..aeed048 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -146,7 +146,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En oldEntry = 0; VhdlParser::current=new Entry(); VhdlParser::initEntry(VhdlParser::current); - groupEnterFile(fileName,yyLineNr); + Doxygen::docGroup.enterFile(fileName,yyLineNr); vhdlFileName = fileName; lineParse=new int[200]; // Dimitri: dangerous constant: should be bigger than largest token id in VhdlParserConstants.h VhdlParserIF::parseVhdlfile(fileBuf,inLine); @@ -193,7 +193,7 @@ void VhdlParser::initEntry(Entry *e) e->fileName = yyFileName; e->lang = SrcLangExt_VHDL; isVhdlDocPending(); - initGroupInfo(e); + Doxygen::docGroup.initGroupInfo(e); } void VhdlParser::newEntry() diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index b992b81..16abbf2 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -154,7 +154,7 @@ static void writeXMLHeader(FTextStream &t) t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; t << "<doxygen xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; t << "xsi:noNamespaceSchemaLocation=\"compound.xsd\" "; - t << "version=\"" << versionString << "\">" << endl; + t << "version=\"" << getVersion() << "\">" << endl; } static void writeCombineScript() @@ -1981,7 +1981,7 @@ void generateXML() t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; t << "<doxygenindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; t << "xsi:noNamespaceSchemaLocation=\"index.xsd\" "; - t << "version=\"" << versionString << "\">" << endl; + t << "version=\"" << getVersion() << "\">" << endl; { ClassSDict::Iterator cli(*Doxygen::classSDict); diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty index bd5fdba..afa0f7d 100644 --- a/templates/latex/doxygen.sty +++ b/templates/latex/doxygen.sty @@ -3,14 +3,14 @@ % Packages used by this style file \RequirePackage{alltt} -\RequirePackage{array} +%%\RequirePackage{array} %% moved to refman.tex due to workaround for LaTex 2019 version and unmaintained tabu package \RequirePackage{calc} \RequirePackage{float} -\RequirePackage{ifthen} +%%\RequirePackage{ifthen} %% moved to refman.tex due to workaround for LaTex 2019 version and unmaintained tabu package \RequirePackage{verbatim} \RequirePackage[table]{xcolor} -\RequirePackage{longtable} -\RequirePackage{tabu} +\RequirePackage{longtable_doxygen} +\RequirePackage{tabu_doxygen} \RequirePackage{fancyvrb} \RequirePackage{tabularx} \RequirePackage{multirow} @@ -306,16 +306,9 @@ % Used by @par and @paragraph \newenvironment{DoxyParagraph}[1]{% - \begin{list}{}{% - \settowidth{\labelwidth}{40pt}% - \setlength{\leftmargin}{\labelwidth+\labelsep}% - \setlength{\parsep}{0pt}% - \setlength{\itemsep}{-4pt}% - \renewcommand{\makelabel}{\entrylabel}% - }% - \item[#1]% + \begin{DoxyDesc}{#1}% }{% - \end{list}% + \end{DoxyDesc}% } % Used by parameter lists diff --git a/templates/latex/longtable_doxygen.sty b/templates/latex/longtable_doxygen.sty new file mode 100755 index 0000000..a0eb314 --- /dev/null +++ b/templates/latex/longtable_doxygen.sty @@ -0,0 +1,448 @@ +%% +%% This is file `longtable.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% longtable.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% The source is maintained by the LaTeX Project team and bug +%% reports for it can be opened at http://latex-project.org/bugs.html +%% (but please observe conditions on bug reports sent to that address!) +%% +%% Copyright 1993-2016 +%% The LaTeX3 Project and any individual authors listed elsewhere +%% in this file. +%% +%% This file was generated from file(s) of the Standard LaTeX `Tools Bundle'. +%% -------------------------------------------------------------------------- +%% +%% It may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3c +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3c or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This file may only be distributed together with a copy of the LaTeX +%% `Tools Bundle'. You may however distribute the LaTeX `Tools Bundle' +%% without such generated files. +%% +%% The list of all files belonging to the LaTeX `Tools Bundle' is +%% given in the file `manifest.txt'. +%% +%% File: longtable.dtx Copyright (C) 1990-2001 David Carlisle +\NeedsTeXFormat{LaTeX2e}[1995/06/01] +\ProvidesPackage{longtable_doxygen} + [2014/10/28 v4.11 Multi-page Table package (DPC) - frozen version for doxygen] +\def\LT@err{\PackageError{longtable}} +\def\LT@warn{\PackageWarning{longtable}} +\def\LT@final@warn{% + \AtEndDocument{% + \LT@warn{Table \@width s have changed. Rerun LaTeX.\@gobbletwo}}% + \global\let\LT@final@warn\relax} +\DeclareOption{errorshow}{% + \def\LT@warn{\PackageInfo{longtable}}} +\DeclareOption{pausing}{% + \def\LT@warn#1{% + \LT@err{#1}{This is not really an error}}} +\DeclareOption{set}{} +\DeclareOption{final}{} +\ProcessOptions +\newskip\LTleft \LTleft=\fill +\newskip\LTright \LTright=\fill +\newskip\LTpre \LTpre=\bigskipamount +\newskip\LTpost \LTpost=\bigskipamount +\newcount\LTchunksize \LTchunksize=20 +\let\c@LTchunksize\LTchunksize +\newdimen\LTcapwidth \LTcapwidth=4in +\newbox\LT@head +\newbox\LT@firsthead +\newbox\LT@foot +\newbox\LT@lastfoot +\newcount\LT@cols +\newcount\LT@rows +\newcounter{LT@tables} +\newcounter{LT@chunks}[LT@tables] +\ifx\c@table\undefined + \newcounter{table} + \def\fnum@table{\tablename~\thetable} +\fi +\ifx\tablename\undefined + \def\tablename{Table} +\fi +\newtoks\LT@p@ftn +\mathchardef\LT@end@pen=30000 +\def\longtable{% + \par + \ifx\multicols\@undefined + \else + \ifnum\col@number>\@ne + \@twocolumntrue + \fi + \fi + \if@twocolumn + \LT@err{longtable not in 1-column mode}\@ehc + \fi + \begingroup + \@ifnextchar[\LT@array{\LT@array[x]}} +\def\LT@array[#1]#2{% + \refstepcounter{table}\stepcounter{LT@tables}% + \if l#1% + \LTleft\z@ \LTright\fill + \else\if r#1% + \LTleft\fill \LTright\z@ + \else\if c#1% + \LTleft\fill \LTright\fill + \fi\fi\fi + \let\LT@mcol\multicolumn + \let\LT@@tabarray\@tabarray + \let\LT@@hl\hline + \def\@tabarray{% + \let\hline\LT@@hl + \LT@@tabarray}% + \let\\\LT@tabularcr\let\tabularnewline\\% + \def\newpage{\noalign{\break}}% + \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}% + \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}% + \let\hline\LT@hline \let\kill\LT@kill\let\caption\LT@caption + \@tempdima\ht\strutbox + \let\@endpbox\LT@endpbox + \ifx\extrarowheight\@undefined + \let\@acol\@tabacol + \let\@classz\@tabclassz \let\@classiv\@tabclassiv + \def\@startpbox{\vtop\LT@startpbox}% + \let\@@startpbox\@startpbox + \let\@@endpbox\@endpbox + \let\LT@LL@FM@cr\@tabularcr + \else + \advance\@tempdima\extrarowheight + \col@sep\tabcolsep + \let\@startpbox\LT@startpbox\let\LT@LL@FM@cr\@arraycr + \fi + \setbox\@arstrutbox\hbox{\vrule + \@height \arraystretch \@tempdima + \@depth \arraystretch \dp \strutbox + \@width \z@}% + \let\@sharp##\let\protect\relax + \begingroup + \@mkpream{#2}% + \xdef\LT@bchunk{% + \global\advance\c@LT@chunks\@ne + \global\LT@rows\z@\setbox\z@\vbox\bgroup + \LT@setprevdepth + \tabskip\LTleft \noexpand\halign to\hsize\bgroup + \tabskip\z@ \@arstrut \@preamble \tabskip\LTright \cr}% + \endgroup + \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols + \LT@make@row + \m@th\let\par\@empty + \everycr{}\lineskip\z@\baselineskip\z@ + \LT@bchunk} +\def\LT@no@pgbk#1[#2]{\penalty #1\@getpen{#2}\ifnum`{=0\fi}} +\def\LT@start{% + \let\LT@start\endgraf + \endgraf\penalty\z@\vskip\LTpre + \dimen@\pagetotal + \advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi + \advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi + \advance\dimen@ \ht\LT@foot + \dimen@ii\vfuzz + \vfuzz\maxdimen + \setbox\tw@\copy\z@ + \setbox\tw@\vsplit\tw@ to \ht\@arstrutbox + \setbox\tw@\vbox{\unvbox\tw@}% + \vfuzz\dimen@ii + \advance\dimen@ \ht + \ifdim\ht\@arstrutbox>\ht\tw@\@arstrutbox\else\tw@\fi + \advance\dimen@\dp + \ifdim\dp\@arstrutbox>\dp\tw@\@arstrutbox\else\tw@\fi + \advance\dimen@ -\pagegoal + \ifdim \dimen@>\z@\vfil\break\fi + \global\@colroom\@colht + \ifvoid\LT@foot\else + \advance\vsize-\ht\LT@foot + \global\advance\@colroom-\ht\LT@foot + \dimen@\pagegoal\advance\dimen@-\ht\LT@foot\pagegoal\dimen@ + \maxdepth\z@ + \fi + \ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi\nobreak + \output{\LT@output}} +\def\endlongtable{% + \crcr + \noalign{% + \let\LT@entry\LT@entry@chop + \xdef\LT@save@row{\LT@save@row}}% + \LT@echunk + \LT@start + \unvbox\z@ + \LT@get@widths + \if@filesw + {\let\LT@entry\LT@entry@write\immediate\write\@auxout{% + \gdef\expandafter\noexpand + \csname LT@\romannumeral\c@LT@tables\endcsname + {\LT@save@row}}}% + \fi + \ifx\LT@save@row\LT@@save@row + \else + \LT@warn{Column \@width s have changed\MessageBreak + in table \thetable}% + \LT@final@warn + \fi + \endgraf\penalty -\LT@end@pen + \endgroup + \global\@mparbottom\z@ + \pagegoal\vsize + \endgraf\penalty\z@\addvspace\LTpost + \ifvoid\footins\else\insert\footins{}\fi} +\def\LT@nofcols#1&{% + \futurelet\@let@token\LT@n@fcols} +\def\LT@n@fcols{% + \advance\LT@cols\@ne + \ifx\@let@token\LT@nofcols + \expandafter\@gobble + \else + \expandafter\LT@nofcols + \fi} +\def\LT@tabularcr{% + \relax\iffalse{\fi\ifnum0=`}\fi + \@ifstar + {\def\crcr{\LT@crcr\noalign{\nobreak}}\let\cr\crcr + \LT@t@bularcr}% + {\LT@t@bularcr}} +\let\LT@crcr\crcr +\let\LT@setprevdepth\relax +\def\LT@t@bularcr{% + \global\advance\LT@rows\@ne + \ifnum\LT@rows=\LTchunksize + \gdef\LT@setprevdepth{% + \prevdepth\z@\global + \global\let\LT@setprevdepth\relax}% + \expandafter\LT@xtabularcr + \else + \ifnum0=`{}\fi + \expandafter\LT@LL@FM@cr + \fi} +\def\LT@xtabularcr{% + \@ifnextchar[\LT@argtabularcr\LT@ntabularcr} +\def\LT@ntabularcr{% + \ifnum0=`{}\fi + \LT@echunk + \LT@start + \unvbox\z@ + \LT@get@widths + \LT@bchunk} +\def\LT@argtabularcr[#1]{% + \ifnum0=`{}\fi + \ifdim #1>\z@ + \unskip\@xargarraycr{#1}% + \else + \@yargarraycr{#1}% + \fi + \LT@echunk + \LT@start + \unvbox\z@ + \LT@get@widths + \LT@bchunk} +\def\LT@echunk{% + \crcr\LT@save@row\cr\egroup + \global\setbox\@ne\lastbox + \unskip + \egroup} +\def\LT@entry#1#2{% + \ifhmode\@firstofone{&}\fi\omit + \ifnum#1=\c@LT@chunks + \else + \kern#2\relax + \fi} +\def\LT@entry@chop#1#2{% + \noexpand\LT@entry + {\ifnum#1>\c@LT@chunks + 1}{0pt% + \else + #1}{#2% + \fi}} +\def\LT@entry@write{% + \noexpand\LT@entry^^J% + \@spaces} +\def\LT@kill{% + \LT@echunk + \LT@get@widths + \expandafter\LT@rebox\LT@bchunk} +\def\LT@rebox#1\bgroup{% + #1\bgroup + \unvbox\z@ + \unskip + \setbox\z@\lastbox} +\def\LT@blank@row{% + \xdef\LT@save@row{\expandafter\LT@build@blank + \romannumeral\number\LT@cols 001 }} +\def\LT@build@blank#1{% + \if#1m% + \noexpand\LT@entry{1}{0pt}% + \expandafter\LT@build@blank + \fi} +\def\LT@make@row{% + \global\expandafter\let\expandafter\LT@save@row + \csname LT@\romannumeral\c@LT@tables\endcsname + \ifx\LT@save@row\relax + \LT@blank@row + \else + {\let\LT@entry\or + \if!% + \ifcase\expandafter\expandafter\expandafter\LT@cols + \expandafter\@gobble\LT@save@row + \or + \else + \relax + \fi + !% + \else + \aftergroup\LT@blank@row + \fi}% + \fi} +\let\setlongtables\relax +\def\LT@get@widths{% + \setbox\tw@\hbox{% + \unhbox\@ne + \let\LT@old@row\LT@save@row + \global\let\LT@save@row\@empty + \count@\LT@cols + \loop + \unskip + \setbox\tw@\lastbox + \ifhbox\tw@ + \LT@def@row + \advance\count@\m@ne + \repeat}% + \ifx\LT@@save@row\@undefined + \let\LT@@save@row\LT@save@row + \fi} +\def\LT@def@row{% + \let\LT@entry\or + \edef\@tempa{% + \ifcase\expandafter\count@\LT@old@row + \else + {1}{0pt}% + \fi}% + \let\LT@entry\relax + \xdef\LT@save@row{% + \LT@entry + \expandafter\LT@max@sel\@tempa + \LT@save@row}} +\def\LT@max@sel#1#2{% + {\ifdim#2=\wd\tw@ + #1% + \else + \number\c@LT@chunks + \fi}% + {\the\wd\tw@}} +\def\LT@hline{% + \noalign{\ifnum0=`}\fi + \penalty\@M + \futurelet\@let@token\LT@@hline} +\def\LT@@hline{% + \ifx\@let@token\hline + \global\let\@gtempa\@gobble + \gdef\LT@sep{\penalty-\@medpenalty\vskip\doublerulesep}% + \else + \global\let\@gtempa\@empty + \gdef\LT@sep{\penalty-\@lowpenalty\vskip-\arrayrulewidth}% + \fi + \ifnum0=`{\fi}% + \multispan\LT@cols + \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr + \noalign{\LT@sep}% + \multispan\LT@cols + \unskip\leaders\hrule\@height\arrayrulewidth\hfill\cr + \noalign{\penalty\@M}% + \@gtempa} +\def\LT@caption{% + \noalign\bgroup + \@ifnextchar[{\egroup\LT@c@ption\@firstofone}\LT@capti@n} +\def\LT@c@ption#1[#2]#3{% + \LT@makecaption#1\fnum@table{#3}% + \def\@tempa{#2}% + \ifx\@tempa\@empty\else + {\let\\\space + \addcontentsline{lot}{table}{\protect\numberline{\thetable}{#2}}}% + \fi} +\def\LT@capti@n{% + \@ifstar + {\egroup\LT@c@ption\@gobble[]}% + {\egroup\@xdblarg{\LT@c@ption\@firstofone}}} +\def\LT@makecaption#1#2#3{% + \LT@mcol\LT@cols c{\hbox to\z@{\hss\parbox[t]\LTcapwidth{% + \sbox\@tempboxa{#1{#2: }#3}% + \ifdim\wd\@tempboxa>\hsize + #1{#2: }#3% + \else + \hbox to\hsize{\hfil\box\@tempboxa\hfil}% + \fi + \endgraf\vskip\baselineskip}% + \hss}}} +\def\LT@output{% + \ifnum\outputpenalty <-\@Mi + \ifnum\outputpenalty > -\LT@end@pen + \LT@err{floats and marginpars not allowed in a longtable}\@ehc + \else + \setbox\z@\vbox{\unvbox\@cclv}% + \ifdim \ht\LT@lastfoot>\ht\LT@foot + \dimen@\pagegoal + \advance\dimen@-\ht\LT@lastfoot + \ifdim\dimen@<\ht\z@ + \setbox\@cclv\vbox{\unvbox\z@\copy\LT@foot\vss}% + \@makecol + \@outputpage + \setbox\z@\vbox{\box\LT@head}% + \fi + \fi + \global\@colroom\@colht + \global\vsize\@colht + \vbox + {\unvbox\z@\box\ifvoid\LT@lastfoot\LT@foot\else\LT@lastfoot\fi}% + \fi + \else + \setbox\@cclv\vbox{\unvbox\@cclv\copy\LT@foot\vss}% + \@makecol + \@outputpage + \global\vsize\@colroom + \copy\LT@head\nobreak + \fi} +\def\LT@end@hd@ft#1{% + \LT@echunk + \ifx\LT@start\endgraf + \LT@err + {Longtable head or foot not at start of table}% + {Increase LTchunksize}% + \fi + \setbox#1\box\z@ + \LT@get@widths + \LT@bchunk} +\def\endfirsthead{\LT@end@hd@ft\LT@firsthead} +\def\endhead{\LT@end@hd@ft\LT@head} +\def\endfoot{\LT@end@hd@ft\LT@foot} +\def\endlastfoot{\LT@end@hd@ft\LT@lastfoot} +\def\LT@startpbox#1{% + \bgroup + \let\@footnotetext\LT@p@ftntext + \setlength\hsize{#1}% + \@arrayparboxrestore + \vrule \@height \ht\@arstrutbox \@width \z@} +\def\LT@endpbox{% + \@finalstrut\@arstrutbox + \egroup + \the\LT@p@ftn + \global\LT@p@ftn{}% + \hfil} +\def\LT@p@ftntext#1{% + \edef\@tempa{\the\LT@p@ftn\noexpand\footnotetext[\the\c@footnote]}% + \global\LT@p@ftn\expandafter{\@tempa{#1}}}% + +\@namedef{ver@longtable.sty}{2014/10/28 v4.11 Multi-page Table package (DPC) - frozen version for doxygen} +\endinput +%% +%% End of file `longtable.sty'. diff --git a/templates/latex/tabu_doxygen.sty b/templates/latex/tabu_doxygen.sty new file mode 100755 index 0000000..f760aca --- /dev/null +++ b/templates/latex/tabu_doxygen.sty @@ -0,0 +1,2557 @@ +%%
+%% This is file `tabu.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% tabu.dtx (with options: `package')
+%%
+%% This is a generated file.
+%% Copyright (FC) 2010-2011 - lppl
+%%
+%% tabu : 2011/02/26 v2.8 - tabu : Flexible LaTeX tabulars
+%%
+%% **********************************************************************************************
+%% \begin{tabu} { preamble } => default target: \linewidth or \linegoal
+%% \begin{tabu} to <dimen>{ preamble } => target specified
+%% \begin{tabu} spread <dimen>{ preamble } => target relative to the ``natural width''
+%%
+%% tabu works in text and in math modes.
+%%
+%% X columns: automatic width ajustment + horizontal and vertical alignment
+%% \begin{tabu} { X[4c] X[1c] X[-2ml] }
+%%
+%% Horizontal lines and / or leaders:
+%% \hline\hline => double horizontal line
+%% \firsthline\hline => for nested tabulars
+%% \lasthline\hline => for nested tabulars
+%% \tabucline[line spec]{column-column} => ``funny'' lines (dash/leader)
+%% Automatic lines / leaders :
+%% \everyrow{\hline\hline}
+%%
+%% Vertical lines and / or leaders:
+%% \begin{tabu} { |[3pt red] X[4c] X[1c] X[-2ml] |[3pt blue] }
+%% \begin{tabu} { |[3pt red] X[4c] X[1c] X[-2ml] |[3pt on 2pt off 4pt blue] }
+%%
+%% Fixed vertical spacing adjustment:
+%% \extrarowheight=<dimen> \extrarowdepth=<dimen>
+%% or: \extrarowsep=<dimen> => may be prefixed by \global
+%%
+%% Dynamic vertical spacing adjustment:
+%% \abovetabulinesep=<dimen> \belowtabulinesep=<dimen>
+%% or: \tabulinesep=<dimen> => may be prefixed by \global
+%%
+%% delarray.sty shortcuts: in math and text modes
+%% \begin{tabu} .... \({ preamble }\)
+%%
+%% Algorithms reports:
+%% \tracingtabu=1 \tracingtabu=2
+%%
+%% **********************************************************************************************
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3 of this license or (at your option) any later
+%% version. The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This work consists of the main source file tabu.dtx
+%% and the derived files
+%% tabu.sty, tabu.pdf, tabu.ins
+%%
+%% tabu : Flexible LaTeX tabulars
+%% lppl copyright 2010-2011 by FC <florent.chervet@free.fr>
+%%
+
+\NeedsTeXFormat{LaTeX2e}[2005/12/01]
+\ProvidesPackage{tabu_doxygen}[2011/02/26 v2.8 - flexible LaTeX tabulars (FC), frozen version for doxygen]
+\RequirePackage{array}[2008/09/09]
+\RequirePackage{varwidth}[2009/03/30]
+\AtEndOfPackage{\tabu@AtEnd \let\tabu@AtEnd \@undefined}
+\let\tabu@AtEnd\@empty
+\def\TMP@EnsureCode#1={%
+ \edef\tabu@AtEnd{\tabu@AtEnd
+ \catcode#1 \the\catcode#1}%
+ \catcode#1=%
+}% \TMP@EnsureCode
+\TMP@EnsureCode 33 = 12 % !
+\TMP@EnsureCode 58 = 12 % : (for siunitx)
+\TMP@EnsureCode124 = 12 % |
+\TMP@EnsureCode 36 = 3 % $ = math shift
+\TMP@EnsureCode 38 = 4 % & = tab alignmment character
+\TMP@EnsureCode 32 = 10 % space
+\TMP@EnsureCode 94 = 7 % ^
+\TMP@EnsureCode 95 = 8 % _
+%% Constants --------------------------------------------------------
+\newcount \c@taburow \def\thetaburow {\number\c@taburow}
+\newcount \tabu@nbcols
+\newcount \tabu@cnt
+\newcount \tabu@Xcol
+\let\tabu@start \@tempcnta
+\let\tabu@stop \@tempcntb
+\newcount \tabu@alloc \tabu@alloc=\m@ne
+\newcount \tabu@nested
+\def\tabu@alloc@{\global\advance\tabu@alloc \@ne \tabu@nested\tabu@alloc}
+\newdimen \tabu@target
+\newdimen \tabu@spreadtarget
+\newdimen \tabu@naturalX
+\newdimen \tabucolX
+\let\tabu@DELTA \@tempdimc
+\let\tabu@thick \@tempdima
+\let\tabu@on \@tempdimb
+\let\tabu@off \@tempdimc
+\newdimen \tabu@Xsum
+\newdimen \extrarowdepth
+\newdimen \abovetabulinesep
+\newdimen \belowtabulinesep
+\newdimen \tabustrutrule \tabustrutrule \z@
+\newtoks \tabu@thebody
+\newtoks \tabu@footnotes
+\newsavebox \tabu@box
+\newsavebox \tabu@arstrutbox
+\newsavebox \tabu@hleads
+\newsavebox \tabu@vleads
+\newif \iftabu@colortbl
+\newif \iftabu@siunitx
+\newif \iftabu@measuring
+\newif \iftabu@spread
+\newif \iftabu@negcoef
+\newif \iftabu@everyrow
+\def\tabu@everyrowtrue {\global\let\iftabu@everyrow \iftrue}
+\def\tabu@everyrowfalse{\global\let\iftabu@everyrow \iffalse}
+\newif \iftabu@long
+\newif \iftabuscantokens
+\def\tabu@rescan {\tabu@verbatim \scantokens }
+%% Utilities (for internal usage) -----------------------------------
+\def\tabu@gobblespace #1 {#1}
+\def\tabu@gobbletoken #1#2{#1}
+\def\tabu@gobbleX{\futurelet\@let@token \tabu@gobblex}
+\def\tabu@gobblex{\if ^^J\noexpand\@let@token \expandafter\@gobble
+ \else\ifx \@sptoken\@let@token
+ \expandafter\tabu@gobblespace\expandafter\tabu@gobbleX
+ \fi\fi
+}% \tabu@gobblex
+\def\tabu@X{^^J}
+{\obeyspaces
+\global\let\tabu@spxiii= % saves an active space (for \ifx)
+\gdef\tabu@@spxiii{ }}
+\def\tabu@ifenvir {% only for \multicolumn
+ \expandafter\tabu@if@nvir\csname\@currenvir\endcsname
+}% \tabu@ifenvir
+\def\tabu@if@nvir #1{\csname @\ifx\tabu#1first\else
+ \ifx\longtabu#1first\else
+ second\fi\fi oftwo\endcsname
+}% \tabu@ifenvir
+\def\tabu@modulo #1#2{\numexpr\ifnum\numexpr#1=\z@ 0\else #1-(#1-(#2-1)/2)/(#2)*(#2)\fi}
+{\catcode`\&=3
+\gdef\tabu@strtrim #1{% #1 = control sequence to trim
+ \ifodd 1\ifx #1\@empty \else \ifx #1\space \else 0\fi \fi
+ \let\tabu@c@l@r \@empty \let#1\@empty
+ \else \expandafter \tabu@trimspaces #1\@nnil
+ \fi
+}% \tabu@strtrim
+\gdef\tabu@trimspaces #1\@nnil{\let\tabu@c@l@r=#2\tabu@firstspace .#1& }%
+\gdef\tabu@firstspace #1#2#3 &{\tabu@lastspace #2#3&}
+\gdef\tabu@lastspace #1{\def #3{#1}%
+ \ifx #3\tabu@c@l@r \def\tabu@c@l@r{\protect\color{#1}}\expandafter\remove@to@nnil \fi
+ \tabu@trimspaces #1\@nnil}
+}% \catcode
+\def\tabu@sanitizearg #1#2{{%
+ \csname \ifcsname if@safe@actives\endcsname % <babel>
+ @safe@activestrue\else
+ relax\fi \endcsname
+ \edef#2{#1}\tabu@strtrim#2\@onelevel@sanitize#2%
+ \expandafter}\expandafter\def\expandafter#2\expandafter{#2}%
+}% \tabu@sanitizearg
+\def\tabu@textbar #1{\begingroup \endlinechar\m@ne \scantokens{\def\:{|}}%
+ \expandafter\endgroup \expandafter#1\:% !!! semi simple group !!!
+}% \tabu@textbar
+\def\tabu@everyrow@bgroup{\iftabu@everyrow \begingroup \else \noalign{\ifnum0=`}\fi \fi}
+\def\tabu@everyrow@egroup{%
+ \iftabu@everyrow \expandafter \endgroup \the\toks@
+ \else \ifnum0=`{\fi}%
+ \fi
+}% \tabu@everyrow@egroup
+\def\tabu@arstrut {\global\setbox\@arstrutbox \hbox{\vrule
+ height \arraystretch \dimexpr\ht\strutbox+\extrarowheight
+ depth \arraystretch \dimexpr\dp\strutbox+\extrarowdepth
+ width \z@}%
+}% \tabu@arstrut
+\def\tabu@rearstrut {%
+ \@tempdima \arraystretch\dimexpr\ht\strutbox+\extrarowheight \relax
+ \@tempdimb \arraystretch\dimexpr\dp\strutbox+\extrarowdepth \relax
+ \ifodd 1\ifdim \ht\@arstrutbox=\@tempdima
+ \ifdim \dp\@arstrutbox=\@tempdimb 0 \fi\fi
+ \tabu@mkarstrut
+ \fi
+}% \tabu@rearstrut
+\def\tabu@@DBG #1{\ifdim\tabustrutrule>\z@ \color{#1}\fi}
+\def\tabu@DBG@arstrut {\global\setbox\@arstrutbox
+ \hbox to\z@{\hbox to\z@{\hss
+ {\tabu@DBG{cyan}\vrule
+ height \arraystretch \dimexpr\ht\strutbox+\extrarowheight
+ depth \z@
+ width \tabustrutrule}\kern-\tabustrutrule
+ {\tabu@DBG{pink}\vrule
+ height \z@
+ depth \arraystretch \dimexpr\dp\strutbox+\extrarowdepth
+ width \tabustrutrule}}}%
+}% \tabu@DBG@arstrut
+\def\tabu@save@decl{\toks\count@ \expandafter{\the\toks\expandafter\count@
+ \@nextchar}}%
+\def\tabu@savedecl{\ifcat$\d@llarend\else
+ \let\save@decl \tabu@save@decl \fi % no inversion of tokens in text mode
+}% \tabu@savedecl
+\def\tabu@finalstrut #1{\unskip\ifhmode\nobreak\fi\vrule height\z@ depth\z@ width\z@}
+\newcommand*\tabuDisableCommands {\g@addto@macro\tabu@trialh@@k }
+\let\tabu@trialh@@k \@empty
+\def\tabu@nowrite #1#{{\afterassignment}\toks@}
+\let\tabu@write\write
+\let\tabu@immediate\immediate
+\def\tabu@WRITE{\begingroup
+ \def\immediate\write{\aftergroup\endgroup
+ \tabu@immediate\tabu@write}%
+}% \tabu@WRITE
+\expandafter\def\expandafter\tabu@GenericError\expandafter{%
+ \expandafter\tabu@WRITE\GenericError}
+\def\tabu@warn{\tabu@WRITE\PackageWarning{tabu}}
+\def\tabu@noxfootnote [#1]{\@gobble}
+\def\tabu@nocolor #1#{\@gobble}
+\newcommand*\tabu@norowcolor[2][]{}
+\def\tabu@maybesiunitx #1{\def\tabu@temp{#1}%
+ \futurelet\@let@token \tabu@m@ybesiunitx}
+\def\tabu@m@ybesiunitx #1{\def\tabu@m@ybesiunitx {%
+ \ifx #1\@let@token \let\tabu@cellleft \@empty \let\tabu@cellright \@empty \fi
+ \tabu@temp}% \tabu@m@ybesiunitx
+}\expandafter\tabu@m@ybesiunitx \csname siunitx_table_collect_begin:Nn\endcsname
+\def\tabu@celllalign@def #1{\def\tabu@celllalign{\tabu@maybesiunitx{#1}}}%
+%% Fixed vertical spacing adjustment: \extrarowsep ------------------
+\newcommand*\extrarowsep{\edef\tabu@C@extra{\the\numexpr\tabu@C@extra+1}%
+ \iftabu@everyrow \aftergroup\tabu@Gextra
+ \else \aftergroup\tabu@n@Gextra
+ \fi
+ \@ifnextchar={\tabu@gobbletoken\tabu@extra} \tabu@extra
+}% \extrarowsep
+\def\tabu@extra {\@ifnextchar_%
+ {\tabu@gobbletoken{\tabu@setextra\extrarowheight \extrarowdepth}}
+ {\ifx ^\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setextra\extrarowdepth \extrarowheight}}%
+ \else \let\tabu@temp \@empty
+ \afterassignment \tabu@setextrasep \extrarowdepth
+ \fi \tabu@temp}%
+}% \tabu@extra
+\def\tabu@setextra #1#2{\def\tabu@temp{\tabu@extr@#1#2}\afterassignment\tabu@temp#2}
+\def\tabu@extr@ #1#2{\@ifnextchar^%
+ {\tabu@gobbletoken{\tabu@setextra\extrarowdepth \extrarowheight}}
+ {\ifx _\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setextra\extrarowheight \extrarowdepth}}%
+ \else \let\tabu@temp \@empty
+ \tabu@Gsave \tabu@G@extra \tabu@C@extra \extrarowheight \extrarowdepth
+ \fi \tabu@temp}%
+}% \tabu@extr@
+\def\tabu@setextrasep {\extrarowheight=\extrarowdepth
+ \tabu@Gsave \tabu@G@extra \tabu@C@extra \extrarowheight \extrarowdepth
+}% \tabu@setextrasep
+\def\tabu@Gextra{\ifx \tabu@G@extra\@empty \else {\tabu@Rextra}\fi}
+\def\tabu@n@Gextra{\ifx \tabu@G@extra\@empty \else \noalign{\tabu@Rextra}\fi}
+\def\tabu@Rextra{\tabu@Grestore \tabu@G@extra \tabu@C@extra}
+\let\tabu@C@extra \z@
+\let\tabu@G@extra \@empty
+%% Dynamic vertical spacing adjustment: \tabulinesep ----------------
+\newcommand*\tabulinesep{\edef\tabu@C@linesep{\the\numexpr\tabu@C@linesep+1}%
+ \iftabu@everyrow \aftergroup\tabu@Glinesep
+ \else \aftergroup\tabu@n@Glinesep
+ \fi
+ \@ifnextchar={\tabu@gobbletoken\tabu@linesep} \tabu@linesep
+}% \tabulinesep
+\def\tabu@linesep {\@ifnextchar_%
+ {\tabu@gobbletoken{\tabu@setsep\abovetabulinesep \belowtabulinesep}}
+ {\ifx ^\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setsep\belowtabulinesep \abovetabulinesep}}%
+ \else \let\tabu@temp \@empty
+ \afterassignment \tabu@setlinesep \abovetabulinesep
+ \fi \tabu@temp}%
+}% \tabu@linesep
+\def\tabu@setsep #1#2{\def\tabu@temp{\tabu@sets@p#1#2}\afterassignment\tabu@temp#2}
+\def\tabu@sets@p #1#2{\@ifnextchar^%
+ {\tabu@gobbletoken{\tabu@setsep\belowtabulinesep \abovetabulinesep}}
+ {\ifx _\@let@token \def\tabu@temp{%
+ \tabu@gobbletoken{\tabu@setsep\abovetabulinesep \belowtabulinesep}}%
+ \else \let\tabu@temp \@empty
+ \tabu@Gsave \tabu@G@linesep \tabu@C@linesep \abovetabulinesep \belowtabulinesep
+ \fi \tabu@temp}%
+}% \tabu@sets@p
+\def\tabu@setlinesep {\belowtabulinesep=\abovetabulinesep
+ \tabu@Gsave \tabu@G@linesep \tabu@C@linesep \abovetabulinesep \belowtabulinesep
+}% \tabu@setlinesep
+\def\tabu@Glinesep{\ifx \tabu@G@linesep\@empty \else {\tabu@Rlinesep}\fi}
+\def\tabu@n@Glinesep{\ifx \tabu@G@linesep\@empty \else \noalign{\tabu@Rlinesep}\fi}
+\def\tabu@Rlinesep{\tabu@Grestore \tabu@G@linesep \tabu@C@linesep}
+\let\tabu@C@linesep \z@
+\let\tabu@G@linesep \@empty
+%% \global\extrarowsep and \global\tabulinesep -------------------
+\def\tabu@Gsave #1#2#3#4{\xdef#1{#1%
+ \toks#2{\toks\the\currentgrouplevel{\global#3\the#3\global#4\the#4}}}%
+}% \tabu@Gsave
+\def\tabu@Grestore#1#2{%
+ \toks#2{}#1\toks\currentgrouplevel\expandafter{\expandafter}\the\toks#2\relax
+ \ifcat$\the\toks\currentgrouplevel$\else
+ \global\let#1\@empty \global\let#2\z@
+ \the\toks\currentgrouplevel
+ \fi
+}% \tabu@Grestore
+%% Setting code for every row ---------------------------------------
+\newcommand*\everyrow{\tabu@everyrow@bgroup
+ \tabu@start \z@ \tabu@stop \z@ \tabu@evrstartstop
+}% \everyrow
+\def\tabu@evrstartstop {\@ifnextchar^%
+ {\afterassignment \tabu@evrstartstop \tabu@stop=}%
+ {\ifx ^\@let@token
+ \afterassignment\tabu@evrstartstop \tabu@start=%
+ \else \afterassignment\tabu@everyr@w \toks@
+ \fi}%
+}% \tabu@evrstartstop
+\def\tabu@everyr@w {%
+ \xdef\tabu@everyrow{%
+ \noexpand\tabu@everyrowfalse
+ \let\noalign \relax
+ \noexpand\tabu@rowfontreset
+ \iftabu@colortbl \noexpand\tabu@rc@ \fi % \taburowcolors
+ \let\noexpand\tabu@docline \noexpand\tabu@docline@evr
+ \the\toks@
+ \noexpand\tabu@evrh@@k
+ \noexpand\tabu@rearstrut
+ \global\advance\c@taburow \@ne}%
+ \iftabu@everyrow \toks@\expandafter
+ {\expandafter\def\expandafter\tabu@evr@L\expandafter{\the\toks@}\ignorespaces}%
+ \else \xdef\tabu@evr@G{\the\toks@}%
+ \fi
+ \tabu@everyrow@egroup
+}% \tabu@everyr@w
+\def\tabu@evr {\def\tabu@evrh@@k} % for internal use only
+\tabu@evr{}
+%% line style and leaders -------------------------------------------
+\newcommand*\newtabulinestyle [1]{%
+ {\@for \@tempa :=#1\do{\expandafter\tabu@newlinestyle \@tempa==\@nil}}%
+}% \newtabulinestyle
+\def\tabu@newlinestyle #1=#2=#3\@nil{\tabu@getline {#2}%
+ \tabu@sanitizearg {#1}\@tempa
+ \ifodd 1\ifx \@tempa\@empty \ifdefined\tabu@linestyle@ 0 \fi\fi
+ \global\expandafter\let
+ \csname tabu@linestyle@\@tempa \endcsname =\tabu@thestyle \fi
+}% \tabu@newlinestyle
+\newcommand*\tabulinestyle [1]{\tabu@everyrow@bgroup \tabu@getline{#1}%
+ \iftabu@everyrow
+ \toks@\expandafter{\expandafter \def \expandafter
+ \tabu@ls@L\expandafter{\tabu@thestyle}\ignorespaces}%
+ \gdef\tabu@ls@{\tabu@ls@L}%
+ \else
+ \global\let\tabu@ls@G \tabu@thestyle
+ \gdef\tabu@ls@{\tabu@ls@G}%
+ \fi
+ \tabu@everyrow@egroup
+}% \tabulinestyle
+\newcommand*\taburulecolor{\tabu@everyrow@bgroup \tabu@textbar \tabu@rulecolor}
+\def\tabu@rulecolor #1{\toks@{}%
+ \def\tabu@temp #1##1#1{\tabu@ruledrsc{##1}}\@ifnextchar #1%
+ \tabu@temp
+ \tabu@rulearc
+}% \tabu@rulecolor
+\def\tabu@ruledrsc #1{\edef\tabu@temp{#1}\tabu@strtrim\tabu@temp
+ \ifx \tabu@temp\@empty \def\tabu@temp{\tabu@rule@drsc@ {}{}}%
+ \else \edef\tabu@temp{\noexpand\tabu@rule@drsc@ {}{\tabu@temp}}%
+ \fi
+ \tabu@temp
+}% \tabu@ruledrsc@
+\def\tabu@ruledrsc@ #1#{\tabu@rule@drsc@ {#1}}
+\def\tabu@rule@drsc@ #1#2{%
+ \iftabu@everyrow
+ \ifx \\#1#2\\\toks@{\let\CT@drsc@ \relax}%
+ \else \toks@{\def\CT@drsc@{\color #1{#2}}}%
+ \fi
+ \else
+ \ifx \\#1#2\\\global\let\CT@drsc@ \relax
+ \else \gdef\CT@drsc@{\color #1{#2}}%
+ \fi
+ \fi
+ \tabu@rulearc
+}% \tabu@rule@drsc@
+\def\tabu@rulearc #1#{\tabu@rule@arc@ {#1}}
+\def\tabu@rule@arc@ #1#2{%
+ \iftabu@everyrow
+ \ifx \\#1#2\\\toks@\expandafter{\the\toks@ \def\CT@arc@{}}%
+ \else \toks@\expandafter{\the\toks@ \def\CT@arc@{\color #1{#2}}}%
+ \fi
+ \toks@\expandafter{\the\toks@
+ \let\tabu@arc@L \CT@arc@
+ \let\tabu@drsc@L \CT@drsc@
+ \ignorespaces}%
+ \else
+ \ifx \\#1#2\\\gdef\CT@arc@{}%
+ \else \gdef\CT@arc@{\color #1{#2}}%
+ \fi
+ \global\let\tabu@arc@G \CT@arc@
+ \global\let\tabu@drsc@G \CT@drsc@
+ \fi
+ \tabu@everyrow@egroup
+}% \tabu@rule@arc@
+\def\taburowcolors {\tabu@everyrow@bgroup \@testopt \tabu@rowcolors 1}
+\def\tabu@rowcolors [#1]#2#{\tabu@rowc@lors{#1}{#2}}
+\def\tabu@rowc@lors #1#2#3{%
+ \toks@{}\@defaultunits \count@ =\number0#2\relax \@nnil
+ \@defaultunits \tabu@start =\number0#1\relax \@nnil
+ \ifnum \count@<\tw@ \count@=\tw@ \fi
+ \advance\tabu@start \m@ne
+ \ifnum \tabu@start<\z@ \tabu@start \z@ \fi
+ \tabu@rowcolorseries #3\in@..\in@ \@nnil
+}% \tabu@rowcolors
+\def\tabu@rowcolorseries #1..#2\in@ #3\@nnil {%
+ \ifx \in@#1\relax
+ \iftabu@everyrow \toks@{\def\tabu@rc@{}\let\tabu@rc@L \tabu@rc@}%
+ \else \gdef\tabu@rc@{}\global\let\tabu@rc@G \tabu@rc@
+ \fi
+ \else
+ \ifx \\#2\\\tabu@rowcolorserieserror \fi
+ \tabu@sanitizearg{#1}\tabu@temp
+ \tabu@sanitizearg{#2}\@tempa
+ \advance\count@ \m@ne
+ \iftabu@everyrow
+ \def\tabu@rc@ ##1##2##3##4{\def\tabu@rc@{%
+ \ifnum ##2=\c@taburow
+ \definecolorseries{tabu@rcseries@\the\tabu@nested}{rgb}{last}{##3}{##4}\fi
+ \ifnum \c@taburow<##2 \else
+ \ifnum \tabu@modulo {\c@taburow-##2}{##1+1}=\z@
+ \resetcolorseries[{##1}]{tabu@rcseries@\the\tabu@nested}\fi
+ \xglobal\colorlet{tabu@rc@\the\tabu@nested}{tabu@rcseries@\the\tabu@nested!!+}%
+ \rowcolor{tabu@rc@\the\tabu@nested}\fi}%
+ }\edef\x{\noexpand\tabu@rc@ {\the\count@}
+ {\the\tabu@start}
+ {\tabu@temp}
+ {\@tempa}%
+ }\x
+ \toks@\expandafter{\expandafter\def\expandafter\tabu@rc@\expandafter{\tabu@rc@}}%
+ \toks@\expandafter{\the\toks@ \let\tabu@rc@L \tabu@rc@ \ignorespaces}%
+ \else % inside \noalign
+ \definecolorseries{tabu@rcseries@\the\tabu@nested}{rgb}{last}{\tabu@temp}{\@tempa}%
+ \expandafter\resetcolorseries\expandafter[\the\count@]{tabu@rcseries@\the\tabu@nested}%
+ \xglobal\colorlet{tabu@rc@\the\tabu@nested}{tabu@rcseries@\the\tabu@nested!!+}%
+ \let\noalign \relax \rowcolor{tabu@rc@\the\tabu@nested}%
+ \def\tabu@rc@ ##1##2{\gdef\tabu@rc@{%
+ \ifnum \tabu@modulo {\c@taburow-##2}{##1+1}=\@ne
+ \resetcolorseries[{##1}]{tabu@rcseries@\the\tabu@nested}\fi
+ \xglobal\colorlet{tabu@rc@\the\tabu@nested}{tabu@rcseries@\the\tabu@nested!!+}%
+ \rowcolor{tabu@rc@\the\tabu@nested}}%
+ }\edef\x{\noexpand\tabu@rc@{\the\count@}{\the\c@taburow}}\x
+ \global\let\tabu@rc@G \tabu@rc@
+ \fi
+ \fi
+ \tabu@everyrow@egroup
+}% \tabu@rowcolorseries
+\tabuDisableCommands {\let\tabu@rc@ \@empty }
+\def\tabu@rowcolorserieserror {\PackageError{tabu}
+ {Invalid syntax for \string\taburowcolors
+ \MessageBreak Please look at the documentation!}\@ehd
+}% \tabu@rowcolorserieserror
+\newcommand*\tabureset {%
+ \tabulinesep=\z@ \extrarowsep=\z@ \extratabsurround=\z@
+ \tabulinestyle{}\everyrow{}\taburulecolor||{}\taburowcolors{}%
+}% \tabureset
+%% Parsing the line styles ------------------------------------------
+\def\tabu@getline #1{\begingroup
+ \csname \ifcsname if@safe@actives\endcsname % <babel>
+ @safe@activestrue\else
+ relax\fi \endcsname
+ \edef\tabu@temp{#1}\tabu@sanitizearg{#1}\@tempa
+ \let\tabu@thestyle \relax
+ \ifcsname tabu@linestyle@\@tempa \endcsname
+ \edef\tabu@thestyle{\endgroup
+ \def\tabu@thestyle{\expandafter\noexpand
+ \csname tabu@linestyle@\@tempa\endcsname}%
+ }\tabu@thestyle
+ \else \expandafter\tabu@definestyle \tabu@temp \@nil
+ \fi
+}% \tabu@getline
+\def\tabu@definestyle #1#2\@nil {\endlinechar \m@ne \makeatletter
+ \tabu@thick \maxdimen \tabu@on \maxdimen \tabu@off \maxdimen
+ \let\tabu@c@lon \@undefined \let\tabu@c@loff \@undefined
+ \ifodd 1\ifcat .#1\else\ifcat\relax #1\else 0\fi\fi % catcode 12 or non expandable cs
+ \def\tabu@temp{\tabu@getparam{thick}}%
+ \else \def\tabu@temp{\tabu@getparam{thick}\maxdimen}%
+ \fi
+ {%
+ \let\tabu@ \relax
+ \def\:{\obeyspaces \tabu@oXIII \tabu@commaXIII \edef\:}% (space active \: happy ;-))
+ \scantokens{\:{\tabu@temp #1#2 \tabu@\tabu@}}%
+ \expandafter}\expandafter
+ \def\expandafter\:\expandafter{\:}% line spec rewritten now ;-)
+ \def\;{\def\:}%
+ \scantokens\expandafter{\expandafter\;\expandafter{\:}}% space is now inactive (catcode 10)
+ \let\tabu@ \tabu@getcolor \:% all arguments are ready now ;-)
+ \ifdefined\tabu@c@lon \else \let\tabu@c@lon\@empty \fi
+ \ifx \tabu@c@lon\@empty \def\tabu@c@lon{\CT@arc@}\fi
+ \ifdefined\tabu@c@loff \else \let\tabu@c@loff \@empty \fi
+ \ifdim \tabu@on=\maxdimen \ifdim \tabu@off<\maxdimen
+ \tabu@on \tabulineon \fi\fi
+ \ifdim \tabu@off=\maxdimen \ifdim \tabu@on<\maxdimen
+ \tabu@off \tabulineoff \fi\fi
+ \ifodd 1\ifdim \tabu@off=\maxdimen \ifdim \tabu@on=\maxdimen 0 \fi\fi
+ \in@true % <leaders>
+ \else \in@false % <rule>
+ \fi
+ \ifdim\tabu@thick=\maxdimen \def\tabu@thick{\arrayrulewidth}%
+ \else \edef\tabu@thick{\the\tabu@thick}%
+ \fi
+ \edef \tabu@thestyle ##1##2{\endgroup
+ \def\tabu@thestyle{%
+ \ifin@ \noexpand\tabu@leadersstyle {\tabu@thick}
+ {\the\tabu@on}{##1}
+ {\the\tabu@off}{##2}%
+ \else \noexpand\tabu@rulesstyle
+ {##1\vrule width \tabu@thick}%
+ {##1\leaders \hrule height \tabu@thick \hfil}%
+ \fi}%
+ }\expandafter \expandafter
+ \expandafter \tabu@thestyle \expandafter
+ \expandafter \expandafter
+ {\expandafter\tabu@c@lon\expandafter}\expandafter{\tabu@c@loff}%
+}% \tabu@definestyle
+{\catcode`\O=\active \lccode`\O=`\o \catcode`\,=\active
+ \lowercase{\gdef\tabu@oXIII {\catcode`\o=\active \let O=\tabu@oxiii}}
+ \gdef\tabu@commaXIII {\catcode`\,=\active \let ,=\space}
+}% \catcode
+\def\tabu@oxiii #1{%
+ \ifcase \ifx n#1\z@ \else
+ \ifx f#1\@ne\else
+ \tw@ \fi\fi
+ \expandafter\tabu@onxiii
+ \or \expandafter\tabu@ofxiii
+ \else o%
+ \fi#1}%
+\def\tabu@onxiii #1#2{%
+ \ifcase \ifx !#2\tw@ \else
+ \ifcat.\noexpand#2\z@ \else
+ \ifx \tabu@spxiii#2\@ne\else
+ \tw@ \fi\fi\fi
+ \tabu@getparam{on}#2\expandafter\@gobble
+ \or \expandafter\tabu@onxiii % (space is active)
+ \else o\expandafter\@firstofone
+ \fi{#1#2}}%
+\def\tabu@ofxiii #1#2{%
+ \ifx #2f\expandafter\tabu@offxiii
+ \else o\expandafter\@firstofone
+ \fi{#1#2}}
+\def\tabu@offxiii #1#2{%
+ \ifcase \ifx !#2\tw@ \else
+ \ifcat.\noexpand#2\z@ \else
+ \ifx\tabu@spxiii#2\@ne \else
+ \tw@ \fi\fi\fi
+ \tabu@getparam{off}#2\expandafter\@gobble
+ \or \expandafter\tabu@offxiii % (space is active)
+ \else o\expandafter\@firstofone
+ \fi{#1#2}}
+\def\tabu@getparam #1{\tabu@ \csname tabu@#1\endcsname=}
+\def\tabu@getcolor #1{% \tabu@ <- \tabu@getcolor after \edef
+ \ifx \tabu@#1\else % no more spec
+ \let\tabu@theparam=#1\afterassignment \tabu@getc@l@r #1\fi
+}% \tabu@getcolor
+\def\tabu@getc@l@r #1\tabu@ {%
+ \def\tabu@temp{#1}\tabu@strtrim \tabu@temp
+ \ifx \tabu@temp\@empty
+ \else%\ifcsname \string\color@\tabu@temp \endcsname % if the color exists
+ \ifx \tabu@theparam \tabu@off \let\tabu@c@loff \tabu@c@l@r
+ \else \let\tabu@c@lon \tabu@c@l@r
+ \fi
+ %\else \tabu@warncolour{\tabu@temp}%
+ \fi%\fi
+ \tabu@ % next spec
+}% \tabu@getc@l@r
+\def\tabu@warncolour #1{\PackageWarning{tabu}
+ {Color #1 is not defined. Default color used}%
+}% \tabu@warncolour
+\def\tabu@leadersstyle #1#2#3#4#5{\def\tabu@leaders{{#1}{#2}{#3}{#4}{#5}}%
+ \ifx \tabu@leaders\tabu@leaders@G \else
+ \tabu@LEADERS{#1}{#2}{#3}{#4}{#5}\fi
+}% \tabu@leadersstyle
+\def\tabu@rulesstyle #1#2{\let\tabu@leaders \@undefined
+ \gdef\tabu@thevrule{#1}\gdef\tabu@thehrule{#2}%
+}% \tabu@rulesstyle
+%% The leaders boxes ------------------------------------------------
+\def\tabu@LEADERS #1#2#3#4#5{%% width, dash, dash color, gap, gap color
+ {\let\color \tabu@color % => during trials -> \color = \tabu@nocolor
+ {% % but the leaders boxes should have colors !
+ \def\@therule{\vrule}\def\@thick{height}\def\@length{width}%
+ \def\@box{\hbox}\def\@unbox{\unhbox}\def\@elt{\wd}%
+ \def\@skip{\hskip}\def\@ss{\hss}\def\tabu@leads{\tabu@hleads}%
+ \tabu@l@@d@rs {#1}{#2}{#3}{#4}{#5}%
+ \global\let\tabu@thehleaders \tabu@theleaders
+ }%
+ {%
+ \def\@therule{\hrule}\def\@thick{width}\def\@length{height}%
+ \def\@box{\vbox}\def\@unbox{\unvbox}\def\@elt{\ht}%
+ \def\@skip{\vskip}\def\@ss{\vss}\def\tabu@leads{\tabu@vleads}%
+ \tabu@l@@d@rs {#1}{#2}{#3}{#4}{#5}%
+ \global\let\tabu@thevleaders \tabu@theleaders
+ }%
+ \gdef\tabu@leaders@G{{#1}{#2}{#3}{#4}{#5}}%
+ }%
+}% \tabu@LEADERS
+\def\tabu@therule #1#2{\@therule \@thick#1\@length\dimexpr#2/2 \@depth\z@}
+\def\tabu@l@@d@rs #1#2#3#4#5{%% width, dash, dash color, gap, gap color
+ \global\setbox \tabu@leads=\@box{%
+ {#3\tabu@therule{#1}{#2}}%
+ \ifx\\#5\\\@skip#4\else{#5\tabu@therule{#1}{#4*2}}\fi
+ {#3\tabu@therule{#1}{#2}}}%
+ \global\setbox\tabu@leads=\@box to\@elt\tabu@leads{\@ss
+ {#3\tabu@therule{#1}{#2}}\@unbox\tabu@leads}%
+ \edef\tabu@theleaders ##1{\def\noexpand\tabu@theleaders {%
+ {##1\tabu@therule{#1}{#2}}%
+ \xleaders \copy\tabu@leads \@ss
+ \tabu@therule{0pt}{-#2}{##1\tabu@therule{#1}{#2}}}%
+ }\tabu@theleaders{#3}%
+}% \tabu@l@@d@rs
+%% \tabu \endtabu \tabu* \longtabu \endlongtabu \longtabu* ----------
+\newcommand*\tabu {\tabu@longfalse
+ \ifmmode \def\tabu@ {\array}\def\endtabu {\endarray}%
+ \else \def\tabu@ {\tabu@tabular}\def\endtabu {\endtabular}\fi
+ \expandafter\let\csname tabu*\endcsname \tabu
+ \expandafter\def\csname endtabu*\endcsname{\endtabu}%
+ \tabu@spreadfalse \tabu@negcoeffalse \tabu@settarget
+}% {tabu}
+\let\tabu@tabular \tabular % <For LyX: some users redefine \tabular...>
+\expandafter\def\csname tabu*\endcsname{\tabuscantokenstrue \tabu}
+\newcommand*\longtabu {\tabu@longtrue
+ \ifmmode\PackageError{tabu}{longtabu not allowed in math mode}\fi
+ \def\tabu@{\longtable}\def\endlongtabu{\endlongtable}%
+ \LTchunksize=\@M
+ \expandafter\let\csname tabu*\endcsname \tabu
+ \expandafter\def\csname endlongtabu*\endcsname{\endlongtabu}%
+ \let\LT@startpbox \tabu@LT@startpbox % \everypar{ array struts }
+ \tabu@spreadfalse \tabu@negcoeffalse \tabu@settarget
+}% {longtabu}
+\expandafter\def\csname longtabu*\endcsname{\tabuscantokenstrue \longtabu}
+\def\tabu@nolongtabu{\PackageError{tabu}
+ {longtabu requires the longtable package}\@ehd}
+%% Read the target and then : \tabular or \@array ------------------
+\def\tabu@settarget {\futurelet\@let@token \tabu@sett@rget }
+\def\tabu@sett@rget {\tabu@target \z@
+ \ifcase \ifx \bgroup\@let@token \z@ \else
+ \ifx \@sptoken\@let@token \@ne \else
+ \if t\@let@token \tw@ \else
+ \if s\@let@token \thr@@\else
+ \z@\fi\fi\fi\fi
+ \expandafter\tabu@begin
+ \or \expandafter\tabu@gobblespace\expandafter\tabu@settarget
+ \or \expandafter\tabu@to
+ \or \expandafter\tabu@spread
+ \fi
+}% \tabu@sett@rget
+\def\tabu@to to{\def\tabu@halignto{to}\tabu@gettarget}
+\def\tabu@spread spread{\tabu@spreadtrue\def\tabu@halignto{spread}\tabu@gettarget}
+\def\tabu@gettarget {\afterassignment\tabu@linegoaltarget \tabu@target }
+\def\tabu@linegoaltarget {\futurelet\tabu@temp \tabu@linegoalt@rget }
+\def\tabu@linegoalt@rget {%
+ \ifx \tabu@temp\LNGL@setlinegoal
+ \LNGL@setlinegoal \expandafter \@firstoftwo \fi % @gobbles \LNGL@setlinegoal
+ \tabu@begin
+}% \tabu@linegoalt@rget
+\def\tabu@begin #1#{%
+ \iftabu@measuring \expandafter\tabu@nestedmeasure \fi
+ \ifdim \tabu@target=\z@ \let\tabu@halignto \@empty
+ \else \edef\tabu@halignto{\tabu@halignto\the\tabu@target}%
+ \fi
+ \@testopt \tabu@tabu@ \tabu@aligndefault #1\@nil
+}% \tabu@begin
+\long\def\tabu@tabu@ [#1]#2\@nil #3{\tabu@setup
+ \def\tabu@align {#1}\def\tabu@savedpream{\NC@find #3}%
+ \tabu@ [\tabu@align ]#2{#3\tabu@rewritefirst }%
+}% \tabu@tabu@
+\def\tabu@nestedmeasure {%
+ \ifodd 1\iftabu@spread \else \ifdim\tabu@target=\z@ \else 0 \fi\fi\relax
+ \tabu@spreadtrue
+ \else \begingroup \iffalse{\fi \ifnum0=`}\fi
+ \toks@{}\def\tabu@stack{b}%
+ \expandafter\tabu@collectbody\expandafter\tabu@quickrule
+ \expandafter\endgroup
+ \fi
+}% \tabu@nestedmeasure
+\def\tabu@quickrule {\indent\vrule height\z@ depth\z@ width\tabu@target}
+%% \tabu@setup \tabu@init \tabu@indent
+\def\tabu@setup{\tabu@alloc@
+ \ifcase \tabu@nested
+ \ifmmode \else \iftabu@spread\else \ifdim\tabu@target=\z@
+ \let\tabu@afterendpar \par
+ \fi\fi\fi
+ \def\tabu@aligndefault{c}\tabu@init \tabu@indent
+ \else % <nested tabu>
+ \def\tabu@aligndefault{t}\let\tabudefaulttarget \linewidth
+ \fi
+ \let\tabu@thetarget \tabudefaulttarget \let\tabu@restored \@undefined
+ \edef\tabu@NC@list{\the\NC@list}\NC@list{\NC@do \tabu@rewritefirst}%
+ \everycr{}\let\@startpbox \tabu@startpbox % for nested tabu inside longtabu...
+ \let\@endpbox \tabu@endpbox % idem " " " " " "
+ \let\@tabarray \tabu@tabarray % idem " " " " " "
+ \tabu@setcleanup \tabu@setreset
+}% \tabu@setup
+\def\tabu@init{\tabu@starttimer \tabu@measuringfalse
+ \edef\tabu@hfuzz {\the\dimexpr\hfuzz+1sp}\global\tabu@footnotes{}%
+ \let\firsthline \tabu@firsthline \let\lasthline \tabu@lasthline
+ \let\firstline \tabu@firstline \let\lastline \tabu@lastline
+ \let\hline \tabu@hline \let\@xhline \tabu@xhline
+ \let\color \tabu@color \let\@arstrutbox \tabu@arstrutbox
+ \iftabu@colortbl\else\let\LT@@hline \tabu@LT@@hline \fi
+ \tabu@trivlist %<restore \\=\@normalcr inside lists>
+ \let\@footnotetext \tabu@footnotetext \let\@xfootnotetext \tabu@xfootnotetext
+ \let\@xfootnote \tabu@xfootnote \let\centering \tabu@centering
+ \let\raggedright \tabu@raggedright \let\raggedleft \tabu@raggedleft
+ \let\tabudecimal \tabu@tabudecimal \let\Centering \tabu@Centering
+ \let\RaggedRight \tabu@RaggedRight \let\RaggedLeft \tabu@RaggedLeft
+ \let\justifying \tabu@justifying \let\rowfont \tabu@rowfont
+ \let\fbox \tabu@fbox \let\color@b@x \tabu@color@b@x
+ \let\tabu@@everycr \everycr \let\tabu@@everypar \everypar
+ \let\tabu@prepnext@tokORI \prepnext@tok\let\prepnext@tok \tabu@prepnext@tok
+ \let\tabu@multicolumnORI\multicolumn \let\multicolumn \tabu@multicolumn
+ \let\tabu@startpbox \@startpbox % for nested tabu inside longtabu pfff !!!
+ \let\tabu@endpbox \@endpbox % idem " " " " " " "
+ \let\tabu@tabarray \@tabarray % idem " " " " " " "
+ \tabu@adl@fix \let\endarray \tabu@endarray % <fix> colortbl & arydshln (delarray)
+ \iftabu@colortbl\CT@everycr\expandafter{\expandafter\iftabu@everyrow \the\CT@everycr \fi}\fi
+}% \tabu@init
+\def\tabu@indent{% correction for indentation
+ \ifdim \parindent>\z@\ifx \linewidth\tabudefaulttarget
+ \everypar\expandafter{%
+ \the\everypar\everypar\expandafter{\the\everypar}%
+ \setbox\z@=\lastbox
+ \ifdim\wd\z@>\z@ \edef\tabu@thetarget
+ {\the\dimexpr -\wd\z@+\tabudefaulttarget}\fi
+ \box\z@}%
+ \fi\fi
+}% \tabu@indent
+\def\tabu@setcleanup {% saves last global assignments
+ \ifodd 1\ifmmode \else \iftabu@long \else 0\fi\fi\relax
+ \def\tabu@aftergroupcleanup{%
+ \def\tabu@aftergroupcleanup{\aftergroup\tabu@cleanup}}%
+ \else
+ \def\tabu@aftergroupcleanup{%
+ \aftergroup\aftergroup\aftergroup\tabu@cleanup
+ \let\tabu@aftergroupcleanup \relax}%
+ \fi
+ \let\tabu@arc@Gsave \tabu@arc@G
+ \let\tabu@arc@G \tabu@arc@L % <init>
+ \let\tabu@drsc@Gsave \tabu@drsc@G
+ \let\tabu@drsc@G \tabu@drsc@L % <init>
+ \let\tabu@ls@Gsave \tabu@ls@G
+ \let\tabu@ls@G \tabu@ls@L % <init>
+ \let\tabu@rc@Gsave \tabu@rc@G
+ \let\tabu@rc@G \tabu@rc@L % <init>
+ \let\tabu@evr@Gsave \tabu@evr@G
+ \let\tabu@evr@G \tabu@evr@L % <init>
+ \let\tabu@celllalign@save \tabu@celllalign
+ \let\tabu@cellralign@save \tabu@cellralign
+ \let\tabu@cellleft@save \tabu@cellleft
+ \let\tabu@cellright@save \tabu@cellright
+ \let\tabu@@celllalign@save \tabu@@celllalign
+ \let\tabu@@cellralign@save \tabu@@cellralign
+ \let\tabu@@cellleft@save \tabu@@cellleft
+ \let\tabu@@cellright@save \tabu@@cellright
+ \let\tabu@rowfontreset@save \tabu@rowfontreset
+ \let\tabu@@rowfontreset@save\tabu@@rowfontreset
+ \let\tabu@rowfontreset \@empty
+ \edef\tabu@alloc@save {\the\tabu@alloc}% restore at \tabu@reset
+ \edef\c@taburow@save {\the\c@taburow}%
+ \edef\tabu@naturalX@save {\the\tabu@naturalX}%
+ \let\tabu@naturalXmin@save \tabu@naturalXmin
+ \let\tabu@naturalXmax@save \tabu@naturalXmax
+ \let\tabu@mkarstrut@save \tabu@mkarstrut
+ \edef\tabu@clarstrut{%
+ \extrarowheight \the\dimexpr \ht\@arstrutbox-\ht\strutbox \relax
+ \extrarowdepth \the\dimexpr \dp\@arstrutbox-\dp\strutbox \relax
+ \let\noexpand\@arraystretch \@ne \noexpand\tabu@rearstrut}%
+}% \tabu@setcleanup
+\def\tabu@cleanup {\begingroup
+ \globaldefs\@ne \tabu@everyrowtrue
+ \let\tabu@arc@G \tabu@arc@Gsave
+ \let\CT@arc@ \tabu@arc@G
+ \let\tabu@drsc@G \tabu@drsc@Gsave
+ \let\CT@drsc@ \tabu@drsc@G
+ \let\tabu@ls@G \tabu@ls@Gsave
+ \let\tabu@ls@ \tabu@ls@G
+ \let\tabu@rc@G \tabu@rc@Gsave
+ \let\tabu@rc@ \tabu@rc@G
+ \let\CT@do@color \relax
+ \let\tabu@evr@G \tabu@evr@Gsave
+ \let\tabu@celllalign \tabu@celllalign@save
+ \let\tabu@cellralign \tabu@cellralign@save
+ \let\tabu@cellleft \tabu@cellleft@save
+ \let\tabu@cellright \tabu@cellright@save
+ \let\tabu@@celllalign \tabu@@celllalign@save
+ \let\tabu@@cellralign \tabu@@cellralign@save
+ \let\tabu@@cellleft \tabu@@cellleft@save
+ \let\tabu@@cellright \tabu@@cellright@save
+ \let\tabu@rowfontreset \tabu@rowfontreset@save
+ \let\tabu@@rowfontreset \tabu@@rowfontreset@save
+ \tabu@naturalX =\tabu@naturalX@save
+ \let\tabu@naturalXmax \tabu@naturalXmax@save
+ \let\tabu@naturalXmin \tabu@naturalXmin@save
+ \let\tabu@mkarstrut \tabu@mkarstrut@save
+ \c@taburow =\c@taburow@save
+ \ifcase \tabu@nested \tabu@alloc \m@ne\fi
+ \endgroup % <end of \globaldefs>
+ \ifcase \tabu@nested
+ \the\tabu@footnotes \global\tabu@footnotes{}%
+ \tabu@afterendpar \tabu@elapsedtime
+ \fi
+ \tabu@clarstrut
+ \everyrow\expandafter {\tabu@evr@G}%
+}% \tabu@cleanup
+\let\tabu@afterendpar \relax
+\def\tabu@setreset {%
+ \edef\tabu@savedparams {% \relax for \tabu@message@save
+ \ifmmode \col@sep \the\arraycolsep
+ \else \col@sep \the\tabcolsep \fi \relax
+ \arrayrulewidth \the\arrayrulewidth \relax
+ \doublerulesep \the\doublerulesep \relax
+ \extratabsurround \the\extratabsurround \relax
+ \extrarowheight \the\extrarowheight \relax
+ \extrarowdepth \the\extrarowdepth \relax
+ \abovetabulinesep \the\abovetabulinesep \relax
+ \belowtabulinesep \the\belowtabulinesep \relax
+ \def\noexpand\arraystretch{\arraystretch}%
+ \ifdefined\minrowclearance \minrowclearance\the\minrowclearance\relax\fi}%
+ \begingroup
+ \@temptokena\expandafter{\tabu@savedparams}% => only for \savetabu / \usetabu
+ \ifx \tabu@arc@L\relax \else \tabu@setsave \tabu@arc@L \fi
+ \ifx \tabu@drsc@L\relax \else \tabu@setsave \tabu@drsc@L \fi
+ \tabu@setsave \tabu@ls@L \tabu@setsave \tabu@evr@L
+ \expandafter \endgroup \expandafter
+ \def\expandafter\tabu@saved@ \expandafter{\the\@temptokena
+ \let\tabu@arc@G \tabu@arc@L
+ \let\tabu@drsc@G \tabu@drsc@L
+ \let\tabu@ls@G \tabu@ls@L
+ \let\tabu@rc@G \tabu@rc@L
+ \let\tabu@evr@G \tabu@evr@L}%
+ \def\tabu@reset{\tabu@savedparams
+ \tabu@everyrowtrue \c@taburow \z@
+ \let\CT@arc@ \tabu@arc@L
+ \let\CT@drsc@ \tabu@drsc@L
+ \let\tabu@ls@ \tabu@ls@L
+ \let\tabu@rc@ \tabu@rc@L
+ \global\tabu@alloc \tabu@alloc@save
+ \everyrow\expandafter{\tabu@evr@L}}%
+}% \tabu@reset
+\def\tabu@setsave #1{\expandafter\tabu@sets@ve #1\@nil{#1}}
+\long\def\tabu@sets@ve #1\@nil #2{\@temptokena\expandafter{\the\@temptokena \def#2{#1}}}
+%% The Rewritting Process -------------------------------------------
+\def\tabu@newcolumntype #1{%
+ \expandafter\tabu@new@columntype
+ \csname NC@find@\string#1\expandafter\endcsname
+ \csname NC@rewrite@\string#1\endcsname
+ {#1}%
+}% \tabu@newcolumntype
+\def\tabu@new@columntype #1#2#3{%
+ \def#1##1#3{\NC@{##1}}%
+ \let#2\relax \newcommand*#2%
+}% \tabu@new@columntype
+\def\tabu@privatecolumntype #1{%
+ \expandafter\tabu@private@columntype
+ \csname NC@find@\string#1\expandafter\endcsname
+ \csname NC@rewrite@\string#1\expandafter\endcsname
+ \csname tabu@NC@find@\string#1\expandafter\endcsname
+ \csname tabu@NC@rewrite@\string#1\endcsname
+ {#1}%
+}% \tabu@privatecolumntype
+\def\tabu@private@columntype#1#2#3#4{%
+ \g@addto@macro\tabu@privatecolumns{\let#1#3\let#2#4}%
+ \tabu@new@columntype#3#4%
+}% \tabu@private@columntype
+\let\tabu@privatecolumns \@empty
+\newcommand*\tabucolumn [1]{\expandafter \def \expandafter
+ \tabu@highprioritycolumns\expandafter{\tabu@highprioritycolumns
+ \NC@do #1}}%
+\let\tabu@highprioritycolumns \@empty
+%% The | ``column'' : rewriting process --------------------------
+\tabu@privatecolumntype |{\tabu@rewritevline}
+\newcommand*\tabu@rewritevline[1][]{\tabu@vlinearg{#1}%
+ \expandafter \NC@find \tabu@rewritten}
+\def\tabu@lines #1{%
+ \ifx|#1\else \tabu@privatecolumntype #1{\tabu@rewritevline}\fi
+ \NC@list\expandafter{\the\NC@list \NC@do #1}%
+}% \tabu@lines@
+\def\tabu@vlinearg #1{%
+ \ifx\\#1\\\def\tabu@thestyle {\tabu@ls@}%
+ \else\tabu@getline {#1}%
+ \fi
+ \def\tabu@rewritten ##1{\def\tabu@rewritten{!{##1\tabu@thevline}}%
+ }\expandafter\tabu@rewritten\expandafter{\tabu@thestyle}%
+ \expandafter \tabu@keepls \tabu@thestyle \@nil
+}% \tabu@vlinearg
+\def\tabu@keepls #1\@nil{%
+ \ifcat $\@cdr #1\@nil $%
+ \ifx \relax#1\else
+ \ifx \tabu@ls@#1\else
+ \let#1\relax
+ \xdef\tabu@mkpreambuffer{\tabu@mkpreambuffer
+ \tabu@savels\noexpand#1}\fi\fi\fi
+}% \tabu@keepls
+\def\tabu@thevline {\begingroup
+ \ifdefined\tabu@leaders
+ \setbox\@tempboxa=\vtop to\dimexpr
+ \ht\@arstrutbox+\dp\@arstrutbox{{\tabu@thevleaders}}%
+ \ht\@tempboxa=\ht\@arstrutbox \dp\@tempboxa=\dp\@arstrutbox
+ \box\@tempboxa
+ \else
+ \tabu@thevrule
+ \fi \endgroup
+}% \tabu@thevline
+\def\tabu@savels #1{%
+ \expandafter\let\csname\string#1\endcsname #1%
+ \expandafter\def\expandafter\tabu@reset\expandafter{\tabu@reset
+ \tabu@resetls#1}}%
+\def\tabu@resetls #1{\expandafter\let\expandafter#1\csname\string#1\endcsname}%
+%% \multicolumn inside tabu environment -----------------------------
+\tabu@newcolumntype \tabu@rewritemulticolumn{%
+ \aftergroup \tabu@endrewritemulticolumn % after \@mkpream group
+ \NC@list{\NC@do *}\tabu@textbar \tabu@lines
+ \tabu@savedecl
+ \tabu@privatecolumns
+ \NC@list\expandafter{\the\expandafter\NC@list \tabu@NC@list}%
+ \let\tabu@savels \relax
+ \NC@find
+}% \tabu@rewritemulticolumn
+\def\tabu@endrewritemulticolumn{\gdef\tabu@mkpreambuffer{}\endgroup}
+\def\tabu@multicolumn{\tabu@ifenvir \tabu@multic@lumn \tabu@multicolumnORI}
+\long\def\tabu@multic@lumn #1#2#3{\multispan{#1}\begingroup
+ \tabu@everyrowtrue
+ \NC@list{\NC@do \tabu@rewritemulticolumn}%
+ \expandafter\@gobbletwo % gobbles \multispan{#1}
+ \tabu@multicolumnORI{#1}{\tabu@rewritemulticolumn #2}%
+ {\iftabuscantokens \tabu@rescan \else \expandafter\@firstofone \fi
+ {#3}}%
+}% \tabu@multic@lumn
+%% The X column(s): rewriting process -----------------------------
+\tabu@privatecolumntype X[1][]{\begingroup \tabu@siunitx{\endgroup \tabu@rewriteX {#1}}}
+\def\tabu@nosiunitx #1{#1{}{}\expandafter \NC@find \tabu@rewritten }
+\def\tabu@siunitx #1{\@ifnextchar \bgroup
+ {\tabu@rewriteX@Ss{#1}}
+ {\tabu@nosiunitx{#1}}}
+\def\tabu@rewriteX@Ss #1#2{\@temptokena{}%
+ \@defaultunits \let\tabu@temp =#2\relax\@nnil
+ \ifodd 1\ifx S\tabu@temp \else \ifx s\tabu@temp \else 0 \fi\fi
+ \def\NC@find{\def\NC@find >####1####2<####3\relax{#1 {####1}{####3}%
+ }\expandafter\NC@find \the\@temptokena \relax
+ }\expandafter\NC@rewrite@S \@gobble #2\relax
+ \else \tabu@siunitxerror
+ \fi
+ \expandafter \NC@find \tabu@rewritten
+}% \tabu@rewriteX@Ss
+\def\tabu@siunitxerror {\PackageError{tabu}{Not a S nor s column !
+ \MessageBreak X column can only embed siunitx S or s columns}\@ehd
+}% \tabu@siunitxerror
+\def\tabu@rewriteX #1#2#3{\tabu@Xarg {#1}{#2}{#3}%
+ \iftabu@measuring
+ \else \tabu@measuringtrue % first X column found in the preamble
+ \let\@halignto \relax \let\tabu@halignto \relax
+ \iftabu@spread \tabu@spreadtarget \tabu@target \tabu@target \z@
+ \else \tabu@spreadtarget \z@ \fi
+ \ifdim \tabu@target=\z@
+ \setlength\tabu@target \tabu@thetarget
+ \tabu@message{\tabu@message@defaulttarget}%
+ \else \tabu@message{\tabu@message@target}\fi
+ \fi
+}% \tabu@rewriteX
+\def\tabu@rewriteXrestore #1#2#3{\let\@halignto \relax
+ \def\tabu@rewritten{l}}
+\def\tabu@Xarg #1#2#3{%
+ \advance\tabu@Xcol \@ne \let\tabu@Xlcr \@empty
+ \let\tabu@Xdisp \@empty \let\tabu@Xmath \@empty
+ \ifx\\#1\\% <shortcut when no option>
+ \def\tabu@rewritten{p}\tabucolX \p@ % <default coef = 1>
+ \else
+ \let\tabu@rewritten \@empty \let\tabu@temp \@empty \tabucolX \z@
+ \tabu@Xparse {}#1\relax
+ \fi
+ \tabu@Xrewritten{#2}{#3}%
+}% \tabu@Xarg
+\def\tabu@Xparse #1{\futurelet\@let@token \tabu@Xtest}
+\expandafter\def\expandafter\tabu@Xparsespace\space{\tabu@Xparse{}}
+\def\tabu@Xtest{%
+ \ifcase \ifx \relax\@let@token \z@ \else
+ \if ,\@let@token \m@ne\else
+ \if p\@let@token 1\else
+ \if m\@let@token 2\else
+ \if b\@let@token 3\else
+ \if l\@let@token 4\else
+ \if c\@let@token 5\else
+ \if r\@let@token 6\else
+ \if j\@let@token 7\else
+ \if L\@let@token 8\else
+ \if C\@let@token 9\else
+ \if R\@let@token 10\else
+ \if J\@let@token 11\else
+ \ifx \@sptoken\@let@token 12\else
+ \if .\@let@token 13\else
+ \if -\@let@token 13\else
+ \ifcat $\@let@token 14\else
+ 15\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\relax
+ \or \tabu@Xtype {p}%
+ \or \tabu@Xtype {m}%
+ \or \tabu@Xtype {b}%
+ \or \tabu@Xalign \raggedright\relax
+ \or \tabu@Xalign \centering\relax
+ \or \tabu@Xalign \raggedleft\relax
+ \or \tabu@Xalign \tabu@justify\relax
+ \or \tabu@Xalign \RaggedRight\raggedright
+ \or \tabu@Xalign \Centering\centering
+ \or \tabu@Xalign \RaggedLeft\raggedleft
+ \or \tabu@Xalign \justifying\tabu@justify
+ \or \expandafter \tabu@Xparsespace
+ \or \expandafter \tabu@Xcoef
+ \or \expandafter \tabu@Xm@th
+ \or \tabu@Xcoef{}%
+ \else\expandafter \tabu@Xparse
+ \fi
+}% \tabu@Xtest
+\def\tabu@Xalign #1#2{%
+ \ifx \tabu@Xlcr\@empty \else \PackageWarning{tabu}
+ {Duplicate horizontal alignment specification}\fi
+ \ifdefined#1\def\tabu@Xlcr{#1}\let#1\relax
+ \else \def\tabu@Xlcr{#2}\let#2\relax\fi
+ \expandafter\tabu@Xparse
+}% \tabu@Xalign
+\def\tabu@Xtype #1{%
+ \ifx \tabu@rewritten\@empty \else \PackageWarning{tabu}
+ {Duplicate vertical alignment specification}\fi
+ \def\tabu@rewritten{#1}\expandafter\tabu@Xparse
+}% \tabu@Xtype
+\def\tabu@Xcoef#1{\edef\tabu@temp{\tabu@temp#1}%
+ \afterassignment\tabu@Xc@ef \tabu@cnt\number\if-#10\fi
+}% \tabu@Xcoef
+\def\tabu@Xc@ef{\advance\tabucolX \tabu@temp\the\tabu@cnt\p@
+ \tabu@Xparse{}%
+}% \tabu@Xc@ef
+\def\tabu@Xm@th #1{\futurelet \@let@token \tabu@Xd@sp}
+\def\tabu@Xd@sp{\let\tabu@Xmath=$%
+ \ifx $\@let@token \def\tabu@Xdisp{\displaystyle}%
+ \expandafter\tabu@Xparse
+ \else \expandafter\tabu@Xparse\expandafter{\expandafter}%
+ \fi
+}% \tabu@Xd@sp
+\def\tabu@Xrewritten {%
+ \ifx \tabu@rewritten\@empty \def\tabu@rewritten{p}\fi
+ \ifdim \tabucolX<\z@ \tabu@negcoeftrue
+ \else\ifdim \tabucolX=\z@ \tabucolX \p@
+ \fi\fi
+ \edef\tabu@temp{{\the\tabu@Xcol}{\tabu@strippt\tabucolX}}%
+ \edef\tabu@Xcoefs{\tabu@Xcoefs \tabu@ \tabu@temp}%
+ \edef\tabu@rewritten ##1##2{\def\noexpand\tabu@rewritten{%
+ >{\tabu@Xlcr \ifx$\tabu@Xmath$\tabu@Xdisp\fi ##1}%
+ \tabu@rewritten {\tabu@hsize \tabu@temp}%
+ <{##2\ifx$\tabu@Xmath$\fi}}%
+ }\tabu@rewritten
+}% \tabu@Xrewritten
+\def\tabu@hsize #1#2{%
+ \ifdim #2\p@<\z@
+ \ifdim \tabucolX=\maxdimen \tabu@wd{#1}\else
+ \ifdim \tabu@wd{#1}<-#2\tabucolX \tabu@wd{#1}\else -#2\tabucolX\fi
+ \fi
+ \else #2\tabucolX
+ \fi
+}% \tabu@hsize
+%% \usetabu and \preamble: rewritting process ---------------------
+\tabu@privatecolumntype \usetabu [1]{%
+ \ifx\\#1\\\tabu@saveerr{}\else
+ \@ifundefined{tabu@saved@\string#1}
+ {\tabu@saveerr{#1}}
+ {\let\tabu@rewriteX \tabu@rewriteXrestore
+ \csname tabu@saved@\string#1\expandafter\endcsname\expandafter\@ne}%
+ \fi
+}% \NC@rewrite@\usetabu
+\tabu@privatecolumntype \preamble [1]{%
+ \ifx\\#1\\\tabu@saveerr{}\else
+ \@ifundefined{tabu@saved@\string#1}
+ {\tabu@saveerr{#1}}
+ {\csname tabu@saved@\string#1\expandafter\endcsname\expandafter\z@}%
+ \fi
+}% \NC@rewrite@\preamble
+%% Controlling the rewritting process -------------------------------
+\tabu@newcolumntype \tabu@rewritefirst{%
+ \iftabu@long \aftergroup \tabu@longpream % <the whole implementation is here !>
+ \else \aftergroup \tabu@pream
+ \fi
+ \let\tabu@ \relax \let\tabu@hsize \relax
+ \let\tabu@Xcoefs \@empty \let\tabu@savels \relax
+ \tabu@Xcol \z@ \tabu@cnt \tw@
+ \gdef\tabu@mkpreambuffer{\tabu@{}}\tabu@measuringfalse
+ \global\setbox\@arstrutbox \box\@arstrutbox
+ \NC@list{\NC@do *}\tabu@textbar \tabu@lines
+ \NC@list\expandafter{\the\NC@list \NC@do X}%
+ \iftabu@siunitx % <siunitx S and s columns>
+ \NC@list\expandafter{\the\NC@list \NC@do S\NC@do s}\fi
+ \NC@list\expandafter{\the\expandafter\NC@list \tabu@highprioritycolumns}%
+ \expandafter\def\expandafter\tabu@NC@list\expandafter{%
+ \the\expandafter\NC@list \tabu@NC@list}% % * | X S <original>
+ \NC@list\expandafter{\expandafter \NC@do \expandafter\usetabu
+ \expandafter \NC@do \expandafter\preamble
+ \the\NC@list \NC@do \tabu@rewritemiddle
+ \NC@do \tabu@rewritelast}%
+ \tabu@savedecl
+ \tabu@privatecolumns
+ \edef\tabu@prev{\the\@temptokena}\NC@find \tabu@rewritemiddle
+}% NC@rewrite@\tabu@rewritefirst
+\tabu@newcolumntype \tabu@rewritemiddle{%
+ \edef\tabu@temp{\the\@temptokena}\NC@find \tabu@rewritelast
+}% \NC@rewrite@\tabu@rewritemiddle
+\tabu@newcolumntype \tabu@rewritelast{%
+ \ifx \tabu@temp\tabu@prev \advance\tabu@cnt \m@ne
+ \NC@list\expandafter{\tabu@NC@list \NC@do \tabu@rewritemiddle
+ \NC@do \tabu@rewritelast}%
+ \else \let\tabu@prev\tabu@temp
+ \fi
+ \ifcase \tabu@cnt \expandafter\tabu@endrewrite
+ \else \expandafter\NC@find \expandafter\tabu@rewritemiddle
+ \fi
+}% \NC@rewrite@\tabu@rewritelast
+%% Choosing the strategy --------------------------------------------
+\def\tabu@endrewrite {%
+ \let\tabu@temp \NC@find
+ \ifx \@arrayright\relax \let\@arrayright \@empty \fi
+ \count@=%
+ \ifx \@finalstrut\tabu@finalstrut \z@ % outer in mode 0 print
+ \iftabu@measuring
+ \xdef\tabu@mkpreambuffer{\tabu@mkpreambuffer
+ \tabu@target \csname tabu@\the\tabu@nested.T\endcsname
+ \tabucolX \csname tabu@\the\tabu@nested.X\endcsname
+ \edef\@halignto {\ifx\@arrayright\@empty to\tabu@target\fi}}%
+ \fi
+ \else\iftabu@measuring 4 % X columns
+ \xdef\tabu@mkpreambuffer{\tabu@{\tabu@mkpreambuffer
+ \tabu@target \the\tabu@target
+ \tabu@spreadtarget \the\tabu@spreadtarget}%
+ \def\noexpand\tabu@Xcoefs{\tabu@Xcoefs}%
+ \edef\tabu@halignto{\ifx \@arrayright\@empty to\tabu@target\fi}}%
+ \let\tabu@Xcoefs \relax
+ \else\ifcase\tabu@nested \thr@@ % outer, no X
+ \global\let\tabu@afterendpar \relax
+ \else \@ne % inner, no X, outer in mode 1 or 2
+ \fi
+ \ifdefined\tabu@usetabu
+ \else \ifdim\tabu@target=\z@
+ \else \let\tabu@temp \tabu@extracolsep
+ \fi\fi
+ \fi
+ \fi
+ \xdef\tabu@mkpreambuffer{\count@ \the\count@ \tabu@mkpreambuffer}%
+ \tabu@temp
+}% \tabu@endrewrite
+\def\tabu@extracolsep{\@defaultunits \expandafter\let
+ \expandafter\tabu@temp \expandafter=\the\@temptokena \relax\@nnil
+ \ifx \tabu@temp\@sptoken
+ \expandafter\tabu@gobblespace \expandafter\tabu@extracolsep
+ \else
+ \edef\tabu@temp{\noexpand\NC@find
+ \if |\noexpand\tabu@temp @%
+ \else\if !\noexpand\tabu@temp @%
+ \else !%
+ \fi\fi
+ {\noexpand\extracolsep\noexpand\@flushglue}}%
+ \fi
+ \tabu@temp
+}% \tabu@extrac@lsep
+%% Implementing the strategy ----------------------------------------
+\long\def\tabu@pream #1\@preamble {%
+ \let\tabu@ \tabu@@ \tabu@mkpreambuffer \tabu@aftergroupcleanup
+ \NC@list\expandafter {\tabu@NC@list}% in case of nesting...
+ \ifdefined\tabu@usetabu \tabu@usetabu \tabu@target \z@ \fi
+ \let\tabu@savedpreamble \@preamble
+ \global\let\tabu@elapsedtime \relax
+ \tabu@thebody ={#1\tabu@aftergroupcleanup}%
+ \tabu@thebody =\expandafter{\the\expandafter\tabu@thebody
+ \@preamble}%
+ \edef\tabuthepreamble {\the\tabu@thebody}% ( no @ allowed for \scantokens )
+ \tabu@select
+}% \tabu@pream
+\long\def\tabu@longpream #1\LT@bchunk #2\LT@bchunk{%
+ \let\tabu@ \tabu@@ \tabu@mkpreambuffer \tabu@aftergroupcleanup
+ \NC@list\expandafter {\tabu@NC@list}% in case of nesting...
+ \let\tabu@savedpreamble \@preamble
+ \global\let\tabu@elapsedtime \relax
+ \tabu@thebody ={#1\LT@bchunk #2\tabu@aftergroupcleanup \LT@bchunk}%
+ \edef\tabuthepreamble {\the\tabu@thebody}% ( no @ allowed for \scantokens )
+ \tabu@select
+}% \tabu@longpream
+\def\tabu@select {%
+ \ifnum\tabu@nested>\z@ \tabuscantokensfalse \fi
+ \ifnum \count@=\@ne \iftabu@measuring \count@=\tw@ \fi\fi
+ \ifcase \count@
+ \global\let\tabu@elapsedtime \relax
+ \tabu@seteverycr
+ \expandafter \tabuthepreamble % vertical adjustment (inheritated from outer)
+ \or % exit in vertical measure + struts per cell because no X and outer in mode 3
+ \tabu@evr{\tabu@verticalinit}\tabu@celllalign@def{\tabu@verticalmeasure}%
+ \def\tabu@cellralign{\tabu@verticalspacing}%
+ \tabu@seteverycr
+ \expandafter \tabuthepreamble
+ \or % exit without measure because no X and outer in mode 4
+ \tabu@evr{}\tabu@celllalign@def{}\let\tabu@cellralign \@empty
+ \tabu@seteverycr
+ \expandafter \tabuthepreamble
+ \else % needs trials
+ \tabu@evr{}\tabu@celllalign@def{}\let\tabu@cellralign \@empty
+ \tabu@savecounters
+ \expandafter \tabu@setstrategy
+ \fi
+}% \tabu@select
+\def\tabu@@ {\gdef\tabu@mkpreambuffer}
+%% Protections to set up before trials ------------------------------
+\def\tabu@setstrategy {\begingroup % <trials group>
+ \tabu@trialh@@k \tabu@cnt \z@ % number of trials
+ \hbadness \@M \let\hbadness \@tempcnta
+ \hfuzz \maxdimen \let\hfuzz \@tempdima
+ \let\write \tabu@nowrite\let\GenericError \tabu@GenericError
+ \let\savetabu \@gobble \let\tabudefaulttarget \linewidth
+ \let\@footnotetext \@gobble \let\@xfootnote \tabu@xfootnote
+ \let\color \tabu@nocolor\let\rowcolor \tabu@norowcolor
+ \let\tabu@aftergroupcleanup \relax % only after the last trial
+ \tabu@mkpreambuffer
+ \ifnum \count@>\thr@@ \let\@halignto \@empty \tabucolX@init
+ \def\tabu@lasttry{\m@ne\p@}\fi
+ \begingroup \iffalse{\fi \ifnum0=`}\fi
+ \toks@{}\def\tabu@stack{b}\iftabuscantokens \endlinechar=10 \obeyspaces \fi %
+ \tabu@collectbody \tabu@strategy %
+}% \tabu@setstrategy
+\def\tabu@savecounters{%
+ \def\@elt ##1{\csname c@##1\endcsname\the\csname c@##1\endcsname}%
+ \edef\tabu@clckpt {\begingroup \globaldefs=\@ne \cl@@ckpt \endgroup}\let\@elt \relax
+}% \tabu@savecounters
+\def\tabucolX@init {% \tabucolX <= \tabu@target / (sum coefs > 0)
+ \dimen@ \z@ \tabu@Xsum \z@ \tabucolX \z@ \let\tabu@ \tabu@Xinit \tabu@Xcoefs
+ \ifdim \dimen@>\z@
+ \@tempdima \dimexpr \tabu@target *\p@/\dimen@ + \tabu@hfuzz\relax
+ \ifdim \tabucolX<\@tempdima \tabucolX \@tempdima \fi
+ \fi
+}% \tabucolX@init
+\def\tabu@Xinit #1#2{\tabu@Xcol #1 \advance \tabu@Xsum
+ \ifdim #2\p@>\z@ #2\p@ \advance\dimen@ #2\p@
+ \else -#2\p@ \tabu@negcoeftrue
+ \@tempdima \dimexpr \tabu@target*\p@/\dimexpr-#2\p@\relax \relax
+ \ifdim \tabucolX<\@tempdima \tabucolX \@tempdima \fi
+ \tabu@wddef{#1}{0pt}%
+ \fi
+}% \tabu@Xinit
+%% Collecting the environment body ----------------------------------
+\long\def\tabu@collectbody #1#2\end #3{%
+ \edef\tabu@stack{\tabu@pushbegins #2\begin\end\expandafter\@gobble\tabu@stack}%
+ \ifx \tabu@stack\@empty
+ \toks@\expandafter{\expandafter\tabu@thebody\expandafter{\the\toks@ #2}%
+ \def\tabu@end@envir{\end{#3}}%
+ \iftabuscantokens
+ \iftabu@long \def\tabu@endenvir {\end{#3}\tabu@gobbleX}%
+ \else \def\tabu@endenvir {\let\endarray \@empty
+ \end{#3}\tabu@gobbleX}%
+ \fi
+ \else \def\tabu@endenvir {\end{#3}}\fi}%
+ \let\tabu@collectbody \tabu@endofcollect
+ \else\def\tabu@temp{#3}%
+ \ifx \tabu@temp\@empty \toks@\expandafter{\the\toks@ #2\end }%
+ \else \ifx\tabu@temp\tabu@@spxiii \toks@\expandafter{\the\toks@ #2\end #3}%
+ \else \ifx\tabu@temp\tabu@X \toks@\expandafter{\the\toks@ #2\end #3}%
+ \else \toks@\expandafter{\the\toks@ #2\end{#3}}%
+ \fi\fi\fi
+ \fi
+ \tabu@collectbody{#1}%
+}% \tabu@collectbody
+\long\def\tabu@pushbegins#1\begin#2{\ifx\end#2\else b\expandafter\tabu@pushbegins\fi}%
+\def\tabu@endofcollect #1{\ifnum0=`{}\fi
+ \expandafter\endgroup \the\toks@ #1%
+}% \tabu@endofcollect
+%% The trials: switching between strategies -------------------------
+\def\tabu@strategy {\relax % stops \count@ assignment !
+ \ifcase\count@ % case 0 = print with vertical adjustment (outer is finished)
+ \expandafter \tabu@endoftrials
+ \or % case 1 = exit in vertical measure (outer in mode 3)
+ \expandafter\xdef\csname tabu@\the\tabu@nested.T\endcsname{\the\tabu@target}%
+ \expandafter\xdef\csname tabu@\the\tabu@nested.X\endcsname{\the\tabucolX}%
+ \expandafter \tabu@endoftrials
+ \or % case 2 = exit with a rule replacing the table (outer in mode 4)
+ \expandafter \tabu@quickend
+ \or % case 3 = outer is in mode 3 because of no X
+ \begingroup
+ \tabu@evr{\tabu@verticalinit}\tabu@celllalign@def{\tabu@verticalmeasure}%
+ \def\tabu@cellralign{\tabu@verticalspacing}%
+ \expandafter \tabu@measuring
+ \else % case 4 = horizontal measure
+ \begingroup
+ \global\let\tabu@elapsedtime \tabu@message@etime
+ \long\def\multicolumn##1##2##3{\multispan{##1}}%
+ \let\tabu@startpboxORI \@startpbox
+ \iftabu@spread
+ \def\tabu@naturalXmax {\z@}%
+ \let\tabu@naturalXmin \tabu@naturalXmax
+ \tabu@evr{\global\tabu@naturalX \z@}%
+ \let\@startpbox \tabu@startpboxmeasure
+ \else\iftabu@negcoef
+ \let\@startpbox \tabu@startpboxmeasure
+ \else \let\@startpbox \tabu@startpboxquick
+ \fi\fi
+ \expandafter \tabu@measuring
+ \fi
+}% \tabu@strategy
+\def\tabu@measuring{\expandafter \tabu@trial \expandafter
+ \count@ \the\count@ \tabu@endtrial
+}% \tabu@measuring
+\def\tabu@trial{\iftabu@long \tabu@longtrial \else \tabu@shorttrial \fi}
+\def\tabu@shorttrial {\setbox\tabu@box \hbox\bgroup \tabu@seteverycr
+ \ifx \tabu@savecounters\relax \else
+ \let\tabu@savecounters \relax \tabu@clckpt \fi
+ $\iftabuscantokens \tabu@rescan \else \expandafter\@secondoftwo \fi
+ \expandafter{\expandafter \tabuthepreamble
+ \the\tabu@thebody
+ \csname tabu@adl@endtrial\endcsname
+ \endarray}$\egroup % got \tabu@box
+}% \tabu@shorttrial
+\def\tabu@longtrial {\setbox\tabu@box \hbox\bgroup \tabu@seteverycr
+ \ifx \tabu@savecounters\relax \else
+ \let\tabu@savecounters \relax \tabu@clckpt \fi
+ \iftabuscantokens \tabu@rescan \else \expandafter\@secondoftwo \fi
+ \expandafter{\expandafter \tabuthepreamble
+ \the\tabu@thebody
+ \tabuendlongtrial}\egroup % got \tabu@box
+}% \tabu@longtrial
+\def\tabuendlongtrial{% no @ allowed for \scantokens
+ \LT@echunk \global\setbox\@ne \hbox{\unhbox\@ne}\kern\wd\@ne
+ \LT@get@widths
+}% \tabuendlongtrial
+\def\tabu@adl@endtrial{% <arydshln in nested trials - problem for global column counters!>
+ \crcr \noalign{\global\adl@ncol \tabu@nbcols}}% anything global is crap, junky and fails !
+\def\tabu@seteverycr {\tabu@reset
+ \everycr \expandafter{\the\everycr \tabu@everycr}%
+ \let\everycr \tabu@noeverycr % <for ialign>
+}% \tabu@seteverycr
+\def\tabu@noeverycr{{\aftergroup\tabu@restoreeverycr \afterassignment}\toks@}
+\def\tabu@restoreeverycr {\let\everycr \tabu@@everycr}
+\def\tabu@everycr {\iftabu@everyrow \noalign{\tabu@everyrow}\fi}
+\def\tabu@endoftrials {%
+ \iftabuscantokens \expandafter\@firstoftwo
+ \else \expandafter\@secondoftwo
+ \fi
+ {\expandafter \tabu@closetrialsgroup \expandafter
+ \tabu@rescan \expandafter{%
+ \expandafter\tabuthepreamble
+ \the\expandafter\tabu@thebody
+ \iftabu@long \else \endarray \fi}}
+ {\expandafter\tabu@closetrialsgroup \expandafter
+ \tabuthepreamble
+ \the\tabu@thebody}%
+ \tabu@endenvir % Finish !
+}% \tabu@endoftrials
+\def\tabu@closetrialsgroup {%
+ \toks@\expandafter{\tabu@endenvir}%
+ \edef\tabu@bufferX{\endgroup
+ \tabucolX \the\tabucolX
+ \tabu@target \the\tabu@target
+ \tabu@cnt \the\tabu@cnt
+ \def\noexpand\tabu@endenvir{\the\toks@}%
+ %Quid de \@halignto = \tabu@halignto ??
+ }% \tabu@bufferX
+ \tabu@bufferX
+ \ifcase\tabu@nested % print out (outer in mode 0)
+ \global\tabu@cnt \tabu@cnt
+ \tabu@evr{\tabu@verticaldynamicadjustment}%
+ \tabu@celllalign@def{\everypar{}}\let\tabu@cellralign \@empty
+ \let\@finalstrut \tabu@finalstrut
+ \else % vertical measure of nested tabu
+ \tabu@evr{\tabu@verticalinit}%
+ \tabu@celllalign@def{\tabu@verticalmeasure}%
+ \def\tabu@cellralign{\tabu@verticalspacing}%
+ \fi
+ \tabu@clckpt \let\@halignto \tabu@halignto
+ \let\@halignto \@empty
+ \tabu@seteverycr
+ \ifdim \tabustrutrule>\z@ \ifnum\tabu@nested=\z@
+ \setbox\@arstrutbox \box\voidb@x % force \@arstrutbox to be rebuilt (visible struts)
+ \fi\fi
+}% \tabu@closetrialsgroup
+\def\tabu@quickend {\expandafter \endgroup \expandafter
+ \tabu@target \the\tabu@target \tabu@quickrule
+ \let\endarray \relax \tabu@endenvir
+}% \tabu@quickend
+\def\tabu@endtrial {\relax % stops \count@ assignment !
+ \ifcase \count@ \tabu@err % case 0 = impossible here
+ \or \tabu@err % case 1 = impossible here
+ \or \tabu@err % case 2 = impossible here
+ \or % case 3 = outer goes into mode 0
+ \def\tabu@bufferX{\endgroup}\count@ \z@
+ \else % case 4 = outer goes into mode 3
+ \iftabu@spread \tabu@spreadarith % inner into mode 1 (outer in mode 3)
+ \else \tabu@arith % or 2 (outer in mode 4)
+ \fi
+ \count@=%
+ \ifcase\tabu@nested \thr@@ % outer goes into mode 3
+ \else\iftabu@measuring \tw@ % outer is in mode 4
+ \else \@ne % outer is in mode 3
+ \fi\fi
+ \edef\tabu@bufferX{\endgroup
+ \tabucolX \the\tabucolX
+ \tabu@target \the\tabu@target}%
+ \fi
+ \expandafter \tabu@bufferX \expandafter
+ \count@ \the\count@ \tabu@strategy
+}% \tabu@endtrial
+\def\tabu@err{\errmessage{(tabu) Internal impossible error! (\count@=\the\count@)}}
+%% The algorithms: compute the widths / stop or go on ---------------
+\def\tabu@arithnegcoef {%
+ \@tempdima \z@ \dimen@ \z@ \let\tabu@ \tabu@arith@negcoef \tabu@Xcoefs
+}% \tabu@arithnegcoef
+\def\tabu@arith@negcoef #1#2{%
+ \ifdim #2\p@>\z@ \advance\dimen@ #2\p@ % saturated by definition
+ \advance\@tempdima #2\tabucolX
+ \else
+ \ifdim -#2\tabucolX <\tabu@wd{#1}% c_i X < natural width <= \tabu@target-> saturated
+ \advance\dimen@ -#2\p@
+ \advance\@tempdima -#2\tabucolX
+ \else
+ \advance\@tempdima \tabu@wd{#1}% natural width <= c_i X => neutralised
+ \ifdim \tabu@wd{#1}<\tabu@target \else % neutralised
+ \advance\dimen@ -#2\p@ % saturated (natural width = tabu@target)
+ \fi
+ \fi
+ \fi
+}% \tabu@arith@negcoef
+\def\tabu@givespace #1#2{% here \tabu@DELTA < \z@
+ \ifdim \@tempdima=\z@
+ \tabu@wddef{#1}{\the\dimexpr -\tabu@DELTA*\p@/\tabu@Xsum}%
+ \else
+ \tabu@wddef{#1}{\the\dimexpr \tabu@hsize{#1}{#2}
+ *(\p@ -\tabu@DELTA*\p@/\@tempdima)/\p@\relax}%
+ \fi
+}% \tabu@givespace
+\def\tabu@arith {\advance\tabu@cnt \@ne
+ \ifnum \tabu@cnt=\@ne \tabu@message{\tabu@titles}\fi
+ \tabu@arithnegcoef
+ \@tempdimb \dimexpr \wd\tabu@box -\@tempdima \relax % <incompressible material>
+ \tabu@DELTA = \dimexpr \wd\tabu@box - \tabu@target \relax
+ \tabu@message{\tabu@message@arith}%
+ \ifdim \tabu@DELTA <\tabu@hfuzz
+ \ifdim \tabu@DELTA<\z@ % wd (tabu)<\tabu@target ?
+ \let\tabu@ \tabu@givespace \tabu@Xcoefs
+ \advance\@tempdima \@tempdimb \advance\@tempdima -\tabu@DELTA % for message
+ \else % already converged: nothing to do but nearly impossible...
+ \fi
+ \tabucolX \maxdimen
+ \tabu@measuringfalse
+ \else % need for narrower X columns
+ \tabucolX =\dimexpr (\@tempdima -\tabu@DELTA) *\p@/\tabu@Xsum \relax
+ \tabu@measuringtrue
+ \@whilesw \iftabu@measuring\fi {%
+ \advance\tabu@cnt \@ne
+ \tabu@arithnegcoef
+ \tabu@DELTA =\dimexpr \@tempdima+\@tempdimb -\tabu@target \relax % always < 0 here
+ \tabu@message{\tabu@header
+ \tabu@msgalign \tabucolX { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \@tempdima+\@tempdimb { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \tabu@target { }{ }{ }{ }{ }\@@
+ \tabu@msgalign@PT \dimen@ { }{}{}{}{}{}{}\@@
+ \ifdim -\tabu@DELTA<\tabu@hfuzz \tabu@spaces target ok\else
+ \tabu@msgalign \dimexpr -\tabu@DELTA *\p@/\dimen@ {}{}{}{}{}\@@
+ \fi}%
+ \ifdim -\tabu@DELTA<\tabu@hfuzz
+ \advance\@tempdima \@tempdimb % for message
+ \tabu@measuringfalse
+ \else
+ \advance\tabucolX \dimexpr -\tabu@DELTA *\p@/\dimen@ \relax
+ \fi
+ }%
+ \fi
+ \tabu@message{\tabu@message@reached}%
+ \edef\tabu@bufferX{\endgroup \tabu@cnt \the\tabu@cnt
+ \tabucolX \the\tabucolX
+ \tabu@target \the\tabu@target}%
+}% \tabu@arith
+\def\tabu@spreadarith {%
+ \dimen@ \z@ \@tempdima \tabu@naturalXmax \let\tabu@ \tabu@spread@arith \tabu@Xcoefs
+ \edef\tabu@naturalXmin {\the\dimexpr\tabu@naturalXmin*\dimen@/\p@}%
+ \@tempdimc =\dimexpr \wd\tabu@box -\tabu@naturalXmax+\tabu@naturalXmin \relax
+ \iftabu@measuring
+ \tabu@target =\dimexpr \@tempdimc+\tabu@spreadtarget \relax
+ \edef\tabu@bufferX{\endgroup \tabucolX \the\tabucolX \tabu@target\the\tabu@target}%
+ \else
+ \tabu@message{\tabu@message@spreadarith}%
+ \ifdim \dimexpr \@tempdimc+\tabu@spreadtarget >\tabu@target
+ \tabu@message{(tabu) spread
+ \ifdim \@tempdimc>\tabu@target useless here: default target used%
+ \else too large: reduced to fit default target\fi.}%
+ \else
+ \tabu@target =\dimexpr \@tempdimc+\tabu@spreadtarget \relax
+ \tabu@message{(tabu) spread: New target set to \the\tabu@target^^J}%
+ \fi
+ \begingroup \let\tabu@wddef \@gobbletwo
+ \@tempdimb \@tempdima
+ \tabucolX@init
+ \tabu@arithnegcoef
+ \wd\tabu@box =\dimexpr \wd\tabu@box +\@tempdima-\@tempdimb \relax
+ \expandafter\endgroup \expandafter\tabucolX \the\tabucolX
+ \tabu@arith
+ \fi
+}% \tabu@spreadarith
+\def\tabu@spread@arith #1#2{%
+ \ifdim #2\p@>\z@ \advance\dimen@ #2\p@
+ \else \advance\@tempdima \tabu@wd{#1}\relax
+ \fi
+}% \tabu@spread@arith
+%% Reporting in the .log file ---------------------------------------
+\def\tabu@message@defaulttarget{%
+ \ifnum\tabu@nested=\z@^^J(tabu) Default target:
+ \ifx\tabudefaulttarget\linewidth \string\linewidth
+ \ifdim \tabu@thetarget=\linewidth \else
+ -\the\dimexpr\linewidth-\tabu@thetarget\fi =
+ \else\ifx\tabudefaulttarget\linegoal\string\linegoal=
+ \fi\fi
+ \else (tabu) Default target (nested): \fi
+ \the\tabu@target \on@line
+ \ifnum\tabu@nested=\z@ , page \the\c@page\fi}
+\def\tabu@message@target {^^J(tabu) Target specified:
+ \the\tabu@target \on@line, page \the\c@page}
+\def\tabu@message@arith {\tabu@header
+ \tabu@msgalign \tabucolX { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \wd\tabu@box { }{ }{ }{ }{ }\@@
+ \tabu@msgalign \tabu@target { }{ }{ }{ }{ }\@@
+ \tabu@msgalign@PT \dimen@ { }{}{}{}{}{}{}\@@
+ \ifdim \tabu@DELTA<\tabu@hfuzz giving space\else
+ \tabu@msgalign \dimexpr (\@tempdima-\tabu@DELTA) *\p@/\tabu@Xsum -\tabucolX {}{}{}{}{}\@@
+ \fi
+}% \tabu@message@arith
+\def\tabu@message@spreadarith {\tabu@spreadheader
+ \tabu@msgalign \tabu@spreadtarget { }{ }{ }{ }{}\@@
+ \tabu@msgalign \wd\tabu@box { }{ }{ }{ }{}\@@
+ \tabu@msgalign -\tabu@naturalXmax { }{}{}{}{}\@@
+ \tabu@msgalign \tabu@naturalXmin { }{ }{ }{ }{}\@@
+ \tabu@msgalign \ifdim \dimexpr\@tempdimc>\tabu@target \tabu@target
+ \else \@tempdimc+\tabu@spreadtarget \fi
+ {}{}{}{}{}\@@}
+\def\tabu@message@negcoef #1#2{
+ \tabu@spaces\tabu@spaces\space * #1. X[\rem@pt#2]:
+ \space width = \tabu@wd {#1}
+ \expandafter\string\csname tabu@\the\tabu@nested.W\number#1\endcsname
+ \ifdim -\tabu@pt#2\tabucolX<\tabu@target
+ < \number-\rem@pt#2 X
+ = \the\dimexpr -\tabu@pt#2\tabucolX \relax
+ \else
+ <= \the\tabu@target\space < \number-\rem@pt#2 X\fi}
+\def\tabu@message@reached{\tabu@header
+ ******* Reached Target:
+ hfuzz = \tabu@hfuzz\on@line\space *******}
+\def\tabu@message@etime{\edef\tabu@stoptime{\the\pdfelapsedtime}%
+ \tabu@message{(tabu)\tabu@spaces Time elapsed during measure:
+ \the\numexpr(\tabu@stoptime-\tabu@starttime-32767)/65536\relax sec
+ \the\numexpr\numexpr(\tabu@stoptime-\tabu@starttime)
+ -\numexpr(\tabu@stoptime-\tabu@starttime-32767)/65536\relax*65536\relax
+ *1000/65536\relax ms \tabu@spaces(\the\tabu@cnt\space
+ cycle\ifnum\tabu@cnt>\@ne s\fi)^^J^^J}}
+\def\tabu@message@verticalsp {%
+ \ifdim \@tempdima>\tabu@ht
+ \ifdim \@tempdimb>\tabu@dp
+ \expandafter\expandafter\expandafter\string\tabu@ht =
+ \tabu@msgalign \@tempdima { }{ }{ }{ }{ }\@@
+ \expandafter\expandafter\expandafter\string\tabu@dp =
+ \tabu@msgalign \@tempdimb { }{ }{ }{ }{ }\@@^^J%
+ \else
+ \expandafter\expandafter\expandafter\string\tabu@ht =
+ \tabu@msgalign \@tempdima { }{ }{ }{ }{ }\@@^^J%
+ \fi
+ \else\ifdim \@tempdimb>\tabu@dp
+ \tabu@spaces\tabu@spaces\tabu@spaces
+ \expandafter\expandafter\expandafter\string\tabu@dp =
+ \tabu@msgalign \@tempdimb { }{ }{ }{ }{ }\@@^^J\fi
+ \fi
+}% \tabu@message@verticalsp
+\edef\tabu@spaces{\@spaces}
+\def\tabu@strippt{\expandafter\tabu@pt\the}
+{\@makeother\P \@makeother\T\lowercase{\gdef\tabu@pt #1PT{#1}}}
+\def\tabu@msgalign{\expandafter\tabu@msg@align\the\dimexpr}
+\def\tabu@msgalign@PT{\expandafter\tabu@msg@align\romannumeral-`\0\tabu@strippt}
+\def\do #1{%
+ \def\tabu@msg@align##1.##2##3##4##5##6##7##8##9\@@{%
+ \ifnum##1<10 #1 #1\else
+ \ifnum##1<100 #1 \else
+ \ifnum##1<\@m #1\fi\fi\fi
+ ##1.##2##3##4##5##6##7##8#1}%
+ \def\tabu@header{(tabu) \ifnum\tabu@cnt<10 #1\fi\the\tabu@cnt) }%
+ \def\tabu@titles{\ifnum \tabu@nested=\z@
+ (tabu) Try#1 #1 tabu X #1 #1 #1tabu Width #1 #1 Target
+ #1 #1 #1 Coefs #1 #1 #1 Update^^J\fi}%
+ \def\tabu@spreadheader{%
+ (tabu) Try#1 #1 Spread #1 #1 tabu Width #1 #1 #1 Nat. X #1 #1 #1 #1Nat. Min.
+ #1 New Target^^J%
+ (tabu) sprd}
+ \def\tabu@message@save {\begingroup
+ \def\x ####1{\tabu@msg@align ####1{ }{ }{ }{ }{}\@@}
+ \def\z ####1{\expandafter\x\expandafter{\romannumeral-`\0\tabu@strippt
+ \dimexpr####1\p@{ }{ }}}%
+ \let\color \relax \def\tabu@rulesstyle ####1####2{\detokenize{####1}}%
+ \let\CT@arc@ \relax \let\@preamble \@gobble
+ \let\tabu@savedpream \@firstofone
+ \let\tabu@savedparams \@firstofone
+ \def\tabu@target ####1\relax {(tabu) target #1 #1 #1 #1 #1 = \x{####1}^^J}%
+ \def\tabucolX ####1\relax {(tabu) X columns width#1 = \x{####1}^^J}%
+ \def\tabu@nbcols ####1\relax {(tabu) Number of columns: \z{####1}^^J}%
+ \def\tabu@aligndefault ####1{(tabu) Default alignment: #1 #1 ####1^^J}%
+ \def\col@sep ####1\relax {(tabu) column sep #1 #1 #1 = \x{####1}^^J}%
+ \def\arrayrulewidth ####1\relax{(tabu) arrayrulewidth #1 = \x{####1}}%
+ \def\doublerulesep ####1\relax { doublerulesep = \x{####1}^^J}%
+ \def\extratabsurround####1\relax{(tabu) extratabsurround = \x{####1}^^J}%
+ \def\extrarowheight ####1\relax{(tabu) extrarowheight #1 = \x{####1}}%
+ \def\extrarowdepth ####1\relax {extrarowdepth = \x{####1}^^J}%
+ \def\abovetabulinesep####1\relax{(tabu) abovetabulinesep=\x{####1} }%
+ \def\belowtabulinesep####1\relax{ belowtabulinesep=\x{####1}^^J}%
+ \def\arraystretch ####1{(tabu) arraystretch #1 #1 = \z{####1}^^J}%
+ \def\minrowclearance####1\relax{(tabu) minrowclearance #1 = \x{####1}^^J}%
+ \def\tabu@arc@L ####1{(tabu) taburulecolor #1 #1 = ####1^^J}%
+ \def\tabu@drsc@L ####1{(tabu) tabudoublerulecolor= ####1^^J}%
+ \def\tabu@evr@L ####1{(tabu) everyrow #1 #1 #1 #1 = \detokenize{####1}^^J}%
+ \def\tabu@ls@L ####1{(tabu) line style = \detokenize{####1}^^J}%
+ \def\NC@find ####1\@nil{(tabu) tabu preamble#1 #1 = \detokenize{####1}^^J}%
+ \def\tabu@wddef####1####2{(tabu) Natural width ####1 = \x{####2}^^J}%
+ \let\edef \@gobbletwo \let\def \@empty \let\let \@gobbletwo
+ \tabu@message{%
+ (tabu) \string\savetabu{\tabu@temp}: \on@line^^J%
+ \tabu@usetabu \@nil^^J}%
+ \endgroup}
+}\do{ }
+%% Measuring the natural width (varwidth) - store the results -------
+\def\tabu@startpboxmeasure #1{\bgroup % entering \vtop
+ \edef\tabu@temp{\expandafter\@secondoftwo \ifx\tabu@hsize #1\else\relax\fi}%
+ \ifodd 1\ifx \tabu@temp\@empty 0 \else % starts with \tabu@hsize ?
+ \iftabu@spread \else % if spread -> measure
+ \ifdim \tabu@temp\p@>\z@ 0 \fi\fi\fi% if coef>0 -> do not measure
+ \let\@startpbox \tabu@startpboxORI % restore immediately (nesting)
+ \tabu@measuringtrue % for the quick option...
+ \tabu@Xcol =\expandafter\@firstoftwo\ifx\tabu@hsize #1\fi
+ \ifdim \tabu@temp\p@>\z@ \ifdim \tabu@temp\tabucolX<\tabu@target
+ \tabu@target=\tabu@temp\tabucolX \fi\fi
+ \setbox\tabu@box \hbox \bgroup
+ \begin{varwidth}\tabu@target
+ \let\FV@ListProcessLine \tabu@FV@ListProcessLine % \hbox to natural width...
+ \narrowragged \arraybackslash \parfillskip \@flushglue
+ \ifdefined\pdfadjustspacing \pdfadjustspacing\z@ \fi
+ \bgroup \aftergroup\tabu@endpboxmeasure
+ \ifdefined \cellspacetoplimit \tabu@cellspacepatch \fi
+ \else \expandafter\@gobble
+ \tabu@startpboxquick{#1}% \@gobble \bgroup
+ \fi
+}% \tabu@startpboxmeasure
+\def\tabu@cellspacepatch{\def\bcolumn##1\@nil{}\let\ecolumn\@empty
+ \bgroup\color@begingroup}
+\def\tabu@endpboxmeasure {%
+ \@finalstrut \@arstrutbox
+ \end{varwidth}\egroup % <got my \tabu@box>
+ \ifdim \tabu@temp\p@ <\z@ % neg coef
+ \ifdim \tabu@wd\tabu@Xcol <\wd\tabu@box
+ \tabu@wddef\tabu@Xcol {\the\wd\tabu@box}%
+ \tabu@debug{\tabu@message@endpboxmeasure}%
+ \fi
+ \else % spread coef>0
+ \global\advance \tabu@naturalX \wd\tabu@box
+ \@tempdima =\dimexpr \wd\tabu@box *\p@/\dimexpr \tabu@temp\p@\relax \relax
+ \ifdim \tabu@naturalXmax <\tabu@naturalX
+ \xdef\tabu@naturalXmax {\the\tabu@naturalX}\fi
+ \ifdim \tabu@naturalXmin <\@tempdima
+ \xdef\tabu@naturalXmin {\the\@tempdima}\fi
+ \fi
+ \box\tabu@box \egroup % end of \vtop (measure) restore \tabu@target
+}% \tabu@endpboxmeasure
+\def\tabu@wddef #1{\expandafter\xdef
+ \csname tabu@\the\tabu@nested.W\number#1\endcsname}
+\def\tabu@wd #1{\csname tabu@\the\tabu@nested.W\number#1\endcsname}
+\def\tabu@message@endpboxmeasure{\tabu@spaces\tabu@spaces<-> % <-> save natural wd
+ \the\tabu@Xcol. X[\tabu@temp]:
+ target = \the\tabucolX \space
+ \expandafter\expandafter\expandafter\string\tabu@wd\tabu@Xcol
+ =\tabu@wd\tabu@Xcol
+}% \tabu@message@endpboxmeasure
+\def\tabu@startpboxquick {\bgroup
+ \let\@startpbox \tabu@startpboxORI % restore immediately
+ \let\tabu \tabu@quick % \begin is expanded before...
+ \expandafter\@gobble \@startpbox % gobbles \bgroup
+}% \tabu@startpboxquick
+\def\tabu@quick {\begingroup \iffalse{\fi \ifnum0=`}\fi
+ \toks@{}\def\tabu@stack{b}\tabu@collectbody \tabu@endquick
+}% \tabu@quick
+\def\tabu@endquick {%
+ \ifodd 1\ifx\tabu@end@envir\tabu@endtabu \else
+ \ifx\tabu@end@envir\tabu@endtabus \else 0\fi\fi\relax
+ \endgroup
+ \else \let\endtabu \relax
+ \tabu@end@envir
+ \fi
+}% \tabu@quick
+\def\tabu@endtabu {\end{tabu}}
+\def\tabu@endtabus {\end{tabu*}}
+%% Measuring the heights and depths - store the results -------------
+\def\tabu@verticalmeasure{\everypar{}%
+ \ifnum \currentgrouptype>12 % 14=semi-simple, 15=math shift group
+ \setbox\tabu@box =\hbox\bgroup
+ \let\tabu@verticalspacing \tabu@verticalsp@lcr
+ \d@llarbegin % after \hbox ...
+ \else
+ \edef\tabu@temp{\ifnum\currentgrouptype=5\vtop
+ \else\ifnum\currentgrouptype=12\vcenter
+ \else\vbox\fi\fi}%
+ \setbox\tabu@box \hbox\bgroup$\tabu@temp \bgroup
+ \let\tabu@verticalspacing \tabu@verticalsp@pmb
+ \fi
+}% \tabu@verticalmeasure
+\def\tabu@verticalsp@lcr{%
+ \d@llarend \egroup % <got my \tabu@box>
+ \@tempdima \dimexpr \ht\tabu@box+\abovetabulinesep
+ \@tempdimb \dimexpr \dp\tabu@box+\belowtabulinesep \relax
+ \ifdim\tabustrutrule>\z@ \tabu@debug{\tabu@message@verticalsp}\fi
+ \ifdim \tabu@ht<\@tempdima \tabu@htdef{\the\@tempdima}\fi
+ \ifdim \tabu@dp<\@tempdimb \tabu@dpdef{\the\@tempdimb}\fi
+ \noindent\vrule height\@tempdima depth\@tempdimb
+}% \tabu@verticalsp@lcr
+\def\tabu@verticalsp@pmb{% inserts struts as needed
+ \par \expandafter\egroup
+ \expandafter$\expandafter
+ \egroup \expandafter
+ \@tempdimc \the\prevdepth
+ \@tempdima \dimexpr \ht\tabu@box+\abovetabulinesep
+ \@tempdimb \dimexpr \dp\tabu@box+\belowtabulinesep \relax
+ \ifdim\tabustrutrule>\z@ \tabu@debug{\tabu@message@verticalsp}\fi
+ \ifdim \tabu@ht<\@tempdima \tabu@htdef{\the\@tempdima}\fi
+ \ifdim \tabu@dp<\@tempdimb \tabu@dpdef{\the\@tempdimb}\fi
+ \let\@finalstrut \@gobble
+ \hrule height\@tempdima depth\@tempdimb width\hsize
+%% \box\tabu@box
+}% \tabu@verticalsp@pmb
+
+\def\tabu@verticalinit{%
+ \ifnum \c@taburow=\z@ \tabu@rearstrut \fi % after \tabu@reset !
+ \advance\c@taburow \@ne
+ \tabu@htdef{\the\ht\@arstrutbox}\tabu@dpdef{\the\dp\@arstrutbox}%
+ \advance\c@taburow \m@ne
+}% \tabu@verticalinit
+\def\tabu@htdef {\expandafter\xdef \csname tabu@\the\tabu@nested.H\the\c@taburow\endcsname}
+\def\tabu@ht {\csname tabu@\the\tabu@nested.H\the\c@taburow\endcsname}
+\def\tabu@dpdef {\expandafter\xdef \csname tabu@\the\tabu@nested.D\the\c@taburow\endcsname}
+\def\tabu@dp {\csname tabu@\the\tabu@nested.D\the\c@taburow\endcsname}
+\def\tabu@verticaldynamicadjustment {%
+ \advance\c@taburow \@ne
+ \extrarowheight \dimexpr\tabu@ht - \ht\strutbox
+ \extrarowdepth \dimexpr\tabu@dp - \dp\strutbox
+ \let\arraystretch \@empty
+ \advance\c@taburow \m@ne
+}% \tabu@verticaldynamicadjustment
+\def\tabuphantomline{\crcr \noalign{%
+ {\globaldefs \@ne
+ \setbox\@arstrutbox \box\voidb@x
+ \let\tabu@@celllalign \tabu@celllalign
+ \let\tabu@@cellralign \tabu@cellralign
+ \let\tabu@@cellleft \tabu@cellleft
+ \let\tabu@@cellright \tabu@cellright
+ \let\tabu@@thevline \tabu@thevline
+ \let\tabu@celllalign \@empty
+ \let\tabu@cellralign \@empty
+ \let\tabu@cellright \@empty
+ \let\tabu@cellleft \@empty
+ \let\tabu@thevline \relax}%
+ \edef\tabu@temp{\tabu@multispan \tabu@nbcols{\noindent &}}%
+ \toks@\expandafter{\tabu@temp \noindent\tabu@everyrowfalse \cr
+ \noalign{\tabu@rearstrut
+ {\globaldefs\@ne
+ \let\tabu@celllalign \tabu@@celllalign
+ \let\tabu@cellralign \tabu@@cellralign
+ \let\tabu@cellleft \tabu@@cellleft
+ \let\tabu@cellright \tabu@@cellright
+ \let\tabu@thevline \tabu@@thevline}}}%
+ \expandafter}\the\toks@
+}% \tabuphantomline
+%% \firsthline and \lasthline corrections ---------------------------
+\def\tabu@firstline {\tabu@hlineAZ \tabu@firsthlinecorrection {}}
+\def\tabu@firsthline{\tabu@hlineAZ \tabu@firsthlinecorrection \hline}
+\def\tabu@lastline {\tabu@hlineAZ \tabu@lasthlinecorrection {}}
+\def\tabu@lasthline {\tabu@hlineAZ \tabu@lasthlinecorrection \hline}
+\def\tabu@hline {% replaces \hline if no colortbl (see \AtBeginDocument)
+ \noalign{\ifnum0=`}\fi
+ {\CT@arc@\hrule height\arrayrulewidth}%
+ \futurelet \tabu@temp \tabu@xhline
+}% \tabu@hline
+\def\tabu@xhline{%
+ \ifx \tabu@temp \hline
+ {\ifx \CT@drsc@\relax \vskip
+ \else\ifx \CT@drsc@\@empty \vskip
+ \else \CT@drsc@\hrule height
+ \fi\fi
+ \doublerulesep}%
+ \fi
+ \ifnum0=`{\fi}%
+}% \tabu@xhline
+\def\tabu@hlineAZ #1#2{\noalign{\ifnum0=`}\fi \dimen@ \z@ \count@ \z@
+ \toks@{}\def\tabu@hlinecorrection{#1}\def\tabu@temp{#2}%
+ \tabu@hlineAZsurround
+}% \tabu@hlineAZ
+\newcommand*\tabu@hlineAZsurround[1][\extratabsurround]{%
+ \extratabsurround #1\let\tabucline \tabucline@scan
+ \let\hline \tabu@hlinescan \let\firsthline \hline
+ \let\cline \tabu@clinescan \let\lasthline \hline
+ \expandafter \futurelet \expandafter \tabu@temp
+ \expandafter \tabu@nexthlineAZ \tabu@temp
+}% \tabu@hlineAZsurround
+\def\tabu@hlinescan {\tabu@thick \arrayrulewidth \tabu@xhlineAZ \hline}
+\def\tabu@clinescan #1{\tabu@thick \arrayrulewidth \tabu@xhlineAZ {\cline{#1}}}
+\def\tabucline@scan{\@testopt \tabucline@sc@n {}}
+\def\tabucline@sc@n #1[#2]{\tabu@xhlineAZ {\tabucline[{#1}]{#2}}}
+\def\tabu@nexthlineAZ{%
+ \ifx \tabu@temp\hline \else
+ \ifx \tabu@temp\cline \else
+ \ifx \tabu@temp\tabucline \else
+ \tabu@hlinecorrection
+ \fi\fi\fi
+}% \tabu@nexthlineAZ
+\def\tabu@xhlineAZ #1{%
+ \toks@\expandafter{\the\toks@ #1}%
+ \@tempdimc \tabu@thick % The last line width
+ \ifcase\count@ \@tempdimb \tabu@thick % The first line width
+ \else \advance\dimen@ \dimexpr \tabu@thick+\doublerulesep \relax
+ \fi
+ \advance\count@ \@ne \futurelet \tabu@temp \tabu@nexthlineAZ
+}% \tabu@xhlineAZ
+\def\tabu@firsthlinecorrection{% \count@ = number of \hline -1
+ \@tempdima \dimexpr \ht\@arstrutbox+\dimen@
+ \edef\firsthline{% <local in \noalign>
+ \omit \hbox to\z@{\hss{\noexpand\tabu@DBG{yellow}\vrule
+ height \the\dimexpr\@tempdima+\extratabsurround
+ depth \dp\@arstrutbox
+ width \tabustrutrule}\hss}\cr
+ \noalign{\vskip -\the\dimexpr \@tempdima+\@tempdimb
+ +\dp\@arstrutbox \relax}%
+ \the\toks@
+ }\ifnum0=`{\fi
+ \expandafter}\firsthline % we are then !
+}% \tabu@firsthlinecorrection
+\def\tabu@lasthlinecorrection{%
+ \@tempdima \dimexpr \dp\@arstrutbox+\dimen@+\@tempdimb+\@tempdimc
+ \edef\lasthline{% <local in \noalign>
+ \the\toks@
+ \noalign{\vskip -\the\dimexpr\dimen@+\@tempdimb+\dp\@arstrutbox}%
+ \omit \hbox to\z@{\hss{\noexpand\tabu@DBG{yellow}\vrule
+ depth \the\dimexpr \dp\@arstrutbox+\@tempdimb+\dimen@
+ +\extratabsurround-\@tempdimc
+ height \z@
+ width \tabustrutrule}\hss}\cr
+ }\ifnum0=`{\fi
+ \expandafter}\lasthline % we are then !
+}% \tabu@lasthlinecorrection
+\def\tabu@LT@@hline{%
+ \ifx\LT@next\hline
+ \global\let\LT@next \@gobble
+ \ifx \CT@drsc@\relax
+ \gdef\CT@LT@sep{%
+ \noalign{\penalty-\@medpenalty\vskip\doublerulesep}}%
+ \else
+ \gdef\CT@LT@sep{%
+ \multispan\LT@cols{%
+ \CT@drsc@\leaders\hrule\@height\doublerulesep\hfill}\cr}%
+ \fi
+ \else
+ \global\let\LT@next\empty
+ \gdef\CT@LT@sep{%
+ \noalign{\penalty-\@lowpenalty\vskip-\arrayrulewidth}}%
+ \fi
+ \ifnum0=`{\fi}%
+ \multispan\LT@cols
+ {\CT@arc@\leaders\hrule\@height\arrayrulewidth\hfill}\cr
+ \CT@LT@sep
+ \multispan\LT@cols
+ {\CT@arc@\leaders\hrule\@height\arrayrulewidth\hfill}\cr
+ \noalign{\penalty\@M}%
+ \LT@next
+}% \tabu@LT@@hline
+%% Horizontal lines : \tabucline ------------------------------------
+\let\tabu@start \@tempcnta
+\let\tabu@stop \@tempcntb
+\newcommand*\tabucline{\noalign{\ifnum0=`}\fi \tabu@cline}
+\newcommand*\tabu@cline[2][]{\tabu@startstop{#2}%
+ \ifnum \tabu@stop<\z@ \toks@{}%
+ \else \tabu@clinearg{#1}\tabu@thestyle
+ \edef\tabucline{\toks@{%
+ \ifnum \tabu@start>\z@ \omit
+ \tabu@multispan\tabu@start {\span\omit}&\fi
+ \omit \tabu@multispan\tabu@stop {\span\omit}%
+ \tabu@thehline\cr
+ }}\tabucline
+ \tabu@tracinglines{(tabu:tabucline) Style: #1^^J\the\toks@^^J^^J}%
+ \fi
+ \futurelet \tabu@temp \tabu@xcline
+}% \tabu@cline
+\def\tabu@clinearg #1{%
+ \ifx\\#1\\\let\tabu@thestyle \tabu@ls@
+ \else \@defaultunits \expandafter\let\expandafter\@tempa
+ \romannumeral-`\0#1\relax \@nnil
+ \ifx \hbox\@tempa \tabu@clinebox{#1}%
+ \else\ifx \box\@tempa \tabu@clinebox{#1}%
+ \else\ifx \vbox\@tempa \tabu@clinebox{#1}%
+ \else\ifx \vtop\@tempa \tabu@clinebox{#1}%
+ \else\ifx \copy\@tempa \tabu@clinebox{#1}%
+ \else\ifx \leaders\@tempa \tabu@clineleads{#1}%
+ \else\ifx \cleaders\@tempa \tabu@clineleads{#1}%
+ \else\ifx \xleaders\@tempa \tabu@clineleads{#1}%
+ \else\tabu@getline {#1}%
+ \fi\fi\fi\fi\fi\fi\fi\fi
+ \fi
+}% \tabu@clinearg
+\def\tabu@clinebox #1{\tabu@clineleads{\xleaders#1\hss}}
+\def\tabu@clineleads #1{%
+ \let\tabu@thestyle \relax \let\tabu@leaders \@undefined
+ \gdef\tabu@thehrule{#1}}
+\def\tabu@thehline{\begingroup
+ \ifdefined\tabu@leaders
+ \noexpand\tabu@thehleaders
+ \else \noexpand\tabu@thehrule
+ \fi \endgroup
+}% \tabu@thehline
+\def\tabu@xcline{%
+ \ifx \tabu@temp\tabucline
+ \toks@\expandafter{\the\toks@ \noalign
+ {\ifx\CT@drsc@\relax \vskip
+ \else \CT@drsc@\hrule height
+ \fi
+ \doublerulesep}}%
+ \fi
+ \tabu@docline
+}% \tabu@xcline
+\def\tabu@docline {\ifnum0=`{\fi \expandafter}\the\toks@}
+\def\tabu@docline@evr {\xdef\tabu@doclineafter{\the\toks@}%
+ \ifnum0=`{\fi}\aftergroup\tabu@doclineafter}
+\def\tabu@multispan #1#2{%
+ \ifnum\numexpr#1>\@ne #2\expandafter\tabu@multispan
+ \else \expandafter\@gobbletwo
+ \fi {#1-1}{#2}%
+}% \tabu@multispan
+\def\tabu@startstop #1{\tabu@start@stop #1\relax 1-\tabu@nbcols \@nnil}
+\def\tabu@start@stop #1-#2\@nnil{%
+ \@defaultunits \tabu@start\number 0#1\relax \@nnil
+ \@defaultunits \tabu@stop \number 0#2\relax \@nnil
+ \tabu@stop \ifnum \tabu@start>\tabu@nbcols \m@ne
+ \else\ifnum \tabu@stop=\z@ \tabu@nbcols
+ \else\ifnum \tabu@stop>\tabu@nbcols \tabu@nbcols
+ \else \tabu@stop
+ \fi\fi\fi
+ \advance\tabu@start \m@ne
+ \ifnum \tabu@start>\z@ \advance\tabu@stop -\tabu@start \fi
+}% \tabu@start@stop
+%% Numbers: siunitx S columns (and \tabudecimal) -------------------
+\def\tabu@tabudecimal #1{%
+ \def\tabu@decimal{#1}\@temptokena{}%
+ \let\tabu@getdecimal@ \tabu@getdecimal@ignorespaces
+ \tabu@scandecimal
+}% \tabu@tabudecimal
+\def\tabu@scandecimal{\futurelet \tabu@temp \tabu@getdecimal@}
+\def\tabu@skipdecimal#1{#1\tabu@scandecimal}
+\def\tabu@getdecimal@ignorespaces{%
+ \ifcase 0\ifx\tabu@temp\ignorespaces\else
+ \ifx\tabu@temp\@sptoken1\else
+ 2\fi\fi\relax
+ \let\tabu@getdecimal@ \tabu@getdecimal
+ \expandafter\tabu@skipdecimal
+ \or \expandafter\tabu@gobblespace\expandafter\tabu@scandecimal
+ \else \expandafter\tabu@skipdecimal
+ \fi
+}% \tabu@getdecimal@ignorespaces
+\def\tabu@get@decimal#1{\@temptokena\expandafter{\the\@temptokena #1}%
+ \tabu@scandecimal}
+\def\do#1{%
+ \def\tabu@get@decimalspace#1{%
+ \@temptokena\expandafter{\the\@temptokena #1}\tabu@scandecimal}%
+}\do{ }
+\let\tabu@@tabudecimal \tabu@tabudecimal
+\def\tabu@getdecimal{%
+ \ifcase 0\ifx 0\tabu@temp\else
+ \ifx 1\tabu@temp\else
+ \ifx 2\tabu@temp\else
+ \ifx 3\tabu@temp\else
+ \ifx 4\tabu@temp\else
+ \ifx 5\tabu@temp\else
+ \ifx 6\tabu@temp\else
+ \ifx 7\tabu@temp\else
+ \ifx 8\tabu@temp\else
+ \ifx 9\tabu@temp\else
+ \ifx .\tabu@temp\else
+ \ifx ,\tabu@temp\else
+ \ifx -\tabu@temp\else
+ \ifx +\tabu@temp\else
+ \ifx e\tabu@temp\else
+ \ifx E\tabu@temp\else
+ \ifx\tabu@cellleft\tabu@temp1\else
+ \ifx\ignorespaces\tabu@temp1\else
+ \ifx\@sptoken\tabu@temp2\else
+ 3\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\relax
+ \expandafter\tabu@get@decimal
+ \or \expandafter\tabu@skipdecimal
+ \or \expandafter\tabu@get@decimalspace
+ \else\expandafter\tabu@printdecimal
+ \fi
+}% \tabu@getdecimal
+\def\tabu@printdecimal{%
+ \edef\tabu@temp{\the\@temptokena}%
+ \ifx\tabu@temp\@empty\else
+ \ifx\tabu@temp\space\else
+ \expandafter\tabu@decimal\expandafter{\the\@temptokena}%
+ \fi\fi
+}% \tabu@printdecimal
+%% Verbatim inside X columns ----------------------------------------
+\def\tabu@verbatim{%
+ \let\verb \tabu@verb
+ \let\FV@DefineCheckEnd \tabu@FV@DefineCheckEnd
+}% \tabu@verbatim
+\let\tabu@ltx@verb \verb
+\def\tabu@verb{\@ifstar {\tabu@ltx@verb*} \tabu@ltx@verb}
+\def\tabu@fancyvrb {%
+ \def\tabu@FV@DefineCheckEnd ##1{%
+ \def\tabu@FV@DefineCheckEnd{%
+ ##1% <original definition (if fancyvrb is loaded)>
+ \let\FV@CheckEnd \tabu@FV@CheckEnd
+ \let\FV@@CheckEnd \tabu@FV@@CheckEnd
+ \let\FV@@@CheckEnd \tabu@FV@@@CheckEnd
+ \edef\FV@EndScanning{%
+ \def\noexpand\next{\noexpand\end{\FV@EnvironName}}%
+ \global\let\noexpand\FV@EnvironName\relax
+ \noexpand\next}%
+ \xdef\FV@EnvironName{\detokenize\expandafter{\FV@EnvironName}}}%
+ }\expandafter\tabu@FV@DefineCheckEnd\expandafter{\FV@DefineCheckEnd}
+}% \tabu@fancyvrb
+\def\tabu@FV@CheckEnd #1{\expandafter\FV@@CheckEnd \detokenize{#1\end{}}\@nil}
+\edef\tabu@FV@@@CheckEnd {\detokenize{\end{}}}
+\begingroup
+\catcode`\[1 \catcode`\]2
+\@makeother\{ \@makeother\}
+ \edef\x[\endgroup
+ \def\noexpand\tabu@FV@@CheckEnd ##1\detokenize[\end{]##2\detokenize[}]##3%
+ ]\x \@nil{\def\@tempa{#2}\def\@tempb{#3}}
+\def\tabu@FV@ListProcessLine #1{%
+ \hbox {%to \hsize{%
+ \kern\leftmargin
+ \hbox {%to \linewidth{%
+ \FV@LeftListNumber
+ \FV@LeftListFrame
+ \FancyVerbFormatLine{#1}\hss
+%% DG/SR modification begin - Jan. 28, 1998 (for numbers=right add-on)
+%% \FV@RightListFrame}%
+ \FV@RightListFrame
+ \FV@RightListNumber}%
+%% DG/SR modification end
+ \hss}}
+%% \savetabu --------------------------------------------------------
+\newcommand*\savetabu[1]{\noalign{%
+ \tabu@sanitizearg{#1}\tabu@temp
+ \ifx \tabu@temp\@empty \tabu@savewarn{}{The tabu will not be saved}\else
+ \@ifundefined{tabu@saved@\tabu@temp}{}{\tabu@savewarn{#1}{Overwritting}}%
+ \ifdefined\tabu@restored \expandafter\let
+ \csname tabu@saved@\tabu@temp \endcsname \tabu@restored
+ \else {\tabu@save}%
+ \fi
+ \fi}%
+}% \savetabu
+\def\tabu@save {%
+ \toks0\expandafter{\tabu@saved@}%
+ \iftabu@negcoef
+ \let\tabu@wddef \relax \let\tabu@ \tabu@savewd \edef\tabu@savewd{\tabu@Xcoefs}%
+ \toks0\expandafter{\the\toks\expandafter0\tabu@savewd}\fi
+ \toks1\expandafter{\tabu@savedpream}%
+ \toks2\expandafter{\tabu@savedpreamble}%
+ \let\@preamble \relax
+ \let\tabu@savedpream \relax \let\tabu@savedparams \relax
+ \edef\tabu@preamble{%
+ \def\noexpand\tabu@aligndefault{\tabu@align}%
+ \def\tabu@savedparams {\noexpand\the\toks0}%
+ \def\tabu@savedpream {\noexpand\the\toks1}}%
+ \edef\tabu@usetabu{%
+ \def\@preamble {\noexpand\the\toks2}%
+ \tabu@target \the\tabu@target \relax
+ \tabucolX \the\tabucolX \relax
+ \tabu@nbcols \the\tabu@nbcols \relax
+ \def\noexpand\tabu@aligndefault{\tabu@align}%
+ \def\tabu@savedparams {\noexpand\the\toks0}%
+ \def\tabu@savedpream {\noexpand\the\toks1}}%
+ \let\tabu@aligndefault \relax \let\@sharp \relax
+ \edef\@tempa{\noexpand\tabu@s@ved
+ {\tabu@usetabu}
+ {\tabu@preamble}
+ {\the\toks1}}\@tempa
+ \tabu@message@save
+}% \tabu@save
+\long\def\tabu@s@ved #1#2#3{%
+ \def\tabu@usetabu{#1}% <for \tabu@message@save>
+ \expandafter\gdef\csname tabu@saved@\tabu@temp\endcsname ##1{%
+ \ifodd ##1% \usetabu
+ \tabu@measuringfalse \tabu@spreadfalse % Just in case...
+ \gdef\tabu@usetabu {%
+ \ifdim \tabu@target>\z@ \tabu@warn@usetabu \fi
+ \global\let\tabu@usetabu \@undefined
+ \def\@halignto {to\tabu@target}%
+ #1%
+ \ifx \tabu@align\tabu@aligndefault@text
+ \ifnum \tabu@nested=\z@
+ \let\tabu@align \tabu@aligndefault \fi\fi}%
+ \else % \preamble
+ \gdef\tabu@preamble {%
+ \global\let\tabu@preamble \@undefined
+ #2%
+ \ifx \tabu@align\tabu@aligndefault@text
+ \ifnum \tabu@nested=\z@
+ \let\tabu@align \tabu@aligndefault \fi\fi}%
+ \fi
+ #3}%
+}% \tabu@s@ved
+\def\tabu@aligndefault@text {\tabu@aligndefault}%
+\def\tabu@warn@usetabu {\PackageWarning{tabu}
+ {Specifying a target with \string\usetabu\space is useless
+ \MessageBreak The target cannot be changed!}}
+\def\tabu@savewd #1#2{\ifdim #2\p@<\z@ \tabu@wddef{#1}{\tabu@wd{#1}}\fi}
+\def\tabu@savewarn#1#2{\PackageInfo{tabu}
+ {User-name `#1' already used for \string\savetabu
+ \MessageBreak #2}}%
+\def\tabu@saveerr#1{\PackageError{tabu}
+ {User-name `#1' is unknown for \string\usetabu
+ \MessageBreak I cannot restore an unknown preamble!}\@ehd}
+%% \rowfont ---------------------------------------------------------
+\newskip \tabu@cellskip
+\def\tabu@rowfont{\ifdim \baselineskip=\z@\noalign\fi
+ {\ifnum0=`}\fi \tabu@row@font}
+\newcommand*\tabu@row@font[2][]{%
+ \ifnum7=\currentgrouptype
+ \global\let\tabu@@cellleft \tabu@cellleft
+ \global\let\tabu@@cellright \tabu@cellright
+ \global\let\tabu@@celllalign \tabu@celllalign
+ \global\let\tabu@@cellralign \tabu@cellralign
+ \global\let\tabu@@rowfontreset\tabu@rowfontreset
+ \fi
+ \global\let\tabu@rowfontreset \tabu@rowfont@reset
+ \expandafter\gdef\expandafter\tabu@cellleft\expandafter{\tabu@cellleft #2}%
+ \ifcsname tabu@cell@#1\endcsname % row alignment
+ \csname tabu@cell@#1\endcsname \fi
+ \ifnum0=`{\fi}% end of group / noalign group
+}% \rowfont
+\def\tabu@ifcolorleavevmode #1{\let\color \tabu@leavevmodecolor #1\let\color\tabu@color}%
+\def\tabu@rowfont@reset{%
+ \global\let\tabu@rowfontreset \tabu@@rowfontreset
+ \global\let\tabu@cellleft \tabu@@cellleft
+ \global\let\tabu@cellright \tabu@@cellright
+ \global\let\tabu@cellfont \@empty
+ \global\let\tabu@celllalign \tabu@@celllalign
+ \global\let\tabu@cellralign \tabu@@cellralign
+}% \tabu@@rowfontreset
+\let\tabu@rowfontreset \@empty % overwritten \AtBeginDocument if colortbl
+%% \tabu@prepnext@tok -----------------------------------------------
+\newif \iftabu@cellright
+\def\tabu@prepnext@tok{%
+ \ifnum \count@<\z@ % <first initialisation>
+ \@tempcnta \@M % <not initialized by array.sty>
+ \tabu@nbcols\z@
+ \let\tabu@fornoopORI \@fornoop
+ \tabu@cellrightfalse
+ \else
+ \ifcase \numexpr \count@-\@tempcnta \relax % (case 0): prev. token is left
+ \advance \tabu@nbcols \@ne
+ \iftabu@cellright % before-previous token is right and is finished
+ \tabu@cellrightfalse % <only once>
+ \tabu@righttok
+ \fi
+ \tabu@lefttok
+ \or % (case 1) previous token is right
+ \tabu@cellrighttrue \let\@fornoop \tabu@lastnoop
+ \else % special column: do not change the token
+ \iftabu@cellright % before-previous token is right
+ \tabu@cellrightfalse
+ \tabu@righttok
+ \fi
+ \fi % \ifcase
+ \fi
+ \tabu@prepnext@tokORI
+}% \tabu@prepnext@tok
+\long\def\tabu@lastnoop#1\@@#2#3{\tabu@lastn@@p #2\@nextchar \in@\in@@}
+\def\tabu@lastn@@p #1\@nextchar #2#3\in@@{%
+ \ifx \in@#2\else
+ \let\@fornoop \tabu@fornoopORI
+ \xdef\tabu@mkpreambuffer{\tabu@nbcols\the\tabu@nbcols \tabu@mkpreambuffer}%
+ \toks0\expandafter{\expandafter\tabu@everyrowtrue \the\toks0}%
+ \expandafter\prepnext@tok
+ \fi
+}% \tabu@lastnoop
+\def\tabu@righttok{%
+ \advance \count@ \m@ne
+ \toks\count@\expandafter {\the\toks\count@ \tabu@cellright \tabu@cellralign}%
+ \advance \count@ \@ne
+}% \tabu@righttok
+\def\tabu@lefttok{\toks\count@\expandafter{\expandafter\tabu@celllalign
+ \the\toks\count@ \tabu@cellleft}% after because of $
+}% \tabu@lefttok
+%% Neutralisation of glues ------------------------------------------
+\let\tabu@cellleft \@empty
+\let\tabu@cellright \@empty
+\tabu@celllalign@def{\tabu@cellleft}%
+\let\tabu@cellralign \@empty
+\def\tabu@cell@align #1#2#3{%
+ \let\tabu@maybesiunitx \toks@ \tabu@celllalign
+ \global \expandafter \tabu@celllalign@def \expandafter {\the\toks@ #1}%
+ \toks@\expandafter{\tabu@cellralign #2}%
+ \xdef\tabu@cellralign{\the\toks@}%
+ \toks@\expandafter{\tabu@cellleft #3}%
+ \xdef\tabu@cellleft{\the\toks@}%
+}% \tabu@cell@align
+\def\tabu@cell@l{% force alignment to left
+ \tabu@cell@align
+ {\tabu@removehfil \raggedright \tabu@cellleft}% left
+ {\tabu@flush1\tabu@ignorehfil}% right
+ \raggedright
+}% \tabu@cell@l
+\def\tabu@cell@c{% force alignment to center
+ \tabu@cell@align
+ {\tabu@removehfil \centering \tabu@flush{.5}\tabu@cellleft}
+ {\tabu@flush{.5}\tabu@ignorehfil}
+ \centering
+}% \tabu@cell@c
+\def\tabu@cell@r{% force alignment to right
+ \tabu@cell@align
+ {\tabu@removehfil \raggedleft \tabu@flush1\tabu@cellleft}
+ \tabu@ignorehfil
+ \raggedleft
+}% \tabu@cell@r
+\def\tabu@cell@j{% force justification (for p, m, b columns)
+ \tabu@cell@align
+ {\tabu@justify\tabu@cellleft}
+ {}
+ \tabu@justify
+}% \tabu@cell@j
+\def\tabu@justify{%
+ \leftskip\z@skip \@rightskip\leftskip \rightskip\@rightskip
+ \parfillskip\@flushglue
+}% \tabu@justify
+%% ragged2e settings
+\def\tabu@cell@L{% force alignment to left (ragged2e)
+ \tabu@cell@align
+ {\tabu@removehfil \RaggedRight \tabu@cellleft}
+ {\tabu@flush 1\tabu@ignorehfil}
+ \RaggedRight
+}% \tabu@cell@L
+\def\tabu@cell@C{% force alignment to center (ragged2e)
+ \tabu@cell@align
+ {\tabu@removehfil \Centering \tabu@flush{.5}\tabu@cellleft}
+ {\tabu@flush{.5}\tabu@ignorehfil}
+ \Centering
+}% \tabu@cell@C
+\def\tabu@cell@R{% force alignment to right (ragged2e)
+ \tabu@cell@align
+ {\tabu@removehfil \RaggedLeft \tabu@flush 1\tabu@cellleft}
+ \tabu@ignorehfil
+ \RaggedLeft
+}% \tabu@cell@R
+\def\tabu@cell@J{% force justification (ragged2e)
+ \tabu@cell@align
+ {\justifying \tabu@cellleft}
+ {}
+ \justifying
+}% \tabu@cell@J
+\def\tabu@flush#1{%
+ \iftabu@colortbl % colortbl uses \hfill rather than \hfil
+ \hskip \ifnum13<\currentgrouptype \stretch{#1}%
+ \else \ifdim#1pt<\p@ \tabu@cellskip
+ \else \stretch{#1}
+ \fi\fi \relax
+ \else % array.sty
+ \ifnum 13<\currentgrouptype
+ \hfil \hskip1sp \relax \fi
+ \fi
+}% \tabu@flush
+\let\tabu@hfil \hfil
+\let\tabu@hfill \hfill
+\let\tabu@hskip \hskip
+\def\tabu@removehfil{%
+ \iftabu@colortbl
+ \unkern \tabu@cellskip =\lastskip
+ \ifnum\gluestretchorder\tabu@cellskip =\tw@ \hskip-\tabu@cellskip
+ \else \tabu@cellskip \z@skip
+ \fi
+ \else
+ \ifdim\lastskip=1sp\unskip\fi
+ \ifnum\gluestretchorder\lastskip =\@ne
+ \hfilneg % \hfilneg for array.sty but not for colortbl...
+ \fi
+ \fi
+}% \tabu@removehfil
+\def\tabu@ignorehfil{\aftergroup \tabu@nohfil}
+\def\tabu@nohfil{% \hfil -> do nothing + restore original \hfil
+ \def\hfil{\let\hfil \tabu@hfil}% local to (alignment template) group
+}% \tabu@nohfil
+\def\tabu@colortblalignments {% if colortbl
+ \def\tabu@nohfil{%
+ \def\hfil {\let\hfil \tabu@hfil}% local to (alignment template) group
+ \def\hfill {\let\hfill \tabu@hfill}% (colortbl uses \hfill) pfff...
+ \def\hskip ####1\relax{\let\hskip \tabu@hskip}}% local
+}% \tabu@colortblalignments
+%% Taking care of footnotes and hyperfootnotes ----------------------
+\long\def\tabu@footnotetext #1{%
+ \edef\@tempa{\the\tabu@footnotes
+ \noexpand\footnotetext [\the\csname c@\@mpfn\endcsname]}%
+ \global\tabu@footnotes\expandafter{\@tempa {#1}}}%
+\long\def\tabu@xfootnotetext [#1]#2{%
+ \global\tabu@footnotes\expandafter{\the\tabu@footnotes
+ \footnotetext [{#1}]{#2}}}
+\let\tabu@xfootnote \@xfootnote
+\long\def\tabu@Hy@ftntext{\tabu@Hy@ftntxt {\the \c@footnote }}
+\long\def\tabu@Hy@xfootnote [#1]{%
+ \begingroup
+ \value\@mpfn #1\relax
+ \protected@xdef \@thefnmark {\thempfn}%
+ \endgroup
+ \@footnotemark \tabu@Hy@ftntxt {#1}%
+}% \tabu@Hy@xfootnote
+\long\def\tabu@Hy@ftntxt #1#2{%
+ \edef\@tempa{%
+ \the\tabu@footnotes
+ \begingroup
+ \value\@mpfn #1\relax
+ \noexpand\protected@xdef\noexpand\@thefnmark {\noexpand\thempfn}%
+ \expandafter \noexpand \expandafter
+ \tabu@Hy@footnotetext \expandafter{\Hy@footnote@currentHref}%
+ }%
+ \global\tabu@footnotes\expandafter{\@tempa {#2}%
+ \endgroup}%
+}% \tabu@Hy@ftntxt
+\long\def\tabu@Hy@footnotetext #1#2{%
+ \H@@footnotetext{%
+ \ifHy@nesting
+ \hyper@@anchor {#1}{#2}%
+ \else
+ \Hy@raisedlink{%
+ \hyper@@anchor {#1}{\relax}%
+ }%
+ \def\@currentHref {#1}%
+ \let\@currentlabelname \@empty
+ #2%
+ \fi
+ }%
+}% \tabu@Hy@footnotetext
+%% No need for \arraybackslash ! ------------------------------------
+\def\tabu@latextwoe {%
+\def\tabu@temp##1##2##3{{\toks@\expandafter{##2##3}\xdef##1{\the\toks@}}}
+\tabu@temp \tabu@centering \centering \arraybackslash
+\tabu@temp \tabu@raggedleft \raggedleft \arraybackslash
+\tabu@temp \tabu@raggedright \raggedright \arraybackslash
+}% \tabu@latextwoe
+\def\tabu@raggedtwoe {%
+\def\tabu@temp ##1##2##3{{\toks@\expandafter{##2##3}\xdef##1{\the\toks@}}}
+\tabu@temp \tabu@Centering \Centering \arraybackslash
+\tabu@temp \tabu@RaggedLeft \RaggedLeft \arraybackslash
+\tabu@temp \tabu@RaggedRight \RaggedRight \arraybackslash
+\tabu@temp \tabu@justifying \justifying \arraybackslash
+}% \tabu@raggedtwoe
+\def\tabu@normalcrbackslash{\let\\\@normalcr}
+\def\tabu@trivlist{\expandafter\def\expandafter\@trivlist\expandafter{%
+ \expandafter\tabu@normalcrbackslash \@trivlist}}
+%% Utilities: \fbox \fcolorbox and \tabudecimal -------------------
+\def\tabu@fbox {\leavevmode\afterassignment\tabu@beginfbox \setbox\@tempboxa\hbox}
+\def\tabu@beginfbox {\bgroup \kern\fboxsep
+ \bgroup\aftergroup\tabu@endfbox}
+\def\tabu@endfbox {\kern\fboxsep\egroup\egroup
+ \@frameb@x\relax}
+\def\tabu@color@b@x #1#2{\leavevmode \bgroup
+ \def\tabu@docolor@b@x{#1{#2\color@block{\wd\z@}{\ht\z@}{\dp\z@}\box\z@}}%
+ \afterassignment\tabu@begincolor@b@x \setbox\z@ \hbox
+}% \tabu@color@b@x
+\def\tabu@begincolor@b@x {\kern\fboxsep \bgroup
+ \aftergroup\tabu@endcolor@b@x \set@color}
+\def\tabu@endcolor@b@x {\kern\fboxsep \egroup
+ \dimen@\ht\z@ \advance\dimen@ \fboxsep \ht\z@ \dimen@
+ \dimen@\dp\z@ \advance\dimen@ \fboxsep \dp\z@ \dimen@
+ \tabu@docolor@b@x \egroup
+}% \tabu@endcolor@b@x
+%% Corrections (arydshln, delarray, colortbl) -----------------------
+\def\tabu@fix@arrayright {%% \@arrayright is missing from \endarray
+ \iftabu@colortbl
+ \ifdefined\adl@array % <colortbl + arydshln>
+ \def\tabu@endarray{%
+ \adl@endarray \egroup \adl@arrayrestore \CT@end \egroup %<original>
+ \@arrayright % <FC>
+ \gdef\@preamble{}}% <FC>
+ \else % <colortbl / no arydshln>
+ \def\tabu@endarray{%
+ \crcr \egroup \egroup %<original>
+ \@arrayright % <FC>
+ \gdef\@preamble{}\CT@end}%
+ \fi
+ \else
+ \ifdefined\adl@array % <arydshln / no colortbl>
+ \def\tabu@endarray{%
+ \adl@endarray \egroup \adl@arrayrestore \egroup %<original>
+ \@arrayright % <FC>
+ \gdef\@preamble{}}% <FC>
+ \else % <no arydshln / no colotbl + \@arrayright missing>
+ \PackageWarning{tabu}
+ {\string\@arrayright\space is missing from the
+ \MessageBreak definition of \string\endarray.
+ \MessageBreak Comptability with delarray.sty is broken.}%
+ \fi\fi
+}% \tabu@fix@arrayright
+\def\tabu@adl@xarraydashrule #1#2#3{%
+ \ifnum\@lastchclass=\adl@class@start\else
+ \ifnum\@lastchclass=\@ne\else
+ \ifnum\@lastchclass=5 \else % <FC> @-arg (class 5) and !-arg (class 1)
+ \adl@leftrulefalse \fi\fi % must be treated the same
+ \fi
+ \ifadl@zwvrule\else \ifadl@inactive\else
+ \@addtopreamble{\vrule\@width\arrayrulewidth
+ \@height\z@ \@depth\z@}\fi \fi
+ \ifadl@leftrule
+ \@addtopreamble{\adl@vlineL{\CT@arc@}{\adl@dashgapcolor}%
+ {\number#1}#3}%
+ \else \@addtopreamble{\adl@vlineR{\CT@arc@}{\adl@dashgapcolor}%
+ {\number#2}#3}
+ \fi
+}% \tabu@adl@xarraydashrule
+\def\tabu@adl@act@endpbox {%
+ \unskip \ifhmode \nobreak \fi \@finalstrut \@arstrutbox
+ \egroup \egroup
+ \adl@colhtdp \box\adl@box \hfil
+}% \tabu@adl@act@endpbox
+\def\tabu@adl@fix {%
+ \let\adl@xarraydashrule \tabu@adl@xarraydashrule % <fix> arydshln
+ \let\adl@act@endpbox \tabu@adl@act@endpbox % <fix> arydshln
+ \let\adl@act@@endpbox \tabu@adl@act@endpbox % <fix> arydshln
+ \let\@preamerror \@preamerr % <fix> arydshln
+}% \tabu@adl@fix
+%% Correction for longtable' \@startbox definition ------------------
+%% => \everypar is ``missing'' : TeX should be in vertical mode
+\def\tabu@LT@startpbox #1{%
+ \bgroup
+ \let\@footnotetext\LT@p@ftntext
+ \setlength\hsize{#1}%
+ \@arrayparboxrestore
+ \everypar{%
+ \vrule \@height \ht\@arstrutbox \@width \z@
+ \everypar{}}%
+}% \tabu@LT@startpbox
+%% \tracingtabu and the package options ------------------
+\DeclareOption{delarray}{\AtEndOfPackage{\RequirePackage{delarray}}}
+\DeclareOption{linegoal}{%
+ \AtEndOfPackage{%
+ \RequirePackage{linegoal}[2010/12/07]%
+ \let\tabudefaulttarget \linegoal% \linegoal is \linewidth if not pdfTeX
+}}
+\DeclareOption{scantokens}{\tabuscantokenstrue}
+\DeclareOption{debugshow}{\AtEndOfPackage{\tracingtabu=\tw@}}
+\def\tracingtabu {\begingroup\@ifnextchar=%
+ {\afterassignment\tabu@tracing\count@}
+ {\afterassignment\tabu@tracing\count@1\relax}}
+\def\tabu@tracing{\expandafter\endgroup
+ \expandafter\tabu@tr@cing \the\count@ \relax
+}% \tabu@tracing
+\def\tabu@tr@cing #1\relax {%
+ \ifnum#1>\thr@@ \let\tabu@tracinglines\message
+ \else \let\tabu@tracinglines\@gobble
+ \fi
+ \ifnum#1>\tw@ \let\tabu@DBG \tabu@@DBG
+ \def\tabu@mkarstrut {\tabu@DBG@arstrut}%
+ \tabustrutrule 1.5\p@
+ \else \let\tabu@DBG \@gobble
+ \def\tabu@mkarstrut {\tabu@arstrut}%
+ \tabustrutrule \z@
+ \fi
+ \ifnum#1>\@ne \let\tabu@debug \message
+ \else \let\tabu@debug \@gobble
+ \fi
+ \ifnum#1>\z@
+ \let\tabu@message \message
+ \let\tabu@tracing@save \tabu@message@save
+ \let\tabu@starttimer \tabu@pdftimer
+ \else
+ \let\tabu@message \@gobble
+ \let\tabu@tracing@save \@gobble
+ \let\tabu@starttimer \relax
+ \fi
+}% \tabu@tr@cing
+%% Setup \AtBeginDocument
+\AtBeginDocument{\tabu@AtBeginDocument}
+\def\tabu@AtBeginDocument{\let\tabu@AtBeginDocument \@undefined
+ \ifdefined\arrayrulecolor \tabu@colortbltrue % <colortbl>
+ \tabu@colortblalignments % different glues are used
+ \else \tabu@colortblfalse \fi
+ \ifdefined\CT@arc@ \else \let\CT@arc@ \relax \fi
+ \ifdefined\CT@drsc@\else \let\CT@drsc@ \relax \fi
+ \let\tabu@arc@L \CT@arc@ \let\tabu@drsc@L \CT@drsc@
+ \ifodd 1\ifcsname siunitx_table_collect_begin:Nn\endcsname % <siunitx: ok>
+ \expandafter\ifx
+ \csname siunitx_table_collect_begin:Nn\endcsname\relax 0\fi\fi\relax
+ \tabu@siunitxtrue
+ \else \let\tabu@maybesiunitx \@firstofone % <not siunitx: setup>
+ \let\tabu@siunitx \tabu@nosiunitx
+ \tabu@siunitxfalse
+ \fi
+ \ifdefined\adl@array % <arydshln>
+ \else \let\tabu@adl@fix \relax
+ \let\tabu@adl@endtrial \@empty \fi
+ \ifdefined\longtable % <longtable>
+ \else \let\longtabu \tabu@nolongtabu \fi
+ \ifdefined\cellspacetoplimit \tabu@warn@cellspace\fi
+ \csname\ifcsname ifHy@hyperfootnotes\endcsname % <hyperfootnotes>
+ ifHy@hyperfootnotes\else iffalse\fi\endcsname
+ \let\tabu@footnotetext \tabu@Hy@ftntext
+ \let\tabu@xfootnote \tabu@Hy@xfootnote \fi
+ \ifdefined\FV@DefineCheckEnd% <fancyvrb>
+ \tabu@fancyvrb \fi
+ \ifdefined\color % <color / xcolor>
+ \let\tabu@color \color
+ \def\tabu@leavevmodecolor ##1{%
+ \def\tabu@leavevmodecolor {\leavevmode ##1}%
+ }\expandafter\tabu@leavevmodecolor\expandafter{\color}%
+ \else
+ \let\tabu@color \tabu@nocolor
+ \let\tabu@leavevmodecolor \@firstofone \fi
+ \tabu@latextwoe
+ \ifdefined\@raggedtwoe@everyselectfont % <ragged2e>
+ \tabu@raggedtwoe
+ \else
+ \let\tabu@cell@L \tabu@cell@l
+ \let\tabu@cell@R \tabu@cell@r
+ \let\tabu@cell@C \tabu@cell@c
+ \let\tabu@cell@J \tabu@cell@j \fi
+ \expandafter\in@ \expandafter\@arrayright \expandafter{\endarray}%
+ \ifin@ \let\tabu@endarray \endarray
+ \else \tabu@fix@arrayright \fi% <fix for colortbl & arydshln (delarray)>
+ \everyrow{}%
+}% \tabu@AtBeginDocument
+\def\tabu@warn@cellspace{%
+ \PackageWarning{tabu}{%
+ Package cellspace has some limitations
+ \MessageBreak And redefines some macros of array.sty.
+ \MessageBreak Please use \string\tabulinesep\space to control
+ \MessageBreak vertical spacing of lines inside tabu environnement}%
+}% \tabu@warn@cellspace
+%% tabu Package initialisation
+\tabuscantokensfalse
+\let\tabu@arc@G \relax
+\let\tabu@drsc@G \relax
+\let\tabu@evr@G \@empty
+\let\tabu@rc@G \@empty
+\def\tabu@ls@G {\tabu@linestyle@}%
+\let\tabu@@rowfontreset \@empty % <init>
+\let\tabu@@celllalign \@empty
+\let\tabu@@cellralign \@empty
+\let\tabu@@cellleft \@empty
+\let\tabu@@cellright \@empty
+\def\tabu@naturalXmin {\z@}
+\def\tabu@naturalXmax {\z@}
+\let\tabu@rowfontreset \@empty
+\def\tabulineon {4pt}\let\tabulineoff \tabulineon
+\tabu@everyrowtrue
+\ifdefined\pdfelapsedtime % <pdfTeX>
+ \def\tabu@pdftimer {\xdef\tabu@starttime{\the\pdfelapsedtime}}%
+\else \let\tabu@pdftimer \relax \let\tabu@message@etime \relax
+\fi
+\tracingtabu=\z@
+\newtabulinestyle {=\maxdimen}% creates the 'factory' settings \tabu@linestyle@
+\tabulinestyle{}
+\taburowcolors{}
+\let\tabudefaulttarget \linewidth
+\ProcessOptions* % \ProcessOptions* is quicker !
+\endinput
+%%
+%% End of file `tabu.sty'.
diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd index e4ca883..7a65bd2 100644 --- a/templates/xml/compound.xsd +++ b/templates/xml/compound.xsd @@ -232,6 +232,7 @@ <xsd:complexType name="paramType"> <xsd:sequence> + <xsd:element name="attributes" minOccurs="0" /> <xsd:element name="type" type="linkedTextType" minOccurs="0" /> <xsd:element name="declname" minOccurs="0" /> <xsd:element name="defname" minOccurs="0" /> @@ -423,9 +424,9 @@ <xsd:element name="rtfonly" type="xsd:string" /> <xsd:element name="latexonly" type="xsd:string" /> <xsd:element name="image" type="docImageType" /> - <xsd:element name="dot" type="xsd:string" /> - <xsd:element name="msc" type="xsd:string" /> - <xsd:element name="plantuml" type="xsd:string" /> + <xsd:element name="dot" type="docImageType" /> + <xsd:element name="msc" type="docImageType" /> + <xsd:element name="plantuml" type="docImageType" /> <xsd:element name="anchor" type="docAnchorType" /> <xsd:element name="formula" type="docFormulaType" /> <xsd:element name="ref" type="docRefTextType" /> @@ -456,9 +457,9 @@ <xsd:element name="table" type="docTableType" /> <xsd:element name="heading" type="docHeadingType" /> <xsd:element name="image" type="docImageType" /> - <xsd:element name="dotfile" type="docFileType" /> - <xsd:element name="mscfile" type="docFileType" /> - <xsd:element name="diafile" type="docFileType" /> + <xsd:element name="dotfile" type="docImageType" /> + <xsd:element name="mscfile" type="docImageType" /> + <xsd:element name="diafile" type="docImageType" /> <xsd:element name="toclist" type="docTocListType" /> <xsd:element name="language" type="docLanguageType" /> <xsd:element name="parameterlist" type="docParamListType" /> @@ -578,16 +579,12 @@ <xsd:complexType name="docImageType" mixed="true"> <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" /> - <xsd:attribute name="type" type="DoxImageKind" /> - <xsd:attribute name="name" type="xsd:string" /> - <xsd:attribute name="width" type="xsd:string" /> - <xsd:attribute name="height" type="xsd:string" /> - <xsd:attribute name="inline" type="DoxBool" /> - </xsd:complexType> - - <xsd:complexType name="docFileType" mixed="true"> - <xsd:group ref="docTitleCmdGroup" minOccurs="0" maxOccurs="unbounded" /> - <xsd:attribute name="name" type="xsd:string" /> + <xsd:attribute name="type" type="DoxImageKind" use="optional"/> + <xsd:attribute name="name" type="xsd:string" use="optional"/> + <xsd:attribute name="width" type="xsd:string" use="optional"/> + <xsd:attribute name="height" type="xsd:string" use="optional"/> + <xsd:attribute name="inline" type="DoxBool" use="optional"/> + <xsd:attribute name="caption" type="xsd:string" use="optional"/> </xsd:complexType> <xsd:complexType name="docTocItemType" mixed="true"> diff --git a/testing/071/namespace_a_namespace_1_1_0D0.xml b/testing/071/namespace_a_namespace_1_1_0d0.xml index 14f5a51..14f5a51 100644 --- a/testing/071/namespace_a_namespace_1_1_0D0.xml +++ b/testing/071/namespace_a_namespace_1_1_0d0.xml diff --git a/testing/runtests.py b/testing/runtests.py index fa3c186..fa3c186 100644..100755 --- a/testing/runtests.py +++ b/testing/runtests.py |