#
# Functions for ../bin/daps
#
# Copyright (C) 2011 Frank Sundermeyer <fs@suse.de>, openSUSE.org
# Authors: Frank Sundermeyer <fs@suse.de>
#
#

# TODO:
#
# Consider moving init_wd to a separate script


###########################################################################
#
# ARGUMENT PARSER FOR ALL SUBCOMANDS 
#
# Generic parser for the subcommand's 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 = $? ]]; then
        wrong_parameter "$SUB_CMD"
    fi

    eval set -- "$C_ARGS"
    
    while true ; do
        case "$1" in
            -c|--comments)
		P_COMMENTS=1
		shift
		;;
            --compact)
                P_COMPACT=1
                shift
                ;;
            -d|--draft)
		P_DRAFT=1
		shift
		;;
            --def-file)
                P_DEF_FILE="$2"
                shift 2
                ;;
            --dirname)
                P_DIRNAME="$2"
                shift 2
                ;;
            -f|--file)
                P_FILE="$2"
                shift 2
                ;;
            --fop)
                P_FOP="$2"
		shift 2
		;;
            -h|--help)
                P_HELP=1
                shift
                ;;
            -m|--meta)
                P_META=1
                shift
                ;;
            --modified)
                P_MODIFIED=1
                shift
                ;;
            -n|--nopdf)
                P_NOPDF=1
                shift
                ;;
            --name)
                P_PDFNAME="$2"
                shift 2
                ;;
            -p|--pretty)
                P_PRETTY=1
                shift
                ;;
            -r|--remarks)
		P_REMARKS=1
		shift
		;;
            --rootelement)
                ROOTELEMENT="$2"
		shift 2
		;;
            --rootid)
		P_ROOTID="$2"
		shift 2
		;;
            -s|--show)
                P_SHOW=1
                shift
                ;;
            --static)
		P_STATIC=1
		shift
		;; 
	    --viewer)
                P_VIEWER="$2"
		shift 2
		;;
            --xsltparam)
                P_XSLTPARAM="$2"
		shift 2
		;;
            --)
                shift
                break
                ;;
            *)
                wrong_parameter "SUB_CMD"
                ;;
        esac
    done

    P_REMAIN_ARGS="$@"

}

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

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

    
    if [[ ! -f ${R_DIR}/$ENVFILE ]]; then
        ln -sf ${BASE_DIR}/$ENVFILE ${R_DIR}/$ENVFILE || ccecho "warn" "Warning: Cannot create link to $ENVFILE in $R_DIR"
    fi

    # There should only be one ENVFILE in $R_DIR
    #
    ENV_COUNT=$(find -L $R_DIR -maxdepth 1 -name "${CONF_PREFIX}*" -type f | wc -l)
    if [[ $ENV_COUNT -gt 1 ]]; then
        ccecho "warn" "$R_DIR contains more than one ENVFILE"
    fi

    #
    # The DocBook stylesheets require a 0|1 for REMARKS and COMMENTS, 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 USEMETA 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, COMMENTS or DRAFT has been disabled
    #
    
    # COMMENTS must be set to 1|0
    case "$COMMENTS" in
        1|yes)
            export COMMENTS=1 ;;
        0|no|"")
            export COMMENTS=0
            unset COMMENT_STR ;;
        *)
            exit_on_error "Wrong value for COMMENTS. Must be \"yes\" or \"no\""
            ;;
    esac
    
    # DRAFT must be set to yes|no
    case "$DRAFT" in
        1|yes)
            export DRAFT="yes" ;;
         0|no|"")
            export DRAFT="no"
            unset DRAFT_STR ;;
        *)
            exit_on_error "Wrong value for DRAFT. Must be \"yes\" or \"no\"" ;;
    esac
    
    # REMARKS must be set to 1|0
    case "$REMARKS" in
        1|yes)
            export REMARKS=1 ;;
        0|no|"")
            export REMARKS=0
            unset REMARK_STR ;;
        *)
            exit_on_error "Wrong value for REMARKS. Must be \"yes\" or \"no\""
            ;;
        esac
    
    # USEMETA must be set to 1|0
    case "$USEMETA" in
        1|yes)
            export USEMETA=1 ;;
          0|no|"")
            export USEMETA=0 ;;
        *)
            exit_on_error "Wrong value for USEMETA. Must be \"yes\" or \"no\""
            ;;
    esac

}   

