##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
## Fonctions "récupérées" de utools, pas encore classées ou réécrites, mais
## gardées pour compatibilité.
##@cooked nocomments
##@require base
uprovide legacy
urequire base

function file_get_vars() {
    # lire les variables dans un fichier
    local OENC="$UTF8"
    local done_ prefix_ whole_file_ file_ vars_ var_ script_

    # traiter les arguments
    done_=
    while [ -z "$done_" ]; do
        case "$1" in
        --prefix|-p)
            # prefixe pour la variable
            prefix_="$2"
            shift; shift
            ;;
        --whole-file|-w)
            # lire les variables dans le fichier en entier, et pas seulement
            # dans l'en-tête.
            whole_file_=1
            shift
            ;;
        *)
            done_=1
            ;;
        esac
    done

    # obtenir le nom du fichier
    file_="$1"; shift
    if [ ! -f "$file_" ]; then
        # fichier inexistant
        ewarn "Fichier inexistant: $file_"
        return 1
    fi

    # initialiser les valeurs par défaut
    vars_=
    while [ -n "$1" ]; do
        var_="$1"; shift
        vars_="${vars_:+$vars_ }$var_"
        _setv "$var_" "$1"; shift
    done

    # puis parcourir le fichier pour initialiser la valeur définitive des
    # variables
    if [ -z "$whole_file_" ]; then
        script_="/^ *$/ { exit }
"
    fi

    for var_ in $vars_; do
        script_="$script_
"'$0 ~ "^ *#* *" prefix "'"$var_"'=" {
    # enlever les caractères inutiles
    sub(" *#* *" prefix "'"$var_"'=", "")
    # enlever éventuellement les quotes autour de la valeur
    if ($0 ~ /^".*" *$/) {
        $0 = substr($0, 2) # premier quote
        match($0, /" *$/)
        $0 = substr($0, 1, RSTART - 1) # dernier quote
    }
    # remplacer dans les valeurs les occurences de quotes
    gsub("\"", "\\\"")
    # afficher la ligne à évaluer
    print "'"$var_"'=\"" $0 "\""
}
'
    done

    eval "$(awkrun prefix="$prefix_" "$script_" <"$file_")"
}

function file_set_vars() {
    # écrire les variables dans un fichier. Le fichier *doit exister*
    local OENC="$UTF8"
    local done_ quote_ comment_ prefix_ whole_file_ file_ var_ script_

    # traiter les arguments
    done_=
    while [ -z "$done_" ]; do
        case "$1" in
        --quote-always|-q)
            # toujours mettre les valeurs entre quotes
            quote_=1
            shift
            ;;
        --comment-prefix|-c)
            # commentaire à préfixer
            comment_="$2"
            shift; shift
            ;;
        --prefix|-p)
            # prefixe pour la variable
            prefix_="$2"
            shift; shift
            ;;
        --whole-file|-w)
            # écrire les variables dans le fichier en entier, et pas seulement
            # dans l'en-tête.
            whole_file_=1
            shift
            ;;
        *)
            done_=1
            ;;
        esac
    done

    # obtenir le nom du fichier
    file_="$1"; shift
    if [ ! -f "$file_" ]; then
        # fichier inexistant
        ewarn "Fichier inexistant: $file_"
        return 1
    fi

    # puis parcourir le fichier pour mettre à jour les valeurs
    script_='BEGIN {
    # faut-il mettre à jour les variables?
    update_vars = 1'
    for var_ in "$@"; do
        script_="$script_
    ${var_}_done = 0"
    done
    script_="$script_
}"

    script_="$script_"'
function quote_value_maybe(value) {
    if (quote_always || index(value, " ") != 0) {
        return "\"" value "\""
    } else {
        return value
    }
}

