# -*-Shell-script-*-
#
# Copyright (C) 2012-2021 SUSE Software Solutions Germany GmbH
#
# Author:
# Frank Sundermeyer <fsundermeyer at opensuse dot org>
#
# Functions for ../bin/daps
#
#


###########################################################################
#
# ARGUMENT PARSER FOR ALL SUBCOMMANDS
#
# Generic parser for the subcommands' command line switches. If a function
# introduces a new switch, it needs to be added here
#
###########################################################################
function parse_args {
    #
    # help is always handled within the function directly
    # everything else is parsed here

    # this functions only parses the getopts arguments and sets
    # variables accordingly.

    local SHORT_OPTS LONG_OPTS SUB_CMD
    SHORT_OPTS=$1
    LONG_OPTS=$2
    SUB_CMD=$3
    shift 3

    C_ARGS=$(getopt -s bash -o "$SHORT_OPTS" -l "$LONG_OPTS" -n "$0" -- "$@")
    if [[ 1 -eq $? ]]; then
        wrong_parameter "$SUB_CMD"
    fi

    eval set -- "$C_ARGS"

    while true ; do
        case "$1" in
            --check)
                # epub: validating result
                # also requires a minimum verbosity level of 1
                #
                [[ 0 -eq "$VERBOSITY" ]] && export VERBOSITY=1
                export RESULTCHECK=1
                shift
                ;;
            --clean)
                # html/webhelp: clean up previous builds
                export CLEAN_DIR=1
                shift
                ;;
            --color)
                # images: only create color images
                export IMAGES_COLOR=1
                shift
                ;;
            --compact)
                # getimages: one line filelist
                # no need to export (not passed to make)
                COMPACT=1
                shift
                ;;
            --cropmarks)
                # pdf/package-pdf/show-names: PDF Cropmarks
                export CROPMARKS=1
                shift
                ;;
            --css)
                # epub/html/package-html/webhelp: Path to custom CSS file
                # processed differently in respective targets
                # no direct export here
                declare P_CSS
                if [[ $2 != "none" ]]; then
                    sanitize_path "$2" "P_CSS"
                else
                    P_CSS="$2"
                fi
                shift 2
                ;;
            --def-file)
                # locdrop/package-src: include DEF-file
                declare DEF_FILE
                sanitize_path "$2" "DEF_FILE"
                export DEF_FILE
                shift 2
                ;;
            --desktopfiles)
                # package-html/package-pdf: Create desktop files
                export DESKTOPFILES=1
                shift
                ;;
            --documentfiles)
                # package-html/package-pdf: Create document files
                export DOCUMENTFILES=1
                shift
                ;;
            --draft)
                # html/pdf/profile-first/show-names/webhelp: draft mode
                # exported in init_env
                DRAFT=yes
                shift
                ;;
            --epub3)
                # epub: Create ePub 3
                export EPUB3=1
                shift
                ;;
            --export-dir)
                # locdrop: export directory
                declare EXPORT_DIR
                sanitize_path "$2" "EXPORT_DIR"
                export EXPORT_DIR
                shift 2
                ;;
            --extra-dict)
                # spellcheck: additional dictionary
                # no need to export (not passed to make)
                SPELL_EXTRA_DICT="$2"
                shift 2
                ;;
            --file)
                # getimages/linkcheck/spellcheck/stylecheck/xmlformat
                # no need to export (not passed to make)
                declare P_FILE
                sanitize_path "$2" "P_FILE"
                shift 2
                ;;
            --formatter)
                # package-pdf/pdf/show-names: PDF formatter
                if [[ xep = "$2" || fop = "$2" ]]; then
                    export FORMATTER="$2"
                else
                    exit_on_error "Wrong parameter for --formatter: must be \"xep\" or \"fop\"!"
                fi
                shift 2
                ;;
            --gen)
                # images: no links
                export IMAGES_GEN=1
                shift
                ;;
            --grayscale)
                # images/pdf/package-pdf/show-names: only grayscale images
                export GRAYSCALE=1
                shift
                ;;
            -h|--help)
                # basically all targets
                # no need to export (not passed to make)
                P_HELP=1
                shift
                ;;
            --html5)
                # html/package-html: create html5
                export HTML5=1
                shift
                ;;
            --ignore-styleroot)
                # text / call_make: force use upstream DB stylesheets
                export TXT_IGNORE_STYLEROOT=1
                shift
                ;;
            --imgonly)
                # "meta" attribute, will preset other attributes for
                # list-srcfiles
                # no need to export (not passed to make)
                P_LIST_IMG_ONLY=1
                shift
                ;;
            --lang)
                # spellcheck: Language
                # no need to export (not passed to make)
                P_LANG="$2"
                shift 2
                ;;
            --lean)
                # pdf: create PDF with rediced graphics quailty
                export LEAN="1"
                shift
                ;;
            --list)
                # spellcheck: dump misspelled to STDOUT
                # no need to export (not passed to make)
                LISTMODE=1
                shift
                ;;
            --locdrop)
                # package-src: include manifest files for translation
                export IS_LOCDROP=1
                shift
                ;;
            --meta)
                # html/pdf: display meta data in draft mode
                # exported in init_env
                META=1
                shift
                ;;
            --modified)
                # getimages: show file modification times
                # no need to export (not passed to make)
                MOD=1
                shift
                ;;
            --name)
                # used almost everywhere to set the filename
                export OUTPUTNAME="$2" BOOK="$2"
                shift 2
                ;;
            --nodc)
                # filelists: Do not show DC-file
                export LIST_NODC=1
                shift
                ;;
            --noent)
                # filelists: Do not show entity files
                export LIST_NOENT=1
                shift
                ;;
            --nogzip)
                # man: do not gzip man pages
                export GZIP_MAN="no"
                shift
                ;;
            --noimg)
                # filelists: Do not show images
                export LIST_NOIMG=1
                shift
                ;;
            --nopdf)
                # locdrop: Do not generate PDF
                export NOPDF=1
                shift
                ;;
            --nosearch)
                export WH_SEARCH="no"
                shift
                ;;
            --nostatic)
                # html/webhelp: Do not copy images, link them
                export STATIC_HTML=0
                shift
                ;;
            --norefcheck)
                # used in many targets: do not validate xrefs
                export NOREFCHECK="1"
                shift
                ;;
            --notrans-dir)
                # unpack-locdrop: path to en directory
                # no need to export (not passed to make)
                declare P_NOTRANS_DIR
                sanitize_path "$2" "P_NOTRANS_DIR"
                shift 2
                ;;
            --not-validate-tables)
                export NOT_VALIDATE_TABLES=1
                shift
                ;;
            --novalid)
                # bigfile: Do not validate profiled sources
                export NOVALID=1
                shift
                ;;
            --noxml|--noadoc)
                # filelists: Do not show XML/ADOC files
                export LIST_NOXML=1
                shift
                ;;
            --online)
                # images: generate online images
                export IMAGES_ONLINE=1
                shift
                ;;
            --optipng)
                # locdrop/package-src/unpack-locdrop: Optimize PNGs
                export OPTIPNG=1
                shift
                ;;
            --output-dir)
                # unpack lockdrop: output directory
                # no need to export (not passed to make)
                declare P_OUTPUT_DIR=""
                sanitize_path "$2" "P_OUTPUT_DIR"
                shift 2
                ;;
            --pagefiles)
                # package-html/package-pdf: Generate pagefiles
                export PAGEFILES=1
                shift
                ;;
            --param)
                # various targets: xslt (numeric) parameters
                # Values are concatenated here
                # exported in init_env
                P_PARAMS="$P_PARAMS --param $2"
                shift 2
                ;;
            --pretty)
                # filelists: make outpot human readyble
                export PRETTY_FILELIST=1
                shift
                ;;
            --remarks)
                # epub/html/pdf/profile-first/show-names/webhelp: draft mode
                # exported in init_env
                REMARKS=1
                shift
                ;;
            --remove-dm)
                # unpack-locdrop: Remove Docmanager blocks
                # no need to export (not passed to make)
                P_REMOVEDM=1
                shift
                ;;
            --rootid)
                # used almost everywhere: ROOTID
                # P_ROOTID is needed for
                # getimages/linkcheck//spellcheck/stylecheck/xmlformat
                # to distinguish between valkues provided by
                # config and command line
                P_ROOTID="$2"
                export ROOTID="$2"
                shift 2
                ;;
            --show)
                # getimages/linkcheck/stylecheck
                export SHOW=1
                shift
                ;;
            --set-date)
                # package-html/package-pdf/package-src: manually set date
                SETDATE=$(date -d "$2" +"%b %d %Y" 2>/dev/null) || exit_on_error "Wrong value for set-date: must be in a \"date\" compatible format,\ne.g. \"YYYY-MM-DD\"!"
                export SETDATE
                shift 2
                ;;
            --single)
                # html/package-html/show-names: create single HTML
                export HTMLSINGLE=1
                shift
                ;;
            --spellchecker)
                # spellcheck: aspell or hunspell
                SPELL_CHECKER="$2"
                shift 2
                ;;
            --static)
                ccecho -- "warn" "--static is deprecated, since it is the default now."
                shift
                ;;
            --statdir)
                # epub/html/package-html: directory containing js and css
                declare STATIC_DIR
                sanitize_path "$2" "STATIC_DIR"
                export STATIC
                shift 2
                ;;
            --stringparam)
                # various targets: xslt (numeric) parameters
                # Values are concatenated here
                # exported in init_env
                P_STRINGPARAMS="$P_STRINGPARAMS --stringparam $2"
                shift 2
                ;;
            --subdirs)
                # mnn: use subdirectories
                export MAN_SUBDIRS="yes"
                shift
                ;;
            --target)
                # dapsenv/showvariable: specify subcommand
                TARGET="$2"
                shift 2
                ;;
            --trans-files)
                # unpack_locdrop
                # no need to export (not passed to make)
                P_TRANS_FILES="$2"
                shift 2
                ;;
            --validate-ids)
                export VALIDATE_IDS=1
                shift
                ;;
            --validate-images)
                export VALIDATE_IMAGES=1
                shift
                ;;
            --viewer)
                # getimages: specify image viewer
                # no need to export (not passed to make)
                IMG_VIEWER="$2"
                shift 2
                ;;
            --xmlonly|--adoconly)
                # "meta" attribute, will preset other attributes for
                # list-srcfiles
                # no need to export (not passed to make)
                P_LIST_XML_ONLY=1
                shift
                ;;
            --)
                shift
                break
                ;;
            *)
                wrong_parameter "$SUB_CMD"
                ;;
        esac
    done

    P_REMAIN_ARGS="$*"

    # Deprecation warning if PDFNAME is still used (and does not
    # get overwritten by --name)
    #
    if [[ -n "$PDFNAME" && -z "$P_NAME" ]]; then
        ccecho "warn" "Warning: PDFNAME is deprecated. Use OUTPUTNAME instead."
    fi
}

