#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8

PUBKEYS="@@PUBKEYS@@"
[ "$PUBKEYS" != "@@""PUBKEYS""@@" ] || exit 1

##@inc[../base
## Fonctions de base
##@*inc[base.ulib
## Support des fonctions uprovided(), uprovide() et urequire() de ulib dans le
## cas où cette librairie n'est pas chargée
if [ -z "$ULIBDIR" -o "$ULIBDIR" != "$ULIBINIT" ]; then
    ULIBPROVIDED=()
    function uprovided() {
        local module
        for module in "${ULIBPROVIDED[@]}"; do
            [ "$module" == "$1" ] && return 0
        done
        return 1
    }
    function uprovide() {
        uprovided "$1" && return 1
        ULIBPROVIDED=("${ULIBPROVIDED[@]}" "$1")
    }
    function urequire() {
        local module r=0
        for module in "$@"; do
            uprovided "$module" && continue
            echo "error: $module: this module is required but cannot be automatically loaded" 1>&2
            r=1
        done
        return $r
    }
    uprovide base.ulib
fi
##@*inc]base.ulib
##@inc[base.init
## Fonctions de base: initialisation de l'environnement
uprovide base.init

if [ -n "$UTOOLS_HAVE_SCRIPTVARS" ]; then
    :
elif [ "$0" == "-bash" ]; then
    scriptname=
    scriptdir=
    script=
elif [ ! -f "$0" -a -f "${0#-}" ]; then
    scriptname="$(basename -- "${0#-}")"
    scriptdir="$(dirname -- "${0#-}")"
    scriptdir="$(cd "$scriptdir"; pwd)"
    script="$scriptdir/$scriptname"
else
    scriptname="$(basename -- "$0")"
    scriptdir="$(dirname -- "$0")"
    scriptdir="$(cd "$scriptdir"; pwd)"
    script="$scriptdir/$scriptname"
fi
: "${ULIBDIR:=$scriptdir}"

[ -z "$TMPDIR" -a -d "$HOME/tmp" ] && TMPDIR="$HOME/tmp"
export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}"

[ -z "$USER" -a -n "$LOGNAME" ] && export USER="$LOGNAME"

[ -f /etc/debian_chroot ] && UTOOLS_CHROOT=1
[ -f /etc/nutoolsrc ] && . /etc/nutoolsrc
[ -f ~/.nutoolsrc ] && . ~/.nutoolsrc
true
##@inc]base.init
##@inc[base.core
## Fonctions de base: fondement
uprovide base.core

function echo_() {
    echo -n "$*"
}
function recho() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo "$first" "$@"
    else
        echo "$@"
    fi
}
function recho_() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo -n "$first" "$@"
    else
        echo -n "$@"
    fi
}
function _qval() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    recho_ "$s"
}
function should_quote() {
    local s="$*"
    local l="${#s}"
    [ $l -eq 0 -o $l -gt 80 ] && return 0
    s="${s//[a-zA-Z0-9]/}"
    s="${s//,/}"
    s="${s//./}"
    s="${s//+/}"
    s="${s//\//}"
    s="${s//-/}"
    s="${s//_/}"
    s="${s//=/}"
    [ -n "$s" ]
}
function qval() {
    echo -n \"
    _qval "$@"
    echo \"
}
function qvalm() {
    if should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvalr() {
    if [ -z "$*" ]; then
        :
    elif should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvals() {
    local arg first=1
    for arg in "$@"; do
        [ -z "$first" ] && echo -n " "
        if should_quote "$arg"; then
            echo -n \"
            _qval "$arg"
            echo -n \"
        else
            recho_ "$arg"
        fi
        first=
    done
    [ -z "$first" ] && echo
}
function qwc() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    local r a b
    while [ -n "$s" ]; do
        if [[ "$s" == *\** ]]; then
            if [[ "$s" == *\?* ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\**}"
                s="${s#*\*}"
                r="$r\"$a\"*"
            fi
        elif [[ "$s" == *\?* ]]; then
            if [[ "$s" == *\** ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\?*}"
                s="${s#*\?}"
                r="$r\"$a\"?"
            fi
        else
            r="$r\"$s\""
            break
        fi
    done
    recho_ "$r"
}
function qlines() {
    sed "s/'/'\\\\''/g; s/.*/'&'/g"
}
function setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    eval "$__s_var=\"\$*\""
}
function _setv() {
    local __s_var="$1"; shift
    eval "$__s_var=\"\$*\""
}
function echo_setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    echo "$__s_var=$(qvalr "$*")"
}
function setx() {
    if [ "$1" == -a ]; then
        shift
        local __s_array="$1"; shift
        if [[ "$__s_array" == *=* ]]; then
            set -- "${__s_array#*=}" "$@"
            __s_array="${__s_array%%=*}"
        fi
        eval "$__s_array=($("$@" | qlines))"
    else
        local __s_var="$1"; shift
        if [[ "$__s_var" == *=* ]]; then
            set -- "${__s_var#*=}" "$@"
            __s_var="${__s_var%%=*}"
        fi
        eval "$__s_var="'"$("$@")"'
    fi
}
function _setvx() {
    local __s_var="$1"; shift
    eval "$__s_var="'"$("$@")"'
}
function _setax() {
    local __s_array="$1"; shift
    eval "$__s_array=($("$@" | qlines))"
}
function evalx() {
    local __e_val __e_arg __e_r=0
    local -a __e_cmd

    local __e_first=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            __e_cmd=("${__e_cmd[@]}" "$__e_arg")
        done

        if [ -n "$__e_first" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_first=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
function setxx() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalx "$@"
}
function evalp() {
    local __e_arg __e_cmd

    while [ $# -gt 0 ]; do
        __e_arg="$1"; shift
        if [ "$__e_arg" == // ]; then
            __e_cmd="$__e_cmd |"
            continue
        elif [ "${__e_arg%//}" != "$__e_arg" ]; then
            local __e_tmp="${__e_arg%//}"
            if [ -z "${__e_tmp//\\/}" ]; then
                __e_arg="${__e_arg#\\}"
            fi
        fi
        __e_cmd="${__e_cmd:+$__e_cmd }\"$(_qval "$__e_arg")\""
    done
    eval "$__e_cmd"
}
function setxp() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalp "$@"
}
function testx() {
    local __t_op="$1"; shift
    local __t_val="$(evalx "$@")"
    [ $__t_op "$__t_val" ]
}
function test2x() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrx() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}
function testp() {
    local __t_op="$1"; shift
    local __t_val="$(evalp "$@")"
    [ $__t_op "$__t_val" ]
}
function test2p() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrp() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}

function err2out() {
    "$@" 2>&1
}

function is_defined() {
    [ -n "$(declare -p "$1" 2>/dev/null)" ]
}
function is_array() {
    case "$(declare -p "$1" 2>/dev/null)" in declare\ -a*) return 0;; esac
    return 1
}

function upvar() {
    if unset -v "$1"; then
        if [ $# -eq 2 ]; then
            eval "$1=\"\$2\""
        else
            eval "$1=(\"\${@:2}\")"
        fi
    fi
}
function array_upvar() {
    unset -v "$1" && eval "$1=(\"\${@:2}\")"
}
function upvars() {
    while [ $# -gt 0 ]; do
        case "$1" in
        -a)
            unset -v "$2" && eval "$2=(\"\${@:3}\")"
            break
            ;;
        -a*)
            unset -v "$2" && eval "$2=(\"\${@:3:${1#-a}}\")"
            shift $((${1#-a} + 2)) || return 1
            ;;
        *)
            unset -v "$1" && eval "$1=\"\$2\""
            shift; shift
            ;;
        esac
    done
}

function __ab_process_pending() {
    local -a values
    case "$mode" in
    cmd) values="$("${pending[@]}")";;
    ssplit) eval "values=($("${pending[@]}"))";;
    lsplit) eval "values=($("${pending[@]}" | qlines))";;
    add) values=("${pending[@]}");;
    esac
    cmd=("${cmd[@]}" "${values[@]}")
    pending=()
}
function array_buildcmd() {
    local desta="$1"; shift; local "$desta"
    local mode=add
    local -a pending cmd
    while [ $# -gt 0 ]; do
        case "$1" in
            ++c|++cmd|++) __ab_process_pending; mode=cmd;;
            ++s|++ssplit) __ab_process_pending; mode=ssplit;;
            ++l|++lsplit) __ab_process_pending; mode=lsplit;;
            ++a|++add) __ab_process_pending; mode=add;;
            *) pending=("${pending[@]}" "$1");;
        esac
        shift
    done
    __ab_process_pending
    array_upvar "$desta" "${cmd[@]}"
}
function buildcmd() {
    local -a args
    array_buildcmd args "$@"
    qvals "${args[@]}"
}
function evalcmd() {
    local -a args
    array_buildcmd args "$@"
    "${args[@]}"
}
##@inc]base.core
##@inc[base.string
## Fonctions de base: gestion des valeurs chaines scalaires
uprovide base.string
urequire base.core


function straddp() {
    local p="$1"; shift
    echo "$p$*"
}
function strdelp() {
    local p="$1"; shift
    local str="$*"
    echo "${str#$p}"
}
function strdelp2() {
    local p="$1"; shift
    local str="$*"
    echo "${str##$p}"
}
function stradds() {
    local s="$1"; shift
    echo "$*$s"
}
function strdels() {
    local s="$1"; shift
    local str="$*"
    echo "${str%$s}"
}
function strdels2() {
    local s="$1"; shift
    local str="$*"
    echo "${str%%$s}"
}
function strlower() {
    local str="$*"
    echo "${str,,}"
}
function strlower1() {
    local str="$*"
    echo "${str,}"
}
function strlowers() {
    local str="$*"
    echo "${*,}"
}
function strupper() {
    local str="$*"
    echo "${str^^}"
}
function strupper1() {
    local str="$*"
    echo "${str^}"
}
function struppers() {
    echo "${*^}"
}
function strmid() {
    local range="$1"; shift
    local str="$*"
    if [[ "$range" == *:-* ]]; then
        local max=${#str}
        [ $max -eq 0 ] && return
        local start="${range%%:*}"
        [ -n "$start" ] || start=0
        while [ "$start" -lt 0 ]; do
            start=$(($max$start))
        done
        max=$(($max-$start))
        local length="${range#*:}"
        while [ "$length" -lt 0 ]; do
            length=$(($max$length))
        done
        range="$start:$length"
    fi
    eval 'echo "${str:'" $range"'}"'
}
function strrepl() {
    local pattern="$1"; shift
    local repl="$1"; shift
    local str="$*"
    local cmd='echo "${str/'
    if [ "${pattern#/}" != "$pattern" ]; then
        pattern="${pattern#/}"
        cmd="$cmd/"
    elif [ "${pattern#\#}" != "$pattern" ]; then
        pattern="${pattern#\#}"
        cmd="$cmd#"
    elif [ "${pattern#%}" != "$pattern" ]; then
        pattern="${pattern#%}"
        cmd="$cmd%"
    fi
    cmd="$cmd"'$pattern/$repl}"'
    eval "$cmd"
}

function strops() {
    local -a __s_tmp
    local __s_value="$1"; shift
    while [ $# -gt 0 ]; do
        case "$1" in
        :-*|:=*|:\?*|:+*) eval '__s_value="${'"${__s_value}$1"'}"';;
        d|deref) __s_value="${!__s_value}";;
        dc|dcount|ds|dsize)
            __s_value="${__s_value}[@]"
            __s_tmp=("${!__s_value}")
            __s_value="${#__s_tmp[@]}"
            ;;
        \#*|%*|/*|:*|^*|,*) eval '__s_value="${__s_value'"$1"'}"';;
        l|length) __s_value="${#__s_value}";;
        =|==|!=|\<|\>|-eq|-ne|-lt|-le|-gt|-ge)
            __s_tmp=(\[ "$__s_value" "$@" ]); "${__s_tmp[@]}"; return $?;;
        -n|-z) __s_tmp=(\[ "$1" "$__s_value" ]); "${__s_tmp[@]}"; return $?;;
        +#*) eval '__s_value="'"${1#+#}"'$__s_value"';;
        -#*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        +%*) eval '__s_value="$__s_value"'"${1#+%}";;
        +*) eval '__s_value="$__s_value"'"${1#+}";;
        -%*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        -*) eval '__s_value="${__s_value%'"${1#-}"'}"';;
        mid|strmid) eval '__s_value="$(strmid "$2" "$__s_value")"'; shift;;
        repl|strrepl) eval '__s_value="$(strrepl "$2" "$3" "$__s_value")"'; shift; shift;;
        *) echo 1>&2 "strops: unknown operator: $1";;
        esac
        shift
    done
    echo "$__s_value"
}

function first_char() {
    local str="$*"
    echo "${str:0:1}"
}
function last_char() {
    local str="$*"
    echo "${str: -1:1}"
}
function first_chars() {
    local str="$*"
    recho "${str:0:$((${#1}-1))}"
}
function last_chars() {
    local str="$*"
    recho "${str:1}"
}
function first_char_is() {
    [ "${1:0:1}" == "$2" ]
}
function last_char_is() {
    [ "${1:$((-1)):1}" == "$2" ]
}
function beginswith() {
    local str="$1" pattern="$2"
    eval '[ "${str#$pattern}" != "$str" ]'
}
function endswith() {
    local str="$1" pattern="$2"
    eval '[ "${str%$pattern}" != "$str" ]'
}

function strsplitf() {
    [ $# -gt 0 ] || return 127
    local func count
    func="$1"; shift
    count=$#
    if [ $count -gt 0 ]; then
        eval 'set -- "${@:1:$(($count-1))}" '"${!count}" || return 126
    fi
    "$func" "$@"
}
function strecho() { recho "$@"; }
function strqvals() {
    qvals "$@"
}
function strqlines() {
    local -a lines
    _setax lines cat "$@"
    qvals "${lines[@]}"
}
function strqarray() {
    local __a __s="qvals"
    for __a in "$@"; do __s="$__s \"\${$__a[@]}\""; done
    eval "$__s"
}

function evals() {
    local __e_val __e_arg __e_r=0
    local __e_firstcmd __e_firstarg __e_splitf
    local -a __e_cmd

    __e_firstcmd=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        __e_firstarg=1 # premier argument
        __e_splitf= # premier argument après splitf
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            if [ -n "$__e_firstarg" ]; then
                __e_cmd=("str$__e_arg")
                __e_firstarg=
                [ "$__e_arg" == "splitf" ] && __e_splitf=1
            elif [ -n "$__e_splitf" ]; then
                __e_cmd=("${__e_cmd[@]}" "str$__e_arg")
                __e_splitf=
            else
                __e_cmd=("${__e_cmd[@]}" "$__e_arg")
            fi
        done

        if [ -n "$__e_firstcmd" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_firstcmd=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
##@inc]base.string
##@inc[base.num
## Fonctions de base: gestion des valeurs numériques
uprovide base.num

function isnum() {
    [ ${#1} -gt 0 ] || return 1
    local v="${1#-}"
    [ ${#v} -gt 0 ] || return 1
    v="${v//[0-9]/}"
    [ -z "$v" ]
}
function ispnum() {
    [ ${#1} -gt 0  ] || return 1
    [ -z "${1//[0-9]/}" ]
}
function isrnum() {
    [ ${#1} -gt 0 ] || return 1
    local v="${1#-}"
    [ ${#v} -gt 0 ] || return 1
    v="${v//./}"
    v="${v//,/}"
    v="${v//[0-9]/}"
    [ -z "$v" ]
}

function evali() {
    echo "$(($*))"
}
##@inc]base.num
##@inc[base.bool
## Fonctions de base: valeurs booléennes
##@inc[base.num
## Fonctions de base: gestion des valeurs numériques
uprovide base.num

function isnum() {
    [ ${#1} -gt 0 ] || return 1
    local v="${1#-}"
    [ ${#v} -gt 0 ] || return 1
    v="${v//[0-9]/}"
    [ -z "$v" ]
}
function ispnum() {
    [ ${#1} -gt 0  ] || return 1
    [ -z "${1//[0-9]/}" ]
}
function isrnum() {
    [ ${#1} -gt 0 ] || return 1
    local v="${1#-}"
    [ ${#v} -gt 0 ] || return 1
    v="${v//./}"
    v="${v//,/}"
    v="${v//[0-9]/}"
    [ -z "$v" ]
}

function evali() {
    echo "$(($*))"
}
##@inc]base.num
uprovide base.bool
urequire base.num

function is_yes() {
    case "${1,,}" in
    o|oui|y|yes|v|vrai|t|true|on) return 0;;
    esac
    isnum "$1" && [ "$1" -ne 0 ] && return 0
    return 1
}
function is_no() {
    case "${1,,}" in
    n|non|no|f|faux|false|off) return 0;;
    esac
    isnum "$1" && [ "$1" -eq 0 ] && return 0
    return 1
}
function yesval() {
    is_yes "$1" && echo 1
}

function setb() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    local __s_r
    if "$@" >/dev/null; then
        eval "$__s_var=1"
    else
        __s_r=$?
        eval "$__s_var="
        return $__s_r
    fi
}
function _setb() {
    local __s_var="$1"; shift
    if "$@" >/dev/null; then
        eval "$__s_var=1"
    else
        eval "$__s_var="
    fi
}

function evalb() {
    if evalx "$@" >/dev/null; then
        echo 1
    else
        return $?
    fi
}
function setxb() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    setx "$__s_var" evalb "$@"
}
##@inc]base.bool
##@inc[base.array
## Fonctions de base: gestion des tableaux
uprovide base.array
urequire base.core
##@inc]base.array
##@inc[base.quote
## Fonctions de base: protection de valeurs chaine
uprovide base.quote
urequire base.core

function _qawk() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//
/\\n}"
    recho_ "$s"
}
function qawk() {
    echo -n \"
    _qawk "$@"
    echo \"
}
function qseds() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\//\\/}"
    s="${s//
/\\n}"
    recho "$s"
}
function _qform() {
    local s="$*"
    s="${s//\%/%25}"
    s="${s//+/%2B}"
    s="${s//&/%26}"
    s="${s//=/%3D}"
    s="${s// /+}"
    recho_ "$s"
}
function qform() {
    local s="$*"
    if [[ "$s" == *=* ]]; then
        _qform "${s%%=*}"
        echo -n =
        _qform "${s#*=}"
        echo
    else
        _qform "$s"
        echo
    fi
}
function _qsql() {
    local q="'" qq="''"
    echo "${*//$q/$qq}"
}
function qsql() {
    local q="'" qq="''"
    echo "'${*//$q/$qq}'"
}
##@inc]base.quote
##@inc[base.split
## Fonctions de base: analyse et découpage de valeurs
uprovide base.split
urequire base.core

function splitfsep() {
    if [[ "$1" == *"$2"* ]]; then
        setv "${3:-first}" "${1%%$2*}"
        setv "${4:-second}" "${1#*$2}"
    else
        setv "${3:-first}" "$1"
        setv "${4:-second}"
    fi
}
function splitfsep2() {
    if [[ "$1" == *"$2"* ]]; then
        setv "${3:-first}" "${1%%$2*}"
        setv "${4:-second}" "${1#*$2}"
    else
        setv "${3:-first}"
        setv "${4:-second}" "$1"
    fi
}
function splitlsep() {
    if [[ "$1" == *"$2"* ]]; then
        setv "${3:-first}" "${1%$2*}"
        setv "${4:-second}" "${1##*$2}"
    else
        setv "${3:-first}" "$1"
        setv "${4:-second}"
    fi
}
function splitlsep2() {
    if [[ "$1" == *"$2"* ]]; then
        setv "${3:-first}" "${1%$2*}"
        setv "${4:-second}" "${1##*$2}"
    else
        setv "${3:-first}"
        setv "${4:-second}" "$1"
    fi
}
function splitvar() {
    splitfsep "$1" = "${2:-name}" "${3:-value}"
}
function splitpath() {
    splitlsep2 "$1" / "${2:-dir}" "${3:-name}"
}
function splitname() {
    splitlsep "$1" . "${2:-basename}" "${3:-ext}"
}
function splithost() {
    splitfsep "$1" . "${2:-hostname}" "${3:-domain}"
}
function splituserhost() {
    splitfsep2 "$1" @ "${2:-user}" "${3:-host}"
}
function splitpair() {
    splitfsep "$1" : "${2:-src}" "${3:-dest}"
}
function splitproxy() {
    local __sp_tmp __sp_host __sp_port __sp_creds __sp_user __sp_password

    __sp_tmp="${1#http://}"
    if [[ "$__sp_tmp" == *@* ]]; then
        __sp_creds="${__sp_tmp%%@*}"
        __sp_tmp="${__sp_tmp#${__sp_creds}@}"
        splitpair "$__sp_creds" __sp_user __sp_password
    fi
    __sp_tmp="${__sp_tmp%%/*}"
    splitpair "$__sp_tmp" __sp_host __sp_port
    [ -n "$__sp_port" ] || __sp_port=3128

    setv "${2:-host}" "$__sp_host"
    setv "${3:-port}" "$__sp_port"
    setv "${4:-user}" "$__sp_user"
    setv "${5:-password}" "$__sp_password"
}
function spliturl() {
    local __su_tmp __su_scheme __su_creds __su_user __su_password __su_host __su_port __su_path

    __su_scheme="${1%%:*}"
    __su_tmp="${1#${__su_scheme}://}"
    if [[ "$__su_tmp" == */* ]]; then
        __su_path="${__su_tmp#*/}"
        __su_tmp="${__su_tmp%%/*}"
    fi
    if [[ "$__su_tmp" == *@* ]]; then
        __su_creds="${__su_tmp%%@*}"
        __su_tmp="${__su_tmp#${__su_creds}@}"
        splitpair "$__su_creds" __su_user __su_password
    fi
    splitpair "$__su_tmp" __su_host __su_port
    if [ -z "$__su_port" ]; then
        [ "$__su_scheme" == "http" ] && __su_port=80
        [ "$__su_scheme" == "https" ] && __su_port=443
        [ "$__su_scheme" == "ftp" ] && __su_port=21
    fi

    setv "${2:-scheme}" "$__su_scheme"
    setv "${3:-user}" "$__su_user"
    setv "${4:-password}" "$__su_password"
    setv "${5:-host}" "$__su_host"
    setv "${6:-port}" "$__su_port"
    setv "${7:-path}" "$__su_path"
}
##@inc]base.split
##@inc[base.args
## Analyse des arguments de la ligne de commande
##@inc[base.core
## Fonctions de base: fondement
uprovide base.core

function echo_() {
    echo -n "$*"
}
function recho() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo "$first" "$@"
    else
        echo "$@"
    fi
}
function recho_() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo -n "$first" "$@"
    else
        echo -n "$@"
    fi
}
function _qval() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    recho_ "$s"
}
function should_quote() {
    local s="$*"
    local l="${#s}"
    [ $l -eq 0 -o $l -gt 80 ] && return 0
    s="${s//[a-zA-Z0-9]/}"
    s="${s//,/}"
    s="${s//./}"
    s="${s//+/}"
    s="${s//\//}"
    s="${s//-/}"
    s="${s//_/}"
    s="${s//=/}"
    [ -n "$s" ]
}
function qval() {
    echo -n \"
    _qval "$@"
    echo \"
}
function qvalm() {
    if should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvalr() {
    if [ -z "$*" ]; then
        :
    elif should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvals() {
    local arg first=1
    for arg in "$@"; do
        [ -z "$first" ] && echo -n " "
        if should_quote "$arg"; then
            echo -n \"
            _qval "$arg"
            echo -n \"
        else
            recho_ "$arg"
        fi
        first=
    done
    [ -z "$first" ] && echo
}
function qwc() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    local r a b
    while [ -n "$s" ]; do
        if [[ "$s" == *\** ]]; then
            if [[ "$s" == *\?* ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\**}"
                s="${s#*\*}"
                r="$r\"$a\"*"
            fi
        elif [[ "$s" == *\?* ]]; then
            if [[ "$s" == *\** ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\?*}"
                s="${s#*\?}"
                r="$r\"$a\"?"
            fi
        else
            r="$r\"$s\""
            break
        fi
    done
    recho_ "$r"
}
function qlines() {
    sed "s/'/'\\\\''/g; s/.*/'&'/g"
}
function setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    eval "$__s_var=\"\$*\""
}
function _setv() {
    local __s_var="$1"; shift
    eval "$__s_var=\"\$*\""
}
function echo_setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    echo "$__s_var=$(qvalr "$*")"
}
function setx() {
    if [ "$1" == -a ]; then
        shift
        local __s_array="$1"; shift
        if [[ "$__s_array" == *=* ]]; then
            set -- "${__s_array#*=}" "$@"
            __s_array="${__s_array%%=*}"
        fi
        eval "$__s_array=($("$@" | qlines))"
    else
        local __s_var="$1"; shift
        if [[ "$__s_var" == *=* ]]; then
            set -- "${__s_var#*=}" "$@"
            __s_var="${__s_var%%=*}"
        fi
        eval "$__s_var="'"$("$@")"'
    fi
}
function _setvx() {
    local __s_var="$1"; shift
    eval "$__s_var="'"$("$@")"'
}
function _setax() {
    local __s_array="$1"; shift
    eval "$__s_array=($("$@" | qlines))"
}
function evalx() {
    local __e_val __e_arg __e_r=0
    local -a __e_cmd

    local __e_first=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            __e_cmd=("${__e_cmd[@]}" "$__e_arg")
        done

        if [ -n "$__e_first" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_first=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
function setxx() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalx "$@"
}
function evalp() {
    local __e_arg __e_cmd

    while [ $# -gt 0 ]; do
        __e_arg="$1"; shift
        if [ "$__e_arg" == // ]; then
            __e_cmd="$__e_cmd |"
            continue
        elif [ "${__e_arg%//}" != "$__e_arg" ]; then
            local __e_tmp="${__e_arg%//}"
            if [ -z "${__e_tmp//\\/}" ]; then
                __e_arg="${__e_arg#\\}"
            fi
        fi
        __e_cmd="${__e_cmd:+$__e_cmd }\"$(_qval "$__e_arg")\""
    done
    eval "$__e_cmd"
}
function setxp() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalp "$@"
}
function testx() {
    local __t_op="$1"; shift
    local __t_val="$(evalx "$@")"
    [ $__t_op "$__t_val" ]
}
function test2x() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrx() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}
function testp() {
    local __t_op="$1"; shift
    local __t_val="$(evalp "$@")"
    [ $__t_op "$__t_val" ]
}
function test2p() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrp() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}

function err2out() {
    "$@" 2>&1
}

function is_defined() {
    [ -n "$(declare -p "$1" 2>/dev/null)" ]
}
function is_array() {
    case "$(declare -p "$1" 2>/dev/null)" in declare\ -a*) return 0;; esac
    return 1
}

function upvar() {
    if unset -v "$1"; then
        if [ $# -eq 2 ]; then
            eval "$1=\"\$2\""
        else
            eval "$1=(\"\${@:2}\")"
        fi
    fi
}
function array_upvar() {
    unset -v "$1" && eval "$1=(\"\${@:2}\")"
}
function upvars() {
    while [ $# -gt 0 ]; do
        case "$1" in
        -a)
            unset -v "$2" && eval "$2=(\"\${@:3}\")"
            break
            ;;
        -a*)
            unset -v "$2" && eval "$2=(\"\${@:3:${1#-a}}\")"
            shift $((${1#-a} + 2)) || return 1
            ;;
        *)
            unset -v "$1" && eval "$1=\"\$2\""
            shift; shift
            ;;
        esac
    done
}

function __ab_process_pending() {
    local -a values
    case "$mode" in
    cmd) values="$("${pending[@]}")";;
    ssplit) eval "values=($("${pending[@]}"))";;
    lsplit) eval "values=($("${pending[@]}" | qlines))";;
    add) values=("${pending[@]}");;
    esac
    cmd=("${cmd[@]}" "${values[@]}")
    pending=()
}
function array_buildcmd() {
    local desta="$1"; shift; local "$desta"
    local mode=add
    local -a pending cmd
    while [ $# -gt 0 ]; do
        case "$1" in
            ++c|++cmd|++) __ab_process_pending; mode=cmd;;
            ++s|++ssplit) __ab_process_pending; mode=ssplit;;
            ++l|++lsplit) __ab_process_pending; mode=lsplit;;
            ++a|++add) __ab_process_pending; mode=add;;
            *) pending=("${pending[@]}" "$1");;
        esac
        shift
    done
    __ab_process_pending
    array_upvar "$desta" "${cmd[@]}"
}
function buildcmd() {
    local -a args
    array_buildcmd args "$@"
    qvals "${args[@]}"
}
function evalcmd() {
    local -a args
    array_buildcmd args "$@"
    "${args[@]}"
}
##@inc]base.core
##@inc[base.string
## Fonctions de base: gestion des valeurs chaines scalaires
uprovide base.string
urequire base.core


function straddp() {
    local p="$1"; shift
    echo "$p$*"
}
function strdelp() {
    local p="$1"; shift
    local str="$*"
    echo "${str#$p}"
}
function strdelp2() {
    local p="$1"; shift
    local str="$*"
    echo "${str##$p}"
}
function stradds() {
    local s="$1"; shift
    echo "$*$s"
}
function strdels() {
    local s="$1"; shift
    local str="$*"
    echo "${str%$s}"
}
function strdels2() {
    local s="$1"; shift
    local str="$*"
    echo "${str%%$s}"
}
function strlower() {
    local str="$*"
    echo "${str,,}"
}
function strlower1() {
    local str="$*"
    echo "${str,}"
}
function strlowers() {
    local str="$*"
    echo "${*,}"
}
function strupper() {
    local str="$*"
    echo "${str^^}"
}
function strupper1() {
    local str="$*"
    echo "${str^}"
}
function struppers() {
    echo "${*^}"
}
function strmid() {
    local range="$1"; shift
    local str="$*"
    if [[ "$range" == *:-* ]]; then
        local max=${#str}
        [ $max -eq 0 ] && return
        local start="${range%%:*}"
        [ -n "$start" ] || start=0
        while [ "$start" -lt 0 ]; do
            start=$(($max$start))
        done
        max=$(($max-$start))
        local length="${range#*:}"
        while [ "$length" -lt 0 ]; do
            length=$(($max$length))
        done
        range="$start:$length"
    fi
    eval 'echo "${str:'" $range"'}"'
}
function strrepl() {
    local pattern="$1"; shift
    local repl="$1"; shift
    local str="$*"
    local cmd='echo "${str/'
    if [ "${pattern#/}" != "$pattern" ]; then
        pattern="${pattern#/}"
        cmd="$cmd/"
    elif [ "${pattern#\#}" != "$pattern" ]; then
        pattern="${pattern#\#}"
        cmd="$cmd#"
    elif [ "${pattern#%}" != "$pattern" ]; then
        pattern="${pattern#%}"
        cmd="$cmd%"
    fi
    cmd="$cmd"'$pattern/$repl}"'
    eval "$cmd"
}

function strops() {
    local -a __s_tmp
    local __s_value="$1"; shift
    while [ $# -gt 0 ]; do
        case "$1" in
        :-*|:=*|:\?*|:+*) eval '__s_value="${'"${__s_value}$1"'}"';;
        d|deref) __s_value="${!__s_value}";;
        dc|dcount|ds|dsize)
            __s_value="${__s_value}[@]"
            __s_tmp=("${!__s_value}")
            __s_value="${#__s_tmp[@]}"
            ;;
        \#*|%*|/*|:*|^*|,*) eval '__s_value="${__s_value'"$1"'}"';;
        l|length) __s_value="${#__s_value}";;
        =|==|!=|\<|\>|-eq|-ne|-lt|-le|-gt|-ge)
            __s_tmp=(\[ "$__s_value" "$@" ]); "${__s_tmp[@]}"; return $?;;
        -n|-z) __s_tmp=(\[ "$1" "$__s_value" ]); "${__s_tmp[@]}"; return $?;;
        +#*) eval '__s_value="'"${1#+#}"'$__s_value"';;
        -#*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        +%*) eval '__s_value="$__s_value"'"${1#+%}";;
        +*) eval '__s_value="$__s_value"'"${1#+}";;
        -%*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        -*) eval '__s_value="${__s_value%'"${1#-}"'}"';;
        mid|strmid) eval '__s_value="$(strmid "$2" "$__s_value")"'; shift;;
        repl|strrepl) eval '__s_value="$(strrepl "$2" "$3" "$__s_value")"'; shift; shift;;
        *) echo 1>&2 "strops: unknown operator: $1";;
        esac
        shift
    done
    echo "$__s_value"
}