function write_all_remaining_vars() {'
    for var_ in "$@"; do
        value="${!var_}"
        script_="$script_"'
    if (! '"$var_"'_done) {
        print comment prefix "'"$var_"'=" quote_value_maybe("'"${value//\"/\\\"}"'")
        '"$var_"'_done = 1
    }'
    done
    script_="$script_
}"

    if [ -z "$whole_file_" ]; then
        script_="$script_"'
/^[ \t]*$/ {
    write_all_remaining_vars()
    update_vars = 0
}'
    fi

    script_="$script_"'
update_vars && comment == "" && $0 ~ "^ *#* *.*=.*$" {
    #comment = gensub("^( *#* *).*=.*$", "\\1", 1)
    comment = ""
    if (match($0, /^ *#* */) != 0) {
        comment = substr($0, RSTART, RLENGTH)
    }
}'

    for var_ in "$@"; do
        value="${!var_}"
        script_="$script_"'
update_vars && ! '"$var_"'_done && $0 ~ "^ *#* *" prefix "'"$var_"'=" {
    #$0 = gensub("^( *#* *" prefix "'"$var_"'=).*$", "\\1", 1)
    match($0, "^ *#* *" prefix "'"$var_"'=")
    $0 = substr($0, RSTART, RLENGTH)
    $0 = $0 quote_value_maybe("'"${value//\"/\\\"}"'")
    print
    '"$var_"'_done = 1
    next
}'
    done

    script_="$script_"'
{
    print
}
END {
    if (update_vars) {
        write_all_remaining_vars()
    }
}'

    doinplace "$file_" awkrun quote_always="$quote_" comment="$comment_" prefix="$prefix_" "$script_"
}

function file_get_properties() {
    # lire les propriétés d'un fichier de propriété java ou xml
    if endswith "$1" .xml; then
        file_get_xml_properties "$@"
    else
        file_get_java_properties "$@"
    fi
}

function file_set_properties() {
    # écrire les propriétés d'un fichier de propriété java ou xml
    local done_ create_
    while [ -z "$done_" ]; do
        case "$1" in
        --create|-c)
            create_=1
            shift
            ;;
        *)
            done_=1
            ;;
        esac
    done
    if endswith "$1" .xml; then
        file_set_xml_properties ${create_:+-c} "$@"
    else
        file_set_java_properties ${create_:+-c} "$@"
    fi
}


function file_get_java_properties() {
    # lire les propriétés d'un fichier de propriétés java. note: les noms de
    # propriété java peuvent contenir le caractère "." mais pas les noms de
    # variable bash. La conversion est faite automatiquement. Par exemple::
    #    file_get_properties build.properties path.to.package "default value"
    # charge la valeur de la propriété dans la variable path_to_package

    # $1=nom du fichier de propriété
    # $2..n=propriétés qu'il faut lire et valeurs par défaut de ces propriétés
    #   $__2*i  __=nom de la propriété
    #   $__2*i+1__=valeur par défaut de la propriété si la valeur n'existe pas
    #              dans le fichier
    local OENC="$UTF8"
    local file_="$1"; shift
    if [ ! -f "$file_" ]; then
        # fichier inexistant
        ewarn "Fichier de propriété inexistant: $file_"
        return 1
    fi

    local var_ sh_var_ awk_var_
    local script
    while [ -n "$1" ]; do
        # pour chacune des variables...
        var_="$1"; shift
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        awkre_var_="${var_//./\\.}" # nom de la variable pour une expression régulière awk

        # initialiser la valeur par défaut
        _setv "$sh_var_" "$1"; shift

        # et créer le script qui affichera sa valeur
        script="$script"'
$0 ~ "^[ \t]*'"$(_qawk "$awkre_var_")"'=" {
    # enlever les caractères de début
    sub("^[ \t]*'"$(_qawk "$awkre_var_")"'=", "")
    value = $0
    # éventuellement ajouter les lignes de continuation
    while (substr(value, length(value), 1) == "\\") {
        getline
        sub("^[ \t]*", "")
        value = substr(value, 1, length(value) - 1) $0
    }
    gsub("\"", "\\\"", value)
    print "'"$sh_var_"'=\"" value "\""
}
'
    done

    eval "$(awk "$script" <"$file_")"
}

function file_set_java_properties() {
    # écrire des propriétés dans un fichier de propriétés java.

    # $1=nom du fichier de propriété
    # $2..n=propriétés qu'il faut écrire et valeurs de ces propriétés
    #   $__2*i  __=nom de la propriété
    #   $__2*i+1__=valeur de la propriété
    # traiter les arguments
    local OENC="$UTF8"
    local done_ create_
    while [ -z "$done_" ]; do
        case "$1" in
        --create|-c)
            # créer le fichier s'il n'existe pas
            create_=1
            shift
            ;;
        *)
            done_=1
            ;;
        esac
    done

    local file_="$1"; shift
    if [ ! -f "$file_" ]; then
        if [ -n "$create_" ]; then
            touch "$file_"
        else
            # fichier inexistant
            ewarn "Fichier de propriété inexistant: $file_"
            return 1
        fi
    fi

    # récupérer les noms des propriétés et leur valeur
    local var_ arg_ sh_var_ awkre_var_ value_
    local -a vars_ values_
    value_=vars_
    for arg_ in "$@"; do
        array_add "$value_" "$arg_"
        if [ "$value_" == "vars_" ]; then
            value_=values_
        else
            value_=vars_
        fi
    done

    # créer le script qui va parcourir le fichier pour mettre à jour les valeurs
    script_="BEGIN {"
    for var_ in "${vars_[@]}"; do
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        script_="$script_
    ${sh_var_}_done = 0"
    done
    script_="$script_"'
}
function write_all_remaining_vars() {'
    local i=0
    while [ $i -lt ${#vars_[*]} ]; do
        var_="${vars_[$i]}"
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        awkre_var_="${var_//./\\.}" # nom de la variable pour une expression régulière awk
        value_="${values_[$i]}"

        script_="$script_"'
    if (! '"$sh_var_"'_done) {
        print "'"$var_"'=" "'"${value_//\"/\\\"}"'"
        '"$sh_var_"'_done = 1
    }'
        i=$((i + 1))
    done
    script_="$script_
}"

    local i=0
    while [ $i -lt ${#vars_[*]} ]; do
        var_="${vars_[$i]}"
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        awkre_var_="${var_//./\\.}" # nom de la variable pour une expression régulière awk
        value_="${values_[$i]}"
        script_="$script_"'
! '"$sh_var_"'_done && $0 ~ "^[ \t]*'"$awkre_var_"'=" {
    #name = gensub("^([ \t]*'"$awkre_var_"'=).*$", "\\1", 1)
    match($0, "^[ \t]*'"$awkre_var_"'=")
    name = substr($0, RSTART, RLENGTH)
    value = substr($0, length(name) + 1)

    while (substr(value, length(value), 1) == "\\") {
        getline
        value = value $0
    }
    line = name "'"${value_//\"/\\\"}"'"
    prefix = ""
    max_len = 75
    if (length(line) > max_len) {
        do {
            print prefix substr(line, 1, max_len) "\\"
            line = substr(line, max_len + 1)
            prefix = "    "
            max_len = 71
        } while (length(line) > max_len)
    }
    print prefix line
    '"$sh_var_"'_done = 1
    next
}'
        i=$((i + 1))
    done

    script_="$script_
{
    print
}
END {
    write_all_remaining_vars()
}"

    doinplace "$file_" awk "$script_"
}

function file_get_xml_properties() {
    # lire les propriétés d'un fichier de propriétés xml. Limitation: les
    # propriétés ne doivent pas être continuées sur plusieurs lignes. Les
    # propriétés doivent être écrites sous la forme::
    #    <propname>propvalue</propname>

    # note: les noms de propriété java peuvent contenir le caractère "." mais
    # pas les noms de variable bash. La conversion est faite
    # automatiquement. Par exemple::
    #    file_get_properties build.properties path.to.package "default value"
    # charge la valeur de la propriété dans la variable path_to_package

    # $1=nom du fichier de propriété
    # $2..n=propriétés qu'il faut lire et valeurs par défaut de ces propriétés
    #   $__2*i  __=nom de la propriété
    #   $__2*i+1__=valeur par défaut de la propriété si la valeur n'existe pas
    #              dans le fichier
    local OENC="$UTF8"
    local file_="$1"; shift
    if [ ! -f "$file_" ]; then
        # fichier inexistant
        ewarn "Fichier de propriété inexistant: $file_"
        return 1
    fi

    local var_ sh_var_ awk_var_
    local script
    while [ -n "$1" ]; do
        # pour chacune des variables...
        var_="$1"; shift
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        awkre_var_="${var_//./\\.}" # nom de la variable pour une expression régulière awk

        # initialiser la valeur par défaut
        _setv "$sh_var_" "$1"; shift

        # et créer le script qui affichera sa valeur
        script="$script"'
$0 ~ /^[ \t]*<'"$awkre_var_"'>.*<\/'"$awkre_var_"'>/ {
    sub(/^[ \t]*<'"$awkre_var_"'>/, "")
    sub(/<\/'"$awkre_var_"'>.*$/, "")
    gsub("\"", "\\\"", $0)
    print "'"$sh_var_"'=\"" $0 "\""
}
'
    done

    eval "$(awk "$script" <"$file_")"
}

function file_set_xml_properties() {
    # écrire des propriétés dans un fichier de propriétés java.

    # $1=nom du fichier de propriété
    # $2..n=propriétés qu'il faut écrire et valeurs de ces propriétés
    #   $__2*i  __=nom de la propriété
    #   $__2*i+1__=valeur de la propriété
    # traiter les arguments
    local OENC="$UTF8"
    local done_ create_
    while [ -z "$done_" ]; do
        case "$1" in
        --create|-c)
            # créer le fichier s'il n'existe pas
            create_=1
            shift
            ;;
        *)
            done_=1
            ;;
        esac
    done

    local file_="$1"; shift
    if [ ! -f "$file_" ]; then
        if [ -n "$create_" ]; then
            touch "$file_"
        else
            # fichier inexistant
            ewarn "Fichier de propriété inexistant: $file_"
            return 1
        fi
    fi

    # récupérer les noms des propriétés et leur valeur
    local var_ arg_ sh_var_ awkre_var_ value_
    local -a vars_ values_
    value_=vars_
    for arg_ in "$@"; do
        array_add "$value_" "$arg_"
        if [ "$value_" == "vars_" ]; then
            value_=values_
        else
            value_=vars_
        fi
    done

    # créer le script qui va parcourir le fichier pour mettre à jour les valeurs
    script_='BEGIN {
    rootElement = ""'
    for var_ in "${vars_[@]}"; do
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        script_="$script_
    ${sh_var_}_done = 0"
    done
    script_="$script_"'
}
function write_all_remaining_vars() {'
    local i=0
    while [ $i -lt ${#vars_[*]} ]; do
        var_="${vars_[$i]}"
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        awkre_var_="${var_//./\\.}" # nom de la variable pour une expression régulière awk
        value_="${values_[$i]}"

        script_="$script_"'
    if (! '"$sh_var_"'_done) {
        print "<'"$var_"'>'"${value_//\"/\\\"}"'</'"$var_"'>"
        '"$sh_var_"'_done = 1
    }'
        i=$((i + 1))
    done
    script_="$script_
}"'
rootElement == "" {
    match($0, /<.*>/)
    element = substr($0, RSTART + 1, RLENGTH - 2)
    firstChar = substr(element, 1, 1)
    if (firstChar != "?" && firstChar != "!") {
        rootElement = element
    }
}'

    local i=0
    while [ $i -lt ${#vars_[*]} ]; do
        var_="${vars_[$i]}"
        sh_var_="${var_//./_}"    # nom de la variable shell traduite ("." --> "_")
        sh_var_="${sh_var_//-/_}" #                                   ("-" --> "_")
        awkre_var_="${var_//./\\.}" # nom de la variable pour une expression régulière awk
        value_="${values_[$i]}"
        script_="$script_"'
rootElement != "" && ! '"$sh_var_"'_done && $0 ~ /^[ \t]*<'"$awkre_var_"'>.*<\/'"$awkre_var_"'>/ {
    match($0, /^[ \t]*<'"$awkre_var_"'>/)
    first = substr($0, RSTART, RLENGTH)
    value = substr($0, length(first) + 1)
    match(value, /<\/'"$awkre_var_"'>.*$/)
    last = substr(value, RSTART, RLENGTH)
    value = substr(value, 1, RSTART)

    print first "'"${value_//\"/\\\"}"'" last
    '"$sh_var_"'_done = 1
    next
}'
        i=$((i + 1))
    done

    script_="$script_"'
rootElement != "" && $0 ~ "</" rootElement ">" {
    rootElement = ""
    write_all_remaining_vars()
}
{
    print
}
END {
    write_all_remaining_vars()
}'

    doinplace "$file_" awk "$script_"
}