###########################################################################
#
# RUN MAKE
#
# Set up log writing and verbosity
# and call make
#
###########################################################################
function call_make () {
    local CORE_NO LOG_PIPE LOGFILE MAKECMD MCMD SHOWVARS SUB_CMD

    # first argument passed to the function is the subcommand
    # 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

    # set up the final environment
    init_env

    # the make command
    if [[ 1 = $DEBUG ]]; then
        # use remake if installed
        # disable threading (-j1) in order to have the output in the
        # same order as the code
        #
        which remake &>/dev/null
        if [[ 0 = $? ]]; then
            MAKECMD="/usr/bin/remake -j1 --debug=b"
        else
            MAKECMD="/usr/bin/make -j1 --debug=b"
        fi
    else
        # calculate Number of CPUs (cores) for -j option, set to "1" if empty
        CORE_NO=$(egrep -s -m1 "cpu cores\s*:" /proc/cpuinfo 2>/dev/null | sed 's/cpu cores\s*:\s*//')
        test -z "$CORE_NO" && CORE_NO=1
        MAKECMD="/usr/bin/make -j${CORE_NO} -s"
    fi
    MCMD="$MAKECMD -f $DTDROOT/make/common.mk $SUB_CMD $@"

    
    # Variable settings summary printed on debug and high verbosity mode
    if [[ 2 = $VERBOSITY ]]; then
        SHOWVARS=$(cat <<EOF
---------------
   BASE_DIR: $BASE_DIR
  BUILD_DIR: $BUILD_DIR
    ENVFILE: $ENVFILE
    DTDROOT: $DTDROOT
       BOOK: $BOOK
        FOP: $FOPTYPE
    MAKECMD: $MAKECMD
    STYLEFO: $STYLEFO
XML_CATALOG: $XML_CATALOG_FILES
---------------
EOF
        )
    fi

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

    if [[ 0 != $VERBOSITY ]]; then
        eval "echo \"$SHOWVARS\" $LOG_PIPE"
        eval "$MCMD 2>&1 $LOG_PIPE"
    else
        if [[ 1 = $WRITE_LOG ]]; then
            eval "$MCMD >> $LOGFILE 2>&1"
            if [[ 0 = $? ]]; 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
           eval "$MCMD"
        fi
    fi
}

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

    # 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="cdhr"
#    LONG_OPTS="comments,draft,fop:,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" "$@"


###########################################################################
#
# BUILD PDFS 
#
# Subcommands: pdf,color-pdf
#
###########################################################################
function build_pdfs () {
    local SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="cdhmr"
    LONG_OPTS="comments,draft,fop:,help,meta,name:,remarks,rootid:,xsltparam:"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Build a $SUB_CMD book"
        help_comments
        help_draft
        help_fop
        help_help
        help_meta
        help_name
        help_remarks
        help_rootid
        help_xsltparam "creates the .fo file from the profiled sources"
        echo
        exit 0
    fi
    
    [[ 1 = $P_COMMENTS ]] && COMMENTS=1
    [[ 1 = $P_DRAFT ]]    && DRAFT="yes"
    [[ 1 = $P_REMARKS ]]  && REMARKS=1 DRAFT="yes"
    # usemeta implies draft mode with remarks
    [[ 1 = $P_META ]]     && USEMETA=1 DRAFT="yes"
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"
    [[ -n $P_XSLTPARAM ]] && export XSLTPARAM="$P_XSLTPARAM"
    
    if [[ -n $P_FOP ]]; then
        if [[ xep = $P_FOP || fop = $P_FOP ]]; then
            export FOPTYPE="$P_FOP"
            export FOP="${LIB_DIR}/daps-$P_FOP"
        else
	    exit_on_error "Wrong parameter for --fop: must be \"xep\" or \"fop\"!"
        fi
    fi
    
    call_make "$SUB_CMD" "$@"
}