function first_char() {
    local str="$*"
    echo "${str:0:1}"
}
function last_char() {
    local str="$*"
    echo "${str: -1:1}"
}
function first_chars() {
    local str="$*"
    recho "${str:0:$((${#1}-1))}"
}
function last_chars() {
    local str="$*"
    recho "${str:1}"
}
function first_char_is() {
    [ "${1:0:1}" == "$2" ]
}
function last_char_is() {
    [ "${1:$((-1)):1}" == "$2" ]
}
function beginswith() {
    local str="$1" pattern="$2"
    eval '[ "${str#$pattern}" != "$str" ]'
}
function endswith() {
    local str="$1" pattern="$2"
    eval '[ "${str%$pattern}" != "$str" ]'
}

function strsplitf() {
    [ $# -gt 0 ] || return 127
    local func count
    func="$1"; shift
    count=$#
    if [ $count -gt 0 ]; then
        eval 'set -- "${@:1:$(($count-1))}" '"${!count}" || return 126
    fi
    "$func" "$@"
}
function strecho() { recho "$@"; }
function strqvals() {
    qvals "$@"
}
function strqlines() {
    local -a lines
    _setax lines cat "$@"
    qvals "${lines[@]}"
}
function strqarray() {
    local __a __s="qvals"
    for __a in "$@"; do __s="$__s \"\${$__a[@]}\""; done
    eval "$__s"
}

function evals() {
    local __e_val __e_arg __e_r=0
    local __e_firstcmd __e_firstarg __e_splitf
    local -a __e_cmd

    __e_firstcmd=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        __e_firstarg=1 # premier argument
        __e_splitf= # premier argument après splitf
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            if [ -n "$__e_firstarg" ]; then
                __e_cmd=("str$__e_arg")
                __e_firstarg=
                [ "$__e_arg" == "splitf" ] && __e_splitf=1
            elif [ -n "$__e_splitf" ]; then
                __e_cmd=("${__e_cmd[@]}" "str$__e_arg")
                __e_splitf=
            else
                __e_cmd=("${__e_cmd[@]}" "$__e_arg")
            fi
        done

        if [ -n "$__e_firstcmd" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_firstcmd=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
##@inc]base.string
##@inc[base.array
## Fonctions de base: gestion des tableaux
uprovide base.array
urequire base.core
##@inc]base.array
uprovide base.args
urequire base.core base.string base.array #XXX maj de cette liste

function __po_parse_optdescs() {
    local -a optdescs_
    local optdesc_ option_ name_ flag_ value_
    local reset_
    local shift_
    local i_ count_

    let shift_=0
    while [ -n "$1" ]; do
        if [ "$1" == -- ]; then
            shift
            let shift_=$shift_+1
            break
        elif [ "$1" == "%" ]; then
            reset_=1
            shift
            let shift_=$shift_+1
        elif [ "$1" == "-" -o "$1" == "+" ]; then
            if [ "${opts_#+}" != "$opts_" ]; then
                opts_="${opts_#+}"
            elif  [ "${opts_#-}" != "$opts_" ]; then
                opts_="${opts_#-}"
            fi
            opts_="$1$opts_"
            shift
            let shift_=$shift_+1
        elif [ "$1" == "@" ]; then
            destargs_="$2"
            shift; shift
            let shift_=$shift_+2
        elif [[ "$1" == --* ]] || [[ "$1" == -* ]]; then
            array_split optdescs_ "$1" ","
            if [ "$2" == . ]; then
                local autoname_=
                for optdesc_ in "${optdescs_[@]}"; do
                    if [ ${#optdesc_} -gt ${#autoname_} ]; then
                        autoname_="$optdesc_"
                    fi
                done
                while [ -n "$autoname_" -a "${autoname_#-}" != "$autoname_" ]; do autoname_="${autoname_#-}"; done
                while [ -n "$autoname_" -a "${autoname_%:}" != "$autoname_" ]; do autoname_="${autoname_%:}"; done
                autoname_="${autoname_//-/_}"
                shift; shift
                set -- dummy "$autoname_" "$@"
            fi
            for optdesc_ in "${optdescs_[@]}"; do
                if [[ "$2" == \$* ]]; then
                    name_="$2"
                    if [[ "$optdesc_" == *:: ]]; then
                        option_="${optdesc_%::}"
                        flag_='::$'
                    elif [[ "$optdesc_" == *: ]]; then
                        option_="${optdesc_%:}"
                        flag_=':$'
                    else
                        option_="$optdesc_"
                        flag_='$'
                    fi
                elif [[ "$optdesc_" == *:: ]]; then
                    option_="${optdesc_%::}"
                    if [[ "$2" == *=* ]]; then
                        name_="${2%%=*}="
                        [ -n "$reset_" ] && eval "$name_="
                    else
                        name_="$2"
                        [ -n "$reset_" ] && eval "$name_=()"
                    fi
                    flag_=::
                elif [[ "$optdesc_" == *: ]]; then
                    option_="${optdesc_%:}"
                    if [[ "$2" == *=* ]]; then
                        name_="${2%%=*}="
                        [ -n "$reset_" ] && eval "$name_="
                    else
                        name_="$2"
                        [ -n "$reset_" ] && eval "$name_=()"
                    fi
                    flag_=:
                else
                    option_="$optdesc_"
                    name_="$2"
                    [ -n "$reset_" ] && eval "$name_="
                    flag_=
                fi

                if i_="$(array_find options_ "$option_")"; then
                    options_=("${options_[@]:0:$i_}" "${options_[@]:$(($i_ + 1))}")
                    names_=("${names_[@]:0:$i_}" "${names_[@]:$(($i_ + 1))}")
                    flags_=("${flags_[@]:0:$i_}" "${flags_[@]:$(($i_ + 1))}")
                fi
                options_=("${options_[@]}" "$option_")
                names_=("${names_[@]}" "$name_")
                flags_=("${flags_[@]}" "$flag_")
            done
            shift; shift
            let shift_=$shift_+2
        else
            break
        fi
    done

    i_=0
    count_=${#options_[*]}
    while [ $i_ -lt $count_ ]; do
        option_="${options_[$i_]}"
        flag_="${flags_[$i_]}"
        i_=$(($i_ + 1))

        flag_="${flag_%$}"
        if [[ "$option_" == --* ]]; then
            longopts_="${longopts_:+$longopts_,}${option_#--}$flag_"
        elif [[ "$option_" == -* ]]; then
            opts_="$opts_${option_#-}$flag_"
        fi
    done

    return $shift_
}
function __po_check_options() {
    local -a getopt_args_
    getopt_args_=(-o "$opts_" ${longopts_:+-l "$longopts_"} -- "$@")
    local args_
    if args_="$(getopt -q "${getopt_args_[@]}")"; then
        recho "$args_"
        return 0
    else
        LANG=C getopt "${getopt_args_[@]}" 2>&1 1>/dev/null
        return 1
    fi
}
function __po_process_options() {
    while [ -n "$1" ]; do
        if [ "$1" == -- ]; then
            shift
            break
        elif [[ "$1" == -* ]]; then
            local i_
            let i_=0
            for option_ in "${options_[@]}"; do
                [ "$1" == "${options_[$i_]}" ] && break
                let i_=$i_+1
            done
            name_="names_[$i_]"; name_="${!name_}"
            flag_="flags_[$i_]"; flag_="${!flag_}"
            function inc@ { eval "let $1=\$$1+1"; }
            function res@ { setv "$1" "${value_:-$2}"; }
            function add@ { array_add "$1" "${value_:-$2}"; }
            if [ -z "$name_" ]; then
                ewarn "$1: option non reconnue, elle sera ignorée"
            elif [[ "$flag_" == *\$ ]]; then
                if [[ "$flag_" == :* ]]; then
                    value_="$2"; shift
                    function set@ { res@ "$@"; }
                else
                    value_=
                    function set@ { inc@ "$@"; }
                fi
                eval "${name_#\$}"
            elif [ "$flag_" == "" ]; then
                if [[ "$name_" == *=* ]]; then
                    setv "${name_%%=*}" "${name_#*=}"
                else
                    inc@ "$name_"
                fi
            elif [ "$flag_" == ":" -o "$flag_" == "::" ]; then
                value_="$2"; shift
                if [ "${name_%=}" != "$name_" ]; then
                    setv "${name_%=}" "$value_"
                elif [[ "$name_" == *=* ]]; then
                    setv "${name_%%=*}" "${name_#*=}"
                else
                    array_add "$name_" "$value_"
                fi
            fi
        else
            break
        fi
        shift
    done
    unset -f inc@ res@ add@ set@
    [ -n "$destargs_" ] &&
    set_array "$destargs_" @ "$@"
    return 0
}
function parse_opts() {



    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_PARSE_OPTS_SET_X=1; } # désactiver set -x pour cette fonction

    local -a options_ names_ flags_ destargs_
    local opts_ longopts_
    __po_parse_optdescs "$@" || shift $?
    local args_
    if args_="$(__po_check_options "$@")"; then
        eval "set -- $args_"
        __po_process_options "$@"
    else
        [ -n "$destargs_" ] && setv "$destargs_" "$args_"
        [ -n "$__ULIB_SET_X" ] && set -x
        return 1
    fi

    [ -n "$__ULIB_PARSE_OPTS_SET_X" ] && set -x; return 0
}

function parse_args_check() {
    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_PARSE_ARGS_SET_X=1; } # désactiver set -x pour cette fonction
    if parse_opts "${PRETTYOPTS[@]}" "${args[@]}" @ args -- "$@"; then
        [ -n "$__ULIB_PARSE_ARGS_SET_X" ] && set -x
        return 0
    else
        eerror "$args"
        [ -n "$__ULIB_PARSE_ARGS_SET_X" ] && set -x
        return 1
    fi
}
function parse_args() {
    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_PARSE_ARGS_SET_X=1; } # désactiver set -x pour cette fonction
    parse_opts "${PRETTYOPTS[@]}" "${args[@]}" @ args -- "$@" || die "$args"
    [ -n "$__ULIB_PARSE_ARGS_SET_X" ] && set -x; return 0
}

HELP_DESC=
HELP_USAGE=
HELP_OPTIONS=
function __genparse_shortopt() {
    local LC_COLLATE=C
    local shortopt="${1//[^A-Z]}"
    shortopt="$(strlower "${shortopt:0:1}")"
    [ -n "$shortopt" ] && echo "$shortopt"
}
function genparse() {

    local -a names descs vars options
    local i desc var option name uname value shortopt

    for var in "$@"; do
        if [[ "$var" == *=* ]]; then
            splitvar "$var" name value
            shortopt="$(__genparse_shortopt "$name")"
            option="$(strlower "$name")"
            name="${option//-/_}"
            array_add names "$name"
            array_add descs "${shortopt:+-$shortopt, }--$option VALUE"
            array_add vars "$(echo_setv "$name" "$value")"
            array_add options "${shortopt:+-$shortopt:,}--$option: $name="
        else
            name="$var"
            shortopt="$(__genparse_shortopt "$name")"
            option="$(strlower "$name")"
            name="${option//-/_}"
            array_add names "$name"
            array_add descs "${shortopt:+-$shortopt, }--$option"
            array_add vars "$name="
            array_add options "${shortopt:+-$shortopt,}--$option $name=1"
        fi
    done

    echo -n 'function display_help() {
    [ -n "$HELP_USAGE" ] || HELP_USAGE="USAGE
    $scriptname'
    [ -n "$descs" ] && echo -n ' [options]'
    echo '"'
    if [ -n "$descs" ]; then
        echo -n '    [ -n "$HELP_OPTIONS" ] || HELP_OPTIONS="OPTIONS'
        i=0
        while [ $i -lt ${#descs[*]} ]; do
            name="${names[$i]}"
            uname="$(strupper "$name")"
            desc="${descs[$i]}"
            echo -n "
\${HELP_${uname}_OPTION:-    $desc\${HELP_${uname}_DESC:+
        \${HELP_${uname}_DESC//
/
        }}}"
            i=$(($i + 1))
        done
        echo '"'
    fi
    echo '    uecho "${HELP_DESC:+$HELP_DESC

}$HELP_USAGE${HELP_OPTIONS:+

$HELP_OPTIONS}"
}
'
    for var in "${vars[@]}"; do
        echo "$var"
    done
    echo 'parse_opts "${PRETTYOPTS[@]}" \'
    echo '    --help '\''$exit_with display_help'\'' \'
    for option in "${options[@]}"; do
        echo "    $option \\"
    done
    echo '    @ args -- "$@" && set -- "${args[@]}" || die "$args"'
}
##@inc]base.args
##@inc[base.tools
## Fonctions de base: outils divers
##@inc[base.args
## Analyse des arguments de la ligne de commande
##@inc[base.core
## Fonctions de base: fondement
uprovide base.core

function echo_() {
    echo -n "$*"
}
function recho() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo "$first" "$@"
    else
        echo "$@"
    fi
}
function recho_() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo -n "$first" "$@"
    else
        echo -n "$@"
    fi
}
function _qval() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    recho_ "$s"
}
function should_quote() {
    local s="$*"
    local l="${#s}"
    [ $l -eq 0 -o $l -gt 80 ] && return 0
    s="${s//[a-zA-Z0-9]/}"
    s="${s//,/}"
    s="${s//./}"
    s="${s//+/}"
    s="${s//\//}"
    s="${s//-/}"
    s="${s//_/}"
    s="${s//=/}"
    [ -n "$s" ]
}
function qval() {
    echo -n \"
    _qval "$@"
    echo \"
}
function qvalm() {
    if should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvalr() {
    if [ -z "$*" ]; then
        :
    elif should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvals() {
    local arg first=1
    for arg in "$@"; do
        [ -z "$first" ] && echo -n " "
        if should_quote "$arg"; then
            echo -n \"
            _qval "$arg"
            echo -n \"
        else
            recho_ "$arg"
        fi
        first=
    done
    [ -z "$first" ] && echo
}
function qwc() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    local r a b
    while [ -n "$s" ]; do
        if [[ "$s" == *\** ]]; then
            if [[ "$s" == *\?* ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\**}"
                s="${s#*\*}"
                r="$r\"$a\"*"
            fi
        elif [[ "$s" == *\?* ]]; then
            if [[ "$s" == *\** ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\?*}"
                s="${s#*\?}"
                r="$r\"$a\"?"
            fi
        else
            r="$r\"$s\""
            break
        fi
    done
    recho_ "$r"
}
function qlines() {
    sed "s/'/'\\\\''/g; s/.*/'&'/g"
}
function setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    eval "$__s_var=\"\$*\""
}
function _setv() {
    local __s_var="$1"; shift
    eval "$__s_var=\"\$*\""
}
function echo_setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    echo "$__s_var=$(qvalr "$*")"
}
function setx() {
    if [ "$1" == -a ]; then
        shift
        local __s_array="$1"; shift
        if [[ "$__s_array" == *=* ]]; then
            set -- "${__s_array#*=}" "$@"
            __s_array="${__s_array%%=*}"
        fi
        eval "$__s_array=($("$@" | qlines))"
    else
        local __s_var="$1"; shift
        if [[ "$__s_var" == *=* ]]; then
            set -- "${__s_var#*=}" "$@"
            __s_var="${__s_var%%=*}"
        fi
        eval "$__s_var="'"$("$@")"'
    fi
}
function _setvx() {
    local __s_var="$1"; shift
    eval "$__s_var="'"$("$@")"'
}
function _setax() {
    local __s_array="$1"; shift
    eval "$__s_array=($("$@" | qlines))"
}
function evalx() {
    local __e_val __e_arg __e_r=0
    local -a __e_cmd

    local __e_first=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            __e_cmd=("${__e_cmd[@]}" "$__e_arg")
        done

        if [ -n "$__e_first" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_first=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
function setxx() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalx "$@"
}
function evalp() {
    local __e_arg __e_cmd

    while [ $# -gt 0 ]; do
        __e_arg="$1"; shift
        if [ "$__e_arg" == // ]; then
            __e_cmd="$__e_cmd |"
            continue
        elif [ "${__e_arg%//}" != "$__e_arg" ]; then
            local __e_tmp="${__e_arg%//}"
            if [ -z "${__e_tmp//\\/}" ]; then
                __e_arg="${__e_arg#\\}"
            fi
        fi
        __e_cmd="${__e_cmd:+$__e_cmd }\"$(_qval "$__e_arg")\""
    done
    eval "$__e_cmd"
}
function setxp() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalp "$@"
}
function testx() {
    local __t_op="$1"; shift
    local __t_val="$(evalx "$@")"
    [ $__t_op "$__t_val" ]
}
function test2x() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrx() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}
function testp() {
    local __t_op="$1"; shift
    local __t_val="$(evalp "$@")"
    [ $__t_op "$__t_val" ]
}
function test2p() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrp() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}

function err2out() {
    "$@" 2>&1
}

function is_defined() {
    [ -n "$(declare -p "$1" 2>/dev/null)" ]
}
function is_array() {
    case "$(declare -p "$1" 2>/dev/null)" in declare\ -a*) return 0;; esac
    return 1
}

function upvar() {
    if unset -v "$1"; then
        if [ $# -eq 2 ]; then
            eval "$1=\"\$2\""
        else
            eval "$1=(\"\${@:2}\")"
        fi
    fi
}
function array_upvar() {
    unset -v "$1" && eval "$1=(\"\${@:2}\")"
}
function upvars() {
    while [ $# -gt 0 ]; do
        case "$1" in
        -a)
            unset -v "$2" && eval "$2=(\"\${@:3}\")"
            break
            ;;
        -a*)
            unset -v "$2" && eval "$2=(\"\${@:3:${1#-a}}\")"
            shift $((${1#-a} + 2)) || return 1
            ;;
        *)
            unset -v "$1" && eval "$1=\"\$2\""
            shift; shift
            ;;
        esac
    done
}

function __ab_process_pending() {
    local -a values
    case "$mode" in
    cmd) values="$("${pending[@]}")";;
    ssplit) eval "values=($("${pending[@]}"))";;
    lsplit) eval "values=($("${pending[@]}" | qlines))";;
    add) values=("${pending[@]}");;
    esac
    cmd=("${cmd[@]}" "${values[@]}")
    pending=()
}
function array_buildcmd() {
    local desta="$1"; shift; local "$desta"
    local mode=add
    local -a pending cmd
    while [ $# -gt 0 ]; do
        case "$1" in
            ++c|++cmd|++) __ab_process_pending; mode=cmd;;
            ++s|++ssplit) __ab_process_pending; mode=ssplit;;
            ++l|++lsplit) __ab_process_pending; mode=lsplit;;
            ++a|++add) __ab_process_pending; mode=add;;
            *) pending=("${pending[@]}" "$1");;
        esac
        shift
    done
    __ab_process_pending
    array_upvar "$desta" "${cmd[@]}"
}
function buildcmd() {
    local -a args
    array_buildcmd args "$@"
    qvals "${args[@]}"
}
function evalcmd() {
    local -a args
    array_buildcmd args "$@"
    "${args[@]}"
}
##@inc]base.core
##@inc[base.string
## Fonctions de base: gestion des valeurs chaines scalaires
uprovide base.string
urequire base.core


function straddp() {
    local p="$1"; shift
    echo "$p$*"
}
function strdelp() {
    local p="$1"; shift
    local str="$*"
    echo "${str#$p}"
}
function strdelp2() {
    local p="$1"; shift
    local str="$*"
    echo "${str##$p}"
}
function stradds() {
    local s="$1"; shift
    echo "$*$s"
}
function strdels() {
    local s="$1"; shift
    local str="$*"
    echo "${str%$s}"
}
function strdels2() {
    local s="$1"; shift
    local str="$*"
    echo "${str%%$s}"
}
function strlower() {
    local str="$*"
    echo "${str,,}"
}
function strlower1() {
    local str="$*"
    echo "${str,}"
}
function strlowers() {
    local str="$*"
    echo "${*,}"
}
function strupper() {
    local str="$*"
    echo "${str^^}"
}
function strupper1() {
    local str="$*"
    echo "${str^}"
}
function struppers() {
    echo "${*^}"
}
function strmid() {
    local range="$1"; shift
    local str="$*"
    if [[ "$range" == *:-* ]]; then
        local max=${#str}
        [ $max -eq 0 ] && return
        local start="${range%%:*}"
        [ -n "$start" ] || start=0
        while [ "$start" -lt 0 ]; do
            start=$(($max$start))
        done
        max=$(($max-$start))
        local length="${range#*:}"
        while [ "$length" -lt 0 ]; do
            length=$(($max$length))
        done
        range="$start:$length"
    fi
    eval 'echo "${str:'" $range"'}"'
}
function strrepl() {
    local pattern="$1"; shift
    local repl="$1"; shift
    local str="$*"
    local cmd='echo "${str/'
    if [ "${pattern#/}" != "$pattern" ]; then
        pattern="${pattern#/}"
        cmd="$cmd/"
    elif [ "${pattern#\#}" != "$pattern" ]; then
        pattern="${pattern#\#}"
        cmd="$cmd#"
    elif [ "${pattern#%}" != "$pattern" ]; then
        pattern="${pattern#%}"
        cmd="$cmd%"
    fi
    cmd="$cmd"'$pattern/$repl}"'
    eval "$cmd"
}

function strops() {
    local -a __s_tmp
    local __s_value="$1"; shift
    while [ $# -gt 0 ]; do
        case "$1" in
        :-*|:=*|:\?*|:+*) eval '__s_value="${'"${__s_value}$1"'}"';;
        d|deref) __s_value="${!__s_value}";;
        dc|dcount|ds|dsize)
            __s_value="${__s_value}[@]"
            __s_tmp=("${!__s_value}")
            __s_value="${#__s_tmp[@]}"
            ;;
        \#*|%*|/*|:*|^*|,*) eval '__s_value="${__s_value'"$1"'}"';;
        l|length) __s_value="${#__s_value}";;
        =|==|!=|\<|\>|-eq|-ne|-lt|-le|-gt|-ge)
            __s_tmp=(\[ "$__s_value" "$@" ]); "${__s_tmp[@]}"; return $?;;
        -n|-z) __s_tmp=(\[ "$1" "$__s_value" ]); "${__s_tmp[@]}"; return $?;;
        +#*) eval '__s_value="'"${1#+#}"'$__s_value"';;
        -#*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        +%*) eval '__s_value="$__s_value"'"${1#+%}";;
        +*) eval '__s_value="$__s_value"'"${1#+}";;
        -%*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        -*) eval '__s_value="${__s_value%'"${1#-}"'}"';;
        mid|strmid) eval '__s_value="$(strmid "$2" "$__s_value")"'; shift;;
        repl|strrepl) eval '__s_value="$(strrepl "$2" "$3" "$__s_value")"'; shift; shift;;
        *) echo 1>&2 "strops: unknown operator: $1";;
        esac
        shift
    done
    echo "$__s_value"
}

function first_char() {
    local str="$*"
    echo "${str:0:1}"
}
function last_char() {
    local str="$*"
    echo "${str: -1:1}"
}
function first_chars() {
    local str="$*"
    recho "${str:0:$((${#1}-1))}"
}
function last_chars() {
    local str="$*"
    recho "${str:1}"
}
function first_char_is() {
    [ "${1:0:1}" == "$2" ]
}
function last_char_is() {
    [ "${1:$((-1)):1}" == "$2" ]
}
function beginswith() {
    local str="$1" pattern="$2"
    eval '[ "${str#$pattern}" != "$str" ]'
}
function endswith() {
    local str="$1" pattern="$2"
    eval '[ "${str%$pattern}" != "$str" ]'
}