###########################################################################
#
# INITIALIZE ENVIRONMENT
#
# Create needed directories and links
# Finally export some variables
#
###########################################################################
function init_env {
    # Create the log directory and a link to the DC-file in R_DIR
    # (R_DIR and LOG_DIR are set in bin/daps)

    local DC_COUNT TEST_ROOTID_RESULT

    # create directories

    mkdir -p "$R_DIR"
    if [[ 1 -eq $WRITE_LOG ]]; then
        mkdir -p "$LOG_DIR" || exit_on_error "Cannot create $LOG_DIR"
    fi


    if [[ -n $"$DOCCONF" && ! -f ${R_DIR}/$(basename "$DOCCONF") ]]; then
        ln -sf "$DOCCONF" "${R_DIR}/$(basename "$DOCCONF")"
        if [[ 0 -ne $? && 0 -ne $VERBOSITY ]]; then
            ccecho "warn" "Warning: Cannot create link to $DOCCONF in $R_DIR"
        fi
    fi

    # There should only be one DC-file in $R_DIR
    #
    DC_COUNT=$(find -L "$R_DIR" -maxdepth 1 -name "${CONF_PREFIX}*" -type f | wc -l 2>/dev/null)
    if [[ $DC_COUNT -gt 1 && 0 -ne $VERBOSITY ]]; then
        ccecho "warn" "$R_DIR contains more than one DC-file"
    fi

    # test if ROOTID exist
    #
    if [[ -n "$ROOTID" ]]; then
        EXISTS_ROOTID=$($XSLTPROC --stringparam "rootid=$ROOTID" --xinclude --stylesheet "${DAPSROOT}/daps-xslt/common/check_rootid.xsl" --file "$MAIN" "$XSLTPROCESSOR" 2>/dev/null)
        TEST_ROOTID_RESULT=$?
        if [[ 0 -eq $TEST_ROOTID_RESULT  && "yes" != "$EXISTS_ROOTID" ]]; then
            exit_on_error "Fatal: ROOTID \"$ROOTID\" does not exist."
        elif [[ 0 -ne $TEST_ROOTID_RESULT && 0 -ne $VERBOSITY ]]; then
            ccecho "warn" "Warning: Could not determine whether ROOTID \"$ROOTID\" exists."
        fi
    fi

    #
    # The DocBook stylesheets require a 0|1 for REMARKS, but
    # yes|no for DRAFT
    # In order not to add to that confusion we will accept 0|1|yes|no for
    # all of them and export the correct value here. Since META falls
    # into a similar category, we also handle it the same way.
    # We also need to reset the _STR variables that get added to the resulting
    # filename here, when REMARKS, META or DRAFT has been disabled
    #
    # DRAFT must be set to yes|no
    case "$DRAFT" in
        1|yes)
            export DRAFT="yes" ;;
        0|no|"")
            export DRAFT="no" ;;
        *)
            exit_on_error "Wrong value for DRAFT. Must be \"yes\" or \"no\"" ;;
    esac

    # REMARKS must be set to 1|0
    # if enabled (set to 1) implies DRAFT mode
    case "$REMARKS" in
        1|yes)
            export REMARKS=1 DRAFT="yes" ;;
        0|no|"")
            export REMARKS=0 ;;
        *)
            exit_on_error "Invalid value for REMARKS. Must be \"yes\" or \"no\""
            ;;
        esac

    # META must be set to 1|0
    # if enabled (set to 1) implies DRAFT mode
    case "$META" in
        1|yes)
            export META=1 DRAFT="yes" ;;
        0|no|"")
            export META=0 ;;
        *)
            exit_on_error "Invalid value for META. Must be \"yes\" or \"no\""
            ;;
    esac

    # COLOR must be set to 1|0
    # if we are not in a terminal but rather in a pipe, script, etc.
    # disable color output otherwise use the value specified on the
    # command line or in the config
    if [[  -t 1 ]]; then
        case $COLOR in
            "1" | "yes")
                export COLOR=1 ;;
            "0" | "no" | "")
                COLOR=0 ;;
            *)
                exit_on_error "Invalid value for COLOR. Must be \"yes\" or \"no\""
                ;;
        esac
    else
        # No terminal
        COLOR=0
    fi

    # export PARAMS and STRINGPARAMS
    [[ -n "$P_PARAMS" ]]      && export PARAMS="$P_PARAMS"
    [[ -n "$P_STRINGPARAMS" ]] && export STRINGPARAMS="$P_STRINGPARAMS"

    # Unset the strings last, because values for DRAFT or REMARKS
    # may have been altered in-between
    [[ "no" = "$DRAFT" ]] && unset DRAFT_STR
    [[ 0 -eq $META ]] && unset META_STR
    [[ 0 -eq $REMARKS ]] && unset REMARK_STR

}