###########################################################################
#
# BUILD HTML and JSP 
#
# Subcommands: html, htmlsingle, jsp 
#
###########################################################################
function build_html_jsp () {
    local SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="cdhmr"
    LONG_OPTS="comments,draft,help,name:,meta,remarks,rootid:,static,xsltparam:"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Build a $SUB_CMD book"
        help_comments
        help_draft
        help_help
        help_meta
        help_name
        help_remarks
        help_rootid
        help_static
        help_xsltparam "creates HTML from the profiled sources"
        echo
        exit 0
    fi
    
    [[ 1 = $P_COMMENTS ]] && COMMENTS=1
    [[ 1 = $P_DRAFT ]]    && DRAFT="yes"
    [[ 1 = $P_REMARKS ]]  && REMARKS=1 DRAFT="yes"
    # usemeta implies draft mode with remarks
    [[ 1 = $P_META ]]     && USEMETA=1 DRAFT="yes"
    [[ 1 = $P_STATIC ]]   && export STATIC_HTML=1
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_XSLTPARAM ]] && export XSLTPARAM="$P_XSLTPARAM"

    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
# BUILD ePUB 
#
# Subcommands: epub only
#
###########################################################################
function build_epub () {
    local SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="hr"
    LONG_OPTS="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 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Build a $SUB_CMD book"
        help_help
        help_name
        help_rootid
        echo
        exit 0
    fi
    
    [[ 1 = $P_REMARKS ]]  && REMARKS=1
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"

    call_make "$SUB_CMD" "$@"
}

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

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

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Build a $SUB_CMD book"
        help_help
        help_name
        help_rootid
        echo
        exit 0
    fi

    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"
    
    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
# PACKAGING locdrop
#
# Subcommand: locdrop only
#
###########################################################################
function build_locdrop () {
    local SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="hn"
    LONG_OPTS="def-file:,help,name:,nopdf,rootid:"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Provide everything that is needed to translate a set"
        help_def-file
        help_help
        help_name
        help_nopdf
        help_rootid
        echo
        exit 0
    fi
    
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_NOPDF ]]     && export export NOPDF=1
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"

    if [[ -f $P_DEF_FILE ]]; then
        export DEF_FILE="$P_DEF_FILE"
    elif [[ -z $P_DEF_FILE ]]; then
        ccecho "warn" "Warning: No DEF file was specified"
    else
        exit_on_error "Cannot find DEF file P_DEF_FILE"
    fi
    
    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
#  Generic PACKAGING
#
#  Subcommands: all packaging targets except locdrop
#
###########################################################################
function packaging () {
    local SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="hn"
    LONG_OPTS="def-file:,help,name:,nopdf,rootid:"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Provide a $SUB_CMD package"
        if [[ package-pdf = $TARGET ]]; then
            help_fop
        elif [[ package-src = $TARGET ]]; then
            help_def-file
        fi
        help_help
        help_name
        help_rootid
        echo
        exit 0       
    fi
    
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"

    if [[ -f $P_DEF_FILE ]]; then
        export DEF_FILE="$P_DEF_FILE"
    else
        exit_on_error "Cannot find DEF file P_DEF_FILE"
    fi

    if [[ -n $P_FOP ]]; then
        if [[ xep = $P_FOP || fop = $P_FOP ]]; then
            export FOPTYPE="$P_FOP"
            export FOP="${LIB_DIR}/daps-$P_FOP"
        else
	    exit_on_error "Wrong parameter for --fop: must be \"xep\" or \"fop\"!"
        fi
    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 HELPTXT SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="cdhr"
    LONG_OPTS="comments,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 = $P_HELP ]]; then
        case "$SUB_CMD" in
            dist-all)
                HELPTXT="This is an unmaintained target and may not work" ;;
            showvariable)
                HELPTXT="Show the value of the given make variable: Example: daps showvariable -r VARIABLE=REMARKS" ;;
        esac
        help_scmd_head "$SUB_CMD" "$HELPTXT"
        help_comments
        help_draft
        help_name
        help_remarks
        help_rootid
        echo
	exit 0
    fi
    
    [[ 1 = $P_COMMENTS ]] && COMMENTS=1
    [[ 1 = $P_DRAFT ]]    && DRAFT="yes"
    [[ 1 = $P_REMARKS ]]  && REMARKS=1
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"
    
    # 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" "$@"
}