function strsplitf() {
    [ $# -gt 0 ] || return 127
    local func count
    func="$1"; shift
    count=$#
    if [ $count -gt 0 ]; then
        eval 'set -- "${@:1:$(($count-1))}" '"${!count}" || return 126
    fi
    "$func" "$@"
}
function strecho() { recho "$@"; }
function strqvals() {
    qvals "$@"
}
function strqlines() {
    local -a lines
    _setax lines cat "$@"
    qvals "${lines[@]}"
}
function strqarray() {
    local __a __s="qvals"
    for __a in "$@"; do __s="$__s \"\${$__a[@]}\""; done
    eval "$__s"
}

function evals() {
    local __e_val __e_arg __e_r=0
    local __e_firstcmd __e_firstarg __e_splitf
    local -a __e_cmd

    __e_firstcmd=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        __e_firstarg=1 # premier argument
        __e_splitf= # premier argument après splitf
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            if [ -n "$__e_firstarg" ]; then
                __e_cmd=("str$__e_arg")
                __e_firstarg=
                [ "$__e_arg" == "splitf" ] && __e_splitf=1
            elif [ -n "$__e_splitf" ]; then
                __e_cmd=("${__e_cmd[@]}" "str$__e_arg")
                __e_splitf=
            else
                __e_cmd=("${__e_cmd[@]}" "$__e_arg")
            fi
        done

        if [ -n "$__e_firstcmd" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_firstcmd=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
##@inc]base.string
##@inc[base.array
## Fonctions de base: gestion des tableaux
uprovide base.array
urequire base.core
##@inc]base.array
uprovide base.args
urequire base.core base.string base.array #XXX maj de cette liste

function __po_parse_optdescs() {
    local -a optdescs_
    local optdesc_ option_ name_ flag_ value_
    local reset_
    local shift_
    local i_ count_

    let shift_=0
    while [ -n "$1" ]; do
        if [ "$1" == -- ]; then
            shift
            let shift_=$shift_+1
            break
        elif [ "$1" == "%" ]; then
            reset_=1
            shift
            let shift_=$shift_+1
        elif [ "$1" == "-" -o "$1" == "+" ]; then
            if [ "${opts_#+}" != "$opts_" ]; then
                opts_="${opts_#+}"
            elif  [ "${opts_#-}" != "$opts_" ]; then
                opts_="${opts_#-}"
            fi
            opts_="$1$opts_"
            shift
            let shift_=$shift_+1
        elif [ "$1" == "@" ]; then
            destargs_="$2"
            shift; shift
            let shift_=$shift_+2
        elif [[ "$1" == --* ]] || [[ "$1" == -* ]]; then
            array_split optdescs_ "$1" ","
            if [ "$2" == . ]; then
                local autoname_=
                for optdesc_ in "${optdescs_[@]}"; do
                    if [ ${#optdesc_} -gt ${#autoname_} ]; then
                        autoname_="$optdesc_"
                    fi
                done
                while [ -n "$autoname_" -a "${autoname_#-}" != "$autoname_" ]; do autoname_="${autoname_#-}"; done
                while [ -n "$autoname_" -a "${autoname_%:}" != "$autoname_" ]; do autoname_="${autoname_%:}"; done
                autoname_="${autoname_//-/_}"
                shift; shift
                set -- dummy "$autoname_" "$@"
            fi
            for optdesc_ in "${optdescs_[@]}"; do
                if [[ "$2" == \$* ]]; then
                    name_="$2"
                    if [[ "$optdesc_" == *:: ]]; then
                        option_="${optdesc_%::}"
                        flag_='::$'
                    elif [[ "$optdesc_" == *: ]]; then
                        option_="${optdesc_%:}"
                        flag_=':$'
                    else
                        option_="$optdesc_"
                        flag_='$'
                    fi
                elif [[ "$optdesc_" == *:: ]]; then
                    option_="${optdesc_%::}"
                    if [[ "$2" == *=* ]]; then
                        name_="${2%%=*}="
                        [ -n "$reset_" ] && eval "$name_="
                    else
                        name_="$2"
                        [ -n "$reset_" ] && eval "$name_=()"
                    fi
                    flag_=::
                elif [[ "$optdesc_" == *: ]]; then
                    option_="${optdesc_%:}"
                    if [[ "$2" == *=* ]]; then
                        name_="${2%%=*}="
                        [ -n "$reset_" ] && eval "$name_="
                    else
                        name_="$2"
                        [ -n "$reset_" ] && eval "$name_=()"
                    fi
                    flag_=:
                else
                    option_="$optdesc_"
                    name_="$2"
                    [ -n "$reset_" ] && eval "$name_="
                    flag_=
                fi

                if i_="$(array_find options_ "$option_")"; then
                    options_=("${options_[@]:0:$i_}" "${options_[@]:$(($i_ + 1))}")
                    names_=("${names_[@]:0:$i_}" "${names_[@]:$(($i_ + 1))}")
                    flags_=("${flags_[@]:0:$i_}" "${flags_[@]:$(($i_ + 1))}")
                fi
                options_=("${options_[@]}" "$option_")
                names_=("${names_[@]}" "$name_")
                flags_=("${flags_[@]}" "$flag_")
            done
            shift; shift
            let shift_=$shift_+2
        else
            break
        fi
    done

    i_=0
    count_=${#options_[*]}
    while [ $i_ -lt $count_ ]; do
        option_="${options_[$i_]}"
        flag_="${flags_[$i_]}"
        i_=$(($i_ + 1))

        flag_="${flag_%$}"
        if [[ "$option_" == --* ]]; then
            longopts_="${longopts_:+$longopts_,}${option_#--}$flag_"
        elif [[ "$option_" == -* ]]; then
            opts_="$opts_${option_#-}$flag_"
        fi
    done

    return $shift_
}
function __po_check_options() {
    local -a getopt_args_
    getopt_args_=(-o "$opts_" ${longopts_:+-l "$longopts_"} -- "$@")
    local args_
    if args_="$(getopt -q "${getopt_args_[@]}")"; then
        recho "$args_"
        return 0
    else
        LANG=C getopt "${getopt_args_[@]}" 2>&1 1>/dev/null
        return 1
    fi
}
function __po_process_options() {
    while [ -n "$1" ]; do
        if [ "$1" == -- ]; then
            shift
            break
        elif [[ "$1" == -* ]]; then
            local i_
            let i_=0
            for option_ in "${options_[@]}"; do
                [ "$1" == "${options_[$i_]}" ] && break
                let i_=$i_+1
            done
            name_="names_[$i_]"; name_="${!name_}"
            flag_="flags_[$i_]"; flag_="${!flag_}"
            function inc@ { eval "let $1=\$$1+1"; }
            function res@ { setv "$1" "${value_:-$2}"; }
            function add@ { array_add "$1" "${value_:-$2}"; }
            if [ -z "$name_" ]; then
                ewarn "$1: option non reconnue, elle sera ignorée"
            elif [[ "$flag_" == *\$ ]]; then
                if [[ "$flag_" == :* ]]; then
                    value_="$2"; shift
                    function set@ { res@ "$@"; }
                else
                    value_=
                    function set@ { inc@ "$@"; }
                fi
                eval "${name_#\$}"
            elif [ "$flag_" == "" ]; then
                if [[ "$name_" == *=* ]]; then
                    setv "${name_%%=*}" "${name_#*=}"
                else
                    inc@ "$name_"
                fi
            elif [ "$flag_" == ":" -o "$flag_" == "::" ]; then
                value_="$2"; shift
                if [ "${name_%=}" != "$name_" ]; then
                    setv "${name_%=}" "$value_"
                elif [[ "$name_" == *=* ]]; then
                    setv "${name_%%=*}" "${name_#*=}"
                else
                    array_add "$name_" "$value_"
                fi
            fi
        else
            break
        fi
        shift
    done
    unset -f inc@ res@ add@ set@
    [ -n "$destargs_" ] &&
    set_array "$destargs_" @ "$@"
    return 0
}
function parse_opts() {



    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_PARSE_OPTS_SET_X=1; } # désactiver set -x pour cette fonction

    local -a options_ names_ flags_ destargs_
    local opts_ longopts_
    __po_parse_optdescs "$@" || shift $?
    local args_
    if args_="$(__po_check_options "$@")"; then
        eval "set -- $args_"
        __po_process_options "$@"
    else
        [ -n "$destargs_" ] && setv "$destargs_" "$args_"
        [ -n "$__ULIB_SET_X" ] && set -x
        return 1
    fi

    [ -n "$__ULIB_PARSE_OPTS_SET_X" ] && set -x; return 0
}

function parse_args_check() {
    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_PARSE_ARGS_SET_X=1; } # désactiver set -x pour cette fonction
    if parse_opts "${PRETTYOPTS[@]}" "${args[@]}" @ args -- "$@"; then
        [ -n "$__ULIB_PARSE_ARGS_SET_X" ] && set -x
        return 0
    else
        eerror "$args"
        [ -n "$__ULIB_PARSE_ARGS_SET_X" ] && set -x
        return 1
    fi
}
function parse_args() {
    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_PARSE_ARGS_SET_X=1; } # désactiver set -x pour cette fonction
    parse_opts "${PRETTYOPTS[@]}" "${args[@]}" @ args -- "$@" || die "$args"
    [ -n "$__ULIB_PARSE_ARGS_SET_X" ] && set -x; return 0
}

HELP_DESC=
HELP_USAGE=
HELP_OPTIONS=
function __genparse_shortopt() {
    local LC_COLLATE=C
    local shortopt="${1//[^A-Z]}"
    shortopt="$(strlower "${shortopt:0:1}")"
    [ -n "$shortopt" ] && echo "$shortopt"
}
function genparse() {

    local -a names descs vars options
    local i desc var option name uname value shortopt

    for var in "$@"; do
        if [[ "$var" == *=* ]]; then
            splitvar "$var" name value
            shortopt="$(__genparse_shortopt "$name")"
            option="$(strlower "$name")"
            name="${option//-/_}"
            array_add names "$name"
            array_add descs "${shortopt:+-$shortopt, }--$option VALUE"
            array_add vars "$(echo_setv "$name" "$value")"
            array_add options "${shortopt:+-$shortopt:,}--$option: $name="
        else
            name="$var"
            shortopt="$(__genparse_shortopt "$name")"
            option="$(strlower "$name")"
            name="${option//-/_}"
            array_add names "$name"
            array_add descs "${shortopt:+-$shortopt, }--$option"
            array_add vars "$name="
            array_add options "${shortopt:+-$shortopt,}--$option $name=1"
        fi
    done

    echo -n 'function display_help() {
    [ -n "$HELP_USAGE" ] || HELP_USAGE="USAGE
    $scriptname'
    [ -n "$descs" ] && echo -n ' [options]'
    echo '"'
    if [ -n "$descs" ]; then
        echo -n '    [ -n "$HELP_OPTIONS" ] || HELP_OPTIONS="OPTIONS'
        i=0
        while [ $i -lt ${#descs[*]} ]; do
            name="${names[$i]}"
            uname="$(strupper "$name")"
            desc="${descs[$i]}"
            echo -n "
\${HELP_${uname}_OPTION:-    $desc\${HELP_${uname}_DESC:+
        \${HELP_${uname}_DESC//
/
        }}}"
            i=$(($i + 1))
        done
        echo '"'
    fi
    echo '    uecho "${HELP_DESC:+$HELP_DESC

}$HELP_USAGE${HELP_OPTIONS:+

$HELP_OPTIONS}"
}
'
    for var in "${vars[@]}"; do
        echo "$var"
    done
    echo 'parse_opts "${PRETTYOPTS[@]}" \'
    echo '    --help '\''$exit_with display_help'\'' \'
    for option in "${options[@]}"; do
        echo "    $option \\"
    done
    echo '    @ args -- "$@" && set -- "${args[@]}" || die "$args"'
}
##@inc]base.args
uprovide base.tools
urequire base.args #XXX il manque des dépendances!

function base_umove() {
    local -a args
    local updatedir
    args=(-d:,--updatedir: .)
    parse_args_check "$@" || return; set -- "${args[@]}"

    eerror_unless [ -z "$updatedir" -o -d "$updatedir" ] "$updatedir: doit être un répertoire" || return
    eerror_if [ $# -eq 0 ] "Vous devez spécifier les fichiers à déplacer" || return
    eerror_if [ $# -eq 1 ] "Vous devez spécifier la destination" || return

    local -a srcs
    local src dest

    srcs=("$@")
    setx dest=last_value srcs
    array_del_last srcs

    if [ $# -eq 2 ]; then
        if [ -d "$dest" ]; then
            : # ce cas sera traité ci-dessous
        elif [ -e "$dest" ]; then
            eerror "$dest: refus d'écraser la destination"
            return 1
        else
            src="${srcs[0]}"
            if [ -n "$updatedir" ]; then
                if [ -L "$src" ]; then
                    ldest="$(readlinka "$src")"
                    array_find_links update_links "$ldest" "$updatedir"
                else
                    array_find_links update_links "$src" "$updatedir"
                fi
                move_file "$src" "$dest" "${update_links[@]}"
            else
                move_link "$src" "$dest"
            fi
            return $?
        fi
    fi

    [ -d "$dest" ] || {
        eerror "$dest: doit être un répertoire"
        return 1
    }
    local r=0
    for src in "${srcs[@]}"; do
        if [ -n "$updatedir" ]; then
            if [ -L "$src" ]; then
                move_link "$src" "$dest" || r=$?
            else
                array_find_links update_links "$src" "$updatedir"
                move_file "$src" "$dest" "${update_links[@]}" || r=$?
            fi
        else
            move_link "$src" "$dest" || r=$?
        fi
    done
    return $r
}

function base_udelete() {
    local -a args
    local updatedir
    args=(-d:,--updatedir: .)
    parse_args_check "$@" || return; set -- "${args[@]}"

    eerror_unless [ -z "$updatedir" -o -d "$updatedir" ] "$updatedir: doit être un répertoire" || return
    eerror_if [ $# -eq 0 ] "Vous devez spécifier les fichiers à supprimer" || return

    local file r=0
    for file in "$@"; do
        if [ -n "$updatedir" ]; then
            if [ -L "$file" ]; then
                rm "$file" || r=$?
            else
                array_find_links update_links "$file" "$updatedir"
                rm "$file" "${update_links[@]}" || r=$?
            fi
        else
            rm "$file" || r=$?
        fi
    done
    return $r
}

function base_ucopy() {
    eerror_if [ $# -eq 0 ] "Vous devez spécifier les fichiers à copier" || return
    eerror_if [ $# -eq 1 ] "Vous devez spécifier la destination" || return

    local -a srcs
    local src dest

    srcs=("$@")
    setx dest=last_value srcs
    array_del_last srcs

    if [ $# -eq 2 ]; then
        if [ -d "$dest" ]; then
            : # ce cas sera traité ci-dessous
        elif [ -e "$dest" ]; then
            eerror "$dest: refus d'écraser la destination"
            return 1
        else
            src="${srcs[0]}"
            copy_link "$src" "$dest"
            return $?
        fi
    fi

    [ -d "$dest" ] || {
        eerror "$dest: doit être un répertoire"
        return 1
    }
    local r=0
    for src in "${srcs[@]}"; do
        copy_link "$src" "$dest" || r=$?
    done
    return $r
}
##@inc]base.tools
##@inc[base.compat
## Fonctions de base: support des fonctions obsolètes et des versions de bash < 4.x
##@inc[base.core
## Fonctions de base: fondement
uprovide base.core

function echo_() {
    echo -n "$*"
}
function recho() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo "$first" "$@"
    else
        echo "$@"
    fi
}
function recho_() {
    if [[ "${1:0:2}" == -[eEn] ]]; then
        local first="${1:1}"; shift
        echo -n -
        echo -n "$first" "$@"
    else
        echo -n "$@"
    fi
}
function _qval() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    recho_ "$s"
}
function should_quote() {
    local s="$*"
    local l="${#s}"
    [ $l -eq 0 -o $l -gt 80 ] && return 0
    s="${s//[a-zA-Z0-9]/}"
    s="${s//,/}"
    s="${s//./}"
    s="${s//+/}"
    s="${s//\//}"
    s="${s//-/}"
    s="${s//_/}"
    s="${s//=/}"
    [ -n "$s" ]
}
function qval() {
    echo -n \"
    _qval "$@"
    echo \"
}
function qvalm() {
    if should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvalr() {
    if [ -z "$*" ]; then
        :
    elif should_quote "$*"; then
        echo -n \"
        _qval "$@"
        echo \"
    else
        recho "$*"
    fi
}
function qvals() {
    local arg first=1
    for arg in "$@"; do
        [ -z "$first" ] && echo -n " "
        if should_quote "$arg"; then
            echo -n \"
            _qval "$arg"
            echo -n \"
        else
            recho_ "$arg"
        fi
        first=
    done
    [ -z "$first" ] && echo
}
function qwc() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//\$/\\\$}"
    s="${s//\`/\\\`}"
    local r a b
    while [ -n "$s" ]; do
        if [[ "$s" == *\** ]]; then
            if [[ "$s" == *\?* ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\**}"
                s="${s#*\*}"
                r="$r\"$a\"*"
            fi
        elif [[ "$s" == *\?* ]]; then
            if [[ "$s" == *\** ]]; then
                a="${s%%\**}"
                b="${s%%\?*}"
                if [ ${#a} -lt ${#b} ]; then
                    s="${s#*\*}"
                    r="$r\"$a\"*"
                else
                    s="${s#*\?}"
                    r="$r\"$b\"?"
                fi
            else
                a="${s%%\?*}"
                s="${s#*\?}"
                r="$r\"$a\"?"
            fi
        else
            r="$r\"$s\""
            break
        fi
    done
    recho_ "$r"
}
function qlines() {
    sed "s/'/'\\\\''/g; s/.*/'&'/g"
}
function setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    eval "$__s_var=\"\$*\""
}
function _setv() {
    local __s_var="$1"; shift
    eval "$__s_var=\"\$*\""
}
function echo_setv() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    echo "$__s_var=$(qvalr "$*")"
}
function setx() {
    if [ "$1" == -a ]; then
        shift
        local __s_array="$1"; shift
        if [[ "$__s_array" == *=* ]]; then
            set -- "${__s_array#*=}" "$@"
            __s_array="${__s_array%%=*}"
        fi
        eval "$__s_array=($("$@" | qlines))"
    else
        local __s_var="$1"; shift
        if [[ "$__s_var" == *=* ]]; then
            set -- "${__s_var#*=}" "$@"
            __s_var="${__s_var%%=*}"
        fi
        eval "$__s_var="'"$("$@")"'
    fi
}
function _setvx() {
    local __s_var="$1"; shift
    eval "$__s_var="'"$("$@")"'
}
function _setax() {
    local __s_array="$1"; shift
    eval "$__s_array=($("$@" | qlines))"
}
function evalx() {
    local __e_val __e_arg __e_r=0
    local -a __e_cmd

    local __e_first=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            __e_cmd=("${__e_cmd[@]}" "$__e_arg")
        done

        if [ -n "$__e_first" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_first=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
function setxx() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalx "$@"
}
function evalp() {
    local __e_arg __e_cmd

    while [ $# -gt 0 ]; do
        __e_arg="$1"; shift
        if [ "$__e_arg" == // ]; then
            __e_cmd="$__e_cmd |"
            continue
        elif [ "${__e_arg%//}" != "$__e_arg" ]; then
            local __e_tmp="${__e_arg%//}"
            if [ -z "${__e_tmp//\\/}" ]; then
                __e_arg="${__e_arg#\\}"
            fi
        fi
        __e_cmd="${__e_cmd:+$__e_cmd }\"$(_qval "$__e_arg")\""
    done
    eval "$__e_cmd"
}
function setxp() {
    local -a __s_args
    if [ "$1" == -a ]; then __s_args=(-a); shift; fi
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    __s_args=("${__s_args[@]}" "$__s_var")
    setx "${__s_args[@]}" evalp "$@"
}
function testx() {
    local __t_op="$1"; shift
    local __t_val="$(evalx "$@")"
    [ $__t_op "$__t_val" ]
}
function test2x() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrx() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalx "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}
function testp() {
    local __t_op="$1"; shift
    local __t_val="$(evalp "$@")"
    [ $__t_op "$__t_val" ]
}
function test2p() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    [ "$__t_val1" $__t_op "$__t_val2" ]
}
function testrp() {
    local __t_val1="$1"; shift
    local __t_op="$1"; shift
    local __t_val2="$(evalp "$@")"
    eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
}

function err2out() {
    "$@" 2>&1
}

function is_defined() {
    [ -n "$(declare -p "$1" 2>/dev/null)" ]
}
function is_array() {
    case "$(declare -p "$1" 2>/dev/null)" in declare\ -a*) return 0;; esac
    return 1
}

function upvar() {
    if unset -v "$1"; then
        if [ $# -eq 2 ]; then
            eval "$1=\"\$2\""
        else
            eval "$1=(\"\${@:2}\")"
        fi
    fi
}
function array_upvar() {
    unset -v "$1" && eval "$1=(\"\${@:2}\")"
}
function upvars() {
    while [ $# -gt 0 ]; do
        case "$1" in
        -a)
            unset -v "$2" && eval "$2=(\"\${@:3}\")"
            break
            ;;
        -a*)
            unset -v "$2" && eval "$2=(\"\${@:3:${1#-a}}\")"
            shift $((${1#-a} + 2)) || return 1
            ;;
        *)
            unset -v "$1" && eval "$1=\"\$2\""
            shift; shift
            ;;
        esac
    done
}

function __ab_process_pending() {
    local -a values
    case "$mode" in
    cmd) values="$("${pending[@]}")";;
    ssplit) eval "values=($("${pending[@]}"))";;
    lsplit) eval "values=($("${pending[@]}" | qlines))";;
    add) values=("${pending[@]}");;
    esac
    cmd=("${cmd[@]}" "${values[@]}")
    pending=()
}
function array_buildcmd() {
    local desta="$1"; shift; local "$desta"
    local mode=add
    local -a pending cmd
    while [ $# -gt 0 ]; do
        case "$1" in
            ++c|++cmd|++) __ab_process_pending; mode=cmd;;
            ++s|++ssplit) __ab_process_pending; mode=ssplit;;
            ++l|++lsplit) __ab_process_pending; mode=lsplit;;
            ++a|++add) __ab_process_pending; mode=add;;
            *) pending=("${pending[@]}" "$1");;
        esac
        shift
    done
    __ab_process_pending
    array_upvar "$desta" "${cmd[@]}"
}
function buildcmd() {
    local -a args
    array_buildcmd args "$@"
    qvals "${args[@]}"
}
function evalcmd() {
    local -a args
    array_buildcmd args "$@"
    "${args[@]}"
}
##@inc]base.core
##@inc[base.quote
## Fonctions de base: protection de valeurs chaine
uprovide base.quote
urequire base.core

function _qawk() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//
/\\n}"
    recho_ "$s"
}
function qawk() {
    echo -n \"
    _qawk "$@"
    echo \"
}
function qseds() {
    local s="$*"
    s="${s//\\/\\\\}"
    s="${s//\//\\/}"
    s="${s//
/\\n}"
    recho "$s"
}
function _qform() {
    local s="$*"
    s="${s//\%/%25}"
    s="${s//+/%2B}"
    s="${s//&/%26}"
    s="${s//=/%3D}"
    s="${s// /+}"
    recho_ "$s"
}
function qform() {
    local s="$*"
    if [[ "$s" == *=* ]]; then
        _qform "${s%%=*}"
        echo -n =
        _qform "${s#*=}"
        echo
    else
        _qform "$s"
        echo
    fi
}
function _qsql() {
    local q="'" qq="''"
    echo "${*//$q/$qq}"
}
function qsql() {
    local q="'" qq="''"
    echo "'${*//$q/$qq}'"
}
##@inc]base.quote
##@inc[base.string
## Fonctions de base: gestion des valeurs chaines scalaires
uprovide base.string
urequire base.core


function straddp() {
    local p="$1"; shift
    echo "$p$*"
}
function strdelp() {
    local p="$1"; shift
    local str="$*"
    echo "${str#$p}"
}
function strdelp2() {
    local p="$1"; shift
    local str="$*"
    echo "${str##$p}"
}
function stradds() {
    local s="$1"; shift
    echo "$*$s"
}
function strdels() {
    local s="$1"; shift
    local str="$*"
    echo "${str%$s}"
}
function strdels2() {
    local s="$1"; shift
    local str="$*"
    echo "${str%%$s}"
}
function strlower() {
    local str="$*"
    echo "${str,,}"
}
function strlower1() {
    local str="$*"
    echo "${str,}"
}
function strlowers() {
    local str="$*"
    echo "${*,}"
}
function strupper() {
    local str="$*"
    echo "${str^^}"
}
function strupper1() {
    local str="$*"
    echo "${str^}"
}
function struppers() {
    echo "${*^}"
}
function strmid() {
    local range="$1"; shift
    local str="$*"
    if [[ "$range" == *:-* ]]; then
        local max=${#str}
        [ $max -eq 0 ] && return
        local start="${range%%:*}"
        [ -n "$start" ] || start=0
        while [ "$start" -lt 0 ]; do
            start=$(($max$start))
        done
        max=$(($max-$start))
        local length="${range#*:}"
        while [ "$length" -lt 0 ]; do
            length=$(($max$length))
        done
        range="$start:$length"
    fi
    eval 'echo "${str:'" $range"'}"'
}
function strrepl() {
    local pattern="$1"; shift
    local repl="$1"; shift
    local str="$*"
    local cmd='echo "${str/'
    if [ "${pattern#/}" != "$pattern" ]; then
        pattern="${pattern#/}"
        cmd="$cmd/"
    elif [ "${pattern#\#}" != "$pattern" ]; then
        pattern="${pattern#\#}"
        cmd="$cmd#"
    elif [ "${pattern#%}" != "$pattern" ]; then
        pattern="${pattern#%}"
        cmd="$cmd%"
    fi
    cmd="$cmd"'$pattern/$repl}"'
    eval "$cmd"
}

function strops() {
    local -a __s_tmp
    local __s_value="$1"; shift
    while [ $# -gt 0 ]; do
        case "$1" in
        :-*|:=*|:\?*|:+*) eval '__s_value="${'"${__s_value}$1"'}"';;
        d|deref) __s_value="${!__s_value}";;
        dc|dcount|ds|dsize)
            __s_value="${__s_value}[@]"
            __s_tmp=("${!__s_value}")
            __s_value="${#__s_tmp[@]}"
            ;;
        \#*|%*|/*|:*|^*|,*) eval '__s_value="${__s_value'"$1"'}"';;
        l|length) __s_value="${#__s_value}";;
        =|==|!=|\<|\>|-eq|-ne|-lt|-le|-gt|-ge)
            __s_tmp=(\[ "$__s_value" "$@" ]); "${__s_tmp[@]}"; return $?;;
        -n|-z) __s_tmp=(\[ "$1" "$__s_value" ]); "${__s_tmp[@]}"; return $?;;
        +#*) eval '__s_value="'"${1#+#}"'$__s_value"';;
        -#*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        +%*) eval '__s_value="$__s_value"'"${1#+%}";;
        +*) eval '__s_value="$__s_value"'"${1#+}";;
        -%*) eval '__s_value="${__s_value'"${1#-}"'}"';;
        -*) eval '__s_value="${__s_value%'"${1#-}"'}"';;
        mid|strmid) eval '__s_value="$(strmid "$2" "$__s_value")"'; shift;;
        repl|strrepl) eval '__s_value="$(strrepl "$2" "$3" "$__s_value")"'; shift; shift;;
        *) echo 1>&2 "strops: unknown operator: $1";;
        esac
        shift
    done
    echo "$__s_value"
}

function first_char() {
    local str="$*"
    echo "${str:0:1}"
}
function last_char() {
    local str="$*"
    echo "${str: -1:1}"
}
function first_chars() {
    local str="$*"
    recho "${str:0:$((${#1}-1))}"
}
function last_chars() {
    local str="$*"
    recho "${str:1}"
}
function first_char_is() {
    [ "${1:0:1}" == "$2" ]
}
function last_char_is() {
    [ "${1:$((-1)):1}" == "$2" ]
}
function beginswith() {
    local str="$1" pattern="$2"
    eval '[ "${str#$pattern}" != "$str" ]'
}
function endswith() {
    local str="$1" pattern="$2"
    eval '[ "${str%$pattern}" != "$str" ]'
}