###########################################################################
#
# Get Stylesheet Version
#
###########################################################################

function get_stylesheet {
    #
    # takes an URN to VERSION.xsl as a required parameter

    local STYLE_FILE STYLE_URN STYLE_VERSION

    STYLE_URN=$1

    [[ -z $STYLE_URN ]] && exit_on_error "Function get_stylesheet must be called with an URN"

    # saxon6 (at least on openSUSE) does not properly resolve http Urls
    # (because it does not ask the catalog but rather directly accesses
    # the URl) we need to resolve it via xmlcatalog first
    #
    STYLE_FILE=$(xmlcatalog "$XML_MAIN_CATALOG" "$STYLE_URN")
    STYLE_FILE=${STYLE_FILE##*file://}
    STYLE_VERSION=$($XSLTPROC --stylesheet "$DAPSROOT/daps-xslt/common/get-dbxslt-version.xsl" --file "$STYLE_FILE" "$XSLTPROCESSOR" 2>/dev/null || echo "Not available")
        echo "$STYLE_VERSION"
}


###########################################################################
#
# RUN MAKE
#
# Set up log writing and verbosity
# and call make
#
###########################################################################
function call_make {
    local COLWIDTH CORE_NO DBSTYLE_FILE DBSTYLE_VERS FB_STYLESHEET_VERS
    local LOGFILE MAKE_BIN MAKE_OPTIONS MAKE_CMD PROFVAR STRING SILENT
    local STYLEROOT_VERS SUB_CMD V
    local -a PROFVARIABLES

    # first argument passed to the function is the subcommand

    # Second and optional argument is "silent" - if set all debug and
    # verbosity settings are ignored. This allows to run call_make to set
    # variables (e.g. FILELIST=$(call_make "list-srcfiles")

    # In some cases, additional arguments are passed to this
    # function - they remain in $@ and will be passed "as is" to make
    #
    SUB_CMD=$1
    shift

    if [[ "silent" = "$1" ]]; then
        SILENT="1"
        shift
    fi

    # Check the remaining $@ - if it contains variable definitions (FOO=BAR
    # or FOO="BAR") it's OK, if it contains barewords, exit with an error
    #
    if [[ -n "$@" ]]; then
    for STRING in "$@"; do
        [[ $STRING =~ ^[a-zA-Z][a-zA-Z0-9_]*=..* ]] || exit_on_error "Unknown parameter \"$STRING\"."
    done
    fi

    # set up the final environment
    init_env

    #------
    # the make command
    #

    MAKE_OPTIONS="-f $DAPSROOT/make/selector.mk"
    MAKE_BIN="/usr/bin/make"
    if [[ 1 -ne $SILENT ]]; then
        if [[ 1 -eq $DEBUG || 3 -eq $VERBOSITY ]]; then
            # use remake if installed when in debug or highest verbosity mode
            IS_REMAKE=$(which remake 2>/dev/null)
            [[ -n "$IS_REMAKE" ]] && MAKE_BIN="/usr/bin/remake"
            MAKE_OPTIONS="$MAKE_OPTIONS --debug=b"
        fi
    fi

    # By default the number of parallel jobs for make is set to the number of
    # CPU cores. This can be overwritten with --jobs.
    # If verbosity 3 (-v3) is set, "make -j1" is forced
    #
    if [[ 0 -eq $VERBOSITY || 1 -eq $VERBOSITY || 2 -eq $VERBOSITY ]]; then
        MAKE_OPTIONS="$MAKE_OPTIONS -j${JOBS}"
        [[ 1 -ne $DEBUG || 1 -eq $SILENT ]] && MAKE_OPTIONS="$MAKE_OPTIONS -s"
    else
        # highest verbosity level - use -j1 for a better readability
        MAKE_OPTIONS="$MAKE_OPTIONS -j1"
    fi

    # Is --force set to force a rebuild?
    [[ 1 -eq $FORCE_REBUILD ]] &&  MAKE_OPTIONS="$MAKE_OPTIONS --always-make"

    MAKE_CMD="$MAKE_BIN $MAKE_OPTIONS $SUB_CMD $*"


    # Variable settings summary printed on debug and high verbosity mode
    if [[ 2 -le $VERBOSITY && 1 -ne $SILENT ]]; then
    # list of profiling variables for the debug output
    #
        PROFVARIABLES=(
            PROFARCH
            PROFAUDIENCE
            PROFCONDITION
            PROFCONFORMANCE
            PROFLANG
            PROFOS
            PROFOUTPUTFORMAT
            PROFREVISION
            PROFREVISIONFLAG
            PROFROLE
            PROFSECURITY
            PROFSTATUS
            PROFUSERLEVEL
            PROFVENDOR
            PROFWORDSIZE )

        # column width debug output (for printf)
        COLWIDTH=20

        # get DocBook stylesheet version
        #
        DBSTYLE_VERS=$(get_stylesheet "http://docbook.sourceforge.net/release/xsl/current/VERSION.xsl")

        STYLEROOT_VERS=$(get_stylesheet "file://${STYLEROOT}/VERSION.xsl")
        FB_STYLEROOT_VERS=$(get_stylesheet "file://${FALLBACK_STYLEROOT}/VERSION.xsl")

        echo -e "---------------\n"
        # DAPS version
        printf "%${COLWIDTH}s: %s\n" "$MY_NAME VERSION" "$VERSION"

        echo

        # Directories
        for V in DOC_DIR BUILD_DIR DAPSROOT DOCCONF BOOK; do
            printf "%${COLWIDTH}s: %s\n" "$V" "${!V}"
        done

        echo

        # Profiling
        # show all profiling variables and their values
        for PROFVAR in ${PROFVARIABLES[*]}; do
            [[ -n ${!PROFVAR} ]] && printf "%${COLWIDTH}s: %s\n" "$PROFVAR" "${!PROFVAR}"
        done

        echo

        # DocBook
        for V in DOCBOOK_VERSION DOCBOOK5_RNG DBSTYLE_VERS; do
            printf "%${COLWIDTH}s: %s\n" "$V" "${!V}"
        done

        echo

        # Styleroot / Fallback styleroot
        if [[ $SUB_CMD =~ text && "yes" == "$TXT_IGNORE_STYLEROOT" || 1 -eq "$TXT_IGNORE_STYLEROOT" ]]; then
            printf "%${COLWIDTH}s: %s\n" "STYLEROOT" "$DOCBOOK_STYLES"
        else
            if [[ -n "$STYLEDEVEL" ]]; then
                printf "%${COLWIDTH}s: %s\n" "STYLEROOT" "$STYLEDEVEL"
            else
                if [[ -n "$STYLEROOT" ]]; then
                    printf "%${COLWIDTH}s: %s\n" "STYLEROOT" "$STYLEROOT"
                else
                   printf "%${COLWIDTH}s: %s\n" "STYLEROOT" "$DOCBOOK_STYLES"
                fi
            fi

            printf "%${COLWIDTH}s: %s\n" "STYLEROOT_VERS" "$STYLEROOT_VERS"

            if [[ -n "$FALLBACK_STYLEROOT" ]]; then
                printf "%${COLWIDTH}s: %s\n" "FALLBACK_STYLEROOT" "$FALLBACK_STYLEROOT"
            else
                # no fallback if STYLEROOT is not set
                if [[ -n "$STYLEROOT" ]]; then
                    printf "%${COLWIDTH}s: %s\n" "FALLBACK_STYLEROOT" "$DOCBOOK_STYLES"
                fi
            fi
            printf "%${COLWIDTH}s: %s\n" "FB_STYLEROOT_VERS" "$FB_STYLEROOT_VERS"
        fi

        # CSS
        printf "%${COLWIDTH}s: %s\n" "EPUB_CSS" "$EPUB_CSS"
        printf "%${COLWIDTH}s: %s\n" "HTML_CSS" "$HTML_CSS"

        echo

        # PDF
        printf "%${COLWIDTH}s: %s\n" "PDF FORMATTER" "$FORMATTER"
        if which "$FORMATTER" >/dev/null 2>&1; then
            printf "%${COLWIDTH}s: %s\n" "FORMATTER VERSION" "$($FORMATTER -version)"
        else
            printf "%${COLWIDTH}s: %s\n" "FORMATTER VERSION"
        fi
        if [[ "fop" = "$FORMATTER" ]]; then
            printf "%${COLWIDTH}s: %s\n" "FORMATTER WRAPPER" "$FOP_WRAPPER"
            printf "%${COLWIDTH}s: %s\n" "FORMATTER CONFIG" "$FOP_CONFIG_FILE"
        elif [[ "xep" = "$FORMATTER" ]]; then
            printf "%${COLWIDTH}s: %s\n" "FORMATTER WRAPPER" "$XEP_WRAPPER"
            printf "%${COLWIDTH}s: %s\n" "FORMATTER CONFIG:" "$XEP_CONFIG_FILE"
        fi

        echo

        # Misc
        for V in MAKE_CMD XSLTPROCESSOR XML_CATALOG_FILES; do
            printf "%${COLWIDTH}s: %s\n" "$V" "${!V}"
        done
        echo -e "\n---------------\n"
    fi

    if [[ 1 -eq $WRITE_LOG ]]; then
        LOGFILE="${LOG_DIR}/make_${SUB_CMD}.log"
        date &> "$LOGFILE"
    fi

    if [[ 0 -ne $VERBOSITY ]]; then
        if [[ 1 -eq $WRITE_LOG ]]; then
            $MAKE_CMD 2>&1 | tee -a "$LOGFILE"
            # see http://www.unix.com/shell-programming-scripting/92163-command-does-not-return-exit-status-due-tee.html
            [[ 0 -eq ${PIPESTATUS[0]} ]] || exit 1
        else
            $MAKE_CMD 2>&1
        fi
    else
        if [[ 1 -eq $WRITE_LOG ]]; then
            $MAKE_CMD >> "$LOGFILE" 2>&1
            if [[ 0 -eq $? ]]; then
                # make command successful, only show last line (aka result)
                tail -n 1 "$LOGFILE"
            else
                # an error occured in make
                # show complete logfile except the first line containing the
                # date
                tail -n +2 "$LOGFILE"
                exit 1
            fi
        else
            $MAKE_CMD
        fi
    fi
}

##########################################################
#
# FUNCTION TEMPLATE
#
##########################################################
#    local SHORT_OPTS LONG_OPTS SUB_CMD

    # The subcommand value is passed when calling this function
#    SUB_CMD=$1
#    shift

    # SHORT_OPTS: Value for the getopt -o option
    # LONG_OPTS:  VALUE for the getopt -l option
#    SHORT_OPTS="h"
#    LONG_OPTS="draft,formatter:,help,name:,remarks,rootid:"

    # Call the argument parser
#    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"

    # Reset this functions $@ to what is remaining after having parsed the
    # subcommand switches
#    eval set -- "$P_REMAIN_ARGS"

#    #------ Computing the values returned from the parser -----

#    <REPLACE ME>

#    call_make "$UB_CMD" "$@"


###########################################################################
#
# Generic BUILD function
#
# Subcommands: all commands that does not fit elsewhere
#
###########################################################################
function build_generic {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="help,name:,norefcheck,param:,rootid:,stringparam:"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
        help_help
        help_name
        help_norefcheck
        help_param
        help_rootid
        help_stringparam
        echo
        exit 0
    fi

    call_make "$SUB_CMD" "$@"
}



###########################################################################
#
#  PROFILE First
#
#  Some subcommands (such as projectgraphics and various dist and packaging
#  targets) require an up-tp-date .profiled/*
#  Therefore we call make profile first and then call make a second time
#  with the real target
#
###########################################################################
function profile_first {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="draft,help,name:,remarks,rootid:"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
        help_draft
        help_name
        help_remarks
        help_rootid
        echo
        exit 0
    fi

    # we do not want to write a logfile this time
    WRITE_LOG=0
    call_make "profile" "$@" || exit_on_error "Profiling failed"
    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
#  VALIDATION
#
#  Subcommand: validate
#
###########################################################################
function validate {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="help,norefcheck,not-validate-tables,remarks,validate-ids,validate-images"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
        help_norefcheck
        help_not-validate-tables
        help_remarks
        help_validate-ids
        help_validate-images
        echo
        exit 0
    fi

    # we do not want to write a logfile this time
    WRITE_LOG=0
    call_make "$SUB_CMD" "$@"

}

###########################################################################
#
#  FILELISTS
#
#  Subcommands: list-files, list-srcfiles*, list-images-*
#
###########################################################################
function filelists {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="adoconly,help,imgonly,noadoc,nodc,noent,noimg,noxml,pretty,rootid:,xmlonly"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
        help_help
        if [[ $SUB_CMD =~ list-srcfiles ]]; then
            help_adoconly
            help_imgonly
            help_noadoc
            help_nodc
            help_noent
            help_noimg
            help_noxml
            help_xmlonly
        fi
        [[ $SUB_CMD != list-file ]] && help_pretty
        help_rootid
        echo
        exit 0
    fi

    # --imgonly and --xmlonly are shortcuts
    #
    if [[ 1 -eq $P_LIST_IMG_ONLY ]]; then
        export LIST_NODC=1 LIST_NOENT=1 LIST_NOXML=1
    elif [[ 1 -eq $P_LIST_XML_ONLY ]]; then
        export LIST_NODC=1 LIST_NOENT=1 LIST_NOIMG=1
    fi

    if [[ $SUB_CMD = list-file && -z $ROOTID ]]; then
    exit_on_error "You need to specify an ID with --rootid with the list-file command."
    fi

    # we do not want to write a logfile this time
    WRITE_LOG=0
    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
#  SHOW NAMES
#
#  function for all targets showing a filename or a directory
#  (pdf-name, htmlsingle-name, etc.)
#
###########################################################################

function show_names {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="cropmarks,draft,formatter:,grayscale,help,meta,name:,remarks,rootid:,single"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
                help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
                [[ "pdf-name" = "$SUB_CMD" ]] && help_cropmarks
                help_draft
                [[ "pdf-name" = "$SUB_CMD" ]] && help_formatter
                [[ "pdf-name" = "$SUB_CMD" ]] && help_grayscale_pdf
                help_help
                help_meta
                help_name
                help_remarks
                help_rootid
                [[ "html-dir-name" = "$SUB_CMD" ]] && help_single
                echo
                exit 0
    fi

    # we do not want to write a logfile this time
    WRITE_LOG=0
    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
# Debugging function
#
# Subcommands: dapsenv, nothing, showvariable
#
###########################################################################
function debugging {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="help,name:,rootid:,target:"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
        help_help
        help_name
        help_rootid
        help_target
        echo
        exit 0
    fi

    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
#  MISC
#
#  various functions
#
###########################################################################

# call make directly
# for functions with no command line options
# do not write a log
function no_opts {
    local CURR_DIR SHORT_OPTS LONG_OPTS SUB_CMD
    local SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="help"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}" "0"
        exit 0
    fi

    WRITE_LOG=0
    if [[ $SUB_CMD =~ ^clean.* ]]; then
        #
        # Use the cd commands to avoid errors when running DAPS from
        # one of the directories that get removed
        #
        CURR_DIR=$(pwd 2>/dev/null)
        cd $DOC_DIR > /dev/null
        call_make "$SUB_CMD" "$@"
        [[ -d $CURR_DIR ]] && cd $CURR_DIR
    else
        call_make "$SUB_CMD" "$@"
    fi
}

# error message for deprecated targets
function deprecated {
    local SUB_CMD=$1
    ccecho "error" "${HELP_SUBCOMMAND[$SUB_CMD]}"
    exit 1
}


# error message when specifying an invalid subcommand
function wrong_parameter {
    local SUB_CMD=$1
    echo "Type '$ME $SUB_CMD help' to get a list of valid parameters"
    exit 1;
}

# needed by docmanager
function showenv {
    echo "DOC_DIR=$DOC_DIR;DOCCONF=$DOCCONF"
    exit 0
}

###########################################################################
#
# HELP
#
# There are a lot of options, several functions have in common.
# In order to not have to write the same text again and again, we
# provide a help function for each option
#
###########################################################################

# first line of help
#
function help_scmd_head {
    echo -e "$ME [--global-options] $1 [options]

$2\n"

[[ 0 -ne $3 ]] && echo -e "  Command options:"
}

function help_adoconly {
    cat <<EOF
    --adoconly                Only list AsciiDoc and include files.
                              Shortcut for --nodc --noent --noimg.
EOF
}
function help_check {
    cat <<EOF
    --check                   Validate the resulting document.
                              Implies a verbosity level of at least 1.
                              Default: unset
EOF
}
function help_clean {
    cat <<EOF
    --clean                   Clean up the result directory (delete all files
                              and subdirectories) before building the document.
                              Default: unset
EOF
}
function help_color {
    cat <<EOF
    --color                   Only generate color images.
                              Default: off
EOF
}
function help_compact {
    cat <<EOF
    --compact                 Print the filelist on a single line.
                              Ignored when -s|--show is set.
                              Default: off
EOF
}
function help_cropmarks {
    cat <<EOF
    --cropmarks               Add cropmarks to the PDF. Only available for
                              the XEP formatter, FOP currently does not support
                              cropmarks.
                              Ignored when FOP is used.
                              Default: off
EOF
}
function help_css {
    cat <<EOF
    --css=filename,           Specify a path to a css file.
    --css=none                The special string \"none\" forces DAPS to use
                              no css, even when configured elsewhere
                              (e.g. in a config file).
                              Default: unset
EOF
}
function help_css_epub {
    cat <<EOF
    --css=filename            Specify a path to a css file.
                              Default: unset
EOF
}
function help_def-file {
    cat <<EOF
    --def-file=FILE           Specify a DEF-* file containing build
                              information
EOF
}
function help_desktopfiles {
    cat <<EOF
    --desktopfiles            Generate .desktop files.
                              Default: off
EOF
}
function help_documentfiles {
    cat <<EOF
    --documentfiles           Generate .document files.
                              Default: off
EOF
}
function help_draft {
    cat <<EOF
    --draft                   Add a 'DRAFT' watermark to all pages of the book
                              Default: off
EOF
}
function help_epub3 {
    cat <<EOF
    --epub3                   Generate ePUB version 3 eBooks.
                              Default: ePUB version 2
EOF
}
function help_export-dir {
    cat <<EOF
    --export-dir=DIRECTORY    Specify a directory where to copy the results
                              of the $TARGET command. The directory will be
                              created if it does not exist.
                              Default: <BUILD_DIRECTORY>/locdrop
EOF
}
function help_extra-dict {
    cat <<EOF
    --extra-dict=filename     Specify a path to an additional custom
                              dictionary.
                              Default: unset
EOF
}
function help_file {
    cat <<EOF
    --file=FILE               Specify the name of an input file
EOF
}
function help_formatter {
    cat <<EOF
    --formatter=FORMATTER     Specify the PDF formatter to be used. Currently
                              'xep' or 'fop' are supported.
                              Default: 'fop'
EOF
}
function help_gen {
    cat <<EOF
    --gen                     Do all image conversions (images/gen) but
                              do not generate or link the images to
                              images/color or images/grayscale.
                              Default: unset
EOF
}
function help_grayscale_images {
    cat <<EOF
    --grayscale               Only generate grayscale images.
                              Default: off
EOF
}
function help_grayscale_pdf {
    cat <<EOF
    --grayscale               Generate a grayscale PDF for printing.
                              Default: off
EOF
}
function help_help {
    cat <<EOF
    --help, -h                Print this help text
EOF
}
function help_html5 {
    cat <<EOF
    --html5                   HTML builds are generated as XHTML files.
                              Force HTML 5 with this switch.
                              Default: unset
EOF
}
function help_ignore-styleroot {
    cat <<EOF
    --ignore-styleroot        Ignore all stylesheet assignments (e.g. the
                              DC file) and use the original DocBook stylesheets
                              instead. Use this option if your custom
                              stylesheets produce text output you are not
                              satisfied with.
                              Default: unset
EOF
}
function help_imgonly {
    cat <<EOF
    --imgonly                 Only list images files.
                              Shortcut for --nodc --noent --noxml|--noadoc.
EOF
}
function help_lang {
    cat <<EOF
    --lang                    Specify a language to use for spellchecking.
                              See \"man aspell \" for details.
                              Default: en_US
EOF
}
function help_lean {
    cat <<EOF
    --lean                    Create a lean PDF with reduced graphics
                              quality and a small file size (e.g. for
                              sharing via email). This PDF will be created
                              in addition to the regular one.
                              Default: off
EOF
}
function help_list {
    cat <<EOF
    --list                    Dumps a sorted list of misspelled words to
                              standard output instead of starting the
                              interactive spellchecker.
EOF
}
function help_locdrop {
    cat <<EOF
    --locdrop                 Use this option to create a source tarball
                              from a previous locdrop after translation.
                              If set, will include the files manifest_*.txt
                              in the source tarball.
                              Default: off
EOF
}
function help_meta {
    cat <<EOF
    --meta                    If set, prints additional status information
                              (filename, maintainer and status) for each file.
                              Implies draft mode.
                              Default: off
                              Does not work with AsciiDoc sources
EOF
}
function help_modified {
    cat <<EOF
    --modified                Print the image modification time.
                              Ignored when --compact is set.
                              Default: off
EOF
}
function help_name {
    cat <<EOF
    --name=BOOKNAME           File and directory names for generated content
                              are derived from BOOKNAME.
                              Default: generated by stripping 'DC-' from the
                              doc config filename
EOF
}
function help_noadoc {
    cat <<EOF
    --noxml                   Exclude AsciiDoc and include files from list.
                              Default: unset
EOF
}
function help_nodc {
    cat <<EOF
    --nodc                    Exclude DC-file from list.
                              Default: unset
EOF
}
function help_noent {
    cat <<EOF
    --noent                   Exclude Entity files from list.
                              Default: unset
EOF
}
function help_nogzip {
    cat <<EOF
    --nogzip                  If specified, man pages will not be compressed
                              with gzip.
                              Default: unset
EOF
}
function help_noimg {
    cat <<EOF
    --noimg                   Exclude images from list.
                              Default: unset
EOF
}
function help_nohelp {
    cat <<EOF

No further help for subcommand \"$1\" available.
EOF
}
function help_nopdf {
    cat <<EOF
    --nopdf                   Deactivates creating the color-pdf. Useful when
                              "locdropping" a complete set where you
                              want to deliver separate PDFs for each book
                              rather than one huge PDF for the whole set.
                              Default: PDF is created
EOF
}
function help_norefcheck {
    cat <<EOF
    --norefcheck              Disables checking internal links
                              (ID/IDREF/IDREFS) and thus allows to build
                              or validate with e.g. xref-links pointing
                              to non-existing IDs.
                              This option only affects DocBook 5 sources and is
                              ignored when processing DocBook 4.
                              Default: unset
EOF
}
function help_nosearch {
    cat <<EOF
    --nosearch                Deactivates creating the search tab in webhtml
                              builds.
                              Default: enabled
EOF
}
function help_nostatic {
    cat <<EOF
    --nostatic                Normally images and css files in HTML builds
                              are copied from elsewhere in the file system.
                              Use this option to link these files in order
                              to save disk space. Note that this eventually
                              produces nested links which may cause errors
                              with CSS and Javascript.
EOF
}
function help_not-validate-tables {
    cat <<EOF
    --not-validate-tables     Disable checking for tables that contain
                              structural errors (e.g. missing cells).
                              Default: unset (table check is performed)
EOF
}
function help_novalid {
    cat <<EOF
    --novalid                 Do not perform a validation check on the
                              (profiled) sources. However, they need to be
                              well-formed.
                              Implies a validation check on the resulting
                              bigfile.
                              Default: unset
EOF
}
function help_noxml {
    cat <<EOF
    --noxml                   Exclude XML files from list.
                              Default: unset
EOF
}
function help_online {
    cat <<EOF
    --online                  Only generate images used for HTML builds.
                              Default: off
EOF
}
function help_optipng {
    cat <<EOF
    --optipng                 Optimize PNG images by reducing the color
                              palette (using optipng), Modifies the original
                              sources!
                              Default: off
EOF
}
function help_pagefiles {
    cat <<EOF
    --pagefiles               Generate .page files.
                              Default: off
EOF
}
function help_param {
    cat <<EOF
    --param="KEY=VALUE"       Add an xslt processor parameter.
                              Useful to temporarily overwrite/set style sheet
                              parameters such as margins.
                              This parameter can be specified multiple times.
                              Default: unset
EOF
}
function help_pretty {
    cat <<EOF
    --pretty                  Pretty print file lists (one filename per line)
EOF
}
function help_remarks {
    cat <<EOF
    --remarks                 Include remarks (<remark>...</remark>) in book
                              Implies draft mode.
                              Default: off
EOF
}
function help_rootid {
    cat <<EOF
    --rootid=ID               Specify a ROOTID to build only parts of a book
                              (parts or chapters). Default: Usually set
                              in the DC-file; if not set the complete set
                              defined in \$MAIN will be built
                              Does not work with AsciiDoc sources
EOF
}
function help_set-date {
    cat <<EOF
    --set-date=YYYY/MM/DD     Set a publication date. If not set, the current
                              date will automatically be chosen.
                              Default: current date
EOF
}
function help_show_images {
    cat <<EOF
    --show                    Show images with an image viewer that either
                              has been specified with --viewer or by setting
                              IMG_VIEWER in the config file
                              Default: off
EOF
}
function help_show_check {
    cat <<EOF
    --show                    Show the result of the check command
                              in a browser. Uses \$BROWSER if defined,
                              otherwise xdg-open.
                              Default: off
EOF
}
function help_single {
    cat <<EOF
    --single                  Creates a single file HTML output (as opposed to
                              the default, which generates chunked HTML,
                              consisting of several HTML pages.
                              Default: off
EOF
}
function help_spellchecker {
    cat <<EOF
    --spell-checker           Specify the name of the spell checking command,
                              such as 'aspell' or 'hunspell'.
                              DEFAULT: aspell
EOF
}
function help_statdir {
    cat <<EOF
    --statdir=DIRECTORY       Specify a DIRECTORY containing resource files
                              (CSS, images, Javascript etc.).
                              DEFAULT: \$STYLEROOT/static
EOF
}
function help_stringparam {
    cat <<EOF
    --stringparam="KEY=VALUE" Add an xslt processor parameter.
                              Useful to temporarily overwrite/set style sheet
                              parameters such as margins.
                              This parameter can be specified multiple times.
                              Default: unset
                              Does not work with AsciiDoc sources
EOF
}
function help_subdirs {
    cat <<EOF
    --subdirs                 Man pages are created in a man/ directory.
                              To also enable the subdirectories man1/, man2/,
                              etc., specify this parameter.
                              Default: off
EOF
}
function help_target {
    cat <<EOF
    --target=TARGET           Specify a potential target (such as pdf)
                              to retrieve correct values for target-specific
                              values.
                              Default: same as daps subcommand
EOF
}
function help_validate-ids {
    cat <<EOF
    --validate-ids            Also check IDs to include no other
                              characters than '[-a-zA-Z0-9].
                              Default: unset
EOF
}
function help_validate-images {
    cat <<EOF
    --validate-images         Also check for missing and duplicated images.
                              Missing images cause an error, duplicated
                              imnages a warning only.
                              Default: unset
EOF
}
function help_viewer {
    cat <<EOF
    --viewer=VIEWER           Image viewer to be used.
                              Default: IMG_VIEWER setting from config file
EOF
}
function help_xmlonly {
    cat <<EOF
    --xmlonly                 Only list XML files.
                              Shortcut for --nodc --noent --noimg.
EOF
}