###########################################################################
#
#  COMMENTS/REMARKS
#
#  Subcommands validate and profiledir behave differently when
#  comments or remarks are enabled
#
###########################################################################
function comments_remarks () {
    local HELPTXT SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="chr"
    LONG_OPTS="comments,help,remarks"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        case "$SUB_CMD" in
            profiledir)
                HELPTXT="Print the profiling directory" ;;
            validate)
                HELPTXT="Validate profiled XML sources with xmllint" ;;
        esac
        help_scmd_head "$SUB_CMD" "$HELPTXT"
        help_comments
        help_remarks
        echo
	exit 0
    fi
    
    [[ 1 = $P_COMMENTS ]] && COMMENTS=1
    [[ 1 = $P_REMARKS ]]  && REMARKS=1   

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

###########################################################################
#
#  FILELISTS
#
#  Subcommands: missinggraphics, project(files|graphics),
#               remaining(files|graphics)
#
###########################################################################   
function filelists () {
    local HELPTXT SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="hp"
    LONG_OPTS="help,pretty"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        case "$SUB_CMD" in
            missinggraphics)
                HELPTXT="Print the list of missing graphic files" ;;
            projectfiles)
                HELPTXT="Print the list of the project's XML files" ;;
            projectgraphics)
                HELPTXT="Print the list of the project's graphic files" ;;
            remainingfiles)
                HELPTXT="Print the list of XML files not belonging to the current project" ;;
            remaininggraphics)
                HELPTXT="Print the list of graphics not belonging to the current project";;
        esac
        help_scmd_head "$SUB_CMD" "$HELPTXT"
        help_help
        help_pretty
        echo
        exit 0
    fi
    if [[ 1 = $P_PRETTY ]]; then
#        if [[ 0 != $VERBOSITY ]]; then
#            ccecho "warn" "Pretty printing is automatically disabled in verbose/debug mode"
#        else
            export PRETTY_FILELIST=1
#        fi
    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 REMAIN_ARGS
    SUB_CMD=$1
    shift

    SHORT_OPTS="cdhr"
    LONG_OPTS="comments,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 = $P_HELP ]]; then
                help_scmd_head "$SUB_CMD" "Show a resulting filename/directory"
                help_comments
                help_draft
                help_help
                help_name
                help_remarks
                help_rootid
                echo
                exit 0
    fi
    
    [[ 1 = $P_COMMENTS ]] && COMMENTS=1
    [[ 1 = $P_DRAFT ]]    && DRAFT="yes"
    [[ 1 = $P_REMARKS ]]  && REMARKS=1
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"
    [[ -n $P_NAME ]]      && export PDFNAME="$P_NAME" BOOK="$P_NAME"

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

###########################################################################
#
#  CHECKLINK
#
#  checks http links in file or from rootid
#
###########################################################################  

function checklink () {
    local HELPTXT SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    
    SUB_CMD=$1
    shift

    SHORT_OPTS="f:h"
    LONG_OPTS="file:,help,rootid:"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "Checks ftp and http(s) links"
        help_file
        help_help
        help_rootid
        echo -e "    NOTES: * Options --file (-f) and --rootid exclude one another.\n           * If neither rootid nor rootid is specified, the rootid\n             from the ENV-file is used\n           * $SUB_CMD follows xi:includes\n"
	exit 0
    fi

    if [[ -z $P_ROOTID && -z $P_FILE ]]; then
        if [[ 0 != $VERBOSITY ]]; then
            ccecho "info" "Neither file nor rootid specified, using rootid from ENV-file"
        fi
    elif [[ -n $P_ROOTID && -n $P_FILE ]]; then
        exit_on_error "Options --file (-f) and --rootid exclude one another.\nPlease specify only one of these options"
    fi
                
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"

    if [[ -n $P_FILE ]]; then
        if [[ -f $P_FILE ]]; then
            export ROOTID=$(xsltproc $DTDROOT/xslt/misc/get-rootelement-id.xsl $P_FILE) || exit_on_error "Cannot get a rootid from file $FILE" 
        else
           exit_on_error "File $P_FILE does not exist"
        fi
    fi

    call_make "$SUB_CMD" "$@"
}