function strsplitf() {
    [ $# -gt 0 ] || return 127
    local func count
    func="$1"; shift
    count=$#
    if [ $count -gt 0 ]; then
        eval 'set -- "${@:1:$(($count-1))}" '"${!count}" || return 126
    fi
    "$func" "$@"
}
function strecho() { recho "$@"; }
function strqvals() {
    qvals "$@"
}
function strqlines() {
    local -a lines
    _setax lines cat "$@"
    qvals "${lines[@]}"
}
function strqarray() {
    local __a __s="qvals"
    for __a in "$@"; do __s="$__s \"\${$__a[@]}\""; done
    eval "$__s"
}

function evals() {
    local __e_val __e_arg __e_r=0
    local __e_firstcmd __e_firstarg __e_splitf
    local -a __e_cmd

    __e_firstcmd=1
    while [ $# -gt 0 ]; do
        __e_cmd=()
        __e_firstarg=1 # premier argument
        __e_splitf= # premier argument après splitf
        while [ $# -gt 0 ]; do
            __e_arg="$1"; shift
            [ "$__e_arg" == // ] && break
            if [ "${__e_arg%//}" != "$__e_arg" ]; then
                local __e_tmp="${__e_arg%//}"
                if [ -z "${__e_tmp//\\/}" ]; then
                    __e_arg="${__e_arg#\\}"
                    __e_cmd=("${__e_cmd[@]}" "$__e_arg")
                    continue
                fi
            fi
            if [ -n "$__e_firstarg" ]; then
                __e_cmd=("str$__e_arg")
                __e_firstarg=
                [ "$__e_arg" == "splitf" ] && __e_splitf=1
            elif [ -n "$__e_splitf" ]; then
                __e_cmd=("${__e_cmd[@]}" "str$__e_arg")
                __e_splitf=
            else
                __e_cmd=("${__e_cmd[@]}" "$__e_arg")
            fi
        done

        if [ -n "$__e_firstcmd" ]; then
            __e_val="$("${__e_cmd[@]}")" || __e_r=$?
        else
            __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
        fi
        __e_firstcmd=
    done
    [ -n "$__e_val" ] && echo "$__e_val"
    return $__e_r
}
##@inc]base.string
##@inc[base.bool
## Fonctions de base: valeurs booléennes
##@inc[base.num
## Fonctions de base: gestion des valeurs numériques
uprovide base.num

function isnum() {
    [ ${#1} -gt 0 ] || return 1
    local v="${1#-}"
    [ ${#v} -gt 0 ] || return 1
    v="${v//[0-9]/}"
    [ -z "$v" ]
}
function ispnum() {
    [ ${#1} -gt 0  ] || return 1
    [ -z "${1//[0-9]/}" ]
}
function isrnum() {
    [ ${#1} -gt 0 ] || return 1
    local v="${1#-}"
    [ ${#v} -gt 0 ] || return 1
    v="${v//./}"
    v="${v//,/}"
    v="${v//[0-9]/}"
    [ -z "$v" ]
}

function evali() {
    echo "$(($*))"
}
##@inc]base.num
uprovide base.bool
urequire base.num

function is_yes() {
    case "${1,,}" in
    o|oui|y|yes|v|vrai|t|true|on) return 0;;
    esac
    isnum "$1" && [ "$1" -ne 0 ] && return 0
    return 1
}
function is_no() {
    case "${1,,}" in
    n|non|no|f|faux|false|off) return 0;;
    esac
    isnum "$1" && [ "$1" -eq 0 ] && return 0
    return 1
}
function yesval() {
    is_yes "$1" && echo 1
}

function setb() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    local __s_r
    if "$@" >/dev/null; then
        eval "$__s_var=1"
    else
        __s_r=$?
        eval "$__s_var="
        return $__s_r
    fi
}
function _setb() {
    local __s_var="$1"; shift
    if "$@" >/dev/null; then
        eval "$__s_var=1"
    else
        eval "$__s_var="
    fi
}

function evalb() {
    if evalx "$@" >/dev/null; then
        echo 1
    else
        return $?
    fi
}
function setxb() {
    local __s_var="$1"; shift
    if [[ "$__s_var" == *=* ]]; then
        set -- "${__s_var#*=}" "$@"
        __s_var="${__s_var%%=*}"
    fi
    setx "$__s_var" evalb "$@"
}
##@inc]base.bool
uprovide base.compat


urequire base.core
function setx2() { setxx "$@"; }
function rawecho() { recho "$@"; }
function rawecho_() { recho_ "$@"; }
function quote_arg() { _qval "$@"; }
function quoted_arg() { qvalm "$@"; }
function quoted_args() { qvals "$@"; }
function set_var() { setv "$@"; }
function set_var_cmd() { echo_setv "$@"; }
function set_var_literal() { eval "$1=$2"; }

urequire base.quote
function quote_awk() { _qawk "$@"; }
function quoted_awk() { qawk "$@"; }
function quote_seds() { qseds "$@"; }
function quote_form() { _qform "$@"; }
function quoted_form() { qform "$@"; }


if [ -n "$BASH_VERSINFO" -a "${BASH_VERSINFO[0]}" -lt 4 ]; then
    urequire base.string
    function strlower() { tr A-Z a-z <<<"$*"; }
    function strlower1() {
        local str="$*"
        local h="${str:0:1}" r="${str:1}"
        echo "$(tr A-Z a-z <<<"$h")$r"
    }
    function strlowers() {
        local -a vs; local v
        for v in "$@"; do
            vs=("${vs[@]}" "$(strlower1 "$v")")
        done
        echo "${vs[*]}"
    }
    function strupper() { tr a-z A-Z <<<"$*"; }
    function strupper1() {
        local str="$*"
        local h="${str:0:1}" r="${str:1}"
        echo "$(tr a-z A-Z <<<"$h")$r"
    }
    function struppers() {
        local -a vs; local v
        for v in "$@"; do
            vs=("${vs[@]}" "$(strupper1 "$v")")
        done
        echo "${vs[*]}"
    }

    urequire base.bool
    function is_yes() {
        case "$1" in
        o|oui|y|yes|v|vrai|t|true|on) return 0;;
        O|OUI|Y|YES|V|VRAI|T|TRUE|ON) return 0;;
        esac
        isnum "$1" && [ "$1" -ne 0 ] && return 0
        case "$(strlower "$1")" in
        o|oui|y|yes|v|vrai|t|true|on) return 0;;
        esac
        return 1
    }
    function is_no() {
        case "$1" in
        n|non|no|f|faux|false|off) return 0;;
        N|NON|NO|F|FAUX|FALSE|OFF) return 0;;
        esac
        isnum "$1" && [ "$1" -eq 0 ] && return 0
        case "$(strlower "$1")" in
        n|non|no|f|faux|false|off) return 0;;
        esac
        return 1
    }
fi
##@inc]base.compat
uprovide base
urequire base.init base.core base.string base.num base.bool base.array base.quote base.split base.args base.tools base.compat

UNAME_SYSTEM=`uname -s`
[ "${UNAME_SYSTEM#CYGWIN}" != "$UNAME_SYSTEM" ] && UNAME_SYSTEM=Cygwin
[ "${UNAME_SYSTEM#MINGW32}" != "$UNAME_SYSTEM" ] && UNAME_SYSTEM=Mingw
UNAME_MACHINE=`uname -m`
if [ -n "$UTOOLS_CHROOT" ]; then
    [ -n "$UTOOLS_UNAME_SYSTEM" ] && eval "UNAME_SYSTEM=$UTOOLS_UNAME_SYSTEM"
    [ -n "$UTOOLS_UNAME_MACHINE" ] && eval "UNAME_MACHINE=$UTOOLS_UNAME_MACHINE"
fi

function setyesval() {
    is_yes "$2" && _setv "$1" 1 || _setv "$1" ""
}
function normyesval() {
    is_yes "${2:-"${!1}"}" && _setv "$1" 1 || _setv "$1" ""
}
function normyesvals() {
    local __nyv_yesvar
    for __nyv_yesvar in "$@"; do
        is_yes "${!__nyv_yesvar}" && _setv "$__nyv_yesvar" 1 || _setv "$__nyv_yesvar" ""
    done
}
function quote_in() {
    sed 's/\\/\\\\/g
s/"/\\"/g
s/\$/\\$/g
s/`/\\`/g'
}
function quote_sin() {
    sed "s/'/'\\\\''/g"
}
function quote_sarg() {
    quote_sin <<<"$1"
}
function quoted_sarg() {
    echo "'$(quote_sarg "$1")'"
}
function quoted_sargs() {
    local a s
    for a in "$@"; do
        s="${s:+$s }$(quoted_sarg "$a")"
    done
    recho "$s"
}

function set_array_cmd() {
    [ $# -eq 1 ] && set -- "$1" "$1"
    local __sac_s __sac_v __sac_f
    __sac_s="$1=("; shift
    if [ "$1" == "@" ]; then
        shift
    else
        eval "set -- \"\${$1[@]}\""
    fi
    __sac_f=1
    for __sac_v in "$@"; do
        [ -n "$__sac_f" ] && __sac_f= || __sac_s="$__sac_s "
        __sac_s="$__sac_s$(qvalm "$__sac_v")"
    done
    __sac_s="$__sac_s)"
    echo "$__sac_s"
}
function set_array() {
    eval "$(set_array_cmd "$@")"
}
function array_count() {
    eval "echo \${#$1[*]}"
}
function array_isempty() {
    [ $(array_count "$1") -eq 0 ]
}
function array_new() {
    eval "$1=()"
}
function array_add() {
    local __aa_a="$1"; shift
    eval "$__aa_a=(\"\${$__aa_a[@]}\" \"\$@\")"
}
function array_ins() {
    local __aa_a="$1"; shift
    eval "$__aa_a=(\"\$@\" \"\${$__aa_a[@]}\")"
}
function array_del() {
    local __ad_v
    local -a __ad_vs
    eval 'for __ad_v in "${'"$1"'[@]}"; do
  if [ "$__ad_v" != '"$(qval "$2")"' ]; then
    array_add __ad_vs "$__ad_v"
  fi
done'
    array_copy "$1" __ad_vs
}
function array_addu() {
    local __as_v
    eval 'for __as_v in "${'"$1"'[@]}"; do
  if [ "$__as_v" == '"$(qval "$2")"' ]; then
    return 1
  fi
done'
    array_add "$1" "$2"
    return 0
}
function array_set() {
    array_addu "$@"
}
function array_insu() {
    local __as_v
    eval 'for __as_v in "${'"$1"'[@]}"; do
  if [ "$__as_v" == '"$(qval "$2")"' ]; then
    return 1
  fi
done'
    array_ins "$1" "$2"
    return 0
}
function array_fillrange() {
    local -a __af_vs
    local __af_i="${2:-1}" __af_to="${3:-10}" __af_step="${4:-1}"
    while [ "$__af_i" -le "$__af_to" ]; do
        __af_vs=("${__af_vs[@]}" "$__af_i")
        __af_i=$(($__af_i + $__af_step))
    done
    array_copy "$1" __af_vs
}
function array_eq() {
    local -a __ae_a1 __ae_a2
    array_copy __ae_a1 "$1"
    array_copy __ae_a2 "$2"
    [ ${#__ae_a1[*]} -eq ${#__ae_a2[*]} ] || return 1
    local __ae_v __ae_i=0
    for __ae_v in "${__ae_a1[@]}"; do
        [ "$__ae_v" == "${__ae_a2[$__ae_i]}" ] || return 1
        __ae_i=$(($__ae_i + 1))
    done
    return 0
}
function array_contains() {
    local __ac_v
    eval 'for __ac_v in "${'"$1"'[@]}"; do
  if [ "$__ac_v" == '"$(qvalm "$2")"' ]; then
    return 0
  fi
done'
    return 1
}
function array_icontains() {
    local __ac_v
    eval 'for __ac_v in "${'"$1"'[@]}"; do
  if [ "$(strlower "$__ac_v")" == '"$(strlower "$(qval "$2")")"' ]; then
    return 0
  fi
done'
    return 1
}
function array_find() {
    local __af_i __af_v
    __af_i=0
    eval 'for __af_v in "${'"$1"'[@]}"; do
  if [ "$__af_v" == '"$(qval "$2")"' ]; then
    if [ -n "$3" ]; then
      echo "${'"$3"'[$__af_i]}"
    else
      echo "$__af_i"
    fi
    return 0
  fi
  __af_i=$(($__af_i + 1))
done'
    return 1
}
function array_reverse() {
    local -a __ar_vs
    local __ar_v
    array_copy __ar_vs "$1"
    array_new "$1"
    for __ar_v in "${__ar_vs[@]}"; do
        array_ins "$1" "$__ar_v"
    done
}

function array_replace() {
    local __ar_sn="$1"; shift
    local __ar_f="$1"; shift
    local -a __ar_s __ar_d
    local __ar_v
    array_copy __ar_s "$__ar_sn"
    for __ar_v in "${__ar_s[@]}"; do
        if [ "$__ar_v" == "$__ar_f" ]; then
            __ar_d=("${__ar_d[@]}" "$@")
        else
            __ar_d=("${__ar_d[@]}" "$__ar_v")
        fi
    done
    array_copy "$__ar_sn" __ar_d
}
function array_each() {
    local __ae_an="$1"; shift
    local __ae_f="$1"; shift
    local -a __ae_a
    local __ae_v
    array_copy __ae_a "$__ae_an"
    for __ae_v in "${__ae_a[@]}"; do
        "$__ae_f" "$__ae_v" "$@"
    done
}
function array_map() {
    local __am_an="$1"; shift
    local __am_f="$1"; shift
    local -a __am_a __am_vs
    local __am_v
    array_copy __am_a "$__am_an"
    for __am_v in "${__am_a[@]}"; do
        __am_vs=("${__am_vs[@]}" "$("$__am_f" "$__am_v" "$@")")
    done
    array_copy "$__am_an" __am_vs
}
function first_value() {
    eval "recho \"\${$1[@]:0:1}\""
}
function last_value() {
    eval "recho \"\${$1[@]:\$((-1)):1}\""
}
function array_copy() {
    eval "$1=(\"\${$2[@]}\")"
}
function array_copy_firsts() {
    eval "$1=(\"\${${2:-$1}[@]:0:\$((\${#${2:-$1}[@]}-1))}\")"
}
function array_del_last() {
    array_copy_firsts "$1"
}
function array_copy_lasts() {
    eval "$1=(\"\${${2:-$1}[@]:1}\")"
}
function array_del_first() {
    array_copy_lasts "$1"
}
function array_extend() {
    eval "$1=(\"\${$1[@]}\" \"\${$2[@]}\")"
}
function array_extendu() {
    local __ae_v __ae_s=1
    eval 'for __ae_v in "${'"$2"'[@]}"; do
  array_addu "$1" "$__ae_v" && __ae_s=0
done'
    return "$__ae_s"
}
function array_extend_firsts() {
    eval "$1=(\"\${$1[@]}\" \"\${$2[@]:0:\$((\${#$2[@]}-1))}\")"
}
function array_extend_lasts() {
    eval "$1=(\"\${$1[@]}\" \"\${$2[@]:1}\")"
}
function array_xsplit() {
    eval "$1=($(recho_ "$2" | awkrun RS="${3:-:}" '
{
    gsub(/'\''/, "'\'\\\\\'\''")
    print "'\''" $0 "'\''"
}'))" #"
}
function array_split() {
    eval "$1=($(recho_ "$2" | awkrun RS="${3:-:}" '
/^$/ { next }
{
    gsub(/'\''/, "'\'\\\\\'\''")
    print "'\''" $0 "'\''"
}'))" #"
}
function array_from_path() {
    array_split "$1" "$2" ":"
}
function array_from_xlines() {
    eval "$1=($(recho_ "$2" | _nl2lf | awk '
{
    gsub(/'\''/, "'\'\\\\\'\''")
    print "'\''" $0 "'\''"
}'))" #"
}
function array_from_lines() {
    eval "$1=($(recho_ "$2" | _nl2lf | awk '
/^$/ { next }
{
    gsub(/'\''/, "'\'\\\\\'\''")
    print "'\''" $0 "'\''"
}'))" #"
}
function array_join() {
    local __aj_an __aj_l __aj_j __aj_s="${2:-,}" __aj_pf __aj_sf
    if [ "$1" == "@" ]; then
        __aj_an="\$@"
        shift; shift
    else
        __aj_an="\${$1[@]}"
        __aj_pf="$4"
        __aj_sf="$5"
    fi
    eval 'for __aj_l in "'"$__aj_an"'"; do
  __aj_j="${__aj_j:+$__aj_j'"$__aj_s"'}$__aj_pf$__aj_l$__aj_sf"
done'
    if [ -n "$__aj_j" ]; then
        recho "$__aj_j"
    elif [ "$__aj_an" != "\$@" -a -n "$3" ]; then
        recho "$3"
    fi
}
function array_mapjoin() {
    local __amj_src="$1" __amj_func="$2" __amj_sep="$3"
    shift; shift; shift
    if [ "$__amj_src" == "@" ]; then
        local -a __amj_tmpsrc
        __amj_tmpsrc=("$@")
        __amj_src=__amj_tmpsrc
        set --
    fi
    local -a __amj_tmp
    array_copy __amj_tmp "$__amj_src"
    array_map __amj_tmp "$__amj_func"
    array_join __amj_tmp "$__amj_sep" "$@"
}
function array_to_lines() {
    array_join "$1" "
" "$2" "$3" "$4"
}
function array_to_path() {
    array_join "$1" ":" "$2" "$3" "$4"
}
function array_fix_paths() {
    local __afp_an="$1" __afp_s="${2:-:}"
    local -a __afp_vs
    local __afp_v
    array_copy __afp_vs "$__afp_an"
    array_new "$__afp_an"
    for __afp_v in "${__afp_vs[@]}"; do
        array_split __afp_v "$__afp_v" "$__afp_s"
        array_extend "$__afp_an" __afp_v
    done
}


function get_date_rfc822() {
    LC_TIME=C date +"%a, %d %b %Y %H:%M:%S %Z"
}
function get_date_fr() {
    LC_TIME=C date +"%d/%m/%Y"
}
function get_time_fr() {
    LC_TIME=C date +"%Hh%M"
}
function parse_date() {
    local value="$1" type="${2:-date}"
    local now="$(awk 'BEGIN { print mktime(strftime("%Y %m %d 00 00 00 +0400")) }')"
    case "$value" in
    +*) value="$(($now + ${value#+} * 86400))";;
    *) value="$(<<<"$value" awk -F/ '{
        nd = strftime("%d"); nm = strftime("%m"); ny = strftime("%Y")
        d = $1 + 0; if (d < 1) d = nd;
        m = $2 + 0; if (m < 1) m = nm;
        if ($3 == "") y = ny;
        else { y = $3 + 0; if (y < 100) y = y + 2000; }
        print mktime(sprintf("%04i %02i %02i 00 00 00 +0400", y, m, d));
      }')";;
    esac
    case "$type" in
    d|date) awk '{ print strftime("%d/%m/%Y", $0 + 0) }' <<<"$value";;
    l|ldap) awk '{ print strftime("%Y%m%d%H%M%S+0400", $0 + 0) }' <<<"$value";;
    m|mysql) awk '{ print strftime("%Y-%m-%d", $0 + 0) }' <<<"$value";;
    *) recho "$value";;
    esac
}


function udelpath() {
    local _qdir="${1//\//\\/}"
    eval "export ${2:-PATH}; ${2:-PATH}"'="${'"${2:-PATH}"'#$1:}"; '"${2:-PATH}"'="${'"${2:-PATH}"'%:$1}"; '"${2:-PATH}"'="${'"${2:-PATH}"'//:$_qdir:/:}"; [ "$'"${2:-PATH}"'" == "$1" ] && '"${2:-PATH}"'='
}
function uaddpath() {
    local _qdir="${1//\//\\/}"
    eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="${'"${2:-PATH}"':+$'"${2:-PATH}"':}$1"'
}
function uinspathm() {
    local _qdir="${1//\//\\/}"
    eval "export ${2:-PATH}; "'[ "${'"${2:-PATH}"'#$1:}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'%:$1}" == "$'"${2:-PATH}"'" -a "${'"${2:-PATH}"'//:$_qdir:/:}" == "$'"${2:-PATH}"'" -a "$'"${2:-PATH}"'" != "$1" ] && '"${2:-PATH}"'="$1${'"${2:-PATH}"':+:$'"${2:-PATH}"'}"'
}
function uinspath() {
    udelpath "$@"
    uinspathm "$@"
}

function withpath() {
    [ "${1#./}" != "$1" -o "${1#../}" != "$1" -o "${1#/}" != "$1" ]
}
function withext() {
    local basename="$(basename -- "$1")"
    [ "${basename%.*}" != "$basename" ]
}
function normpath() {
    local -a parts
    local part ap
    array_split parts "$1" /
    if [ "${1#/}" != "$1" ]; then
        ap=/
    elif [ -n "$2" ]; then
        ap="$2"
    else
        ap="$(pwd)"
    fi
    for part in "${parts[@]}"; do
        if [ "$part" == "." ]; then
            continue
        elif [ "$part" == ".." ]; then
            ap="${ap%/*}"
            [ -n "$ap" ] || ap=/
        else
            [ "$ap" != "/" ] && ap="$ap/"
            ap="$ap$part"
        fi
    done
    recho "$ap"
}
function abspath() {
    local ap="$1"
    if [ "${ap#/}" != "$ap" ]; then
        __normpath "$ap" && return
    else
        local cwd
        if [ -n "$2" ]; then
            cwd="$(abspath "$2")"
        else
            cwd="$(pwd)"
        fi
        ap="$cwd/$ap"
        __normpath "$ap" && return
    fi
    normpath "$ap"
}
function __normpath() {
    if [ -d "$1" ]; then
        if [ -x "$1" ]; then
            (cd "$1"; pwd)
            return 0
        fi
    elif [ -f "$1" ]; then
        local dn="$(dirname -- "$1")" bn="$(basename -- "$1")"
        if [ -x "$dn" ]; then
            (cd "$dn"; echo "$(pwd)/$bn")
            return 0
        fi
    fi
    return 1
}
function parentdirs() {
    array_new "$1"
    local __pd_d="$(abspath "$2")"
    if [[ "$3" == r* ]]; then
        while [ "$__pd_d" != "/" ]; do
            array_ins "$1" "$__pd_d"
            __pd_d="$(dirname "$__pd_d")"
        done
    else
        while [ "$__pd_d" != "/" ]; do
            array_add "$1" "$__pd_d"
            __pd_d="$(dirname "$__pd_d")"
        done
    fi
}
function ppath() {
    local path="$1" cwd="$2"

    path="$(abspath "$path")" # essayer de normaliser le chemin
    [ -n "$cwd" ] || cwd="$(pwd)"

    [ "$path" = "$cwd" ] && path="."
    [ "$cwd" != "/" -a "$cwd" != "$HOME" ] && path="${path#$cwd/}"
    [ "${path#$HOME/}" != "$path" ] && path="~${path#$HOME}"

    recho "$path"
}
function relpath() {
    local p="$(abspath "$1" "$3")" cwd="$2"
    if [ -z "$cwd" ]; then
        cwd="$(pwd)"
    else
        cwd="$(abspath "$cwd" "$3")"
    fi
    if [ "$p" == "$cwd" ]; then
        echo ""
    elif [ "${p#$cwd/}" != "$p" ]; then
        recho "${p#$cwd/}"
    else
        local rp
        while [ -n "$cwd" -a "${p#$cwd/}" == "$p" ]; do
            rp="${rp:+$rp/}.."
            cwd="${cwd%/*}"
        done
        rp="$rp/${p#$cwd/}"
        echo "${rp%//}"
    fi
}
function relpathx() {
    local p="$(relpath "$@")"
    if [ -z "$p" ]; then
        echo .
    elif [ "${p#../}" != "$p" -o "${p#./}" != "$p" ]; then
        echo "$p"
    else
        echo "./$p"
    fi
}
function withinpath() {
    local b="$1" p="$2" strict="${3:-N}"
    b="$(abspath "$b")"
    p="$(abspath "$p")"
    if is_yes "$strict"; then
        [ "${p#$b/}" != "$p" ]
    else
        [ "$p" == "$b" -o "${p#$b/}" != "$p" ]
    fi
}
function safe_abspath() {
    local p="$1" ba="$2" br="$3"
    if [ -n "$ba" ]; then
        ba="$(abspath "$ba")"
    else
        ba="$(pwd)"
    fi
    [ -n "$br" ] || br="$ba"
    br="$(abspath "$br" "$ba")"
    p="$(abspath "$p" "$ba")"
    if [ "$p" == "$br" -o "${p#$br/}" != "$p" ]; then
        echo "$p"
    else
        return 1
    fi
}
function safe_relpath() {
    local p
    if p="$(safe_abspath "$1" "$2" "$3")"; then
        relpath "$p" "$2" "$(pwd)"
    else
        return 1
    fi
}
function splitwcs() {
    local __sw_p="$1"
    local __sw_dd="${2:-basedir}" __sw_df="${3:-filespec}" __sw_part __sw_d __sw_f
    local -a __sw_parts
    array_split __sw_parts "$__sw_p" "/"
    for __sw_part in "${__sw_parts[@]}"; do
        if [[ "$__sw_part" == *\** ]] || [[ "$__sw_part" == *\?* ]] || [ -n "$__sw_f" ]; then
            __sw_f="${__sw_f:+$__sw_f/}$__sw_part"
        else
            __sw_d="${__sw_d:+$__sw_d/}$__sw_part"
        fi
    done
    [ "${__sw_p#/}" != "$__sw_p" ] && __sw_d="/$__sw_d"
    _setv "$__sw_dd" "$__sw_d"
    _setv "$__sw_df" "$__sw_f"
}
function deref() {
    local OENC="$UTF8"

    local max_deref=50
    local file="$1"
    local basedir link
    while [ -L "$file" ]; do
        basedir="$(dirname "$file")"
        link="$(readlink "$file")"
        if first_char_is "$link" "/"; then
            file="$link"
        else
            file="$basedir/$link"
        fi

        max_deref=$(($max_deref - 1))
        [ $max_deref -eq 0 ] && die "Plus de 50 indirection. Le lien $file est-il récursif?"
    done
    abspath "$file"
}
function readlinka() {
    if [ -L "$1" ]; then
        local linkdir="$(dirname -- "$1")"
        abspath "$(readlink "$1")" "$linkdir"
    else
        abspath "$1"
    fi
}
function readlinkm() {
    readlink -m "$1"
}
function path_if_test() {
    local op="$1"; shift
    local file="$1"; shift
    local rel="$1" reldir=; shift
    if beginswith "$rel" relative; then
        reldir="${rel#relative}"
        if beginswith "$reldir" :; then
            reldir="${reldir#:}"
            if [ -n "$reldir" ]; then
                reldir="${reldir}/"
            fi
        else
            reldir=
        fi
    else
        rel=
    fi

    while [ -n "$1" ]; do
        local basedir="$1"
        if [ $op "$basedir/$file" ]; then
            if [ -n "$rel" ]; then
                recho "$reldir$file"
            else
                recho "$basedir/$file"
            fi
            break
        fi
        shift
    done
}
function update_link() {
    [ -L "$2" ] || return 1
    local dest link="$2"
    local linkdir="$(dirname "$link")"
    local ldest="$(readlink "$link")"
    if [ "${ldest#/}" != "$ldest" ]; then
        dest="$(abspath "$1")"
    else
        dest="$(relpath "$1" "$linkdir")"
    fi
    if [ "$dest" == "$ldest" ]; then
        : # pas besoin de mettre à jour
    elif [ -d "$link" ]; then
        rm -f "$link" && ln -s "$dest" "$link"
    else
        ln -sf "$dest" "$link"
    fi
}
function update_links() {
    [ -n "$1" ] || return 1
    local dest="$1"; shift
    local r=0 link
    for link in "$@"; do
        update_link "$dest" "$link" || r=$?
    done
    return $r
}
function move_link() {
    [ -n "$1" -a -n "$2" ] || return 1
    local link="$1" dest="$2"
    [ -d "$dest" ] && dest="$dest/$(basename -- "$link")"
    dest="$(abspath "$dest")"
    if [ -L "$link" ]; then
        link="$(abspath "$link")"
        [ "$dest" == "$link" ] && return 0
        ldest="$(readlinka "$link")"
        mv "$link" "$dest" || return 1
        update_link "$ldest" "$dest"
    else
        [ "$dest" == "$link" ] && return 0
        mv "$link" "$dest"
    fi
}
function copy_link() {
    [ -n "$1" -a -n "$2" ] || return 1
    local link="$1" dest="$2"
    [ -d "$dest" ] && dest="$dest/$(basename -- "$link")"
    dest="$(abspath "$dest")"
    if [ -L "$link" ]; then
        link="$(abspath "$link")"
        [ "$dest" == "$link" ] && return 0
        ldest="$(readlinka "$link")"
        cp -P "$link" "$dest" || return 1
        update_link "$ldest" "$dest"
    else
        [ "$dest" == "$link" ] && return 0
        cp "$link" "$dest"
    fi
}
function array_find_links() {
    local -a __afl_links __afl_result
    local __afl_dir="${3:-.}"
    local __afl_dest __afl_destname __afl_link __afl_linkdir __afl_ldest
    __afl_dest="$(abspath "$2")"
    __afl_destname="${__afl_dest##*/}"
    array_from_lines __afl_links "$(find "$__afl_dir" -type l)"
    for __afl_link in "${__afl_links[@]}"; do
        __afl_ldest="$(readlink "$__afl_link")"
        if [ "$__afl_ldest" != "$__afl_destname" ]; then
            [[ "$__afl_ldest" == */"$__afl_destname" ]] || continue
        fi
        __afl_link="$(abspath "$__afl_link" "$__afl_dir")"
        __afl_linkdir="$(dirname -- "$__afl_link")"
        __afl_ldest="$(abspath "$__afl_ldest" "$__afl_linkdir")"
        if [ "$__afl_ldest" == "$__afl_dest" ]; then
            array_add __afl_result "$__afl_link"
        fi
    done
    array_copy "$1" __afl_result
}
function list_links() {
    local -a links
    array_find_links links "$@"
    array_to_lines links
}
function move_file() {
    [ -n "$1" -a -n "$2" ] || return 1
    local src="$1" dest="$2" link
    shift; shift
    [ -d "$dest" ] && dest="$dest/$(basename -- "$src")"
    move_link "$src" "$dest" || return 1
    update_links "$dest" "$@"
}

function get_nblines() {
    [ -f "$1" ] && sed -ne '$=' "$1" || echo 0
}
function mktempf() {
    mktemp "${1:-"$TMPDIR/tmp.XXXXXX"}"
}
function mktempd() {
    mktemp -d "${1:-"$TMPDIR/tmp.XXXXXX"}"
}
function mkdirof() {
    mkdir -p "$(dirname -- "$1")"
}
function cp_a() {
    /bin/cp -a "$@"
}
function cp_R() {
    /bin/cp -pR "$@"
}
function quietgrep() {
    grep -q "$@" 2>/dev/null
}
function quietdiff() {
    diff -q "$@" >&/dev/null
}
function testsame() {
    quietdiff "$@"
}
function testdiff() {
    ! quietdiff "$@"
}
function testupdated() {
    if [ -f "$2" ]; then
        testdiff "$1" "$2"
    else
        return 0
    fi
}
function testnewer() {
    test ! -e "$2" -o "$1" -nt "$2"
}
function ps_all() {
    ps -axww
}
function progexists() {
    test -n "$1" -a -x "$(which "$1" 2>/dev/null)"
}
function has_python() {
    progexists python
}
function has_gawk() {
    progexists gawk
}
function is_root() {
    test `id -u` -eq 0
}
function source_ifexists() {
    if [ -f "$1" ]; then source "$1" || die; fi
}
function little_sleep {
    LC_NUMERIC=C sleep 0.1
}
function random_sleep {
    sleep $(($RANDOM % ${1:-1800}))
}
function is_running() {
    kill -0 "$1" >&/dev/null
}
function sedi() {
    sed -i "$@"
}
function csort() {
    LANG=C sort "$@"
}
function lsort() { sort "$@"; }
function cgrep() {
    LANG=C grep "$@"
}
function lgrep() { grep "$@"; }
function csed() {
    LANG=C sed "$@"
}
function lsed() { sed "$@"; }
function cawk() {
    LANG=C awk "$@"
}
function lawk() { awk "$@"; }
function cdiff() {
    LANG=C diff "$@"
}
function ldiff() { diff "$@"; }


function fix_mode() {
    local file="$1"
    [ -f "$file" ] || touch "$file" || return 1
    if [ ! -w "$file" ]; then
        local mode="$(stat -c %a "$file")"
        chmod ${mode:0:${#mode}-3}6${mode:${#mode}-2:2} "$file"
        echo "$mode"
    fi
}
function unfix_mode() {
    [ -n "$2" ] && chmod "$2" "$1"
}
function get_mode() {
    [ -f "$1" ] || touch "$1" || return 1
    stat -c %a "$1"
}
function rm_maybe() {
    local parse_opts=1 arg rm
    for arg in "$@"; do
        if [ -n "$parse_opts" ]; then
            if [ "$arg" == "--" ]; then
                parse_opts=
            elif [[ "$arg" == "-*" ]]; then
                continue
            elif [ -n "$arg" ]; then
                rm=1
                break
            fi
        elif [ -n "$arg" ]; then
            rm=1
            break
        fi
    done
    [ -n "$rm" ] && /bin/rm "$@"
}
__CPDIR_RSYNC_SLOW=1 # synchro potentiellement plus lente, mais plus fidèle (option -c)
__CPDIR_RSYNC_ARGS=(-q)
function cpdir() {

    if progexists rsync; then
        [ -d "$2" ] || mkdir -p "$2" || return 1
        if [ -d "$1" ]; then
            rsync -a ${__CPDIR_RSYNC_SLOW:+-c} "${__CPDIR_RSYNC_ARGS[@]}" "$1/" "$2/"
        else
            rsync -a ${__CPDIR_RSYNC_SLOW:+-c} "${__CPDIR_RSYNC_ARGS[@]}" "$1" "$2/"
        fi
    else
        __cpdir "$@"
    fi
}
function __cpdir() {
    local src="$1" dest="$2" method="${3:-cp_a}"

    if [ -d "$src" ]; then
        [ -d "$dest" ] || mkdir -p "$dest" || return 1

        local prevdir="$(pwd)"

        dest="$(abspath "$dest")"
        cd "$src"
        if [ -n "$(/bin/ls -a1)" ]; then
            [ -n "$(/bin/ls -1)" ] && "$method" * "$dest"
            local i
            for i in .*; do
                [ "$i" == "." -o "$i" == ".." ] && continue
                "$method" "$i" "$dest"
            done
        fi
        cd "$prevdir"
    else
        if [ -f "$dest" ]; then
            "$method" "$src" "$dest"
        elif [ -d "$dest" ]; then
            "$method" "$src" "$dest"
        else
            mkdir -p "$dest"
            "$method" "$src" "$dest"
        fi
    fi
}
__CPNOVCS_RSYNC_SLOW=1 # synchro potentiellement plus lente, mais plus fidèle (option -c)
__CPNOVCS_RSYNC_ARGS=(-q)
__CPNOVCS_INCLUDE_VCS= # ne pas ignorer les répertoires de VCS
function cpnovcs() {
    local src="$1" destdir="$2"
    [ -d "$destdir" ] || mkdir -p "$destdir" || return 1
    if progexists rsync; then
        local -a novcs
        if [ -z "$__CPNOVCS_INCLUDE_VCS" ]; then
            local gitexclude=/.git/
            [ "${src%/}" == "$src" ] && gitexclude="/$(basename -- "$src")$gitexclude"
            novcs=(--exclude CVS/ --exclude .svn/ --exclude "$gitexclude")
        fi
        rsync -a ${__CPNOVCS_RSYNC_SLOW:+-c} "${novcs[@]}" "${__CPNOVCS_RSYNC_ARGS[@]}" "$src" "$destdir/"
    elif [ "${src%/}" != "$src" ]; then
        __cpdir "$src" "$destdir"
    else
        local srcname="$(basename -- "$src")"
        mkdir -p "$destdir/$srcname"
        __cpdir "$src" "$destdir/$srcname"
    fi
}
function cpvcs() {
    local __CPNOVCS_INCLUDE_VCS=1
    cpnovcs "$@"
}
function cpdirnovcs() {
    if [ -d "$1" ]; then
        cpnovcs "$1/" "$2"
    else
        cpnovcs "$1" "$2"
    fi
}
function doinplace() {
    if [ -n "$1" -a "$1" != "-" ]; then
        local __dip_file="$1"; shift
        autoclean "$__dip_file.tmp.$$"
        "$@" <"$__dip_file" >"$__dip_file.tmp.$$"
        local s=$?
        [ "$s" == 0 ] && /bin/cat "$__dip_file.tmp.$$" >"$__dip_file"
        /bin/rm -f "$__dip_file.tmp.$$"
        return $s
    else
        shift
        "$@"
    fi
}
function doinplacef() {
    if [ -n "$1" -a "$1" != "-" ]; then
        local __dip_file="$1"; shift
        autoclean "$__dip_file.tmp.$$"
        "$@" <"$__dip_file" >"$__dip_file.tmp.$$"
        local s=$?
        /bin/cat "$__dip_file.tmp.$$" >"$__dip_file"
        /bin/rm -f "$__dip_file.tmp.$$"
        return $s
    else
        shift
        "$@"
    fi
}
function stripnl() {
    tr -d '\r\n'
}
function _nl2lf() {
    awk 'BEGIN {RS="\r|\r\n|\n"} {print}'
}
function nl2lf() {
    doinplace "$1" _nl2lf
}
function _nl2crlf() {
    awk 'BEGIN {RS="\r|\r\n|\n"} {print $0 "\r"}'
}
function nl2crlf() {
    doinplace "$1" _nl2crlf
}
function _nl2cr() {
    awk 'BEGIN {RS="\r|\r\n|\n"; ORS=""} {print $0 "\r"}'
}
function nl2cr() {
    doinplace "$1" _nl2cr
}
function _latin1compat() {
    LANG=fr_FR.UTF-8 sed $'
s/[\xE2\x80\x90\xE2\x80\x91\xE2\x80\x92\xE2\x80\x93\xE2\x80\x94\xE2\x80\x95]/-/g
s/[‘’]/\x27/g
s/[«»“”]/"/g
s/[\xC2\xA0\xE2\x80\x87\xE2\x80\xAF\xE2\x81\xA0]/ /g
s/[œ]/oe/g
s/[Œ]/OE/g
s/[æ]/ae/g
s/[Æ]/AE/g
'
}
function _noaccents() {
    LANG=fr_FR.UTF-8 sed '
s/[à]/a/g
s/[éèêë]/e/g
s/[ïî]/i/g
s/[ôö]/o/g
s/[üû]/u/g
s/[ç]/c/g
s/[À]/A/g
s/[ÉÈÊË]/E/g
s/[ÏÎ]/I/g
s/[ÔÖ]/O/g
s/[ÜÛ]/U/g
s/[Ç]/C/g
'
}
function list_all() {
    local curdir="$(pwd)"
    local b="${1:-.}"; shift

    cd "$b" 2>/dev/null || return
    eval "$(__la_cmd "$@")" | while read f; do
        [ "$f" == "." -o "$f" == ".." ] && continue
        recho "$f"
    done
    cd "$curdir"
}
function __la_cmd() {
    [ $# -gt 0 ] || set '*'
    local arg
    local cmd="/bin/ls -1d"
    for arg in "$@"; do
        arg="$(qwc "$arg")"
        cmd="$cmd $arg"
    done
    cmd="$cmd 2>/dev/null"
    echo "$cmd"
}
function list_files() {
    local f
    local curdir="$(pwd)"
    local b="${1:-.}"; shift

    cd "$b" 2>/dev/null || return
    eval "$(__la_cmd "$@")" | while read f; do
        [ -f "$f" ] && recho "$f"
    done
    cd "$curdir"
}
function list_dirs() {
    local f
    local curdir="$(pwd)"
    local b="${1:-.}"; shift

    cd "$b" 2>/dev/null || return
    eval "$(__la_cmd "$@")" | while read f; do
        [ "$f" == "." -o "$f" == ".." ] && continue
        [ -d "$f" ] && recho "$f"
    done
    cd "$curdir"
}
function __array_ls() {
    local __al_l="list_${1:-all}"; shift
    local __al_an="$1"; shift
    local __al_d="${1:-.}"; shift
    local -a __al_fs
    array_from_lines __al_fs "$("$__al_l" "$__al_d" "$@")"
    local __al_f
    array_new "$__al_an"
    for __al_f in "${__al_fs[@]}"; do
        array_add "$__al_an" "$__al_d/$__al_f"
    done
}
function array_lsall() {
    __array_ls all "$@"
}
function array_lsdirs() {
    __array_ls dirs "$@"
}
function array_lsfiles() {
    __array_ls files "$@"
}
function filter_empty() {
    sed '/^$/d'
}
function filter_vcspath() {
    sed '
/^.git$/d
/^.git\//d
/\/.git$/d
/\/.git\//d
/^.svn$/d
/^.svn\//d
/\/.svn$/d
/\/.svn\//d
'
}
function merge_contlines() {
    awk 'substr($0, length($0)) == "\\" {
  while (getline nextline) {
    $0 = substr($0, 1, length($0) - 1) nextline
    if (substr($0, length($0)) != "\\") break
  }
  print
  next
}
{print}'
}
function filter_comment() {
    local -a merge
    [ "$1" == -m ] && merge=(merge_contlines) || merge=(cat)
    awk '
 /^[ \t]*#/ { next }
 /^[ \t]*$/ { next }
 { print }' | "${merge[@]}"
}
function filter_conf() {
    local -a merge
    [ "$1" == -m ] && merge=(merge_contlines) || merge=(cat)
    grep -v '^#' | grep -v '^$' | "${merge[@]}"
}
function is_archive() {
    local name="${1%.zip}"
    name="${name%.tgz}"
    name="${name%.tbz2}"
    name="${name%.tar.gz}"
    name="${name%.tar.bz2}"
    name="${name%.tar}"
    name="${name%.jar}"
    name="${name%.war}"
    name="${name%.ear}"
    [ "$name" != "$1" ]
}
function extract_archive() {
    local arch="$1" destdir="${2:-.}"
    shift; shift
    if endswith "$arch" .zip; then
        unzip -q -d "$destdir" "$arch" "$@" || return
    elif endswith "$arch" .tgz || endswith "$arch" .tar.gz; then
        tar xzf "$arch" -C "$destdir" "$@" || return
    elif endswith "$arch" .tbz2 || endswith "$arch" .tar.bz2; then
        tar xjf "$arch" -C "$destdir" "$@" || return
    elif endswith "$arch" .tar; then
        tar xf "$arch" -C "$destdir" "$@" || return
    elif endswith "$arch" .jar || endswith "$arch" .war || endswith "$arch" .ear; then
        (
            arch="$(abspath "$arch")"
            cd "$destdir"
            jar xf "$arch" "$@"
        ) || return
    else
        return 1
    fi
}
function get_archive_basename() {
    local basename="$(basename -- "$1")"
    basename="${basename%.zip}"
    basename="${basename%.tgz}"
    basename="${basename%.tbz2}"
    basename="${basename%.gz}"
    basename="${basename%.bz2}"
    basename="${basename%.tar}"
    basename="${basename%.jar}"
    basename="${basename%.war}"
    basename="${basename%.ear}"
    echo "$basename"
}
function get_archive_appname() {
    local appname="$(basename -- "$1")"
    appname="${appname%.zip}"
    appname="${appname%.tgz}"
    appname="${appname%.tbz2}"
    appname="${appname%.gz}"
    appname="${appname%.bz2}"
    appname="${appname%.tar}"
    appname="${appname%.jar}"
    appname="${appname%.war}"
    appname="${appname%.ear}"
    echo "$appname" | awk '{
  if (match($0, /[-_.]([0-9]+([-_.][0-9]+)*([a-zA-Z][0-9]*|[-_.][0-9]+[a-zA-Z][0-9]*)?)$/)) {
    print substr($0, 1, RSTART - 1)
  } else if (match($0, /([0-9]+([-_.][0-9]+)*([a-zA-Z][0-9]*|[-_.][0-9]+[a-zA-Z][0-9]*)?)$/)) {
    print substr($0, 1, RSTART - 1)
  } else if (match($0, /([0-9]+[a-z][a-z][a-z0-9]?)$/, vs)) {
    print substr($0, 1, RSTART - 1)
  } else {
    print $0
  }
}'
}
function get_archive_versionsuffix() {
    local basename="$(get_archive_basename "$1")"
    echo "$basename" | awk '{
  if (match($0, /([-_.][0-9]+([-_.][0-9]+)*([a-zA-Z][0-9]*|[-_.][0-9]+[a-zA-Z][0-9]*)?)$/, vs)) {
    print vs["1"]
  } else if (match($0, /([0-9]+([-_.][0-9]+)*([a-zA-Z][0-9]*|[-_.][0-9]+[a-zA-Z][0-9]*)?)$/, vs)) {
    print vs["1"]
  } else if (match($0, /([0-9]+[a-z][a-z][a-z0-9]?)$/, vs)) {
    print vs["1"]
  }
}'
}
function get_archive_version() {
    local basename="$(get_archive_basename "$1")"
    echo "$basename" | awk '{
  if (match($0, /[-_.]([0-9]+([-_.][0-9]+)*([a-zA-Z][0-9]*|[-_.][0-9]+[a-zA-Z][0-9]*)?)$/, vs)) {
    print vs["1"]
  } else if (match($0, /([0-9]+([-_.][0-9]+)*([a-zA-Z][0-9]*|[-_.][0-9]+[a-zA-Z][0-9]*)?)$/, vs)) {
    print vs["1"]
  } else if (match($0, /([0-9]+[a-z][a-z][a-z0-9]?)$/, vs)) {
    print vs["1"]
  }
}'
}
function __dump_usernames() {
    </etc/passwd awkrun FS=: '($3 + 0) >= 500 && $6 ~ /^\/home\// { print $1 }'
}
function dump_usernames() {
    array_from_lines "${1:-usernames}" "$(__dump_usernames)"
}
function __resolv_ips() {
    LANG=C host "$1" 2>/dev/null | awk '/address / { gsub(/^.*address /, ""); print }'
}
function resolv_ips() {
    array_from_lines "${1:-ips}" "$(__resolv_ips "$2")"
}
function __resolv_hosts() {
    LANG=C host "$1" 2>/dev/null | awk '/domain name pointer / { gsub(/^.*domain name pointer /, ""); gsub(/\.$/, ""); print }'
}
function resolv_hosts() {
    array_from_lines "${1:-hosts}" "$(__resolv_hosts "$2")"
}
function runscript_as() {
    local OENC="$UTF8"
    local user="${1:-root}"; shift
    local exec_maybe=
    if [ "$1" = "exec" ]; then
        exec_maybe=exec
        shift
    fi

    local cmd
    cmd="\
__estack=$(qval "$__estack")
__tlevel=$(qval "$__tlevel")
export __estack __tlevel
exec ${BASH:-/bin/sh} $(qvals "$@")"

    if is_yes "$UTOOLS_USES_SU" || ! progexists sudo; then
        eecho "Entrez le mot de passe de root"
        $exec_maybe su "$user" -c "$cmd"
    else
        if [ "$user" == "root" ]; then
            $exec_maybe sudo -p "Entrez le mot de passe de %u: " "${BASH:-/bin/sh}" -c "$cmd"
        else
            $exec_maybe sudo -p "Entrez le mot de passe de %u: " su "$user" -c "$cmd"
        fi
    fi
}
function runscript_as_root() {
    if is_root; then
        local exec_maybe=
        if [ "$1" = "exec" ]; then
            exec_maybe=exec
            shift
        fi
        $exec_maybe "${BASH:-/bin/sh}" "$@"
    else
        runscript_as root "$@"
    fi
}
function run_as() {
    local user="${1:-root}"; shift
    local exec_maybe=exec
    if [ "$1" = "--noexec" ]; then
        exec_maybe=
        shift
    fi

    runscript_as "$user" $exec_maybe "$0" "$@"
}
function run_as_root() {
    is_root || run_as root "$@"
}
function check_user() {
    local user
    for user in "$@"; do
        [ "$USER" == "$user" ] && return 0
    done
    return 1
}
function ensure_user() {
    local -a users
    while [ $# -gt 0 -a "$1" != "--" ]; do
        array_add users "$1"
        shift
    done
    [ "$1" == "--" ] && shift

    if ! check_user "${users[@]}"; then
        if [ ${#users[*]} -gt 1 ]; then
            ewarn "Cette commande doit être lancée avec l'un des users ${users[*]}"
        else
            ewarn "Cette commande doit être lancée avec le user ${users[0]}"
        fi
        if ask_yesno "Voulez-vous tenter de relancer la commande avec le bon user?" O; then
            estep "Lancement du script avec le user ${users[0]}"
            run_as "${users[0]}" "$@"
            return 1
        elif is_root; then
            return 11
        else
            return 10
        fi
    fi
    return 0
}
function check_hostname() {
    local userhost user host path
    for userhost in "$@"; do
        splitfsep "$userhost" : userhost path
        splituserhost "$userhost" user host
        host="${host%%.*}"
        [ "$host" == localhost -o "$host" == "$MYHOSTNAME" ] && return 0
    done
    return 1
}
function check_userhostname() {
    local userhost path user host
    for userhost in "$@"; do
        if check_hostname "$userhost"; then
            [[ "$userhost" == *@* ]] || return 0
            splitfsep "$userhost" : userhost path
            splituserhost "$userhost" user host
            check_user "$user" && return 0
        fi
    done
    return 1
}
UTOOLS_ENSURE_HOSTNAME_SSH_OPTS=()
function ensure_hostname() {
    local -a userhosts
    while [ $# -gt 0 -a "$1" != "--" ]; do
        array_add userhosts "$1"
        shift
    done
    [ "$1" == "--" ] && shift

    local userhost user host path
    if ! check_hostname "${userhosts[@]}"; then
        if [ ${#userhosts[*]} -gt 1 ]; then
            ewarn "Cette commande n'est valide que sur l'un des hôtes ${userhosts[*]}"
        else
            ewarn "Cette commande n'est valide que sur l'hôte ${userhosts[0]}"
        fi

        eimportant "Vous pouvez tenter de relancer le script sur ${userhosts[0]}"
        eimportant "Cela requière que ce script ET les données dont il a besoin soient installés dans la même version et dans le même répertoire sur l'hôte distant.
En l'occurence, ce script est accédé par le chemin $script et ce chemin doit exister aussi sur le serveur distant."
        if ask_yesno "Voulez-vous tenter de relancer le script sur l'hôte distant?" X; then
            splitfsep "${userhosts[0]}" : userhost path
            splituserhost "$userhost" user host
            [ -n "$user" ] || user=root

            estep "Lancement de la commande sur l'hôte distant $user@$host"
            local cmd
            [ -n "$path" ] && cmd="$(qvals cd "$path"); "
            cmd="$cmd$(qvals "$script" "$@")"
            ssh -qt "${UTOOLS_ENSURE_HOSTNAME_SSH_OPTS[@]}" "$user@$host" "$cmd"
            [ $? -eq 255 ] && return 12
            return 1
        else
            return 11
        fi
    fi
    local userhost user host
    for userhost in "${userhosts[@]}"; do
        [[ "$userhost" == *@* ]] || continue
        if check_hostname "$userhost"; then
            splitfsep "$userhost" : userhost path
            splituserhost "$userhost" user host
            [ -n "$path" ] && cd "$path"
            ensure_user "$user" -- "$@"
            return $?
        fi
    done
    return 0
}

__AWKDEF_FUNCTIONS='
function num(s) {
  if (s ~ /^[0-9]+$/) return int(s)
  else return s
}
function ord(s,    i) {
  s = substr(s, 1, 1)
  i = index(" !\"#$%&'\''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", s)
  if (i != 0) i += 32 - 1
  return i
}
function hex(i,    s) {
  s = sprintf("%x", i)
  if (length(s) < 2) s = "0" s
  return s
}
function qhtml(s) {
  gsub(/&/, "\\&amp;", s)
  gsub(/"/, "\\&quot;", s)
  gsub(/>/, "\\&gt;", s)
  gsub(/</, "\\&lt;", s)
  return s
}
function unquote_html(s) {
  gsub(/&lt;/, "<", s)
  gsub(/&gt;/, ">", s)
  gsub(/&quot;/, "\"", s)
  gsub(/&amp;/, "\\&", s)
  return s
}
function qval(s) {'"
  gsub(/'/, \"'\\\\''\", s)
  return \"'\" s \"'\"
"'}
function sqval(s) {
  return " " qval(s)
}
function qvals(             i, line) {
  line = ""
  for (i = 1; i <= NF; i++) {
    if (i > 1) line = line " "
    line = line qval($i)
  }
  return line
}
function sqvals() {
  return " " qvals()
}
function qarr(values, prefix,    i, count, line) {
  line = prefix
  count = array_len(values)
  for (i = 1; i <= count; i++) {
    if (i > 1 || line != "") line = line " "
    line = line qval(values[i])
  }
  return line
}
function qregexp(s) {
  gsub(/[[\\.^$*+?()|{]/, "\\\\&", s)
  return s
}
function qsubrepl(s) {
  gsub(/\\/, "\\\\", s)
  gsub(/&/, "\\\\&", s)
  return s
}
function qgrep(s) {
  gsub(/[[\\.^$*]/, "\\\\&", s)
  return s
}
function qegrep(s) {
  gsub(/[[\\.^$*+?()|{]/, "\\\\&", s)
  return s
}
function qsql(s, suffix) {'"
  gsub(/'/, \"''\", s)
  return \"'\" s \"'\" (suffix != \"\"? \" \" suffix: \"\")
"'}
function cqsql(s, suffix) {
  return "," qsql(s, suffix)
}
function unquote_mysqlcsv(s) {
  gsub(/\\n/, "\n", s)
  gsub(/\\t/, "\t", s)
  gsub(/\\0/, "\0", s)
  gsub(/\\\\/, "\\", s)
  return s
}
function sval(s) {
  if (s == "") return s
  else return " " s
}
function cval(s, suffix) {
  if (s == "") return s
  else return "," s (suffix != ""? " " suffix: "")
}
function quote_html(s) { return qhtml(s) }
function quote_value(s) { return qval(s) }
function qsval(s) { return sqval(s) }
function quoted_values() { return qvals() }
function qsvals(s) { return sqvals(s) }
function quote_regexp(s) { return qregexp(s) }
function quote_subrepl(s) { return qsubrepl(s) }
function quote_grep(s) { return qgrep(s) }
function quote_egrep(s) { return qegrep(s) }
function quote_sql(s) { return qsql(s) }

function __parse_date_fr(date,            parts, y, m, d) {
  if (match(date, /([0-9][0-9]?)\/([0-9][0-9]?)\/([0-9][0-9][0-9][0-9])/, parts)) {
    y = int(parts[3])
    m = int(parts[2])
    d = int(parts[1])
    return mktime(sprintf("%04i %02i %02i 00 00 00 +0400", y, m, d))
  }
  return -1
}
function __parse_date_mysql(date,            parts, y, m, d) {
  if (match(date, /([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])/, parts)) {
    y = int(parts[1])
    m = int(parts[2])
    d = int(parts[3])
    return mktime(sprintf("%04i %02i %02i 00 00 00 +0400", y, m, d))
  }
  return -1
}
function __parse_date_any(date,          serial) {
  serial = __parse_date_fr(date)
  if (serial == -1) serial = __parse_date_mysql(date)
  return serial
}
function date_serial(date) {
  return __parse_date_any(date)
}
function date_parse(date,         serial) {
  serial = __parse_date_any(date)
  if (serial == -1) return date
  return strftime("%d/%m/%Y", serial)
}
function date_monday(date,             serial, dow) {
  serial = __parse_date_any(date)
  if (serial == -1) return date
  dow = strftime("%u", serial)
  serial -= (dow - 1) * 86400
  return strftime("%d/%m/%Y", serial)
}
function date_add(date, nbdays,         serial) {
  serial = __parse_date_any(date)
  if (serial == -1) return date
  serial += nbdays * 86400
  return strftime("%d/%m/%Y", serial)
}

function mkindices(values, indices,        i, j) {
  array_new(indices)
  j = 1
  for (i in values) {
    indices[j++] = int(i)
  }
  return asort(indices)
}
function array_new(dest) {
  dest[0] = 0 # forcer awk à considérer dest comme un tableau
  delete dest
}
function array_newsize(dest, size,              i) {
  dest[0] = 0 # forcer awk à considérer dest comme un tableau
  delete dest
  size = int(size)
  for (i = 1; i <= size; i++) {
    dest[i] = ""
  }
}
function array_len(values,    count, i) {
  count = 0
  for (i in values) {
    count++
  }
  return count
}
function array_copy(dest, src,             count, indices, i) {
  array_new(dest)
  count = mkindices(src, indices)
  for (i = 1; i <= count; i++) {
    dest[indices[i]] = src[indices[i]]
  }
}
function array_getlastindex(src,           count, indices) {
  count = mkindices(src, indices)
  if (count == 0) return 0
  return indices[count]
}
function array_add(dest, value,              lastindex) {
  lastindex = array_getlastindex(dest)
  dest[lastindex + 1] = value
}
function array_deli(dest, i,                 l) {
  i = int(i)
  if (i == 0) return
  l = array_len(dest)
  while (i < l) {
    dest[i] = dest[i + 1]
    i++
  }
  delete dest[l]
}
function array_del(dest, value, ignoreCase,              i) {
  do {
    i = key_index(value, dest, ignoreCase)
    if (i != 0) array_deli(dest, i)
  } while (i != 0)
}
function array_extend(dest, src,             count, lastindex, indices, i) {
  lastindex = array_getlastindex(dest)
  count = mkindices(src, indices)
  for (i = 1; i <= count; i++) {
    dest[lastindex + i] = src[indices[i]]
  }
}
function array_fill(dest,           i) {
  array_new(dest)
  for (i = 1; i <= NF; i++) {
    dest[i] = $i
  }
}
function array_getline(src,             count, indices, i, j) {
  $0 = ""
  count = mkindices(src, indices)
  for (i = 1; i <= count; i++) {
    j = indices[i]
    $j = src[j]
  }
}
function array_appendline(src,             count, indices, i, nf, j) {
  count = mkindices(src, indices)
  nf = NF
  for (i = 1; i <= count; i++) {
    j = nf + indices[i]
    $j = src[indices[i]]
  }
}
function in_array(value, values, ignoreCase,         i) {
  if (ignoreCase) {
    value = tolower(value)
    for (i in values) {
      if (tolower(values[i]) == value) return 1
    }
  } else {
    for (i in values) {
      if (values[i] == value) return 1
    }
  }
  return 0
}
function key_index(value, values, ignoreCase,         i) {
  if (ignoreCase) {
    value = tolower(value)
    for (i in values) {
      if (tolower(values[i]) == value) return int(i)
    }
  } else {
    for (i in values) {
      if (values[i] == value) return int(i)
    }
  }
  return 0
}
function array2s(values, prefix, sep, suffix, noindices,     first, i, s) {
  if (!prefix) prefix = "["
  if (!sep) sep = ", "
  if (!suffix) suffix = "]"
  s = prefix
  first = 1
  for (i in values) {
    if (first) first = 0
    else s = s sep
    if (!noindices) s = s "[" i "]="
    s = s values[i]
  }
  s = s suffix
  return s
}
function array2so(values, prefix, sep, suffix, noindices,      count, indices, i, s) {
  if (!prefix) prefix = "["
  if (!sep) sep = ", "
  if (!suffix) suffix = "]"
  s = prefix
  count = mkindices(values, indices)
  for (i = 1; i <= count; i++) {
    if (i > 1) s = s sep
    if (!noindices) s = s "[" indices[i] "]="
    s = s values[indices[i]]
  }
  s = s suffix
  return s
}
function array_join(values, sep, prefix, suffix,            count, indices, i, s) {
  s = prefix
  count = mkindices(values, indices)
  for (i = 1; i <= count; i++) {
    if (i > 1) s = s sep
    s = s values[indices[i]]
  }
  s = s suffix
  return s
}
function printto(s, output) {
  if (output == "") {
    print s
  } else if (output ~ /^>>/) {
    sub(/^>>/, "", output)
    print s >>output
  } else if (output ~ /^>/) {
    sub(/^>/, "", output)
    print s >output
  } else {
    print s >output
  }
}
function find_line(input, field, value,              orig, line) {
  orig = $0
  line = ""
  while ((getline <input) > 0) {
    if ($field == value) {
      line = $0
      break
    }
  }
  close(input)
  $0 = orig
  return line
}
function merge_line(input, field, key,               line) {
  line = find_line(input, field, $key)
  if (line != "") $0 = $0 FS line
}
function __csv_parse_quoted(line, destl, colsep, qchar, echar,       pos, tmpl, nextc, resl) {
  line = substr(line, 2)
  resl = ""
  while (1) {
    pos = index(line, qchar)
    if (pos == 0) {
      resl = resl line
      destl[0] = ""
      destl[1] = 0
      return resl
    }
    if (echar != "" && pos > 1) {
      prevc = substr(line, pos - 1, 1)
      quotec = substr(line, pos, 1)
      nextc = substr(line, pos + 1, 1)
      if (prevc == echar) {
        tmpl = substr(line, 1, pos - 2)
        resl = resl tmpl quotec
        line = substr(line, pos + 1)
        continue
      }
      tmpl = substr(line, 1, pos - 1)
      if (nextc == colsep || nextc == "") {
        resl = resl tmpl
        destl[0] = substr(line, pos + 2)
        destl[1] = nextc == colsep
        return resl
      } else {
        resl = resl tmpl quotec
        line = substr(line, pos + 1)
      }
    } else {
      tmpl = substr(line, 1, pos - 1)
      quotec = substr(line, pos, 1)
      nextc = substr(line, pos + 1, 1)
      if (nextc == colsep || nextc == "") {
        resl = resl tmpl
        destl[0] = substr(line, pos + 2)
        destl[1] = nextc == colsep
        return resl
      } else if (nextc == qchar) {
        resl = resl tmpl quotec
        line = substr(line, pos + 2)
      } else {
        resl = resl tmpl quotec
        line = substr(line, pos + 1)
      }
    }
  }
}
function __csv_parse_unquoted(line, destl, colsep, qchar, echar,     pos) {
  pos = index(line, colsep)
  if (pos == 0) {
    destl[0] = ""
    destl[1] = 0
    return line
  } else {
    destl[0] = substr(line, pos + 1)
    destl[1] = 1
    return substr(line, 1, pos - 1)
  }
}
function __array_parsecsv(fields, line, nbfields, colsep, qchar, echar,     shouldparse, destl, i) {
  array_new(fields)
  array_new(destl)
  i = 1
  shouldparse = 0
  while (shouldparse || line != "") {
    if (index(line, qchar) == 1) {
      value = __csv_parse_quoted(line, destl, colsep, qchar, echar)
      line = destl[0]
      shouldparse = destl[1]
    } else {
      value = __csv_parse_unquoted(line, destl, colsep, qchar, echar)
      line = destl[0]
      shouldparse = destl[1]
    }
    fields[i] = value
    i = i + 1
  }
  if (nbfields) {
    nbfields = int(nbfields)
    i = array_len(fields)
    while (i < nbfields) {
      i++
      fields[i] = ""
    }
  }
  return array_len(fields)
}
BEGIN {
  DEFAULT_COLSEP = ","
  DEFAULT_QCHAR = "\""
  DEFAULT_ECHAR = ""
}
function array_parsecsv2(fields, line, nbfields, colsep, qchar, echar) {
  return __array_parsecsv(fields, line, nbfields, colsep, qchar, echar)
}
function array_parsecsv(fields, line, nbfields, colsep, qchar, echar) {
  if (colsep == "") colsep = DEFAULT_COLSEP
  if (qchar == "") qchar = DEFAULT_QCHAR
  if (echar == "") echar = DEFAULT_ECHAR
  return __array_parsecsv(fields, line, nbfields, colsep, qchar, echar)
}
function parsecsv(line,             fields) {
  array_parsecsv(fields, line)
  array_getline(fields)
  return NF
}
function getlinecsv(file,          fields) {
  if (file) {
    getline <file
  } else {
    getline
  }
  return parsecsv($0)
}
function __csv_should_quote(s) {
  if (s ~ /^[[:blank:][:cntrl:][:space:]]/) return 1
  if (s ~ /[[:blank:][:cntrl:][:space:]]$/) return 1
  return 0
}
function array_formatcsv2(fields, colsep, mvsep, qchar, echar,      count, indices, line, i, value) {
  line = ""
  count = mkindices(fields, indices)
  for (i = 1; i <= count; i++) {
    value = fields[indices[i]]
    if (i > 1) line = line colsep
    if (qchar != "" && index(value, qchar) != 0) {
      if (echar != "") gsub(qchar, quote_subrepl(echar) "&", value);
      else gsub(qchar, "&&", value);
    }
    if (qchar != "" && (index(value, mvsep) != 0 || index(value, colsep) != 0 || index(value, qchar) != 0 || __csv_should_quote(value))) {
      line = line qchar value qchar
    } else {
      line = line value
    }
  }
  return line
}
function array_formatcsv(fields) {
  return array_formatcsv2(fields, ",", ";", "\"", "")
}
function array_printcsv(fields, output) {
  printto(array_formatcsv(fields), output)
}
function get_formatcsv(                 fields) {
  array_fill(fields)
  return array_formatcsv(fields)
}
function formatcsv() {
  $0 = get_formatcsv()
}
function printcsv(output,           fields) {
  array_fill(fields)
  array_printcsv(fields, output)
}
function array_findcsv(fields, input, field, value, nbfields,          orig, found, i) {
  array_new(orig)
  array_fill(orig)
  array_new(fields)
  found = 0
  while ((getline <input) > 0) {
    array_parsecsv(fields, $0, nbfields)
    if (fields[field] == value) {
      found = 1
      break
    }
  }
  close(input)
  array_getline(orig)
  if (!found) {
    delete fields
    if (nbfields) {
      nbfields = int(nbfields)
      i = array_len(fields)
      while (i < nbfields) {
        i++
        fields[i] = ""
      }
    }
  }
  return found
}

function __and(var, x, l_res, l_i) {
  l_res=0;
  for (l_i=0; l_i < 8; l_i++){
    if (var%2 == 1 && x%2 == 1) l_res=l_res/2 + 128;
    else l_res/=2;
    var=int(var/2);
    x=int(x/2);
  }
  return l_res;
}
function __lshift(var, x) {
  while(x > 0){
    var*=2;
    x--;
  }
  return var;
}
function __rshift(var, x) {
  while(x > 0){
    var=int(var/2);
    x--;
  }
  return var;
}
BEGIN {
  __BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
}
function b64decode(src,      result, base1, base2, base3, base4) {
  result = ""
  while (length(src) > 0) {
    base1 = substr(src, 1, 1)
    base2 = substr(src, 2, 1)
    base3 = substr(src, 3, 1); if (base3 == "") base3 = "="
    base4 = substr(src, 4, 1); if (base4 == "") base4 = "="
    byte1 = index(__BASE64, base1) - 1
    if (byte1 < 0) byte1 = 0
    byte2 = index(__BASE64, base2) - 1
    if (byte2 < 0) byte2 = 0
    byte3 = index(__BASE64, base3) - 1
    if (byte3 < 0) byte3 = 0
    byte4 = index(__BASE64, base4) - 1
    if (byte4 < 0) byte4 = 0
    result = result sprintf( "%c", __lshift(__and(byte1, 63), 2) + __rshift(__and(byte2, 48), 4) )
    if (base3 != "=") result = result sprintf( "%c", __lshift(__and(byte2, 15), 4) + __rshift(__and(byte3, 60), 2) )
    if (base4 != "=") result = result sprintf( "%c", __lshift(__and(byte3, 3), 6) + byte4 )
    src = substr(src, 5)
  }
  return result
}
'
function awkdef() {
    [ -z "$__ULIB_NO_DISABLE_SET_X" ] && [[ $- == *x* ]] && { set +x; local __ULIB_AWKDEF_SET_X=1; } # désactiver set -x pour cette fonction

    if [ "${1:0:3}" == "-f" ]; then
        shift
        echo "$__AWKDEF_FUNCTIONS"
    fi
    if [ $# -gt 0 ]; then
        local __ad_arg __ad_vpos __ad_name __ad_value
        echo "BEGIN {"
        while [ -n "${1:0:1}" ]; do
            __ad_arg="${1:0:256}"
            local __ad_array=
            if [ "${__ad_arg%\[@\]}" != "$__ad_arg" ]; then
                __ad_array=1
                __ad_name="${__ad_arg%\[@\]}"
                [ -z "${__ad_name//[a-zA-Z0-9_]/}" ] || break
                __ad_value="$__ad_name"
            elif [[ "$__ad_arg" == *\[@\]=* ]]; then
                __ad_array=1
                __ad_name="${__ad_arg%%\[@\]=*}"
                [ -z "${__ad_name//[a-zA-Z0-9_]/}" ] || break
                __ad_vpos=$((${#__ad_name} + 4))
                __ad_value="${1:$__ad_vpos}"
                [ ${#__ad_value} -ne 0 ] || __ad_value="$__ad_name"
            elif [[ "$__ad_arg" == *=* ]]; then
                local __ad_int= __ad_str=
                __ad_name="${__ad_arg%%=*}"
                __ad_vpos=$((${#__ad_name} + 1))
                if [ "${__ad_name%:int}" != "$__ad_name" ]; then
                    __ad_int=1
                    __ad_name="${__ad_name%:int}"
                elif [ "${__ad_name%:str}" != "$__ad_name" ]; then
                    __ad_str=1
                    __ad_name="${__ad_name%:str}"
                fi
                [ -z "${__ad_name//[a-zA-Z0-9_]/}" ] || break
                __ad_value="${1:$__ad_vpos}"
                if [ -n "$__ad_int" ]; then
                    echo "$__ad_name = int($(qawk "$__ad_value") + 0)"
                elif [ -n "$__ad_str" ]; then
                    echo "$__ad_name = $(qawk "$__ad_value")"
                elif [ ${#__ad_value} -lt 256 ] && isnum "$__ad_value"; then
                    echo "$__ad_name = $__ad_value"
                else
                    echo "$__ad_name = $(qawk "$__ad_value")"
                fi
            else
                break
            fi
            if [ -n "$__ad_array" ]; then
                if [ "${__ad_value:0:2}" == $'<\n' ]; then
                    local -a __ad_values
                    array_from_lines __ad_values "${__ad_value:2}"
                    __ad_value=__ad_values
                fi
                __ad_value="${__ad_value}[@]"
                local __ad_i=1
                echo "$__ad_name[0] = 0; delete $__ad_name"
                for __ad_arg in "${!__ad_value}"; do
                    echo "$__ad_name[$__ad_i]=$(qawk "$__ad_arg")"
                    __ad_i=$(($__ad_i + 1))
                done
                eval "echo \"\${__ad_name}_count = \${#$__ad_value}\""
            fi
            shift
        done
        echo "}"
        for __ad_arg in "$@"; do
            recho "$__ad_arg"
        done
    fi

    [ -n "$__ULIB_AWKDEF_SET_X" ] && set -x; return 0
}
function lawkrun() {
    local -a __ar_defs __ar_args
    while [ $# -gt 0 -a "$1" != "--" ]; do
        __ar_defs=("${__ar_defs[@]}" "$1")
        shift
    done
    shift
    while [ $# -gt 0 ]; do
        __ar_args=("${__ar_args[@]}" "$1")
        shift
    done
    local __ar_script="$(awkdef "${__ar_defs[@]}")"
    [ -n "$UTOOLS_AWKRUN_DEBUG" ] && estep "Script awkrun: $__ar_script"
    awk "$__ar_script" "${__ar_args[@]}"
}
function cawkrun() { LANG=C lawkrun "$@"; }
function awkrun() { LANG=C lawkrun "$@"; }

function __lf_get_age() {
    local y=$(date "+%Y")
    local dy=$(date "+%j"); while [ "${dy#0}" != "$dy" ]; do dy="${dy#0}"; done
    [ -n "$dy" ] || dy=0
    local h=$(date "+%H"); while [ "${h#0}" != "$h" ]; do h="${h#0}"; done
    [ -n "$h" ] || h=0
    echo $((($y * 365 + $dy) * 24 + $h))
}
function lf_trylock() {
    local eoo lockfile max_hours=4
    while [ -n "$1" ]; do
        case "$1" in
        -h) shift; max_hours="$1";;
        --) shift; eoo=1;;
        *) eoo=1;;
        esac
        [ -n "$eoo" ] && break
        shift
    done

    lockfile="$1"
    [ -n "$lockfile" ] || die "il faut spécifier un fichier pour le verrou"

    local now="$(__lf_get_age)"
    if (set -C; echo "$now" >"$lockfile") 2>/dev/null; then
        return 0
    fi
    local prev diff
    if prev="$(<"$lockfile")"; then
        diff="$(($now - $prev))"
        if [ "$diff" -gt "$max_hours" ]; then
            echo stale
        else
            echo locked
        fi
    elif [ -f "$lockfile" ]; then
        echo retry
    fi
    return 1
}
function pidfile_set() {
    local eoo pidfile pid=$$ replace=
    while [ -n "$1" ]; do
        case "$1" in
        -p)
            shift
            pid="$1"
            ;;
        -r)
            replace=1
            ;;
        --)
            shift
            eoo=1
            ;;
        *)
            eoo=1
            ;;
        esac
        [ -n "$eoo" ] && break
        shift
    done

    pidfile="$1"
    [ -n "$pidfile" ] || return 10

    if [ -f "$pidfile" ]; then
        local curpid="$(<"$pidfile")"
        if is_running "$curpid"; then
            return 1
        elif [ -n "$replace" ]; then
            /bin/rm -f "$pidfile" || return 10
        else
            return 2
        fi
    fi

    echo_ "$pid" >"$pidfile" || return 10
    autoclean "$pidfile"
    return 0
}
function pidfile_check() {
    local pidfile="$1"
    [ -n "$pidfile" ] || return 10

    if [ -f "$pidfile" ]; then
        [ -r "$pidfile" ] || return 10
        local pid="$(<"$pidfile")"
        is_running "$pid" && return 0
    fi
    return 1
}
function page_maybe() {
    if isatty; then
        less -XF "$@"
    else
        cat
    fi
}


function utools_local() {
    local arg
    [ $# -gt 0 ] || set -- opts verbosity interaction
    for arg in "$@"; do
        case "$arg" in
        parse_opts|opts|o|args) echo "local -a args";;
        verbosity|v) echo "local __verbosity='$__verbosity'";;
        interaction|i) echo "local __interaction='$__interaction'";;
        esac
    done
}

function stdredir() {
    local __redirs __in __out __err
    if [ -n "$1" -o "$1" == /dev/stdin ]; then
        if [ "${1#<}" != "$1" ]; then
            __in="${1#<}"
        else
            __in="$1"
        fi
        __redirs="$__redirs"' <"$__in"'
    fi; shift
    if [ -n "$1" -o "$1" == /dev/stdout ]; then
        if [ "${1#>>}" != "$1" ]; then
            __out="${1#>>}"
            __redirs="$__redirs"' >>"$__out"'
        elif [ "${1#>}" != "$1" ]; then
            __out="${1#>}"
            __redirs="$__redirs"' >"$__out"'
        else
            __out="$1"
            __redirs="$__redirs"' >"$__out"'
        fi
    fi; shift
    if [ -n "$1" -o "$1" == /dev/stderr ]; then
        if [ "${1#>>}" != "$1" ]; then
            __err="${1#>>}"
            __redirs="$__redirs"' 2>>"$__err"'
        elif [ "${1#>}" != "$1" ]; then
            __err="${1#>}"
            __redirs="$__redirs"' 2>"$__err"'
        else
            __err="$1"
            __redirs="$__redirs"' 2>"$__err"'
        fi
    fi; shift
    eval '"$@"'"$__redirs"
}

function isatty() {
    tty -s <&1
}
function in_isatty() {
    tty -s
}
function out_isatty() {
    tty -s <&1
}
function err_isatty() {
    tty -s <&2
}
function die() { [ $# -gt 0 ] && eerror "$@"; exit 1; }
function exit_with { if [ $# -gt 0 ]; then "$@"; fi; exit $?; }
function die_with { [ $# -gt 0 ] && eerror "$1"; shift; [ $# -gt 0 ] && "$@"; exit 1; }
function die_unless() {
    local count=$#
    if [ $count -eq 0 ]; then
        exit 1
    elif [ $count -eq 1 ]; then
        "$@" || exit $?
    else
        local m r
        m="${@:$count}"
        count=$(($count - 1))
        set -- "${@:1:$count}"
        if "$@"; then
            :
        else
            r=$?
            eerror "$m"
            exit $r
        fi
    fi
}
function eerror_unless() {
    local count=$#
    if [ $count -eq 0 ]; then
        return 1
    elif [ $count -eq 1 ]; then
        "$@" || return $?
    else
        local m r
        m="${@:$count}"
        count=$(($count - 1))
        set -- "${@:1:$count}"
        if "$@"; then
            :
        else
            r=$?
            eerror "$m"
            return $r
        fi
    fi
}
function die_if() {
    local count=$#
    if [ $count -eq 0 ]; then
        :
    elif [ $count -eq 1 ]; then
        "$@" && exit 1
    else
        local m r
        m="${@:$count}"
        count=$(($count - 1))
        set -- "${@:1:$count}"
        if "$@"; then
            eerror "$m"
            exit 1
        fi
    fi
}
function eerror_if() {
    local count=$#
    if [ $count -eq 0 ]; then
        :
    elif [ $count -eq 1 ]; then
        "$@" && return 1
    else
        local m r
        m="${@:$count}"
        count=$(($count - 1))
        set -- "${@:1:$count}"
        if "$@"; then
            eerror "$m"
            return 1
        fi
    fi
}

function noerror() {
    [ $# -gt 0 ] || set :
    "$@" || return 0
}
function noout() {
    [ $# -gt 0 ] || return 0
    "$@" >/dev/null
}
function noerr() {
    [ $# -gt 0 ] || return 0
    "$@" 2>/dev/null
}

TAB=$'\t'
LATIN1=iso-8859-1
LATIN9=iso-8859-15
UTF8=utf-8
OENC="$UTF8"

if ! progexists iconv; then
    function iconv() { cat; }
fi

function __lang_encoding() {
    local lang="$(<<<"$LANG" awk '{ print tolower($0) }')"
    case "$lang" in
    *@euro) echo "iso-8859-15";;
    *.utf-8|*.utf8) echo "utf-8";;
    *) echo "iso-8859-1";;
    esac
}
function __norm_encoding() {
    awk '{
        enc = tolower($0)
        gsub(/^latin$/, "latin1", enc)
        gsub(/^latin1$/, "iso-8859-1", enc)
        gsub(/^latin9$/, "iso-8859-15", enc)
        gsub(/[-_]/, "", enc)
        if (enc == "iso8859" || enc == "iso88591" || enc == "8859" || enc == "88591") print "iso-8859-1"
        else if (enc == "iso885915"  || enc == "885915") print "iso-8859-15"
        else if (enc == "utf" || enc == "utf8") print "utf-8"
        else print $0
    }' <<<"$1"
}
function __init_encoding() {
    local DEFAULT_ENCODING="$(__lang_encoding)"
    [ -n "$DEFAULT_ENCODING" ] || DEFAULT_ENCODING=utf-8
    [ -n "$UTOOLS_OUTPUT_ENCODING" ] || UTOOLS_OUTPUT_ENCODING="$DEFAULT_ENCODING"
    UTOOLS_OUTPUT_ENCODING="$(__norm_encoding "$UTOOLS_OUTPUT_ENCODING")"
    [ -n "$UTOOLS_INPUT_ENCODING" ] || UTOOLS_INPUT_ENCODING="$UTOOLS_OUTPUT_ENCODING"
    UTOOLS_INPUT_ENCODING="$(__norm_encoding "$UTOOLS_INPUT_ENCODING")"
    [ -n "$UTOOLS_EDITOR_ENCODING" ] || UTOOLS_EDITOR_ENCODING="$UTOOLS_INPUT_ENCODING"
    UTOOLS_EDITOR_ENCODING="$(__norm_encoding "$UTOOLS_EDITOR_ENCODING")"

    IENC="$UTOOLS_INPUT_ENCODING"
    OENC="$UTOOLS_OUTPUT_ENCODING"
}

if [ -n "$UTOOLS_LANG" -a -z "$LANG" ]; then
    export UTOOLS_LANG
    export LANG="$UTOOLS_LANG"
fi
__init_encoding

function tooenc() {
    local src="$1" from="${2:-$OENC}" to="${3:-$UTOOLS_OUTPUT_ENCODING}"
    if [ "$from" == "$to" ]; then
        recho "$src"
    else
        iconv -f "$from" -t "$to" <<<"$src"
    fi
}
function uecho() {
    tooenc "$*"
}
function tooenc_() {
    local src="$1" from="${2:-$OENC}" to="${3:-$UTOOLS_OUTPUT_ENCODING}"
    if [ "$from" == "$to" ]; then
        recho_ "$src"
    else
        recho_ "$src" | iconv -f "$from" -t "$to"
    fi
}
function uecho_() {
    tooenc_ "$*"
}
function toienc() {
    local __tie_var="$1" __tie_to="${2:-$IENC}" __tie_from="${3:-$UTOOLS_INPUT_ENCODING}"
    if [ "$__tie_from" != "$__tie_to" ]; then
        _setv "$__tie_var" "$(iconv -f "$__tie_from" -t "$__tie_to" <<<"${!__tie_var}")"
    fi
}
function uread() {
    [ $# -gt 0 ] || set -- REPLY
    local __r_var
    read "$@"
    for __r_var in "$@"; do
        [ -z "$__r_var" -o "${__r_var:0:1}" == "-" ] && continue # ignorer les options
        toienc "$__r_var"
    done
}

function stooenc() {
    local from="${1:-$OENC}" to="${2:-$UTOOLS_OUTPUT_ENCODING}"
    if [ "$from" == "$to" ]; then
        cat
    else
        iconv -f "$from" -t "$to"
    fi
}
function stoienc() {
    local to="${1:-$IENC}" from="${2:-$UTOOLS_INPUT_ENCODING}"
    if [ "$from" == "$to" ]; then
        cat
    else
        iconv -f "$from" -t "$to"
    fi
}

export UTOOLS_EDATE
function __edate() { [ -n "$UTOOLS_EDATE" ] && date +"[%d/%m/%Y-%H:%M:%S] "; }

export UTOOLS_ELOG_OVERWRITE
function __set_no_colors() { :; }
function elogto() {
    UTOOLS_EDATE=1
    if [ -n "$1" -a -n "$2" ]; then
        LANG=fr_FR.UTF8
        UTOOLS_OUTPUT_ENCODING="$UTF8"
        __set_no_colors 1
        if [ -n "$UTOOLS_ELOG_OVERWRITE" ]; then
            exec >"$1" 2>"$2"
        else
            exec >>"$1" 2>>"$2"
        fi
    elif [ -n "$1" ]; then
        LANG=fr_FR.UTF8
        UTOOLS_OUTPUT_ENCODING="$UTF8"
        __set_no_colors 1
        if [ -n "$UTOOLS_ELOG_OVERWRITE" ]; then
            exec >"$1" 2>&1
        else
            exec >>"$1" 2>&1
        fi
    fi
}

export __estack __tlevel
function __indent() {
    if [ "${1/
/}" != "$1" ]; then
        sed "2,\$s/^/${__tlevel}/g" <<<"$1"
    else
        recho "$1"
    fi
}
function __eerror() { tooenc "$(__edate)${__tlevel}ERROR $(__indent "$1")"; }
function __ewarn() { tooenc "$(__edate)${__tlevel}WARNING $(__indent "$1")"; }
function __enote() { tooenc "$(__edate)${__tlevel}NOTE $(__indent "$1")"; }
function __ebanner() {
    local maxi="${COLUMNS:-80}"
    local -a lines
    local psfix line

    psfix="$(__edate)${__tlevel}"
    while [ ${#psfix} -lt $maxi ]; do psfix="$psfix="; done

    tooenc "$psfix"
    maxi=$(($maxi - 1))
    array_from_xlines lines "$1"
    for line in "" "${lines[@]}" ""; do
        line="$(__edate)${__tlevel}= $line"
        if [ ${#line} -le $maxi ]; then
            while [ ${#line} -lt $maxi ]; do line="$line "; done
            line="$line="
        fi
        tooenc "$line"
    done
    tooenc "$psfix"
}
function __eimportant() { tooenc "$(__edate)${__tlevel}IMPORTANT $(__indent "$1")"; }
function __eattention() { tooenc "$(__edate)${__tlevel}ATTENTION $(__indent "$1")"; }
function __einfo() { tooenc "$(__edate)${__tlevel}INFO $(__indent "$1")"; }
function __eecho() { tooenc "$(__edate)${__tlevel}$(__indent "$1")"; }
function __eecho_() { tooenc_ "$(__edate)${__tlevel}$(__indent "$1")"; }
function __edebug() { tooenc "$(__edate)${__tlevel}DEBUG $(__indent "$1")"; }
function __estep() { tooenc "$(__edate)${__tlevel}. $(__indent "$1")"; }
function __estepe() { tooenc "$(__edate)${__tlevel}.E $(__indent "$1")"; }
function __estepw() { tooenc "$(__edate)${__tlevel}.W $(__indent "$1")"; }
function __estepn() { tooenc "$(__edate)${__tlevel}.N $(__indent "$1")"; }
function __estepi() { tooenc "$(__edate)${__tlevel}.I $(__indent "$1")"; }
function __estep_() { tooenc_ "$(__edate)${__tlevel}. $(__indent "$1")"; }
function __estepe_() { tooenc_ "$(__edate)${__tlevel}.E $(__indent "$1")"; }
function __estepw_() { tooenc_ "$(__edate)${__tlevel}.W $(__indent "$1")"; }
function __estepn_() { tooenc_ "$(__edate)${__tlevel}.N $(__indent "$1")"; }
function __estepi_() { tooenc_ "$(__edate)${__tlevel}.I $(__indent "$1")"; }
function __etitle() { tooenc "$(__edate)${__tlevel}=== $(__indent "$1")"; }
function __ebegin() { tooenc_ "$(__edate)${__tlevel}. $(__indent "$1"): "; }
function __edoto() { echo_ "."; }
function __edotw() { echo_ "w"; }
function __edotx() { echo_ "x"; }
function __edotp() { echo_ "+"; }
function __edotd() { tooenc "($1)"; }
function __eendo() { echo "[ok]"; }
function __eendx() { echo "[error]"; }
PRETTYOPTS=()
function set_verbosity() { :;}
function set_interaction() { :;}
function show_error() {
    return 0
}
function show_warn() {
    return 0
}
function show_info() {
    return 0
}
function show_verbose() {
    return 0
}
function show_debug() {
    [ -n "$DEBUG" ]
}
function check_verbosity() {
    return 0
}
function get_verbosity_option() { :;}
function check_interaction() {
    return 0
}
function is_interaction() {
    return 1
}
function get_interaction_option() { :;}
__epending=
function eflush() {
    if [ -n "$__epending" ]; then recho "$__epending" 1>&2; __epending=; fi
}
function eclearp() {
    __epending=
}
function eerror() {
    show_error || return; eflush; __eerror "$*" 1>&2
}
function ewarn() {
    show_warn || return; eflush; __ewarn "$*" 1>&2
}
function enote() {
    show_info || return; eflush; __enote "$*" 1>&2
}
function ebanner() {
    show_error || return; eflush; __ebanner "$*" 1>&2; sleep 5
}
function eimportant() {
    show_error || return; eflush; __eimportant "$*" 1>&2
}
function eattention() {
    show_warn || return; eflush; __eattention "$*" 1>&2
}
function einfo() {
    show_info || return; eflush; __einfo "$*" 1>&2
}
function eecho() {
    show_info || return; eflush; __eecho "$*" 1>&2
}
function eecho_() {
    show_info || return; eflush; __eecho_ "$*" 1>&2
}
function edebug() {
    show_debug || return; eflush; __edebug "$*" 1>&2
}
function trace() {
    local r cmd="$(qvals "$@")"
    show_info && { eflush; __eecho "\$ $cmd" 1>&2; }
    "$@"; r=$?
    if [ $r -ne 0 ]; then
        if show_info; then
            eflush; __eecho "^ [EC #$r]" 1>&2
        elif show_error; then
            eflush; __eecho "^ $cmd [EC #$r]" 1>&2;
        fi
    fi
    return $r
}
function trace_error() {
    local r
    "$@"; r=$?
    if [ $r -ne 0 ]; then
        local cmd="$(qvals "$@")"
        show_error && { eflush; __eecho "^ $cmd [EC #$r]" 1>&2; }
    fi
    return $r
}

function etitle() {
    local __t_deferred=
    __t_etitle "$@"
}
function etitled() {
    local __t_deferred=1
    __t_etitle "$@"
}
function __t_etitle() {
    local __t_eend=default
    local __t_clearp=
    while [ -n "$1" ]; do
        if [ "$1" == "--" ]; then
            shift
            break
        elif [ "$1" == "-s" ]; then
            __t_eend=
            shift
        elif [ "$1" == "--eend" ]; then
            __t_eend=1
            shift
        elif [ "$1" == "-p" ]; then
            __t_clearp=1
            shift
        else
            break
        fi
    done
    local __t_title="$1"; shift
    local __t_s=0
    [ -n "$__estack" ] && __tlevel="${__tlevel}  "
    __estack="$__estack:t"
    if show_info; then
        if [ -n "$__t_deferred" ]; then
            __epending="${__epending:+$__epending
}$(__etitle "$__t_title")"
        else
            eflush
            __etitle "$__t_title" 1>&2
        fi
    fi
    if [ $# -gt 0 ]; then
        "$@"
        __t_s=$?
        [ "$__t_eend" == "default" ] && __t_eend=1
    fi
    [ "$__t_eend" == "default" ] && __t_eend=
    if [ -n "$__t_eend" ]; then
        eend $__t_s
        [ -n "$__t_clearp" ] && eclearp
    fi
    return $__t_s
}
function estep() {
    show_info || return; eflush; __estep "$*" 1>&2
}
function estepe() {
    show_info || return; eflush; __estepe "$*" 1>&2
}
function estepw() {
    show_info || return; eflush; __estepw "$*" 1>&2
}
function estepn() {
    show_info || return; eflush; __estepn "$*" 1>&2
}
function estepi() {
    show_info || return; eflush; __estepi "$*" 1>&2
}
function estep_() {
    show_info || return; eflush; __estep_ "$*" 1>&2
}
function estepe_() {
    show_info || return; eflush; __estepe_ "$*" 1>&2
}
function estepw_() {
    show_info || return; eflush; __estepw_ "$*" 1>&2
}
function estepn_() {
    show_info || return; eflush; __estepn_ "$*" 1>&2
}
function estepi_() {
    show_info || return; eflush; __estepi_ "$*" 1>&2
}
function ebegin() {
    local __b_eend=default
    while [ -n "$1" ]; do
        if [ "$1" == "--" ]; then
            shift
            break
        elif [ "$1" == "-s" ]; then
            __b_eend=
            shift
        elif [ "$1" == "--eend" ]; then
            __b_eend=1
            shift
        else
            break
        fi
    done
    local __b_msg="$1"; shift
    local __b_s=0
    __estack="$__estack:b"
    if show_info; then
        eflush
        __ebegin "$__b_msg" 1>&2
    fi
    if [ $# -gt 0 ]; then
        "$@"
        __b_s=$?
        [ "$__b_eend" == "default" ] && __b_eend=1
    fi
    [ "$__b_eend" == "default" ] && __b_eend=
    [ -n "$__b_eend" ] && eend $__b_s
    return $__b_s
}
function edot() {
    local s=$?
    show_info || return
    eflush
    [ -n "$1" ] && s="$1"
    shift
    if [ "$s" == "0" ]; then
        __edoto 1>&2
    else
        __edotx 1>&2
    fi
    show_verbose && [ $# -gt 0 ] && __edotd "$*" 1>&2
    return $s
}
function edotw() {
    local s=$?
    show_info || return
    eflush
    [ -n "$1" ] && s="$1"
    shift
    __edotw 1>&2
    show_verbose && [ $# -gt 0 ] && __edotd "$*" 1>&2
    return $s
}
function ewait() {
    [ -n "$1" ] || return 1
    if show_info; then
        local count=2
        eflush
        little_sleep # certains processus retournent tout de suite
        while is_running "$1"; do
            sleep 1
            if [ $count -gt 0 ]; then
                count=$(($count - 1))
            else
                __edotp 1>&2
            fi
        done
        __edoto 1>&2
    else
        wait "$1"
    fi
}
function eend() {
    local s=$?
    if [ "$1" == "-c" ]; then
        __estack=
        __tlevel=
    elif [ "${__estack%:b}" != "$__estack" ]; then
        __estack="${__estack%:b}"
        show_info || return
        eflush
        [ -n "$1" ] && s="$1"
        if [ "$s" == "0" ]; then
            __eendo 1>&2
        else
            __eendx 1>&2
        fi
    elif [ "${__estack%:t}" != "$__estack" ]; then
        __estack="${__estack%:t}"
        __tlevel="${__tlevel%  }"
    fi
}
function __elinedots() {
    ebegin "$1"
    local line
    if show_debug; then
        while read line; do
            __edoto 1>&2
            __edotd "$line" 1>&2
        done
    else
        while read line; do
            __edoto 1>&2
        done
    fi
    eend
}
function elinedots() {
    local msg="$1"; shift
    if [ $# -gt 0 ]; then
        "$@" | __elinedots "$msg"
    else
        __elinedots "$msg"
    fi
}
function ask_yesno() {
    local interactive=1
    if [[ "$1" == -* ]]; then
        if [ "$1" != -- ]; then
            check_interaction "$1" || interactive=
        fi
        shift
    else
        check_interaction -c || interactive=
    fi
    local default="${2:-N}"
    if [ "$default" == "C" ]; then
        [ -n "$interactive" ] && default=N || default=O
    elif [ "$default" == "X" ]; then
        [ -n "$interactive" ] && default=O || default=N
    fi
    if [ -n "$interactive" ]; then
        eflush
        local message="$1"
        local prompt="[oN]"
        local r
        is_yes "$default" && prompt="[On]"
        if [ -n "$message" ]; then
            __eecho_ "$message" 1>&2
        else
            OENC="$UTF8" __eecho_ "Voulez-vous continuer?" 1>&2
        fi
        OENC="$UTF8" tooenc_ " $prompt " 1>&2
        uread r
        is_yes "${r:-$default}"
    else
        is_yes "$default"
    fi
}
function ask_any() {
    local interactive=1
    if [[ "$1" == -* ]]; then
        if [ "$1" != -- ]; then
            check_interaction "$1" || interactive=
        fi
        shift
    else
        check_interaction -c || interactive=
    fi
    local format="${2:-+Oq}"
    format="${format/+O/On}"
    format="${format/+N/oN}"
    if [ -n "$interactive" ]; then
        format="${format/+C/oN}"
        format="${format/+X/On}"
    else
        format="${format/+C/On}"
        format="${format/+X/oN}"
    fi
    local i count="${#format}"

    if [ -n "$interactive" ]; then
        eflush
        local message="${1:-Voulez-vous continuer?}"
        local prompt="[$format]"
        local r f lf defi
        while true; do
            __eecho_ "$message $prompt " 1>&2
            uread r
            r="$(strlower "${r:0:1}")"
            i=0; defi=
            while [ $i -lt $count ]; do
                f="${format:$i:1}"
                lf="$(strlower "$f")"
                [ "$r" == "$lf" ] && return $i
                if [ -z "$defi" ]; then
                    [[ "$f" =~ [A-Z] ]] && defi="$i"
                fi
                if [ "$lf" == o ]; then
                    case "$r" in o|y|1|v|t) return $i;; esac
                elif [ "$lf" == n ]; then
                    case "$r" in n|f|0) return $i;; esac
                fi
                i=$(($i + 1))
            done
            [ -z "$r" ] && return ${defi:-0}
        done
    else
        i=0
        while [ $i -lt $count ]; do
            [[ "${format:$i:1}" =~ [A-Z] ]] && return $i
            i=$(($i + 1))
        done
        return 0
    fi
}
function read_value() {
    local -a __rv_opts __rv_readline=1 __rv_showdef=1 __rv_nl=
    __rv_opts=()
    [ -n "$UTOOLS_NO_READLINE" ] && __rv_readline=
    __rv_read "$@"
}
function read_password() {
    local -a __rv_opts __rv_readline= __rv_showdef= __rv_nl=1
    __rv_opts=(-s)
    __rv_read "$@"
}
function __rv_read() {
    local __rv_int=1
    if [[ "$1" == -* ]]; then
        if [ "$1" != -- ]; then
            check_interaction "$1" || __rv_int=
        fi
        shift
    else
        check_interaction -c || __rv_int=
    fi
    local __rv_msg="$1" __rv_v="${2:-value}" __rv_d="$3" __rv_re="${4:-O}"
    if [ -z "$__rv_int" ]; then
        if is_yes "$__rv_re" && [ -z "$__rv_d" ]; then
            OENC="$UTF8" eerror "La valeur par défaut de $__rv_v doit être non vide"
            return 1
        fi
        _setv "$__rv_v" "$__rv_d"
        return 0
    fi

    eflush
    local __rv_r
    while true; do
        if [ -n "$__rv_msg" ]; then
            __eecho_ "$__rv_msg" 1>&2
        else
            OENC="$UTF8" __eecho_ "Entrez la valeur" 1>&2
        fi
        if [ -n "$__rv_readline" ]; then
            OENC="$UTF8" tooenc_ ": " 1>&2
            uread -e ${__rv_d:+-i"$__rv_d"} "${__rv_opts[@]}" __rv_r
        else
            if [ -n "$__rv_d" ]; then
                if [ -n "$__rv_showdef" ]; then
                    tooenc_ " [$__rv_d]" 1>&2
                else
                    tooenc_ " [****]" 1>&2
                fi
            fi
            OENC="$UTF8" tooenc_ ": " 1>&2
            uread "${__rv_opts[@]}" __rv_r
            [ -n "$__rv_nl" ] && echo
        fi
        __rv_r="${__rv_r:-$__rv_d}"
        if [ -n "$__rv_r" ] || ! is_yes "$__rv_re"; then
            _setv "$__rv_v" "$__rv_r"
            return 0
        fi
    done
}
function simple_menu() {
    local __sm_title= __sm_yourchoice= __sm_default=
    local -a __sm_args
    parse_opts -t: __sm_title= -m: __sm_yourchoice= -d: __sm_default= @ __sm_args -- "$@" &&
    set -- "${__sm_args[@]}" || ewarn "$__sm_args"

    local __sm_option_var="${1:-option}" __sm_options_var="${2:-options}"
    local __sm_option __sm_options
    __sm_options="$__sm_options_var[*]"
    if [ -z "${!__sm_options}" ]; then
        OENC="$UTF8" eerror "Le tableau $__sm_options_var doit être non vide"
        return 1
    fi
    [ -z "$__sm_default" ] && __sm_default="${!__sm_option_var}"

    eflush
    array_copy __sm_options "$__sm_options_var"
    local __sm_c=0 __sm_i __sm_choice
    while true; do
        if [ "$__sm_c" == "0" ]; then
            [ -n "$__sm_title" ] && __eecho "=== $__sm_title ===" 1>&2
            __sm_i=1
            for __sm_option in "${__sm_options[@]}"; do
                if [ "$__sm_option" == "$__sm_default" ]; then
                    __eecho "$__sm_i*- $__sm_option" 1>&2
                else
                    __eecho "$__sm_i - $__sm_option" 1>&2
                fi
                let __sm_i=$__sm_i+1
            done
        fi

        if [ -n "$__sm_yourchoice" ]; then
            __eecho_ "$__sm_yourchoice" 1>&2
        else
            OENC="$UTF8" __eecho_ "Entrez le numéro de l'option choisie" 1>&2
        fi
        OENC="$UTF8" tooenc_ ": " 1>&2
        uread __sm_choice

        if [ -z "$__sm_choice" -a -n "$__sm_default" ]; then
            __sm_option="$__sm_default"
            break
        fi
        if [ -n "$__sm_choice" -a -z "${__sm_choice//[0-9]/}" ]; then
            if [ "$__sm_choice" -gt 0 -a "$__sm_choice" -le "${#__sm_options[*]}" ]; then
                __sm_option="${__sm_options[$(($__sm_choice - 1))]}"
                break
            else
                OENC="$UTF8" eerror "Numéro d'option incorrect"
            fi
        else
            OENC="$UTF8" eerror "Vous devez saisir le numéro de l'option choisie"
        fi

        let __sm_c=$__sm_c+1
        if [ "$__sm_c" -eq 5 ]; then
            OENC="$UTF8" tooenc "" 1>&2
            __sm_c=0
        fi
    done
    _setv "$__sm_option_var" "$__sm_option"
}

function actions_menu() {
    local -a __am_action_descs __am_options __am_void_actions
    local __am_tmp __am_select_action __am_select_option __am_title __am_optyc __am_actyc
    local __am_default_action=auto __am_quit_action=auto
    local __am_default_option=
    local -a __am_args
    parse_opts \
        -t: __am_title= \
        -m: __am_optyc= \
        -M: __am_actyc= \
        -e: __am_void_actions \
        -d: __am_default_action= \
        -q: __am_quit_action= \
        -o: __am_default_option= \
        @ __am_args -- "$@" && set -- "${__am_args[@]}" || { eerror "$__am_args"; return 1; }

    __am_tmp="${1:-action}"; __am_select_action="${!__am_tmp}"
    __am_tmp="${2:-option}"; __am_select_option="${!__am_tmp}"
    [ -n "$__am_default_option" ] && __am_select_option="$__am_default_option"
    array_copy __am_action_descs "${3:-actions}"
    array_copy __am_options "${4:-options}"

    eerror_unless [ ${#__am_action_descs[*]} -gt 0 ] "Vous devez spécifier le tableau des actions" || return
    __actions_menu || return 1
    _setv "${1:-action}" "$__am_select_action"
    _setv "${2:-option}" "$__am_select_option"
}
function __actions_menu() {
    local title="$__am_title"
    local optyc="$__am_optyc" actyc="$__am_actyc"
    local default_action="$__am_default_action"
    local quit_action="$__am_quit_action"
    local select_action="$__am_select_action"
    local select_option="$__am_select_option"
    local -a action_descs options void_actions
    array_copy action_descs __am_action_descs
    array_copy options __am_options
    array_copy void_actions __am_void_actions

    local no_options
    array_isempty options && no_options=1

    local -a actions
    local tmp action name
    for tmp in "${action_descs[@]}"; do
        splitfsep2 "$tmp" : action name
        [ -n "$action" ] || action="${name:0:1}"
        action="$(strlower "$action")"
        array_addu actions "$action"
    done

    if [ "$default_action" == auto ]; then
        default_action="$select_action"
        if [ -n "$default_action" ]; then
            array_contains actions "$default_action" || default_action=
        fi
        [ -n "$default_action" ] || default_action="${actions[0]}"
    fi
    default_action="${default_action:0:1}"
    default_action="$(strlower "$default_action")"

    if [ "$quit_action" == auto ]; then
        if [ ${#actions[*]} -gt 1 ]; then
            quit_action="${actions[@]:$((-1)):1}"
            array_addu void_actions "$quit_action"
        fi
    fi
    quit_action="${quit_action:0:1}"
    quit_action="$(strlower "$quit_action")"

    local action_title
    for tmp in "${action_descs[@]}"; do
        splitfsep2 "$tmp" : action name
        [ -n "$action" ] || action="${name:0:1}"
        [ -n "$name" ] || name="$action"
        action="$(strlower "$action")"
        if [ -n "$no_options" ]; then
            if ! array_contains void_actions "$action"; then
                array_del actions "$action"
                continue
            fi
        fi
        [ "$action" == "$default_action" ] && name="$name*"
        action_title="${action_title:+$action_title/}$name"
    done
    if [ -n "$default_action" ]; then
        array_contains actions "$default_action" || default_action=
    fi
    if [ -n "$quit_action" ]; then
        array_contains actions "$quit_action" || quit_action=
    fi

    if [ -n "$no_options" ]; then
        if array_isempty void_actions; then
            eerror "Aucune option n'est définie. Il faut définir le tableau des actions vides"
            return 1
        fi
        __void_actions_menu
    else
        __options_actions_menu
    fi
}
function __void_actions_menu() {
    eflush
    local c=0 choice
    while true; do
        if [ $c -eq 0 ]; then
            [ -n "$title" ] && __etitle "$title" 1>&2
            __eecho_ "=== Actions disponibles: " 1>&2
            tooenc "$action_title" 1>&2
        fi
        if [ -n "$actyc" ]; then
            __eecho_ "$actyc" 1>&2
        elif [ -n "$optyc" ]; then
            __eecho_ "$optyc" 1>&2
        else
            __eecho_ "Entrez l'action à effectuer" 1>&2
        fi
        tooenc_ ": " 1>&2
        uread choice
        if [ -z "$choice" -a -n "$default_action" ]; then
            select_action="$default_action"
            break
        fi

        choice="${choice:0:1}"
        choice="$(strlower "$choice")"
        if array_contains actions "$choice"; then
            select_action="$choice"
            break
        elif [ -n "$choice" ]; then
            eerror "$choice: action incorrecte"
        else
            eerror "vous devez saisir l'action à effectuer"
        fi
        let c=$c+1
        if [ $c -eq 5 ]; then
            tooenc "" 1>&2
            c=0
        fi
    done
    __am_select_action="$select_action"
    __am_select_option=
}
function __options_actions_menu() {
    eflush
    local c=0 option choice action option
    while true; do
        if [ $c -eq 0 ]; then
            [ -n "$title" ] && __etitle "$title" 1>&2
            i=1
            for option in "${options[@]}"; do
                if [ "$option" == "$select_option" ]; then
                    tooenc "$i*- $option" 1>&2
                else
                    tooenc "$i - $option" 1>&2
                fi
                let i=$i+1
            done
            __estepn_ "Actions disponibles: " 1>&2
            tooenc "$action_title" 1>&2
        fi
        if [ -n "$optyc" ]; then
            __eecho_ "$optyc" 1>&2
        else
            __eecho_ "Entrez l'action et le numéro de l'option choisie" 1>&2
        fi
        tooenc_ ": " 1>&2
        uread choice

        if [ -z "$choice" -a -n "$default_action" ]; then
            action="$default_action"
            if array_contains void_actions "$action"; then
                select_action="$action"
                select_option=
                break
            elif [ -n "$select_option" ]; then
                select_action="$action"
                break
            fi
        fi
        action="${choice:0:1}"
        action="$(strlower "$action")"
        if array_contains actions "$action"; then
            if array_contains void_actions "$action"; then
                select_action="$action"
                select_option=
                break
            else
                option="${choice:1}"
                option="${option// /}"
                if [ -z "$option" -a -n "$select_option" ]; then
                    select_action="$action"
                    break
                elif [ -z "$option" ]; then
                    eerror "vous devez saisir le numéro de l'option"
                elif isnum "$option"; then
                    if [ $option -gt 0 -a $option -le ${#options[*]} ]; then
                        select_action="$action"
                        select_option="${options[$(($option - 1))]}"
                        break
                    fi
                else
                    eerror "$option: numéro d'option incorrecte"
                fi
            fi
        elif isnum "$choice"; then
            action="$default_action"
            if [ -n "$action" ]; then
                if array_contains void_actions "$action"; then
                    select_action="$action"
                    select_option=
                    break
                else
                    option="${choice// /}"
                    if [ -z "$option" ]; then
                        eerror "vous devez saisir le numéro de l'option"
                    elif isnum "$option"; then
                        if [ $option -gt 0 -a $option -le ${#options[*]} ]; then
                            select_action="$action"
                            select_option="${options[$(($option - 1))]}"
                            break
                        fi
                    else
                        eerror "$option: numéro d'option incorrecte"
                    fi
                fi
            else
                eerror "Vous devez spécifier l'action à effectuer"
            fi
        elif [ -n "$choice" ]; then
            eerror "$choice: action et/ou option incorrecte"
        else
            eerror "vous devez saisir l'action à effectuer"
        fi
        let c=$c+1
        if [ $c -eq 5 ]; then
            tooenc "" 1>&2
            c=0
        fi
    done
    __am_select_action="$select_action"
    __am_select_option="$select_option"
}


function __ac_forgetall() { __ac_files=(); }
__ac_forgetall
function __ac_trap() {
    local file
    for file in "${__ac_files[@]}"; do
        [ -e "$file" ] && rm -rf "$file" 2>/dev/null
    done
    __ac_forgetall
}
trap __ac_trap 1 3 15 EXIT
function autoclean() {
    local file
    for file in "$@"; do
        [ -n "$file" ] && array_add __ac_files "$file"
    done
}
function ac_cleanall() {
    __ac_trap
}
function ac_clean() {
    local file
    for file in "$@"; do
        if array_contains __ac_files "$file"; then
            [ -e "$file" ] && rm -rf "$file" 2>/dev/null
            array_del __ac_files "$file"
        fi
    done
}
function ac_set_tmpfile() {
    local __acst_d
    if show_debug; then
        if [ -n "$5" ]; then
            is_yes "${!5}" && __acst_d=1
        else
            __acst_d=1
        fi
    fi
    if [ -n "$__acst_d" -a -n "$3" ]; then
        _setv "$1" "$3"
        [ -f "$3" -a "$4" == keep ] || >"$3"
    else
        local __acst_t="$(mktempf "$2")"
        autoclean "$__acst_t"
        _setv "$1" "$__acst_t"
    fi
}
function ac_set_tmpdir() {
    local __acst_d
    if show_debug; then
        if [ -n "$4" ]; then
            is_yes "${!4}" && __acst_d=1
        else
            __acst_d=1
        fi
    fi
    if [ -n "$__acst_d" -a -n "$3" ]; then
        _setv "$1" "$3"
        mkdir -p "$3"
    else
        local __acst_t="$(mktempd "$2")"
        autoclean "$__acst_t"
        _setv "$1" "$__acst_t"
    fi
}
function debug_tee() {
    if show_debug; then
        tee "$@"
    else
        cat
    fi
}


function get_user_defaults_file() {
    if [ -r "$HOME/etc/default.${HOSTNAME%%.*}/$1" ]; then
        echo "$HOME/etc/default.${HOSTNAME%%.*}/$1"
    elif [ -r "$HOME/etc/default/$1" ]; then
        echo "$HOME/etc/default/$1"
    elif [ -n "$UTOOLS_LOCAL_PROFILES" ]; then
        echo "$HOME/etc/default.${HOSTNAME%%.*}/$1"
    else
        echo "$HOME/etc/default/$1"
    fi
}

function get_defaults_files() {
    local __gd_dest="${1:-defaults}"; shift
    local -a __gd_fs
    local __gd_f __gd_found
    for __gd_f in "$@"; do
        __gd_found=
        if [ -r "/etc/default/$__gd_f" ]; then
            __gd_fs=("${__gd_fs[@]}" "/etc/default/$__gd_f")
            __gd_found=1
        fi
        if [ -r "$HOME/etc/default.${HOSTNAME%%.*}/$__gd_f" ]; then
            __gd_fs=("${__gd_fs[@]}" "$HOME/etc/default.${HOSTNAME%%.*}/$__gd_f")
            __gd_found=1
        elif [ -r "$HOME/etc/default/$__gd_f" ]; then
            __gd_fs=("${__gd_fs[@]}" "$HOME/etc/default/$__gd_f")
            __gd_found=1
        fi
        if [ -z "$__gd_found" -a -r "$scriptdir/lib/default/$__gd_f" ]; then
            __gd_fs=("${__gd_fs[@]}" "$scriptdir/lib/default/$__gd_f")
        fi
    done
    array_copy "$__gd_dest" __gd_fs
}

function set_defaults() {
    local -a __sd_fs
    local __sd_f
    get_defaults_files __sd_fs "$@"
    for __sd_f in "${__sd_fs[@]}"; do
        source "$__sd_f"
    done
}


: "${MYHOST:=$HOSTNAME}"
: "${MYHOSTNAME:=${MYHOST%%.*}}"
export MYHOST MYHOSTNAME

function myhost() {
    hostname -f 2>/dev/null || echo "$MYHOST"
}
function myhostname() {
    hostname -s 2>/dev/null || echo "$MYHOSTNAME"
}
##@inc]../base
##@inc[../sysinfos
## Gestion des informations sur l'hôte local
##@require base
uprovide sysinfos
urequire base


SYSNAMES=(linux linux64 linux32 linuxppc64 linuxppc32 linuxarm macosx)
linux_SYSDISTS=(debianlike debian ubuntu redhatlike ol rhel fedora centos suse gentoo)
linux32_SYSDISTS=(debianlike debian ubuntu redhatlike ol rhel fedora centos suse gentoo)
linux64_SYSDISTS=(debianlike debian ubuntu redhatlike ol rhel fedora centos suse gentoo)
linuxppc32_SYSDISTS=(debianlike debian ubuntu redhatlike fedora)
linuxppc64_SYSDISTS=(debianlike debian ubuntu redhatlike fedora)
linuxarm_SYSDISTS=(debianlike debian ubuntu)
macosx_SYSDISTS=(lion snowleopard leopard tiger panther)
SYSDIST_ALIASES=(
    10.7=lion 10.6=snowleopard 10.5=leopard 10.4=tiger 10.3=panther
)
debianlike_SYSVERS=()
debian_SYSVERS=(stretch jessie wheezy squeeze lenny etch)
ubuntu_SYSVERS=(oneiric natty maverick lucid karmic jaunty intrepid hardy)
redhatlike_SYSVERS=()
ol_SYSVERS=(ol7 ol6 redhat7 redhat6)
rhel_SYSVERS=(rhel7 rhel6 rhel5 rhel4 redhat7 redhat6 redhat5 redhat4)
fedora_SYSVERS=(fedora14 fedora13 fedora12 fedora11)
centos_SYSVERS=(centos7 centos6 centos5 centos4 redhat7 redhat6 redhat5 redhat4)
suse_SYSVERS=()
gentoo_SYSVERS=()
SYSVER_ALIASES=(
    9=stretch 8=jessie 7=wheezy 6=squeeze 5=lenny 4=etch
    11.10=oneiric 11.04=natty 10.10=maverick 10.04=lucid 9.10=karmic 9.04=jaunty 8.10=intrepid 8.04=hardy
)

function __setup_ALL_SYSvars() {
    local s ds d fs f
    ALL_SYSDISTS=()
    for s in "${SYSNAMES[@]}"; do
        array_copy ds "${s}_SYSDISTS"
        for d in "${ds[@]}"; do
            array_set ALL_SYSDISTS "$d"
        done
    done
    ALL_SYSVERS=()
    for d in "${ALL_SYSDISTS[@]}"; do
        array_copy fs "${d}_SYSVERS"
        for f in "${fs[@]}"; do
            array_contains ALL_SYSVERS "$f" && array_del ALL_SYSVERS "$f"
            array_add ALL_SYSVERS "$f"
        done
    done
}
__setup_ALL_SYSvars
unset -f __setup_ALL_SYSvars

function __compute_local_sysinfos_data() {
    SYSINFOS_DATA=(
        "$UNAME_SYSTEM"
        "$UNAME_MACHINE"
        "$([ -f /etc/debian_version ] && cat /etc/debian_version)"
        "$([ -f /etc/gentoo-release ] && cat /etc/gentoo-release)"
        "$([ -f /etc/oracle-release ] && cat /etc/oracle-release)"
        "$([ -f /etc/redhat-release ] && cat /etc/redhat-release)"
        "$([ -f /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist)"
        "$([ -f /System/Library/Frameworks/CoreServices.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Resources/version.plist)"
    )
}
function __dump_remote_sysinfos_data() {
    "${2:-ssh}" "$1" "\
uname -s
echo .----------------.
uname -m
echo .----------------.
[ -f /etc/debian_version ] && cat /etc/debian_version
echo .----------------.
[ -f /etc/gentoo-release ] && cat /etc/gentoo-release
echo .----------------.
[ -f /etc/oracle-release ] && cat /etc/oracle-release
echo .----------------.
[ -f /etc/redhat-release ] && cat /etc/redhat-release
echo .----------------.
[ -f /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist
echo .----------------.
[ -f /System/Library/Frameworks/CoreServices.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Resources/version.plist
echo .----------------."
}
function __build_sysinfos_data() {
    awk '
BEGIN {
  data = ""
  have_data = 0
  print "SYSINFOS_DATA=("
}
function read_data() {
  if (have_data) data = data "\n"
  else have_data = 1
  data = data $0
}
function dump_data() {
  gsub(/'\''/, "'\'\\\\\'\''", data)
  print "'\''" data "'\''"
  data = ""
  have_data = 0
}
$0 == ".----------------." { dump_data(); next }
{ read_data() }
END {
  dump_data()
  print ")"
}
'
}
function __compute_sysinfos() {
    local system="${SYSINFOS_DATA[0]}"
    local machine="${SYSINFOS_DATA[1]}"
    local debian_version="${SYSINFOS_DATA[2]}"
    local gentoo_release="${SYSINFOS_DATA[3]}"
    local oracle_release="${SYSINFOS_DATA[4]}"
    local redhat_release="${SYSINFOS_DATA[5]}"
    local macosx_plist1="${SYSINFOS_DATA[6]}"
    local macosx_plist2="${SYSINFOS_DATA[7]}"

    MYSYSNAME=(unknown)
    MYSYSDIST=(unknown)
    MYSYSVER=(unknown)
    if [ "$system" == "Linux" ]; then
        case "$machine" in
        x86_64) MYSYSNAME=(linux64 linux); MYBITS=64;;
        i386|i586|i686) MYSYSNAME=(linux32 linux); MYBITS=32;;
        ppc) MYSYSNAME=(linuxppc32 linuxppc linux); MYBITS=32;;
        ppc64) MYSYSNAME=(linuxppc64 linuxppc linux); MYBITS=64;;
        arm*) MYSYSNAME=(linuxarm linux);;
        *) MYSYSNAME=(linux);;
        esac
        if [ -n "$debian_version" ]; then
            case "$debian_version" in
            9*|stretch*) MYSYSDIST=(debian debianlike); MYSYSVER=(stretch);;
            8*|jessie*) MYSYSDIST=(debian debianlike); MYSYSVER=(jessie);;
            7*|wheezy*) MYSYSDIST=(debian debianlike); MYSYSVER=(wheezy);;
            6*|squeeze*) MYSYSDIST=(debian debianlike); MYSYSVER=(squeeze);;
            5*) MYSYSDIST=(debian debianlike); MYSYSVER=(lenny);;
            4*) MYSYSDIST=(debian debianlike); MYSYSVER=(etch);;
            *) MYSYSDIST=(debianlike);;
            esac
        elif [ -n "$gentoo_release" ]; then
            MYSYSDIST=(gentoo)
        elif [ -n "$oracle_release" ]; then
            MYSYSDIST=(ol rhel redhatlike)
            case "$oracle_release" in
            Oracle*Linux*release\ 7*) MYSYSVER=(ol7 rhel7 redhat7);;
            Oracle*Linux*release\ 6*) MYSYSVER=(ol6 rhel6 redhat6);;
            esac
        elif [ -n "$redhat_release" ]; then
            case "$redhat_release" in
            Fedora*) MYSYSDIST=(fedora redhatlike);;
            Red*Hat*Enterprise*Linux*) MYSYSDIST=(rhel redhatlike);;
            CentOS*) MYSYSDIST=(centos redhatlike);;
            *) MYSYSDIST=(redhatlike);;
            esac
            case "$redhat_release" in
            Fedora*14*) MYSYSVER=(fedora14);;
            Fedora*13*) MYSYSVER=(fedora13);;
            Fedora*12*) MYSYSVER=(fedora12);;
            Fedora*11*) MYSYSVER=(fedora11);;
            Red*Hat*Enterprise*Linux*release\ 7*) MYSYSVER=(rhel7 redhat7);;
            Red*Hat*Enterprise*Linux*release\ 6*) MYSYSVER=(rhel6 redhat6);;
            Red*Hat*Enterprise*Linux*release\ 5*) MYSYSVER=(rhel5 redhat5);;
            Red*Hat*Enterprise*Linux*release\ 4*) MYSYSVER=(rhel4 redhat4);;
            CentOS*release\ 7*) MYSYSVER=(centos7 redhat7);;
            CentOS*release\ 6*) MYSYSVER=(centos6 redhat6);;
            CentOS*release\ 5*) MYSYSVER=(centos5 redhat5);;
            CentOS*release\ 4*) MYSYSVER=(centos4 redhat4);;
            esac
        fi
    elif [ "$system" == "Darwin" ]; then
        function get_macosx_version() {
            local plist
            for plist in "$@"; do
                [ -n "$plist" ] || continue
                echo "$plist" | grep -A 1 CFBundleShortVersionString | grep string | sed 's/.*<string>//g
s/<\/string>.*$//g'
                break
            done
        }
        MYSYSNAME=(macosx darwin)
        case "$(get_macosx_version "$macosx_plist1" "$macosx_plist2")" in
        10.7*) MYSYSDIST=(lion);;
        10.6*) MYSYSDIST=(snowleopard);;
        10.5*) MYSYSDIST=(leopard);;
        10.4*) MYSYSDIST=(tiger);;
        10.3*) MYSYSDIST=(panther);;
        esac
        MYSYSVER=()
    fi
}

function compute_local_sysinfos() {
    local SYSINFOS_DATA
    __compute_local_sysinfos_data
    __compute_sysinfos
    if [ -n "$UTOOLS_CHROOT" ]; then
        [ -n "$UTOOLS_SYSNAME" ] && eval "MYSYSNAME=($UTOOLS_SYSNAME)"
        [ -n "$UTOOLS_BITS" ] && eval "MYBITS=$UTOOLS_BITS"
        [ -n "$UTOOLS_SYSDIST" ] && eval "MYSYSDIST=($UTOOLS_SYSDIST)"
        [ -n "$UTOOLS_SYSVER" ] && eval "MYSYSVER=($UTOOLS_SYSVER)"
    fi
}
function compute_remote_sysinfos() {
    local SYSINFOS_DATA
    eval "$(__dump_remote_sysinfos_data "$@" | __build_sysinfos_data)"
    __compute_sysinfos
}

SYSINFOSLOCALS="\
local -a MYSYSNAME MYSYSDIST MYSYSVER
local MYBITS"
MYSYSNAME=()
MYBITS=
MYSYSDIST=()
MYSYSVER=()
compute_local_sysinfos

function __get_sysdist_alias() {
    if ! array_contains ALL_SYSDISTS "$1"; then
        local nd n d
        for nd in "${SYSDIST_ALIASES[@]}"; do
            splitvar "$nd" n d
            if [ "$n" == "$1" ]; then
                echo "$d"
                return
            fi
        done
    fi
    echo "$1"
}

function __get_sysver_alias() {
    if ! array_contains ALL_SYSVERS "$1"; then
        local nv n v
        for nv in "${SYSVER_ALIASES[@]}"; do
            splitvar "$nv" n v
            if [ "$n" == "$1" ]; then
                echo "$v"
                return
            fi
        done
    fi
    echo "$1"
}

function __fix_sysinfos_upward() {
    local sysname_ sysdists_ sysdist_ sysvers_ sysver_
    if [ -z "${!sysnamevar_}" ]; then
        if [ -z "${!sysdistvar_}" ]; then
            [ -z "${!sysvervar_}" ] && return
            for sysname_ in "${SYSNAMES[@]}"; do
                array_copy sysdists_ "${sysname_}_SYSDISTS"
                for sysdist_ in "${sysdists_[@]}"; do
                    array_copy sysvers_ "${sysdist_}_SYSVERS"
                    for sysver_ in "${sysvers_[@]}"; do
                        if [ "$sysver_" == "${!sysvervar_}" ]; then
                            _setv "$sysdistvar_" "$sysdist_"
                            _setv "$sysnamevar_" "$sysname_"
                            return
                        fi
                    done
                done
            done
        fi
        [ -z "${!sysdistvar_}" ] && return 0
        for sysname_ in "${SYSNAMES[@]}"; do
            array_copy sysdists_ "${sysname_}_SYSDISTS"
            for sysdist_ in "${sysdists_[@]}"; do
                if [ "$sysdist_" == "${!sysdistvar_}" ]; then
                    _setv "$sysnamevar_" "$sysname_"
                    return
                fi
            done
        done
    fi
}
function __fix_sysinfos_downward() {
    local sysname_ sysdist_ sysver_

    [ -z "${!sysnamevar_}" ] && return

    if [ -z "${!sysdistvar_}" ]; then
        array_copy sysdists_ "${!sysnamevar_}_SYSDISTS"
        for sysdist_ in "${sysdists_[@]}"; do
            _setv "$sysdistvar_" "$sysdist_"
            break
        done
    fi
    [ -z "${!sysdistvar_}" ] && return

    if [ -z "${!sysvervar_}" ]; then
        array_copy sysvers_ "${sysdistvar_}_SYSVERS"
        for sysver_ in "${sysvers_[@]}"; do
            _setv "$sysvervar_" "$sysver_"
            break
        done
    fi
}
function ensure_sysinfos() {
    local sysnamevar_="${1:-SYSNAME}"
    local sysdistvar_="${2:-SYSDIST}"
    local sysvervar_="${3:-SYSVER}"
    [ -n "${!sysdistvar_}" ] && _setv "$sysdistvar_" "$(__get_sysdist_alias "${!sysdistvar_}")"
    [ -n "${!sysvervar_}" ] && _setv "$sysvervar_" "$(__get_sysver_alias "${!sysvervar_}")"
    __fix_sysinfos_upward
    __fix_sysinfos_downward
}

function dump_sysinfos() {
    local sysname_="${1:-MYSYSNAME}[*]"
    local sysdist_="${2:-MYSYSDIST}[*]"
    local sysver_="${3:-MYSYSVER}[*]"
    echo "\
sysname=(${!sysname_})
sysdist=(${!sysdist_})
sysver=(${!sysver_})
bits=$MYBITS"
}

function get_sysinfos_desc() {
    local sysname_="${1:-MYSYSNAME}"; sysname_="${!sysname_}"
    local sysdist_="${2:-MYSYSDIST}"; sysdist_="${!sysdist_}"
    local sysver_="${3:-MYSYSVER}"; sysver_="${!sysver_}"
    echo "$sysname_${sysdist_:+/$sysdist_}${sysver_:+/$sysver_}"
}

function check_sysinfos() {
    local sysnamevar_ sysdistvar_ sysvervar_ bitsvar_
    if [ "$1" == --vars ]; then
        shift
        if [[ "$1" != -* ]]; then sysnamevar_="${1:-MYSYSNAME}"; shift; fi
        if [[ "$1" != -* ]]; then sysdistvar_="${1:-MYSYSDIST}"; shift; fi
        if [[ "$1" != -* ]]; then sysvervar_="${1:-MYSYSVER}"; shift; fi
        if [[ "$1" != -* ]]; then bitsvar_="${1:-MYBITS}"; shift; fi
    else
        sysnamevar_="MYSYSNAME"
        sysdistvar_="MYSYSDIST"
        sysvervar_="MYSYSVER"
        bitsvar_="MYBITS"
    fi

    local check_=sysname r_=0
    while [ -n "$1" ]; do
        if [[ "$1" == -* ]]; then
            [ "$1" == "-S" ] && { sysnamevar_="$2"; shift 2; continue; }
            [ "$1" == "-D" ] && { sysdistvar_="$2"; shift 2; continue; }
            [ "$1" == "-V" ] && { sysvervar_="$2"; shift 2; continue; }
            [ "$1" == "-B" ] && { bitsvar_="$2"; shift 2; continue; }
            [ "$r_" == "1" ] && break
            [ "$1" == "-s" ] && check_=sysname
            [ "$1" == "-d" ] && check_=sysdist
            [ "$1" == "-v" ] && check_=sysver
            [ "$1" == "-b" ] && check_=bits
            r_=1
            shift
            continue
        fi
        if [ "$check_" == "sysname" ]; then
            if array_contains "$sysnamevar_" "$1"; then
                r_=0
                check_=skip
            fi

        elif [ "$check_" == "sysdist" ]; then
            local mode_=exact value_="$1"
            if [ "${value_%+}" != "$value_" ]; then
                mode_=after
                value_="${value_%+}"
            elif [ "${value_%-}" != "$value_" ]; then
                mode_=before
                value_="${value_%-}"
            fi
            value_="$(__get_sysdist_alias "$value_")"
            if [ "$mode_" == "exact" ]; then
                if array_contains "$sysdistvar_" "$value_"; then
                    r_=0
                    check_=skip
                fi
            elif [ "$mode_" == "after" ]; then
                local sysdist_
                for sysdist_ in "${ALL_SYSDISTS[@]}"; do
                    if array_contains "$sysdistvar_" "$sysdist_"; then
                        r_=0
                        check_=skip
                        [ "$sysdist_" == "$value_" ] && break
                    elif [ "$sysdist_" == "$value_" ]; then
                        break
                    fi
                done
            elif [ "$mode_" == "before" ]; then
                local sysdist_ found_
                for sysdist_ in "${ALL_SYSDISTS[@]}"; do
                    [ "$sysdist_" == "$value_" ] && found_=1
                    if [ -n "$found_" ]; then
                        if array_contains "$sysdistvar_" "$sysdist_"; then
                            r_=0
                            check_=skip
                            break
                        fi
                    fi
                done
            fi

        elif [ "$check_" == "sysver" ]; then
            local mode_=exact value_="$1"
            if [ "${value_%+}" != "$value_" ]; then
                mode_=after
                value_="${value_%+}"
            elif [ "${value_%-}" != "$value_" ]; then
                mode_=before
                value_="${value_%-}"
            fi
            value_="$(__get_sysver_alias "$value_")"
            if [ "$mode_" == "exact" ]; then
                if array_contains "$sysvervar_" "$value_"; then
                    r_=0
                    check_=skip
                fi
            elif [ "$mode_" == "after" ]; then
                local sysver_
                for sysver_ in "${ALL_SYSVERS[@]}"; do
                    if array_contains "$sysvervar_" "$sysver_"; then
                        r_=0
                        check_=skip
                        [ "$sysver_" == "$value_" ] && break
                    elif [ "$sysver_" == "$value_" ]; then
                        break
                    fi
                done
            elif [ "$mode_" == "before" ]; then
                local sysver_ found_
                for sysver_ in "${ALL_SYSVERS[@]}"; do
                    [ "$sysver_" == "$value_" ] && found_=1
                    if [ -n "$found_" ]; then
                        if array_contains "$sysvervar_" "$sysver_"; then
                            r_=0
                            check_=skip
                            break
                        fi
                    fi
                done
            fi

        elif [ "$check_" == "bits" ]; then
            if [ "$1" == "${!bitsvar_}" ]; then
                r_=0
                check_=skip
            fi
        fi
        shift
    done
    return $r_
}

function unsupported_system() {
    local msg="Ce script n'est pas supporté sur $(get_sysinfos_desc)"
    [ -n "$*" ] && msg="$msg
Il faut au moins l'un des systèmes suivants: $*"
    die "$msg"
}

function require_sysinfos() {
    check_sysinfos "$@" && return 0
    local -a infos; local info
    for info in "$@"; do
        if ! [[ "$info" == -* ]]; then
            infos=("${infos[@]}" "$info")
        fi
    done
    unsupported_system "${infos[@]}"
}

function on_debian() {
    NUTOOLS_ON_DEBIAN=
    if check_sysinfos -d debian; then
        urequire debian
        if [ $# -gt 0 ]; then
            NUTOOLS_ON_DEBIAN=debian
            "$@"
        else
            NUTOOLS_ON_DEBIAN=1
        fi
        return 0
    else
        return 1
    fi
}
function on_debian:() { on_debian "$@"; }
function __on_debian() {
    [ -z "$NUTOOLS_ON_DEBIAN" -o "$NUTOOLS_ON_DEBIAN" != 1 ] && return 1
    local sysver="$1"; shift
    if [ $# -gt 0 ]; then
        if check_sysinfos -d debian -v "$sysver"; then
            NUTOOLS_ON_DEBIAN="$sysver"
            "$@"
            return 0
        else
            return 1
        fi
    else
        if check_sysinfos -d debian -v "$sysver+"; then
            NUTOOLS_ON_DEBIAN="$sysver"
            return 0
        fi
    fi
}

function on_stretch() { __on_debian stretch "$@"; }
function on_jessie() { __on_debian jessie "$@"; }
function on_wheezy() { __on_debian wheezy "$@"; }
function on_squeeze() { __on_debian squeeze "$@"; }
function on_default() {
    if [ "$NUTOOLS_ON_DEBIAN" == 1 ]; then
        if [ $# -gt 0 ]; then
            "$@"
            return 0
        else
            return 0
        fi
    elif [ -n "$NUTOOLS_ON_DEBIAN" ]; then
        return 1
    fi
    return 1
}
##@inc]../sysinfos
##@inc[../compat
# Code de support pour les architectures autre que Linux
##@require base
##@require sysinfos
uprovide compat
urequire base sysinfos

if check_sysinfos -s macosx; then
    function __rlnp() { local p="$1" np f; [ "${p#/}" == "$p" ] && p="$(pwd)/$p"; while [[ "$p" == *//* ]]; do p="${p//\/\///}"; done; p="${p%/}"; p="${p#/}"; np=; while [ -n "$p" ]; do if [[ "$p" == */* ]]; then f="${p%%/*}"; p="${p#*/}"; else f="$p"; p=; fi; if [ "$f" == . ]; then :; elif [ "$f" == .. ]; then if [[ "$np" == */* ]]; then np="${np%/*}"; else np=; fi; else [ -n "$np" ] && np="$np/"; np="$np$f"; fi; done; echo "/$np"; }
    function readlinkm() { local p="$(__rlnp "$1")" np n; while [ -n "$p" ]; do local max=50; while [ -L "$p" -a $max -gt 0 ]; do n="$(readlink "$p")"; if [ "${n#/}" != "$n" ]; then p="$n"; else p="${p%/*}/$n"; fi; p="$(__rlnp "$p")"; max=$(($max-1)); done; [ -n "$np" ] && np="/$np"; if [[ "$p" == */* ]]; then np="${p##*/}$np"; p="${p%/*}"; else np="$p$np"; p=; fi; done; echo "/$np"; }
    function _nl2lf() { awk '{ sub(/\r$/, ""); gsub(/\r/, "\n"); print }'; }
    function _nl2crlf() { _nl2lf | awk '{ print $0 "\r" }'; }
    function _nl2cr() { _nl2lf | awk 'BEGIN { ORS="" } { print $0 "\r" }'; }
    function sedi() { sed -i '' "$@"; }

    function __po_check_options() {
        local -a options args
        local option value flag
        if [ "${opts_#+}" != "$opts_" ]; then
            while [ -n "$*" ]; do
                if [ "$1" == "--" ]; then
                    shift
                    break
                elif [[ "$1" == --* ]]; then
                    option="${1%%=*}"
                    if flag="$(array_find options_ "$option" flags_)"; then
                        if [[ "$flag" == ::* ]]; then
                            if [[ "$1" == *=* ]]; then
                                value="${1#--*=}"
                            else
                                value=
                            fi
                            shift
                            options=("${options[@]}" "$option" "$value")
                        elif [[ "$flag" == :* ]]; then
                            if [[ "$1" == *=* ]]; then
                                value="${1#--*=}"
                                shift
                            elif [ $# -gt 1 ]; then
                                value="$2"
                                shift 2
                            else
                                echo "option requires an argument: $option"
                                return 1
                            fi
                            options=("${options[@]}" "$option" "$value")
                        else
                            shift
                            options=("${options[@]}" "$option")
                        fi
                    else
                        echo "invalid option: $1"
                        return 1
                    fi

                elif [[ "$1" == -* ]]; then
                    option="${1:0:2}"
                    if flag="$(array_find options_ "$option" flags_)"; then
                        if [[ "$flag" == ::* ]]; then
                            value="${1:2}"
                            shift
                            options=("${options[@]}" "$option" "$value")
                        elif [[ "$flag" == :* ]]; then
                            if [[ -n "${1:2}" ]]; then
                                value="${1:2}"
                                shift
                            elif [ $# -gt 1 ]; then
                                value="$2"
                                shift 2
                            else
                                echo "option requires an argument: $option"
                                return 1
                            fi
                            options=("${options[@]}" "$option" "$value")
                        else
                            shift
                            options=("${options[@]}" "$option")
                        fi
                    else
                        echo "invalid option: $1"
                        return 1
                    fi

                else
                    break
                fi
            done
            args=("$@")
        elif [ "${opts_#-}" != "$opts_" ]; then
            while [ -n "$*" ]; do
                if [ "$1" == "--" ]; then
                    shift
                    break
                elif [[ "$1" == --* ]]; then
                    option="${1%%=*}"
                    if flag="$(array_find options_ "$option" flags_)"; then
                        if [[ "$flag" == ::* ]]; then
                            if [[ "$1" == *=* ]]; then
                                value="${1#--*=}"
                            else
                                value=
                            fi
                            shift
                            options=("${options[@]}" "$option" "$value")
                        elif [[ "$flag" == :* ]]; then
                            if [[ "$1" == *=* ]]; then
                                value="${1#--*=}"
                                shift
                            elif [ $# -gt 1 ]; then
                                value="$2"
                                shift 2
                            else
                                echo "option requires an argument: $option"
                                return 1
                            fi
                            options=("${options[@]}" "$option" "$value")
                        else
                            shift
                            options=("${options[@]}" "$option")
                        fi
                    else
                        echo "invalid option: $1"
                        return 1
                    fi

                elif [[ "$1" == -* ]]; then
                    option="${1:0:2}"
                    if flag="$(array_find options_ "$option" flags_)"; then
                        if [[ "$flag" == ::* ]]; then
                            value="${1:2}"
                            shift
                            options=("${options[@]}" "$option" "$value")
                        elif [[ "$flag" == :* ]]; then
                            if [[ -n "${1:2}" ]]; then
                                value="${1:2}"
                                shift
                            elif [ $# -gt 1 ]; then
                                value="$2"
                                shift 2
                            else
                                echo "option requires an argument: $option"
                                return 1
                            fi
                            options=("${options[@]}" "$option" "$value")
                        else
                            shift
                            options=("${options[@]}" "$option")
                        fi
                    else
                        echo "invalid option: $1"
                        return 1
                    fi

                else
                    options=("${options[@]}" "$1")
                    shift
                fi
            done
            args=("$@")
        else
            while [ -n "$*" ]; do
                if [ "$1" == "--" ]; then
                    shift
                    break
                elif [[ "$1" == --* ]]; then
                    option="${1%%=*}"
                    if flag="$(array_find options_ "$option" flags_)"; then
                        if [[ "$flag" == ::* ]]; then
                            if [[ "$1" == *=* ]]; then
                                value="${1#--*=}"
                            else
                                value=
                            fi
                            shift
                            options=("${options[@]}" "$option" "$value")
                        elif [[ "$flag" == :* ]]; then
                            if [[ "$1" == *=* ]]; then
                                value="${1#--*=}"
                                shift
                            elif [ $# -gt 1 ]; then
                                value="$2"
                                shift 2
                            else
                                echo "option requires an argument: $option"
                                return 1
                            fi
                            options=("${options[@]}" "$option" "$value")
                        else
                            shift
                            options=("${options[@]}" "$option")
                        fi
                    else
                        echo "invalid option: $1"
                        return 1
                    fi

                elif [[ "$1" == -* ]]; then
                    option="${1:0:2}"
                    if flag="$(array_find options_ "$option" flags_)"; then
                        if [[ "$flag" == ::* ]]; then
                            value="${1:2}"
                            shift
                            options=("${options[@]}" "$option" "$value")
                        elif [[ "$flag" == :* ]]; then
                            if [[ -n "${1:2}" ]]; then
                                value="${1:2}"
                                shift
                            elif [ $# -gt 1 ]; then
                                value="$2"
                                shift 2
                            else
                                echo "option requires an argument: $option"
                                return 1
                            fi
                            options=("${options[@]}" "$option" "$value")
                        else
                            shift
                            options=("${options[@]}" "$option")
                        fi
                    else
                        echo "invalid option: $1"
                        return 1
                    fi

                else
                    args=("${args[@]}" "$1")
                    shift
                fi
            done
            args=("${args[@]}" "$@")
        fi
        qvals "${options[@]}" -- "${args[@]}"
        return 0
    }

    function __pd_isleap() {
        [ $(($1 % 4)) -eq 0 -a \( $(($1 % 100)) -ne 0 -o $(($1 % 400)) -eq 0 \) ]
    }
    function __pd_fix_month() {
        local __pdfm_y="${!1}" __pdfm_m="${!2}"
        let __pdfm_m=$__pdfm_m-1
        while [ $__pdfm_m -gt 11 ]; do
            let __pdfm_m=$__pdfm_m-12
            let __pdfm_y=$__pdfm_y+1
        done
        while [ $__pdfm_m -lt 0 ]; do
            let __pdfm_m=$__pdfm_m+12
            let __pdfm_y=$__pdfm_y-1
        done
        let __pdfm_m=$__pdfm_m+1
        eval "$1=$__pdfm_y; $2=$__pdfm_m"
    }
    __PD_MONTHDAYS=(0 31 28 31 30 31 30 31 31 30 31 30 31)
    function __pd_monthdays() {
        local y="$1" m="$2" mds
        __pd_fix_month y m
        mds="${__PD_MONTHDAYS[$m]}"
        [ "$m" -eq 2 ] && __pd_isleap "$y" && let mds=$mds+1
        echo $mds
    }
    function __pd_fix_day() {
        local __pdfd_y="${!1}" __pdfd_m="${!2}" __pdfd_d="${!3}" __pdfd_mds
        let __pdfd_d=$__pdfd_d-1
        let __pdfd_mds=$(__pd_monthdays $__pdfd_y $__pdfd_m)
        while [ $__pdfd_d -gt $(($__pdfd_mds-1)) ]; do
            let __pdfd_d=$__pdfd_d-$__pdfd_mds
            let __pdfd_m=$__pdfd_m+1
            __pd_fix_month __pdfd_y __pdfd_m
            let __pdfd_mds=$(__pd_monthdays $__pdfd_y $__pdfd_m)
        done
        while [ $__pdfd_d -lt 0 ]; do
            let __pdfd_m=$__pdfd_m-1
            __pd_fix_month __pdfd_y __pdfd_m
            let __pdfd_d=$__pdfd_d-$(__pd_monthdays $__pdfd_y $__pdfd_m)
        done
        let __pdfd_d=$__pdfd_d+1
        eval "$1=$__pdfd_y; $2=$__pdfd_m; $3=$__pdfd_d"
    }
    function __pd_fix_date() {
        local __pdf_y="${!1}" __pdf_m="${!2}" __pdf_d="${!3}"
    }
    function parse_date() {
        local value="$1" type="${2:-date}"
        local d m y
        eval "$(date +%d/%m/%Y | awk -F/ '{
            print "d=" $1 "; m=" $2 "; y=" $3
        }')"
        if [ "${value#+}" != "$value" ]; then
            d="$(($d+${value#+}))"
        else
            eval "$(<<<"$value" awkrun FS=/ dn="$dn" mn="$mn" yn="$yn" type="$type" '{
                d = $1 + 0; if (d < 1) d = dn + 0;
                m = $2 + 0; if (m < 1) m = mn + 0;
                if ($3 == "") y = yn + 0;
                else { y = $3 + 0; if (y < 100) y = y + 2000; }
                print "d=" d "; m=" m "; y=" y
            }')"
        fi
        __pd_fix_month y m
        __pd_fix_day y m d
        case "$type" in
        d|date)
            awkrun d="$d" m="$m" y="$y" 'BEGIN { printf "%02i/%02i/%04i\n", d, m, y }'
            ;;
        l|ldap)
            awkrun d="$d" m="$m" y="$y" 'BEGIN { printf "%04i%02i%02i000000+0400\n", y, m, d }'
            ;;
        esac
    }
    function myhost() {
        hostname
    }
    function myhostname() {
        hostname -s
    }
fi
##@inc]../compat

user="${1:-$USER}"
method="$2"

case "$method" in
su) UTOOLS_USES_SU=1;;
sudo) UTOOLS_USES_SU=;;
esac
export UTOOLS_USES_SU

if [ "$user" != "$USER" ]; then
    is_root || run_as_root "$@"
    if [ "$user" != "root" ]; then
        run_as "$user" "$@"
    fi
fi

autoclean "$script"

eval "cd ~$user"; mkdir -p .ssh; chmod 700 .ssh
cd .ssh; touch authorized_keys; chmod 600 authorized_keys
echo "$PUBKEYS" | while read pubkey; do
    quietgrep "$pubkey" authorized_keys ||
    echo "$pubkey" >>authorized_keys
done
