From d9266be21b6169291a08eb203b284bef9db3e70c Mon Sep 17 00:00:00 2001 From: Jephte CLAIN Date: Wed, 17 Sep 2014 10:53:12 +0400 Subject: [PATCH] =?UTF-8?q?commencer=20le=20d=C3=A9coupage=20fin=20de=20ba?= =?UTF-8?q?se=20en=20sous-modules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pyulib/src/ulib/p/uinc/updater.py | 35 ++- lib/ulib/.ulibver | 2 +- lib/ulib/base | 417 +++----------------------- lib/ulib/base.array | 5 + lib/ulib/base.compat | 35 +++ lib/ulib/base.core | 280 +++++++++++++++++ lib/ulib/base.init | 36 +++ lib/ulib/base.string | 56 ++++ lib/ulib/base.ulib | 32 ++ lib/ulib/compat | 26 -- lib/ulib/support/install-pubkeys.sh | 192 +++++++----- lib/ulib/ulib | 59 ++-- lib/ulib/ulibsh | 50 +-- ucrontab | 192 +++++++----- 14 files changed, 806 insertions(+), 611 deletions(-) create mode 100644 lib/ulib/base.array create mode 100644 lib/ulib/base.compat create mode 100644 lib/ulib/base.core create mode 100644 lib/ulib/base.init create mode 100644 lib/ulib/base.string create mode 100644 lib/ulib/base.ulib diff --git a/lib/pyulib/src/ulib/p/uinc/updater.py b/lib/pyulib/src/ulib/p/uinc/updater.py index f9291b7..d138cd0 100644 --- a/lib/pyulib/src/ulib/p/uinc/updater.py +++ b/lib/pyulib/src/ulib/p/uinc/updater.py @@ -62,6 +62,9 @@ class IncLine(object): //@ ''@ + Note: le caractère d'inclusion '@*' existe aussi, mais il est particulier: + une fois déplié, il ne peut pas être replié. C'est la propriété locked. + Une fois qu'un type de ligne de commentaire est reconnue, toutes les lignes de directives suivantes doivent être de ce type. @@ -183,6 +186,8 @@ class IncLine(object): # après analyse d'une ligne, indentation et commentaire avant la directive _prefix, prefix = make_prop('_prefix', None)[:2] + # après analyse d'une ligne, est-ce une inclusion verrouillée? + _locked, locked = make_prop('_locked', None)[:2] # après analyse d'une ligne, nom de la directive _action, action = make_prop('_action', None)[:2] # après analyse d'une ligne, arguments de la directive @@ -192,11 +197,11 @@ class IncLine(object): il_pattern = r'(.*)' # prefix if c in ('*', '@'): self._c = self._orig_c = c - il_pattern += r'(?:@|\*)' + il_pattern += r'((?:@|\*)\*?)' else: self._orig_c = None self._c = '@' - il_pattern += r'@' + il_pattern += r'(@\*?)' # action il_pattern += r'(%s)' % '|'.join([self._RE_SPECIAL.sub(r'\\\1', action) for action in self.ACTIONS]) @@ -221,10 +226,11 @@ class IncLine(object): mo = self._re_il.match(line) if mo is not None: self._prefix = mo.group(1) + self._locked = mo.group(2) in ('@*', '**') if self.is_prefix(self._prefix): - self._action = mo.group(2) - spaces = mo.group(3) - self._args = mo.group(4) + self._action = mo.group(3) + spaces = mo.group(4) + self._args = mo.group(5) if self._NO_SPACES.get(self._action, False): # il ne doit pas y avoir d'espaces entre cette directive et # son argument @@ -234,6 +240,7 @@ class IncLine(object): # argument if self._RE_SPACES.match(spaces): return True self._prefix = None + self._locked = None self._action = None self._args = None return False @@ -246,24 +253,28 @@ class IncLine(object): def is_provide(self): return self._action == self.PROVIDE def is_cooked(self): return self._action == self.COOKED + def __c_or_locked(self): + if self._locked: return '@*' + else: return self._c + def get_include(self, name=None): if name is None: name = self._args - return self.TEMPLATES[self.INCLUDE] % (self._prefix, self._c, name) + return self.TEMPLATES[self.INCLUDE] % (self._prefix, self.__c_or_locked(), name) def get_start_inc(self, name=None): if name is None: name = self._args - return self.TEMPLATES[self.START_INC] % (self._prefix, self._c, name) + return self.TEMPLATES[self.START_INC] % (self._prefix, self.__c_or_locked(), name) def get_end_inc(self, name=None): if name is None: name = self._args - return self.TEMPLATES[self.END_INC] % (self._prefix, self._c, name) + return self.TEMPLATES[self.END_INC] % (self._prefix, self.__c_or_locked(), name) def get_require(self, name=None): if name is None: name = self._args - return self.TEMPLATES[self.REQUIRE] % (self._prefix, self._c, name) + return self.TEMPLATES[self.REQUIRE] % (self._prefix, self.__c_or_locked(), name) def get_provide(self, name=None): if name is None: name = self._args - return self.TEMPLATES[self.PROVIDE] % (self._prefix, self._c, name) + return self.TEMPLATES[self.PROVIDE] % (self._prefix, self.__c_or_locked(), name) def get_cooked(self, args=None): if args is None: args = self._args - return self.TEMPLATES[self.COOKED] % (self._prefix, self._c, args) + return self.TEMPLATES[self.COOKED] % (self._prefix, self.__c_or_locked(), args) class Env(object): """Un environnement pour plier ou déplier un fichier. @@ -515,7 +526,7 @@ class File(Resource): if not folding: ## nous ne somme pas encore dans une section à replier # soit nous débutons une section à replier - if il.is_start_inc(): + if il.is_start_inc() and not il.locked: folding = True incindex = index name = il.args diff --git a/lib/ulib/.ulibver b/lib/ulib/.ulibver index 2584705..62f0127 100644 --- a/lib/ulib/.ulibver +++ b/lib/ulib/.ulibver @@ -1 +1 @@ -002004000 +003000000 diff --git a/lib/ulib/base b/lib/ulib/base index b312d60..24e9e14 100644 --- a/lib/ulib/base +++ b/lib/ulib/base @@ -1,361 +1,43 @@ ##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ## Fonctions de base ##@cooked nocomments - -# Emplacement du script courant -if [ -n "$UTOOLS_HAVE_SCRIPTVARS" ]; then - # ne pas mettre à jour script, scriptname, scriptdir. Ils ont déjà été - # calculés - : -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}" - -# Repertoire temporaire -[ -z "$TMPDIR" -a -d "$HOME/tmp" ] && TMPDIR="$HOME/tmp" -export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}" - -# User -[ -z "$USER" -a -n "$LOGNAME" ] && export USER="$LOGNAME" - -# Le fichier nutoolsrc doit être chargé systématiquement -[ -f /etc/nutoolsrc ] && . /etc/nutoolsrc -[ -f ~/.nutoolsrc ] && . ~/.nutoolsrc - -################################################################################ -## core -function recho() { -# afficher une valeur brute. contrairement à la commande echo, ne reconnaitre -# aucune option (i.e. -e, -E, -n ne sont pas signifiants) - if [[ "${1:0:2}" == -[eEn] ]]; then - echo -n - - local first="${1:1}"; shift - echo "$first$@" - else - echo "$@" - fi -} -function recho_() { -# afficher une valeur brute, sans passer à la ligne. contrairement à la commande -# echo, ne reconnaitre aucune option (i.e. -e, -E, -n ne sont pas signifiants) - if [[ "${1:0:2}" == -[eEn] ]]; then - echo -n - - local first="${1:1}"; shift - echo -n "$first$@" - else - echo -n "$@" - fi -} -function _qval() { -# Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \` -# Cela permet de quoter une chaine à mettre entre guillements. -# Note: la protection de ! n'est pas effectuée, parce que le comportement du -# shell est incohérent entre le shell interactif et les scripts. Pour une -# version plus robuste, il est nécessaire d'utiliser un programme externe tel -# que sed ou awk - local s="$*" - s="${s//\\/\\\\}" - s="${s//\"/\\\"}" - s="${s//\$/\\\$}" - s="${s//\`/\\\`}" - recho_ "$s" -} -function qval() { -# Afficher la chaine $* quotée avec " - echo -n \" - _qval "$@" - echo \" -} -function qvalr() { -# Afficher la chaine $* quotée avec ", sauf si elle est vide - if [ -n "$*" ]; then - echo -n \" - _qval "$@" - echo n \" - fi -} -function should_quote() { -# Tester si la chaine $* doit être mise entre quotes - [ -z "$1" ] && return 0 - local s="${*//[a-zA-Z0-9]/}" - s="${s//,/}" - s="${s//./}" - s="${s//+/}" - s="${s//\//}" - s="${s//-/}" - s="${s//_/}" - s="${s//=/}" - [ -n "$s" ] -} -function qvals() { -# Afficher chaque argument de cette fonction quotée le cas échéant avec " -# Chaque valeur est séparée par un espace. - 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 -} -function qlines() { -# Traiter chaque ligne de l'entrée standard pour en faire des chaines quotées -# avec ' - sed "s/'/'\\\\''/g; s/.*/'&'/g" -} -function setv() { -# initialiser la variable $1 avec la valeur "$2..*" -# note: en principe, la syntaxe est 'setv var values...'. cependant, la -# syntaxe 'setv var=values...' est supportée aussi - local __s_var="$1"; shift - if [[ "$__s_var" == *=* ]]; then - set -- "${__s_var#*=}" "$@" - __s_var="${__s_var%%=*}" - fi - eval "$__s_var=\"$(_qval "$*")\"" -} -function _setv() { -# Comme la fonction setv() mais ne supporte que la syntaxe '_setv var values...' -# Cette fonction est légèrement plus rapide que setv() - local __s_var="$1"; shift - eval "$__s_var=\"$(_qval "$*")\"" -} -function setx() { -# syntaxe 1: setx var cmd -# initialiser la variable $1 avec le résultat de la commande "$2..@" -# note: en principe, la syntaxe est 'setx var cmd args...'. cependant, la -# syntaxe 'setx var=cmd args...' est supportée aussi -# syntaxe 2: setx -a array cmd -# initialiser le tableau $1 avec le résultat de la commande "$2..@", chaque -# ligne du résultat étant un élément du tableau -# note: en principe, la syntaxe est 'setx -a array cmd args...'. cependant, la -# syntaxe 'setx -a array=cmd args...' est supportée aussi - 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() { -# Comme la fonction setx() mais ne supporte que l'initialisation d'une variable -# scalaire avec la syntaxe '_setvx var cmd args...' pour gagner (un peu) en -# rapidité d'exécution. - local __s_var="$1"; shift - eval "$__s_var="'"$("$@")"' -} -function _setax() { -# Comme la fonction setx() mais ne supporte que l'initialisation d'un tableau -# avec la syntaxe '_setax array cmd args...' pour gagner (un peu) en rapidité -# d'exécution. - local __s_array="$1"; shift - eval "$__s_array=($("$@" | qlines))" -} -function evalx() { -# Implémenter une syntaxe lisible et naturelle permettant d'enchainer des -# traitements sur une valeur. Par exemple, la commande -# evalx cmd1... // cmd2... // cmd3... -# affiche le résultat de la commande "$(cmd3 $(cmd2 $(cmd1)))" -# Retourner le dernier code d'erreur non nul, ou 0 si toutes les commandes se -# sont exécutées sans erreur. - 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") +##@*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 - - 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 setx2() { -# équivalent à setx $1 evalx $2..@ - 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() { -# Implémenter une syntaxe alternative permettant d'enchainer des traitements sur -# un flux de données. Par exemple, la commande -# evalp cmd1... // cmd2... // cmd3... -# affiche le résultat de la commande "$(cmd1 | cmd2 | cmd3)" -# Typiquement, cette fonction permet de faciliter la construction d'un -# enchainement de commandes par programme, ou de faciliter l'utilisation de la -# fonction setx() pour récupérer le résultat d'un enchainement. Dans les autres -# cas, il est plus simple et naturel d'écrire les enchainements avec la syntaxe -# de bash. - 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 testx() { -# Faire un test unaire avec la commande [ sur une valeur calculée avec evalx. -# Utiliser la syntaxe 'testx op cmds...' e.g. -# testx -z cmd1 // cmd2 - local __t_op="$1"; shift - local __t_val="$(evalx "$@")" - [ $__t_op "$__t_val" ] -} -function test2x() { -# Faire une test binaire avec la commande [ entre une valeur spécifiée et une -# valeur calculée avec evalx. Utiliser la syntaxe 'test2x value op cmds...' e.g. -# test2x value == cmd1 // cmd2 - local __t_val1="$1"; shift - local __t_op="$1"; shift - local __t_val2="$(evalx "$@")" - [ "$__t_val1" $__t_op "$__t_val2" ] -} -function testrx() { -# Faire une test binaire avec la commande [[ entre une valeur spécifiée et une -# valeur calculée avec evalx. Utiliser la syntaxe 'testrx value op cmds...' e.g. -# testrx value == cmd1 // cmd2 - local __t_val1="$1"; shift - local __t_op="$1"; shift - local __t_val2="$(evalx "$@")" - eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]' -} -function testp() { -# Faire un test unaire avec la commande [ sur une valeur calculée avec evalp. -# Utiliser la syntaxe 'testp op cmds...' e.g. -# testp -z cmd1 // cmd2 - local __t_op="$1"; shift - local __t_val="$(evalp "$@")" - [ $__t_op "$__t_val" ] -} -function test2p() { -# Faire une test binaire avec la commande [ entre une valeur spécifiée et une -# valeur calculée avec evalp. Utiliser la syntaxe 'test2p value op cmds...' e.g. -# test2p value == cmd1 // cmd2 - local __t_val1="$1"; shift - local __t_op="$1"; shift - local __t_val2="$(evalp "$@")" - [ "$__t_val1" $__t_op "$__t_val2" ] -} -function testrp() { -# Faire une test binaire avec la commande [[ entre une valeur spécifiée et une -# valeur calculée avec evalp. Utiliser la syntaxe 'testrp value op cmds...' e.g. -# testrp value == cmd1 // cmd2 - local __t_val1="$1"; shift - local __t_op="$1"; shift - local __t_val2="$(evalp "$@")" - eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]' -} - -function err2out() { -# lancer la commande $@ en redirigeant la sortie d'erreur sur la sortie standard - "$@" 2>&1 -} + 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 +##@include base.init +##@include base.core +##@include base.string +##@include base.array +##@include base.compat +uprovide base +urequire base.init base.core base.string base.array base.compat ## valeurs -function tolower() { -# afficher en minuscule la valeur $1..* - echo ${*,,} -} -function toupper() { -# afficher en majuscule la valeur $1..* - echo ${*^^} -} -function isnum() { -# retourner vrai si $1 est une valeur numérique entière (positive ou négative) - [ ${#1} -gt 0 ] || return 1 - local v="$1" - v="${v#-}" - v="${v//[0-9]/}" - [ -z "$v" ] -} -function ispnum() { -# retourner vrai si $1 est une valeur numérique entière positive - [ ${#1} -gt 0 ] || return 1 - local v="$1" - v="${v//[0-9]/}" - [ -z "$v" ] -} -function isrnum() { -# retourner vrai si $1 est une valeur numérique réelle (positive ou négative) -# le séparateur décimal peut être . ou , - [ ${#1} -gt 0 ] || return 1 - local v="$1" - v="${v#-}" - v="${v//./}" - v="${v//,/}" - v="${v//[0-9]/}" - [ -z "$v" ] -} -function is_yes() { -# retourner vrai si $1 est une valeur "oui" - 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 yesval() { # normaliser une valeur vraie: si $1 est une valeur "oui", afficher 1, sinon # afficher une chaine vide @@ -378,14 +60,6 @@ function normyesvals() { is_yes "${!__nyv_yesvar}" && set_var "$__nyv_yesvar" 1 || set_var "$__nyv_yesvar" "" done } -function is_no() { -# retourner vrai si $1 est une valeur "non" - case "${1,,}" in - n|non|no|f|faux|false|off) return 0;; - esac - isnum "$1" && [ "$1" -eq 0 ] && return 0 - return 1 -} function rawecho() { # afficher une valeur brute. contrairement à echo, ne pas reconnaitre les # options -e, -E, -n. @@ -4351,26 +4025,3 @@ 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 - -################################################################################ -## support de ulib dans le cas où cette librairie n'est pas encore chargée - -if [ -z "$ULIBDIR" -o "$ULIBDIR" != "$ULIBINIT" ]; then - ULIBPROVIDED=() - function uprovided() { - array_contains ULIBPROVIDED "$1" - } - function uprovide() { - uprovided "$1" && return 1 - array_add ULIBPROVIDED "$1" - } - function urequire() { - # si ulib n'est pas disponible pour charger la librairie, on compte sur - # l'utilisateur pour charger manuellement les librairies nécessaires. - local ulib_ - for ulib_ in "$@"; do - uprovided "$ulib_" || ewarn "$ulib_: this module is required" - done - } - uprovide base -fi diff --git a/lib/ulib/base.array b/lib/ulib/base.array new file mode 100644 index 0000000..3940090 --- /dev/null +++ b/lib/ulib/base.array @@ -0,0 +1,5 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Fonctions de base: gestion des tableaux +##@cooked nocomments +uprovide base.array +urequire base.core diff --git a/lib/ulib/base.compat b/lib/ulib/base.compat new file mode 100644 index 0000000..7efc528 --- /dev/null +++ b/lib/ulib/base.compat @@ -0,0 +1,35 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Fonctions de base: support des fonctions obsolètes et des versions de bash < 4.x +##@cooked nocomments +uprovide base.compat +urequire base.string + +if [ -n "$BASH_VERSINFO" -a "${BASH_VERSINFO[0]}" -lt 4 ]; then + if uprovided base.string; then + function strlower() { tr A-Z a-z <<<"$*"; } + function strupper() { tr a-z A-Z <<<"$*"; } + 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 + # pour les perfs, n'utiliser strlower que ici + 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 +fi diff --git a/lib/ulib/base.core b/lib/ulib/base.core new file mode 100644 index 0000000..968b67e --- /dev/null +++ b/lib/ulib/base.core @@ -0,0 +1,280 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Fonctions de base: fondement +##@cooked nocomments +uprovide base.core + +function recho() { +# afficher une valeur brute. contrairement à la commande echo, ne reconnaitre +# aucune option (i.e. -e, -E, -n ne sont pas signifiants) + if [[ "${1:0:2}" == -[eEn] ]]; then + echo -n - + local first="${1:1}"; shift + echo "$first$@" + else + echo "$@" + fi +} +function recho_() { +# afficher une valeur brute, sans passer à la ligne. contrairement à la commande +# echo, ne reconnaitre aucune option (i.e. -e, -E, -n ne sont pas signifiants) + if [[ "${1:0:2}" == -[eEn] ]]; then + echo -n - + local first="${1:1}"; shift + echo -n "$first$@" + else + echo -n "$@" + fi +} +function _qval() { +# Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \` +# Cela permet de quoter une chaine à mettre entre guillements. +# Note: la protection de ! n'est pas effectuée, parce que le comportement du +# shell est incohérent entre le shell interactif et les scripts. Pour une +# version plus robuste, il est nécessaire d'utiliser un programme externe tel +# que sed ou awk + local s="$*" + s="${s//\\/\\\\}" + s="${s//\"/\\\"}" + s="${s//\$/\\\$}" + s="${s//\`/\\\`}" + recho_ "$s" +} +function qval() { +# Afficher la chaine $* quotée avec " + echo -n \" + _qval "$@" + echo \" +} +function qvalr() { +# Afficher la chaine $* quotée avec ", sauf si elle est vide + if [ -n "$*" ]; then + echo -n \" + _qval "$@" + echo n \" + fi +} +function should_quote() { +# Tester si la chaine $* doit être mise entre quotes + [ -z "$1" ] && return 0 + local s="${*//[a-zA-Z0-9]/}" + s="${s//,/}" + s="${s//./}" + s="${s//+/}" + s="${s//\//}" + s="${s//-/}" + s="${s//_/}" + s="${s//=/}" + [ -n "$s" ] +} +function qvals() { +# Afficher chaque argument de cette fonction quotée le cas échéant avec " +# Chaque valeur est séparée par un espace. + 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 +} +function qlines() { +# Traiter chaque ligne de l'entrée standard pour en faire des chaines quotées +# avec ' + sed "s/'/'\\\\''/g; s/.*/'&'/g" +} +function setv() { +# initialiser la variable $1 avec la valeur "$2..*" +# note: en principe, la syntaxe est 'setv var values...'. cependant, la +# syntaxe 'setv var=values...' est supportée aussi + local __s_var="$1"; shift + if [[ "$__s_var" == *=* ]]; then + set -- "${__s_var#*=}" "$@" + __s_var="${__s_var%%=*}" + fi + eval "$__s_var=\"$(_qval "$*")\"" +} +function _setv() { +# Comme la fonction setv() mais ne supporte que la syntaxe '_setv var values...' +# Cette fonction est légèrement plus rapide que setv() + local __s_var="$1"; shift + eval "$__s_var=\"$(_qval "$*")\"" +} +function setx() { +# syntaxe 1: setx var cmd +# initialiser la variable $1 avec le résultat de la commande "$2..@" +# note: en principe, la syntaxe est 'setx var cmd args...'. cependant, la +# syntaxe 'setx var=cmd args...' est supportée aussi +# syntaxe 2: setx -a array cmd +# initialiser le tableau $1 avec le résultat de la commande "$2..@", chaque +# ligne du résultat étant un élément du tableau +# note: en principe, la syntaxe est 'setx -a array cmd args...'. cependant, la +# syntaxe 'setx -a array=cmd args...' est supportée aussi + 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() { +# Comme la fonction setx() mais ne supporte que l'initialisation d'une variable +# scalaire avec la syntaxe '_setvx var cmd args...' pour gagner (un peu) en +# rapidité d'exécution. + local __s_var="$1"; shift + eval "$__s_var="'"$("$@")"' +} +function _setax() { +# Comme la fonction setx() mais ne supporte que l'initialisation d'un tableau +# avec la syntaxe '_setax array cmd args...' pour gagner (un peu) en rapidité +# d'exécution. + local __s_array="$1"; shift + eval "$__s_array=($("$@" | qlines))" +} +function evalx() { +# Implémenter une syntaxe lisible et naturelle permettant d'enchainer des +# traitements sur une valeur. Par exemple, la commande +# evalx cmd1... // cmd2... // cmd3... +# affiche le résultat de la commande "$(cmd3 $(cmd2 $(cmd1)))" +# Retourner le dernier code d'erreur non nul, ou 0 si toutes les commandes se +# sont exécutées sans erreur. + 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 setx2() { +# équivalent à setx $1 evalx $2..@ + 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() { +# Implémenter une syntaxe alternative permettant d'enchainer des traitements sur +# un flux de données. Par exemple, la commande +# evalp cmd1... // cmd2... // cmd3... +# affiche le résultat de la commande "$(cmd1 | cmd2 | cmd3)" +# Typiquement, cette fonction permet de faciliter la construction d'un +# enchainement de commandes par programme, ou de faciliter l'utilisation de la +# fonction setx() pour récupérer le résultat d'un enchainement. Dans les autres +# cas, il est plus simple et naturel d'écrire les enchainements avec la syntaxe +# de bash. + 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 testx() { +# Faire un test unaire avec la commande [ sur une valeur calculée avec evalx. +# Utiliser la syntaxe 'testx op cmds...' e.g. +# testx -z cmd1 // cmd2 + local __t_op="$1"; shift + local __t_val="$(evalx "$@")" + [ $__t_op "$__t_val" ] +} +function test2x() { +# Faire une test binaire avec la commande [ entre une valeur spécifiée et une +# valeur calculée avec evalx. Utiliser la syntaxe 'test2x value op cmds...' e.g. +# test2x value == cmd1 // cmd2 + local __t_val1="$1"; shift + local __t_op="$1"; shift + local __t_val2="$(evalx "$@")" + [ "$__t_val1" $__t_op "$__t_val2" ] +} +function testrx() { +# Faire une test binaire avec la commande [[ entre une valeur spécifiée et une +# valeur calculée avec evalx. Utiliser la syntaxe 'testrx value op cmds...' e.g. +# testrx value == cmd1 // cmd2 + local __t_val1="$1"; shift + local __t_op="$1"; shift + local __t_val2="$(evalx "$@")" + eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]' +} +function testp() { +# Faire un test unaire avec la commande [ sur une valeur calculée avec evalp. +# Utiliser la syntaxe 'testp op cmds...' e.g. +# testp -z cmd1 // cmd2 + local __t_op="$1"; shift + local __t_val="$(evalp "$@")" + [ $__t_op "$__t_val" ] +} +function test2p() { +# Faire une test binaire avec la commande [ entre une valeur spécifiée et une +# valeur calculée avec evalp. Utiliser la syntaxe 'test2p value op cmds...' e.g. +# test2p value == cmd1 // cmd2 + local __t_val1="$1"; shift + local __t_op="$1"; shift + local __t_val2="$(evalp "$@")" + [ "$__t_val1" $__t_op "$__t_val2" ] +} +function testrp() { +# Faire une test binaire avec la commande [[ entre une valeur spécifiée et une +# valeur calculée avec evalp. Utiliser la syntaxe 'testrp value op cmds...' e.g. +# testrp value == cmd1 // cmd2 + local __t_val1="$1"; shift + local __t_op="$1"; shift + local __t_val2="$(evalp "$@")" + eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]' +} + +function err2out() { +# lancer la commande $@ en redirigeant la sortie d'erreur sur la sortie standard + "$@" 2>&1 +} diff --git a/lib/ulib/base.init b/lib/ulib/base.init new file mode 100644 index 0000000..fa22a35 --- /dev/null +++ b/lib/ulib/base.init @@ -0,0 +1,36 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Fonctions de base: initialisation de l'environnement +##@cooked nocomments + +# Emplacement du script courant +if [ -n "$UTOOLS_HAVE_SCRIPTVARS" ]; then + # ne pas mettre à jour script, scriptname, scriptdir. Ils ont déjà été + # calculés + : +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}" + +# Repertoire temporaire +[ -z "$TMPDIR" -a -d "$HOME/tmp" ] && TMPDIR="$HOME/tmp" +export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}" + +# User +[ -z "$USER" -a -n "$LOGNAME" ] && export USER="$LOGNAME" + +# Le fichier nutoolsrc doit être chargé systématiquement +[ -f /etc/nutoolsrc ] && . /etc/nutoolsrc +[ -f ~/.nutoolsrc ] && . ~/.nutoolsrc diff --git a/lib/ulib/base.string b/lib/ulib/base.string new file mode 100644 index 0000000..5ea57a4 --- /dev/null +++ b/lib/ulib/base.string @@ -0,0 +1,56 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Fonctions de base: gestion des valeurs scalaires +##@cooked nocomments +uprovide base.string +urequire base.core + +function strlower() { +# afficher en minuscule la valeur $1..* + echo ${*,,} +} +function strupper() { +# afficher en majuscule la valeur $1..* + echo ${*^^} +} +function isnum() { +# retourner vrai si $1 est une valeur numérique entière (positive ou négative) + [ ${#1} -gt 0 ] || return 1 + local v="$1" + v="${v#-}" + v="${v//[0-9]/}" + [ -z "$v" ] +} +function ispnum() { +# retourner vrai si $1 est une valeur numérique entière positive + [ ${#1} -gt 0 ] || return 1 + local v="$1" + v="${v//[0-9]/}" + [ -z "$v" ] +} +function isrnum() { +# retourner vrai si $1 est une valeur numérique réelle (positive ou négative) +# le séparateur décimal peut être . ou , + [ ${#1} -gt 0 ] || return 1 + local v="$1" + v="${v#-}" + v="${v//./}" + v="${v//,/}" + v="${v//[0-9]/}" + [ -z "$v" ] +} +function is_yes() { +# retourner vrai si $1 est une valeur "oui" + 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() { +# retourner vrai si $1 est une valeur "non" + case "${1,,}" in + n|non|no|f|faux|false|off) return 0;; + esac + isnum "$1" && [ "$1" -eq 0 ] && return 0 + return 1 +} diff --git a/lib/ulib/base.ulib b/lib/ulib/base.ulib new file mode 100644 index 0000000..215c486 --- /dev/null +++ b/lib/ulib/base.ulib @@ -0,0 +1,32 @@ +##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +## Support des fonctions uprovided(), uprovide() et urequire() de ulib dans le +## cas où cette librairie n'est pas chargée +##@cooked nocomments +# Ce fichier ne doit pas être sourcé, mais inclus avec uinc +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() { + # si ulib n'est pas disponible pour charger le module, on compte sur + # l'utilisateur pour charger manuellement les librairies nécessaires. + # retourner 1 si un module n'est pas disponible + 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 diff --git a/lib/ulib/compat b/lib/ulib/compat index 5d2d87e..8bc2870 100644 --- a/lib/ulib/compat +++ b/lib/ulib/compat @@ -16,32 +16,6 @@ if check_sysinfos -s macosx; then function _nl2cr() { _nl2lf | awk 'BEGIN { ORS="" } { print $0 "\r" }'; } # sed -i demande un argument function sedi() { sed -i '' "$@"; } - # Sous MacOSX, la version de bash (3.x) ne supporte pas les opérateurs ,, et ^^ - function tolower() { tr A-Z a-z <<<"$*"; } - function toupper() { tr a-z A-Z <<<"$*"; } - 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 - # pour les perfs, n'utiliser tolower que ici - case "$(tolower "$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 "$(tolower "$1")" in - n|non|no|f|faux|false|off) return 0;; - esac - return 1 - } ## gestion des arguments function __po_check_options() { diff --git a/lib/ulib/support/install-pubkeys.sh b/lib/ulib/support/install-pubkeys.sh index eae216e..00e13ed 100755 --- a/lib/ulib/support/install-pubkeys.sh +++ b/lib/ulib/support/install-pubkeys.sh @@ -6,6 +6,36 @@ PUBKEYS="@@PUBKEYS@@" ##@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 if [ -n "$UTOOLS_HAVE_SCRIPTVARS" ]; then : @@ -33,6 +63,10 @@ export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}" [ -f /etc/nutoolsrc ] && . /etc/nutoolsrc [ -f ~/.nutoolsrc ] && . ~/.nutoolsrc +##@inc]base.init +##@inc[base.core +## Fonctions de base: fondement +uprovide base.core function recho() { if [[ "${1:0:2}" == -[eEn] ]]; then @@ -114,26 +148,28 @@ function _setv() { eval "$__s_var=\"$(_qval "$*")\"" } function setx() { - local __s_var="$1"; shift - if [[ "$__s_var" == *=* ]]; then - set -- "${__s_var#*=}" "$@" - __s_var="${__s_var%%=*}" + 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 - eval "$__s_var="'"$("$@")"' } -function _setx() { +function _setvx() { local __s_var="$1"; shift eval "$__s_var="'"$("$@")"' } -function seta() { - local __s_array="$1"; shift - if [[ "$__s_array" == *=* ]]; then - set -- "${__s_array#*=}" "$@" - __s_array="${__s_array%%=*}" - fi - eval "$__s_array=($("$@" | qlines))" -} -function _seta() { +function _setax() { local __s_array="$1"; shift eval "$__s_array=($("$@" | qlines))" } @@ -158,7 +194,7 @@ function evalx() { __e_cmd=("${__e_cmd[@]}" "$__e_arg") done - if [ -n "$first" ]; then + if [ -n "$__e_first" ]; then __e_val="$("${__e_cmd[@]}")" || __e_r=$? else __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$? @@ -169,12 +205,15 @@ function evalx() { return $__e_r } function setx2() { + 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 - setx "$__s_var" evalx "$@" + __s_args=("${__s_args[@]}" "$__s_var") + setx "${__s_args[@]}" evalx "$@" } function evalp() { local __e_arg __e_cmd @@ -232,11 +271,16 @@ function testrp() { function err2out() { "$@" 2>&1 } +##@inc]base.core +##@inc[base.string +## Fonctions de base: gestion des valeurs scalaires +uprovide base.string +urequire base.core -function tolower() { +function strlower() { echo ${*,,} } -function toupper() { +function strupper() { echo ${*^^} } function isnum() { @@ -268,6 +312,56 @@ function is_yes() { 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 +} +##@inc]base.string +##@inc[base.array +## Fonctions de base: gestion des tableaux +uprovide base.array +urequire base.core +##@inc]base.array +##@inc[base.compat +## Fonctions de base: support des fonctions obsolètes et des versions de bash < 4.x +uprovide base.compat +urequire base.string + +if [ -n "$BASH_VERSINFO" -a "${BASH_VERSINFO[0]}" -lt 4 ]; then + if uprovided base.string; then + function strlower() { tr A-Z a-z <<<"$*"; } + function strupper() { tr a-z A-Z <<<"$*"; } + 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 +fi +##@inc]base.compat +uprovide base +urequire base.init base.core base.string base.array base.compat + function yesval() { is_yes "$1" && echo 1 } @@ -283,13 +377,6 @@ function normyesvals() { is_yes "${!__nyv_yesvar}" && set_var "$__nyv_yesvar" 1 || set_var "$__nyv_yesvar" "" done } -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 rawecho() { local first while [ "${1:0:1}" == "-" ]; do @@ -964,6 +1051,16 @@ function relpath() { 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")" @@ -3348,25 +3445,6 @@ 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 - - -if [ -z "$ULIBDIR" -o "$ULIBDIR" != "$ULIBINIT" ]; then - ULIBPROVIDED=() - function uprovided() { - array_contains ULIBPROVIDED "$1" - } - function uprovide() { - uprovided "$1" && return 1 - array_add ULIBPROVIDED "$1" - } - function urequire() { - local ulib_ - for ulib_ in "$@"; do - uprovided "$ulib_" || ewarn "$ulib_: this module is required" - done - } - uprovide base -fi ##@inc]../base ##@inc[../sysinfos ## Gestion des informations sur l'hôte local @@ -3729,30 +3807,6 @@ if check_sysinfos -s macosx; then function _nl2crlf() { _nl2lf | awk '{ print $0 "\r" }'; } function _nl2cr() { _nl2lf | awk 'BEGIN { ORS="" } { print $0 "\r" }'; } function sedi() { sed -i '' "$@"; } - function tolower() { tr A-Z a-z <<<"$*"; } - function toupper() { tr a-z A-Z <<<"$*"; } - 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 "$(tolower "$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 "$(tolower "$1")" in - n|non|no|f|faux|false|off) return 0;; - esac - return 1 - } function __po_check_options() { local -a options args diff --git a/lib/ulib/ulib b/lib/ulib/ulib index 4e5b577..f017cd8 100644 --- a/lib/ulib/ulib +++ b/lib/ulib/ulib @@ -51,48 +51,52 @@ ULIBINIT="$ULIBDIR" function uprovided() { # Tester si le module $1 a déjà été chargé par urequire - local ulib_ - for ulib_ in "${ULIBPROVIDED[@]}"; do - [ "$ulib_" == "$1" ] && return 0 + local module + for module in "${ULIBPROVIDED[@]}"; do + [ "$module" == "$1" ] && return 0 done return 1 } function uprovide() { # Spécifier que le module $1 a été sourcée, ou prétendre que c'est le cas. - uprovided "$1" && return 0 + # Retourner 1 si le module était déjà pourvu, 0 si c'est la première fois + # qu'on le pourvoit + uprovided "$1" && return 1 ULIBPROVIDED=("${ULIBPROVIDED[@]}" "$1") } function urequire() { - # Sourcer un fichier recherché dans ULIBDIRS - # Si le fichier est DEFAULTS, charger base, pretty, sysinfos et compat à la - # place - local ulib_ ulibdir_ found_ + # Sourcer un module recherché dans ULIBDIRS + # Le module DEFAULTS est traité de façon particulière: si le fichier associé + # n'est pas trouvé, charger base, pretty, sysinfos et compat à la place + # Si un module n'est pas trouvé, quitter le script avec die() + local __u_module __u_ulibdir __u_found [ -n "$*" ] || set DEFAULTS - for ulib_ in "$@"; do - found_= - for ulibdir_ in "${ULIBDIRS[@]}"; do - if [ -f "$ulibdir_/$ulib_" ]; then - found_=1 - if ! uprovided "$ulib_"; then - uprovide "$ulib_" - source "$ulibdir_/$ulib_" || die + for __u_module in "$@"; do + __u_found= + for __u_ulibdir in "${ULIBDIRS[@]}"; do + if [ -f "$__u_ulibdir/$__u_module" ]; then + __u_found=1 + if ! uprovided "$__u_module"; then + uprovide "$__u_module" + source "$__u_ulibdir/$__u_module" || die fi break - elif [ "$ulib_" == "DEFAULTS" ]; then - found_=1 - for ulib_ in base pretty sysinfos compat; do - if ! uprovided "$ulib_"; then - uprovide "$ulib_" - source "$ulibdir_/$ulib_" || die - fi - done - break fi done - [ -n "$found_" ] || die "Unable to find $ulib_ in ${ULIBDIR[*]}" + if [ -z "$__u_found" -a "$__u_module" == DEFAULTS ]; then + __u_found=1 + for __u_module in base pretty sysinfos compat; do + if ! uprovided "$__u_module"; then + uprovide "$__u_module" + source "$__u_ulibdir/$__u_module" || die + fi + done + fi + [ -n "$__u_found" ] || die "Unable to find $__u_module in ${ULIBDIR[*]}" done + return 0 } function ulibadd() { @@ -103,7 +107,8 @@ function ulibadd() { function ulibsync() { # Synchroniser les modules de ulib dans le répertoire $1 local destdir="$(abspath "${1:-.}")" - local __CPNOVCS_RSYNC_ARGS=(-q --delete) + local -a __CPNOVCS_RSYNC_ARGS + __CPNOVCS_RSYNC_ARGS=(-q --delete) [ "$destdir/ulib" != "$ULIBDIR" ] && cpdirnovcs "$ULIBDIR" "$destdir/ulib" } diff --git a/lib/ulib/ulibsh b/lib/ulib/ulibsh index 50b342c..65c3194 100644 --- a/lib/ulib/ulibsh +++ b/lib/ulib/ulibsh @@ -47,44 +47,45 @@ ULIBINIT="$ULIBDIR" [ -n "$ULIBPROVIDED" ] || ULIBPROVIDED=(ulib) function uprovided() { - local ulib_ - for ulib_ in "${ULIBPROVIDED[@]}"; do - [ "$ulib_" == "$1" ] && return 0 + local module + for module in "${ULIBPROVIDED[@]}"; do + [ "$module" == "$1" ] && return 0 done return 1 } function uprovide() { - uprovided "$1" && return 0 + uprovided "$1" && return 1 ULIBPROVIDED=("${ULIBPROVIDED[@]}" "$1") } function urequire() { - local ulib_ ulibdir_ found_ + local __u_module __u_ulibdir __u_found [ -n "$*" ] || set DEFAULTS - for ulib_ in "$@"; do - found_= - for ulibdir_ in "${ULIBDIRS[@]}"; do - if [ -f "$ulibdir_/$ulib_" ]; then - found_=1 - if ! uprovided "$ulib_"; then - uprovide "$ulib_" - source "$ulibdir_/$ulib_" || die + for __u_module in "$@"; do + __u_found= + for __u_ulibdir in "${ULIBDIRS[@]}"; do + if [ -f "$__u_ulibdir/$__u_module" ]; then + __u_found=1 + if ! uprovided "$__u_module"; then + uprovide "$__u_module" + source "$__u_ulibdir/$__u_module" || die fi break - elif [ "$ulib_" == "DEFAULTS" ]; then - found_=1 - for ulib_ in base pretty sysinfos compat; do - if ! uprovided "$ulib_"; then - uprovide "$ulib_" - source "$ulibdir_/$ulib_" || die - fi - done - break fi done - [ -n "$found_" ] || die "Unable to find $ulib_ in ${ULIBDIR[*]}" + if [ -z "$__u_found" -a "$__u_module" == DEFAULTS ]; then + __u_found=1 + for __u_module in base pretty sysinfos compat; do + if ! uprovided "$__u_module"; then + uprovide "$__u_module" + source "$__u_ulibdir/$__u_module" || die + fi + done + fi + [ -n "$__u_found" ] || die "Unable to find $__u_module in ${ULIBDIR[*]}" done + return 0 } function ulibadd() { @@ -93,7 +94,8 @@ function ulibadd() { function ulibsync() { local destdir="$(abspath "${1:-.}")" - local __CPNOVCS_RSYNC_ARGS=(-q --delete) + local -a __CPNOVCS_RSYNC_ARGS + __CPNOVCS_RSYNC_ARGS=(-q --delete) [ "$destdir/ulib" != "$ULIBDIR" ] && cpdirnovcs "$ULIBDIR" "$destdir/ulib" } diff --git a/ucrontab b/ucrontab index 1c5b04b..b4ad673 100755 --- a/ucrontab +++ b/ucrontab @@ -94,6 +94,36 @@ DEFAULT_GDELAY=15 ##@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 if [ -n "$UTOOLS_HAVE_SCRIPTVARS" ]; then : @@ -121,6 +151,10 @@ export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}" [ -f /etc/nutoolsrc ] && . /etc/nutoolsrc [ -f ~/.nutoolsrc ] && . ~/.nutoolsrc +##@inc]base.init +##@inc[base.core +## Fonctions de base: fondement +uprovide base.core function recho() { if [[ "${1:0:2}" == -[eEn] ]]; then @@ -202,26 +236,28 @@ function _setv() { eval "$__s_var=\"$(_qval "$*")\"" } function setx() { - local __s_var="$1"; shift - if [[ "$__s_var" == *=* ]]; then - set -- "${__s_var#*=}" "$@" - __s_var="${__s_var%%=*}" + 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 - eval "$__s_var="'"$("$@")"' } -function _setx() { +function _setvx() { local __s_var="$1"; shift eval "$__s_var="'"$("$@")"' } -function seta() { - local __s_array="$1"; shift - if [[ "$__s_array" == *=* ]]; then - set -- "${__s_array#*=}" "$@" - __s_array="${__s_array%%=*}" - fi - eval "$__s_array=($("$@" | qlines))" -} -function _seta() { +function _setax() { local __s_array="$1"; shift eval "$__s_array=($("$@" | qlines))" } @@ -246,7 +282,7 @@ function evalx() { __e_cmd=("${__e_cmd[@]}" "$__e_arg") done - if [ -n "$first" ]; then + if [ -n "$__e_first" ]; then __e_val="$("${__e_cmd[@]}")" || __e_r=$? else __e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$? @@ -257,12 +293,15 @@ function evalx() { return $__e_r } function setx2() { + 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 - setx "$__s_var" evalx "$@" + __s_args=("${__s_args[@]}" "$__s_var") + setx "${__s_args[@]}" evalx "$@" } function evalp() { local __e_arg __e_cmd @@ -320,11 +359,16 @@ function testrp() { function err2out() { "$@" 2>&1 } +##@inc]base.core +##@inc[base.string +## Fonctions de base: gestion des valeurs scalaires +uprovide base.string +urequire base.core -function tolower() { +function strlower() { echo ${*,,} } -function toupper() { +function strupper() { echo ${*^^} } function isnum() { @@ -356,6 +400,56 @@ function is_yes() { 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 +} +##@inc]base.string +##@inc[base.array +## Fonctions de base: gestion des tableaux +uprovide base.array +urequire base.core +##@inc]base.array +##@inc[base.compat +## Fonctions de base: support des fonctions obsolètes et des versions de bash < 4.x +uprovide base.compat +urequire base.string + +if [ -n "$BASH_VERSINFO" -a "${BASH_VERSINFO[0]}" -lt 4 ]; then + if uprovided base.string; then + function strlower() { tr A-Z a-z <<<"$*"; } + function strupper() { tr a-z A-Z <<<"$*"; } + 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 +fi +##@inc]base.compat +uprovide base +urequire base.init base.core base.string base.array base.compat + function yesval() { is_yes "$1" && echo 1 } @@ -371,13 +465,6 @@ function normyesvals() { is_yes "${!__nyv_yesvar}" && set_var "$__nyv_yesvar" 1 || set_var "$__nyv_yesvar" "" done } -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 rawecho() { local first while [ "${1:0:1}" == "-" ]; do @@ -1052,6 +1139,16 @@ function relpath() { 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")" @@ -3436,25 +3533,6 @@ 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 - - -if [ -z "$ULIBDIR" -o "$ULIBDIR" != "$ULIBINIT" ]; then - ULIBPROVIDED=() - function uprovided() { - array_contains ULIBPROVIDED "$1" - } - function uprovide() { - uprovided "$1" && return 1 - array_add ULIBPROVIDED "$1" - } - function urequire() { - local ulib_ - for ulib_ in "$@"; do - uprovided "$ulib_" || ewarn "$ulib_: this module is required" - done - } - uprovide base -fi ##@inc]base ##@inc[pretty ## Affichage en couleur, et support de niveaux de "verbosité" et d'interaction @@ -4017,30 +4095,6 @@ if check_sysinfos -s macosx; then function _nl2crlf() { _nl2lf | awk '{ print $0 "\r" }'; } function _nl2cr() { _nl2lf | awk 'BEGIN { ORS="" } { print $0 "\r" }'; } function sedi() { sed -i '' "$@"; } - function tolower() { tr A-Z a-z <<<"$*"; } - function toupper() { tr a-z A-Z <<<"$*"; } - 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 "$(tolower "$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 "$(tolower "$1")" in - n|non|no|f|faux|false|off) return 0;; - esac - return 1 - } function __po_check_options() { local -a options args