###########################################################################
#
#  GETIMAGES
#
#  Gets a list of images from the file specified with -f or --file
#  and outputs them as:
#   * default:       long list (one file per line)
#   * --compact:  compact list (single line)
#   * --viewer=VIEWER: shows images in VIEWER and prints long list to STDOUT
#
#  the additional option (--modified) will also print the image file's
#  mtime in long lists (this option is ignored with --compact)
#
###########################################################################  
function getimages () {
    local SHORT_OPTS LONG_OPTS SUB_CMD REMAIN_ARGS
    local COMPACT DEBUG_SAV FILE IMAGEDIR MOD P_FILE
    local PROFDIR SHOW VERBOSITY_SAV

    SUB_CMD=$1
    shift
    
    declare -a IMGLIST
    IMAGEDIR="$BASE_DIR/images/src/"

    # any kind of verbosity is unwanted in this case
    WRITE_LOG=0
    DEBUG=0
    VERBOSITY=0
    
    SHORT_OPTS="f:hs"
    LONG_OPTS="compact,file:,help,modified,rootid:,show,viewer:"

    parse_args $SHORT_OPTS $LONG_OPTS $SUB_CMD "$@"
    eval set -- "$P_REMAIN_ARGS"
    
    #------ Computing the values returned from the parser -----
    if [[ 1 = $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "List or display images from a profiled DocBook XML file"
        help_compact
        help_file
        help_modified
        help_rootid
        help_show
        help_viewer
        echo -e "    NOTES: * Options --file (-f) and --rootid exclude one another.\n           * If neither rootid nor rootid is specified, the rootid\n             from the ENV-file is used\n           * $SUB_CMD follows xi:includes\n"
	exit 0
    fi

    [[ 1 = $P_COMPACT ]]  && COMPACT=1
    [[ 1 = $P_MODIFIED ]] && MOD=1
    [[ 1 = $P_SHOW ]]     && SHOW=1
    [[ -n $P_VIEWER ]] && IMG_VIEWER="$P_VIEWER"

    # set ROOTID - either directly or via $FILE
    if [[ -z $P_ROOTID && -z $P_FILE ]]; then
        if [[ 0 != $VERBOSITY ]]; then
            ccecho "info" "Neither file nor rootid specified, using rootid from ENV-file"
        fi
    elif [[ -n $P_ROOTID && -n $P_FILE ]]; then
        exit_on_error "Options --file (-f) and --rootid exclude one another.\nPlease specify only one of these options"
    fi
                
    [[ -n $P_ROOTID ]]    && export ROOTID="$P_ROOTID"

    if [[ -n $P_FILE ]]; then
        if [[ -f $P_FILE ]]; then
            export ROOTID=$(xsltproc $DTDROOT/xslt/misc/get-rootelement-id.xsl $P_FILE) || exit_on_error "Cannot get a rootid from file $FILE" 
        else
           exit_on_error "File $P_FILE does not exist"
        fi
    fi

    # IMG_VIEWER may also be set via config file:
    if [[ $SHOW ]]; then
        if [[ -z $IMG_VIEWER ]]; then
            exit_on_error "Please specify an image viewer via command-line (--viewer) or via config file"
        else
            IMG_VIEWER=$(which $IMG_VIEWER 2>/dev/null)
            if [[ 0 < $? ]]; then # which command failed
                # Viewer was specified on command-line
                if [[ $P_VIEWER ]]; then
                    exit_on_error "Cannot find VIEWER $CMD_IMG_VIEWER"
                # Viewer was specified via config
                else
                    exit_on_error "Cannot find VIEWER $IMG_VIEWER. Please check your config file"
                fi
            fi
        fi
    fi

    # get the image list
    # we can use projectgraphics, since it returns images for a given rootid
    IMGLIST=( $(call_make projectgraphics) )

    if [[ 0 < ${#IMGLIST[@]} ]]; then
        if [[ $COMPACT ]]; then
            echo -e "${IMGLIST[@]}\n"
        else
            for IMAGE in ${IMGLIST[@]}; do
                if [[ $MOD ]]; then
	            MODIFIED=$(stat -c %y ${IMAGE} | cut -d '.' -f1)
	            echo "${IMAGE} (${MODIFIED})"
                else
	            echo "${IMAGE}"
                fi
            done  | column -t
            if [[ $SHOW && ${#IM[@]} ]]; then
                eval "$IMG_VIEWER ${IMGLIST[@]} &"
            fi
        fi
    fi
    
}

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

# call make directly
# for functions with no command line options
# do not write a log
function no_opts {
    WRITE_LOG=0
    call_make "$SUB_CMD" "$@"
}


# 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 show_env {
         echo "BASE_DIR=$BASE_DIR;ENVFILE=$ENVFILE"
}

#
# This function is a bit out of place here, since it does not use
# any of the make functions
# It should probably be transferred into a script of it's own
# Leaving it unmodified (not using parse_args), so it can be
# cur & paste'd into a new script

function init_wd () {
    # Initialize a working directory to get started with daps
    #
   
    SARGS=$(getopt -o h -l help,name:,rootelement: -n $0 -- "$@")
    if [[ 1 = $? ]]; then
        wrong_parameter "$TARGET"
    fi
    eval set -- "$SARGS"
    while true ; do
	case "$1" in
            -h|--help)
                echo "
daps --envfile=<ENVFILE> --basedir=<BASEDIR> init [options]

Create a working environment for a book/article. Specifying an ENVFILE and
a BASEDIR is mandatory. <BASEDIR> must exist, init will create a subdirectory.
"
                help_dirname
                help_rootelement
                echo
		exit 0
		;;
            --dirname)
                DIRNAME="$2"
                shift 2
                ;;
	    --rootelement)
                if [[ article = $2 || book = $2 ]]; then
                    ROOTELEMENT="$2"
                else
                    exit_on_error "ROOTELEMENT must be either article or book"
                fi
		shift 2
		;;
            --) shift ; break ;;
            *) wrong_parameter "$TARGET $1" ;;
	esac
    done

    test -z "$BASE_DIR" && exit_on_error "You must specify BASE_DIR when calling $ME init"
     
    # default when not set is book
    test -z $ROOTELEMENT && ROOTELEMENT=book
    
    if [[ -n $PDFNAME ]]; then
        BOOK="$PDFNAME"
    else
        BOOK="${ENVFILE#*${CONF_PREFIX}}"
    fi
    
    if [[ -z $DIRNAME ]]; then
        DIRNAME=$BOOK
    fi
    
    BASE_DIR="${BASE_DIR}/$BOOK"
    R_DIR="${BASE_DIR}/build/${BOOK}"
    LOG_DIR="${R_DIR}/log"
    
    # Create BASE_DIR and needed subdirectories
    mkdir -p $BASE_DIR || exit_on_error "Cannot create $BASE_DIR" 
    mkdir -p ${BASE_DIR}/images/src/{dia,fig,png,svg} ${BASE_DIR}/xml || exit_on_error "Cannot create subdirectories in $BASE_DIR" 

    # copy the templates
    #
    # ENV file
    cp ${LIB_DIR}/templates/ENV-file.template ${BASE_DIR}/$ENVFILE && \
        sed -i s/§§MAIN§§/MAIN-$BOOK.xml/g ${BASE_DIR}/$ENVFILE
    # MAIN
    cp ${LIB_DIR}/templates/MAIN.$ROOTELEMENT.template ${BASE_DIR}/xml/MAIN-${BOOK}.xml
    # graphics
    cp ${LIB_DIR}/templates/example{1,2}.png ${BASE_DIR}/images/src/png/
  
    setup_builddir
    if [[ 0 != $VERBOSITY ]]; then
        ccecho "result" "Successfully created a working environment at"
    fi
    ccecho "result" "${BASE_DIR}"
}

###########################################################################
#
# 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 "
$ME [--global-options] $1 [options]

$2

  Command options:"
}

function help_comments () {
    echo "    --comments, -c            Include XML comments in profiled sources
                              Default: off"  
}
function help_compact () {
    echo "    --compact                 Print the filelist on a single line.
                              Ignored when -s|--show is set.
                              Default: off"  
}
function help_dirname () {
    echo "    --dirname=DIR             Directory names to be created in BASE_DIR
                              Default: generated by stripping 'ENV-' from the
                              ENV filename"
}
function help_draft () {
    echo "    --draft, -d               Add a 'DRAFT' watermark to all pages of the book
                              Default: off" 
}
function help_def-file () {
    echo "    --def-file=FILE           Specify a DEF-* file containing build
                              information"
}
function help_file () {
    echo "    --file=FILE, -f FILE      Specify the filename of an XML file"
}
function help_fop () {
    echo "    --fop=FORMATTER           Specify the PDF formatter to be used. Currently
                              'xep' or 'fop' are supported.
                              Default: 'fop'"
}
function help_help () {
    echo "    --help, -h                Print this help text"
}
function help_modified () {
    echo "    --modified, -m            Print the image's modification time.
                              Ignored when --compact is set.
                              Default: off"
}
function help_name () {
    echo "    --name=BOOKNAME           File- and directory names for generated content
                              are derived from BOOKNAME.
                              Default: generated by stripping 'ENV-' from the
                              ENV filename"
}
function help_nohelp () {
    echo "
No further help for subcommand \"$TARGET\" available.
"
}
function help_nopdf () {
    echo "    --nopdf, -n               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: off"
}
function help_meta () {
    echo "    --meta, -m                If set, prints additional status information
                              (filename, maintainer and status) for each file.
                              Implies draft mode.
                              Default: off"
}
function help_pretty () {
    echo "    --pretty, -p              Pretty print file lists (one filename per line)"
}
function help_remarks () {
    echo "    --remarks, -r             Include remarks (<remark>...</remark>) in book
                              Implies draft mode.
                              Default: off"  
}
function help_rootelement () {
    echo "    --rootelement=ELEMENT     Specify a ROOTELEMENT for your main DocBook XML
                              file; must be one either article or book.
                              Default: book"
}
function help_rootid () {
    echo "    --rootid=ID               Specify a ROOTID to build only parts of a book
                              (parts or chapters). Default: Usually set
                              in the ENV-file; if not set the complete set
                              defined in \$MAIN will be built"
}
function help_static () {
    echo "    --static                  Normally images and css files in HTML builds  
                              are linked from elsewhere in the file system.
                              Use this option to copy these files in order
                              to create a distributable HTML build"
}
function help_show () {
    echo "    --show, -s                Show images with an image viewer that either
                              has been specified with --viewer or by setting
                              IMG_VIEWER in the config file
                              Default: off"
}
function help_viewer () {
    echo "    --viewer                  Image viewer to be used.
                              Default: IMG_VIEWER setting from config file"
}
function help_xsltparam () {
    echo "    --xsltparam               Add one or more xsltproc parmeters in the form of
                              \"--stringparam paramname value\". The given string
                              will be passed unmodified to the xsltproc call 
                              that $1.
                              Useful to temporarily overwrite style sheet
                              parameters such as margins.
                              Note: You MUST properly quote the string.
                               Use either
                                --xsltproc=\"\\\"--stringparam paramname value\\\"\"
                                or
                                --xsltproc=\"--stringparam\\ paramname\\ value\"
                              Default: unset"
}
