##----------------------------------------------------------------------------
## Script         : params.lib
## Module Puppet  : gnc-script_core_dtsi
## Auteur         : Emmanuel Confrere
## Date           : 26-11-2017
## Version        : 3.0.1
## Objet          : Gere les options passees a un script
##                  qui ont ete declare dans l entete de ce dernier
##           
## Fonction       : fct_param
##
## Detail         : Cette fonction est appele par le chargement de init.conf
##                  Elle analyse traite les parametres passes a la commande en correlation
##                  avec ceux declares dans l entete du script.
##                   
##                  Cette fonction prend en charge les option -h -s, -dbg N, -hist [N], -log [Sid], -cpt [Sid]
##                  qui n on t pas besoins d etre declare.
##                  
##                  -h     : Affiche l aide du script
##                  -s     : mode silence (Pas d affichage sur la console)
##                  -dbg N : Passe mode debug de niveau N
##                  -hist  : Affiche l historique des N dernieres execution (N vaut 1 par defaut)
##                  -log   : Affiche le dernier journal d execution ou celui specifier par le numero de session d'execution
##                  -cpt   : Affiche le dernier compte-rendus ou celui specifier par le numero de session d'execution
# ----------------------------------------------------------------------------
# Mise a jour :
# 1.0.0    22-08-2016 - Emmanuel Confrere - Cre : Creation
# 1.0.1    23-08-2016 - Emmanuel Confrere - Ano : Expension des variables imcomptible en version Bash 3.2.25 sur deploiement
# 1.1.0    24-08-2016 - Emmanuel Confrere - Evo : Ajout de la gestion des arguments sans option
# 1.1.1    24-08-2016 - Emmanuel Confrere - Ano : Changement des variable du socle NC_EXPL_ -> NC_EXPL
# 1.1.2    24-08-2016 - Emmanuel Confrere - Ano : libelle des erreurs 11 et 10
# 1.1.3    24-08-2016 - Emmanuel Confrere - Ano : Libelle de l erreur 11 erronee
# 1.1.4    24-08-2016 - Emmanuel Confrere - Evo : Ajout de la diponibilite d un compte rendu
#                                                 Ajout de l option par defaut cpt
# 1.1.5    25-08-2016 - Emmanuel Confrere - Ano : Option -hist : ne pas affiche la session en cours
# 2.0.0    29-08-2016 - Emmanuel Confrere - Evo : Les booleen sont desorme traduit par 0 ou 1 (Faux ou Vraix)
# 2.0.1    11-10-2016 - Emmanuel Confrere - Evo : Ajout de commentaire dans le code
# 2.0.2    17-11-2016 - Emmanuel Confrere - Ano : Comportement de la gestion des arguments incoherent.
# 2.1.0    21-11-2016 - Emmanuel Confrere - Evo : Ajout d un controle : Liste de valeurs determinees pour les arguments d une option
#                                                                       ou pour les arguments du script (valeur separee par une virgule ou un espace)
# 2.1.1    30-03-2017 - Emmanuel Confrere - Ano : Interpretation des arguments par Bash ! Cf. DBA-2455
# 2.2.0    13-04-2017 - Emmanuel Confrere - Evo : Prise en compte de la journalisation du compte d execution dans l historique
# 2.2.1    13-04-2017 - Emmanuel Confrere - Ano : Prise en compte de la journalisation avec l option -log
#                                                 Compatibilite ascendente n etait pas assuree.
# 2.2.2    05-07-2017 - Emmanuel Confrere - Ano : Lorsque des option possede une inclusion la librairie entre dans une boucle infinie !
# 3.0.0    26-07-2018 - Emmanuel Confrere - Evo : Changement conceptuel sur la gestion des valeurs par defaut
#                                                 Correction de l analyse des arguments declare par "@ARG:", seul la derniere declaration 
#                                                 est prise en compte.
#                                                 Les variables SH_ARGS et SH_ARG_<option> ou leur representant defini dans la declaration
#                                                 des option et argument (@ARG: et @OPT:) peuvent etre surcharge dans le fichier de configuration.
# 3.0.1    26-11-2017 - Doug Le Tough     - Ano : La construction de L_PARMF ne permet pas de differencier les differentes execution d'un meme script
##----------------------------------------------------------------------------

function fct_params
{
local L_PROG=${SH_DIR}/${SH_PROG} # Nom absolu du script 
local L_IDX=0                     # Index de position de l option dans la declaration
local L_IDX2=0                    # Index de position de l option dans la declaration
local L_PARAM=""                  # Ligne de declaration
local L_PARAM_ARGS=""             # Ligne de declaration pour un argument sans option
local L_PARAM_ARGS_DEF=0          # Detection d un arguments de script defini par defaut (0=non, 1=oui)
local L_PARAM_ARGS_CTL=""         # Liste des valeurs possible pour les arguments du scripts
local L_PARMF=""                  # Fichier contenant l extraction de la declaration
local L_OPT_OBLIGATOIRE=""        # Liste des options obligatoire separees par " "
local L_VAR=""                    # Nom de la variable contenant les argument
local L_VAL=""                    # Valeur de l argument
local L_DEFARG=""                 # Valeur par defaut d un argument
local L_OPTSET=0                  # Map binaire des option positionnees
local L_OPTEXCLUDE=""             # Map binaire des option mutuellement execlusive
local L_OPTINCLUDE=0              # Tableau de map binaire qui pour chaque option fourni la liste des options inclusive
local L_OPTINC=0                  # Map binaire des options pocedant une liste d inclusion
local L_OPTINCONNU=""             # Liste des options non reconnu
local L_OPTARGS_CTL=""            # Liste des valeurs possible pour les arguments d une option
local L_OPTDEF=0                  # detection d une valeur par defaut pour une option (0=non, 1=oui) 
local L_NB_MINARG=0               # Nombre d argument obligatoire
local L_NB_MAXARG=0               # Nombre d argument max
local L_NB_ARG=0                  # Indexe
local L_OPTMAJ="non"              # Option de mise en majuscule des arguments
local L_TMP=""                    # Variable temporaire a tout faire ;-)
local L_ERREUR=0                  # Detection des erreurs
local L_ERREUR_MSG=""             # Table de libelle d erreur
local L_OPT_NOM=""                # Tableau des option declare
local L_UORI=""                   # Utilisateur a l origine de la demande d execution du script
local L_UEXE=""                   # Utilisateur sous lequel s execute le script

# -- Le srcipt doit etre defini, pour lire la declaration des options !!
# -- Il s agit d une securite au cas ou "init.conf" n aurais pas ete sourcee
if [ -z "${L_PROG}" ]
then
    fct_message -color rouge "<lib:fct_params> Le nom du script Bash n est pas defini"
    fct_erreur 254
fi

# -- Extraction des options de la declaration
# -- ----------------------------------------
# -- Definition d un fichier tempon ( ${L_PARMF} ) pour acceuillir l entete du script contenant la declaration
# -- des options. Comme ce fichier va etre parcouru souvent, on le charge en RAM disque de preference ( sur /dev/shm).
# -- Le nom  du fichier tempon sera le nom du script suffixee par ".parms" en lieu et place de ".sh"
L_PARMF="${SH_PROG%*.sh}_${SH_SESSION_ID}.parms"
[ -d /dev/shm ] && L_PARMF="/dev/shm/${L_PARMF}" || L_PARMF="/tmp/${L_PARMF}"
> ${L_PARMF}

# -- Extraction de la declaration des arguments du script et affectation de la valeur par defaut
# -- Il s agit de recuperer la dernier ligne de l entete du script qui commence par "# ARG:"
L_PARAM_ARGS=`grep -E "^# *@ARG:" ${L_PROG}|head -1|sed "s/# *@ARG: *\([^ #]*\).*$/\1/"|tail -1`
if [ -n "${L_PARAM_ARGS}" ]
then
    # -- Un arguments a ete declare on initialise la valeur par defaut
    L_DEFARG=`echo ${L_PARAM_ARGS}|cut -d: -f4`  # Valeur par defaut de l arguments
    L_VAR=`echo ${L_PARAM_ARGS}|cut -d: -f2`     # Nom de la variable acceuillant la valeur de l argument
    L_VAR=${L_VAR:="SH_ARGS"}                    # Nom par defaut de la variable acceuillant la valeur de l argument

    # -- detection d une valeur par defaut pour l argument du script
    # -- La variable L_PARAM_ARGS_DEF sera utilise pour ecraser le parametre par defaut si ce dernier a ete soumis au script
    if [ -n "${L_DEFARG}" ] && L_PARAM_ARGS_DEF=1 || L_PARAM_ARGS_DEF=0
    then
        L_PARAM_ARGS_DEF=1
        # -- initialisation de la valeur par defaut, si cela n a pas ete effectuer dans le fichier de conf du script
        eval ${L_VAR}=\$\{${L_VAR}:=\"${L_DEFARG}\"\}
    else
        L_PARAM_ARGS_DEF=0
    fi

    # -- On recupere la liste des valeurs possibles pour les arguments du script
    L_PARAM_ARGS_CTL=`echo ${L_PARAM_ARGS}|cut -d: -f5`
fi

# -- Extraction de la declaration des options de l entete du script, et chargement dans le fichier tampon
L_IDX=0
grep -E "^# *@OPT:" ${L_PROG}|sed "s/# *@OPT: *\([^ #]*\).*$/\1/" > ${L_PARMF}

# -- Si aucun parametre n est declare dans l entete du script alors on laise le script gere lui meme les parametres d entree
# -- Cette partie de code est temporaire le temps qe les scripts existant adopte cette librairie. Le probleme c est 
# -- que les options par defaut (-h,-s ...) ne seront pas gere pour un scripts qui n a pas d option, pour contourner ce probleme
# -- Il faut declarer une oprion bidon dans l entete du script
# -- On compte le nombre d option declaree :
L_IDX=`wc -l ${L_PARMF}|awk '{print $1}'`
if [ ${L_IDX} -eq 0 ]
then
    # Pas d option declaree, on supprime le fichier tempon et on sort
    [ -f ${L_PARMF} -a -n "${L_PARMF}" ] && rm -f ${L_PARMF}
    return 0
fi

# -- Ajouter a cette liste les options pris en charge par defaut
# -- -h, -s, -dbg, -log et -hist
for L_PARAM in "fb:h::0::::" "fb:s::0::::" "fn:dbg:SH_NIV_DEBUG:1::::" "fb:log:SH_ARG_LOG:0/1::::" "fn:hist:SH_ARG_HIST:0/1:10:::" "fb:cpt:SH_ARG_CPT:0/1::::"
do
  echo "${L_PARAM}" >> ${L_PARMF}
done

# -- Initialisation des variables
# -- On parcours la liste des options declarees qui a ete extraite precedement.
# -- Puis on initialise les variables qui servirons de comparaison par la suite 
# -- avec les options soumis au script...
L_IDX=0
while read L_PARAM
do
  L_OPT_LIGNE[${L_IDX}]=${L_PARAM}                      # -- Ligne de parametre d une option
  L_OPT_NOM[${L_IDX}]=`echo ${L_PARAM}|cut -d: -f2`     # -- Nom de l option en cours de taritement
  eval SH_OPTION_${L_OPT_NOM[${L_IDX}]}=0               # -- Par defaut on intialise l indicateur d utilisation d une option a faux (0)

  # -- On verifie que la declaration comporte bien 7 ou 8 champs
  L_TMP=`echo ${L_PARAM}|sed 's/[^:]//g'`
  if [ ${#L_TMP} -lt 6 -o ${#L_TMP} -gt 7 ]
  then
      L_ERREUR_MSG[1]="<lib:fct_params> La declaration de l option \"${L_OPT_NOM[${L_IDX}]}\" ne comporte pas le nombre de champs requis (7 ou 8)"
      L_ERREUR=1
  else
      [ `echo ${L_PARAM}|cut -d: -f1|grep -c "o"` -eq 1 ] && L_OPT_OBLIGATOIRE="${L_OPT_OBLIGATOIRE}${L_OPT_NOM[${L_IDX}]}:${L_IDX} "
      # -- On controle que la declarartion est bien unique 
      L_TMP=L_POS_${L_OPT_NOM[${L_IDX}]}
      if [ -n "${!L_TMP}" ]
      then
          L_ERREUR_MSG[2]="<lib:fct_params> Declaration dupliquee de l option : ${L_OPT_NOM[${L_IDX}]}"
          L_ERREUR=2
      else
          eval ${L_TMP}=${L_IDX}
      fi
    
      # -- Affectation de la valeur par defaut pour les parametres non booleen, ayant defini une valeur par defaut
      L_DEFARG=`echo ${L_PARAM}|cut -d: -f5`                # valeur par defaut
      if [ `echo ${L_PARAM}|cut -d: -f1|grep -c "b"` -eq 0 -a -n "${L_DEFARG}" ]
      then
          L_VAR=`echo ${L_PARAM}|cut -d: -f3`               # Nom de la variable acceuillant la valeur de l argument
          L_VAR=${L_VAR:="SH_ARG_${L_OPT_NOM[${L_IDX}]}"}   # Nom par defaut de la variable acceuillant la valeur de l argument  
          eval ${L_VAR}=\$\{${L_VAR}:=\"${L_DEFARG}\"\}     # Valorisation, si cela n a pas ete effectuer dans le fichier de conf du script
      fi      
  fi
  ((L_IDX++))
done < ${L_PARMF}

# -- Le fichier tempon ${L_PARMF} n est plus utile
[ -f ${L_PARMF} -a -n "${L_PARMF}" ] && rm -f ${L_PARMF}

# -- Calcul des exclusions et inclusion
# -- ----------------------------------
L_IDX=0
while [ ${L_IDX} -le ${#L_OPT_NOM[*]} ] 
do
  # -- Option mutuellement exclusive
  L_PARAM=`echo ${L_OPT_LIGNE[${L_IDX}]}|cut -d: -f6|sed 's/,/ /g'`
  if [ -n "${L_PARAM}" ]
  then
      # -- Une liste d exclusion a ete defini pour cette option
      # -- On contruit un Bitmap listant les options incompatibles
      for L_TMP in ${L_PARAM}
      do
        eval L_IDX2=\${L_POS_${L_TMP}}
        if [ -z "${L_IDX2}" ]
        then
            L_ERREUR_MSG[3]="<lib:fct_params> L option ${L_TMP} declaree dans la liste d exclusion de l option ${L_OPT_NOM[${L_IDX}]} est inconnue"
            L_ERREUR=3
        else
            L_OPTEXCLUDE="${L_OPTEXCLUDE} ${L_OPT_NOM[${L_IDX}]},${L_TMP}:$(( 2 ** ${L_IDX2} + 2 ** ${L_IDX} ))"
        fi
      done
  fi
  # -- Option inclusive
  L_PARAM=`echo ${L_OPT_LIGNE[${L_IDX}]}|cut -d: -f7|sed 's/,/ /g'`
  if [ -n "${L_PARAM}" ]
  then
      # -- Une liste d inclusion a ete defini pour cette option
      # -- On contruit un Bitmap listant les options obligatoire qui doivent etre position avec l option L_IDX 
      # -- Map des option  qui declare une inclusion
      L_OPTINC=$(( 2 ** ${L_IDX} + ${L_OPTINC} ))
      L_VAL=0
      for L_TMP in ${L_PARAM}
      do
        eval L_IDX2=\${L_POS_${L_TMP}}
        if [ -z "${L_IDX2}" ]
        then
            L_ERREUR_MSG[4]="<lib:fct_params> L option ${L_TMP} declaree dans la liste d inclusion de l option ${L_OPT_NOM[${L_IDX}]} est inconnue"
            L_ERREUR=4
        else
            L_VAL=$(( 2 ** ${L_IDX2} + ${L_VAL} ))
        fi
      done
      L_PARAM=`echo ${L_PARAM}|sed 's/ /,/g'`
      L_OPTINCLUDE[${L_IDX}]="${L_PARAM}:${L_VAL}"
  fi
  (( L_IDX++ ))
done

# -- Analyse des options et argument sousmis au script
# -- -------------------------------------------------
# -- Si une erreur a ete detecte dans les declaration ont ne fait pas l analyse
if (( ! ${L_ERREUR} ))
then
    # -- Aucune option sousmise ?
    # -- si oui, on verifie l existance d option obligatoire puis on sort...
    if [ ${#} -eq 0  -a ${#L_OPT_OBLIGATOIRE} -gt 0 ]
    then
        L_ERREUR_MSG[5]="Au moins une des options suivantes est requise : `echo ${L_OPT_OBLIGATOIRE}|sed 's/:[0-9]*//g'`"
        L_ERREUR=5
    fi

    # -- Pas d erreur detecte dans la declarartion des options. On peut continuer ...
    while [ ${#} -gt 0 ]
    do
      # -- Des options ont ete utilisees ...
      # -- Lecture de la ligne de commande
      if [ ${1:0:1} = "-" ]
      then
          # -- Nous sommes en presence d une option
          # -- L option a t elle ete declaree ?
          if [ `echo ${L_OPT_NOM[*]}|grep -cw ${1:1}` -eq 0 ]
          then
              # -- L option n a pas ete declare dans l entete du script 
              L_OPTINCONNU="${L_OPTINCONNU}${1:1} "
              shift
              continue
          fi
          eval L_IDX=\${L_POS_${1:1}}
          L_OPTSET=$(( ${L_OPTSET} + 2 ** ${L_IDX} ))
          eval SH_OPTION_${L_OPT_NOM[${L_IDX}]}=1

          # -- Recuperation des arguments de l option
          # -- Nombre d argument pour cette option ?
          L_NB_ARG=0
          L_NB_MINARG=`echo ${L_OPT_LIGNE[${L_IDX}]}|cut -d: -f4`
          if [ `echo ${L_NB_MINARG}|grep -c "/"` -eq 0 ]
          then
              # -- Seul le nombre max d argument a ete renseigne ( ou pas si L_NB_MINARG est vide )
              [ -z "${L_NB_MINARG}" ] && L_NB_MAXARG=-1 || L_NB_MAXARG=$(( ${L_NB_MINARG} - 1 ))
              L_NB_MINARG=0
          else
              # -- le nombre de agument est declare sous la forme "min/max"
              L_NB_MAXARG=$(( ${L_NB_MINARG#*/} - 1 ))
              # -- Si la forme declare est "nim/" alors L_NB_MAXARG vaut -1
              # -- dans ce cas on considere le nombre d argument infini (999999)
              (( ! ${L_NB_MAXARG} + 1 )) && L_NB_MAXARG=999999
              L_NB_MINARG=${L_NB_MINARG%/*}
          fi
          # -- Existe t-il une liste de valeurs possible pour les argument de cette option ?
          L_OPTARGS_CTL=`echo ${L_OPT_LIGNE[${L_IDX}]}|cut -d: -f8`
          
          # -- Les argument doivent il etre transforme en majuscule ?
          [ `echo ${L_OPT_LIGNE[${L_IDX}]}|cut -d: -f1|grep -c "M"` -eq 1 ] && L_OPTMAJ="oui" || L_OPTMAJ="non"
          # -- Recuparation du nom de la variable qui va contenir les argument
          L_VAR=`echo ${L_OPT_LIGNE[${L_IDX}]}|cut -d: -f3`
          [ -z "${L_VAR}" ] && L_VAR="SH_ARG_${L_OPT_NOM[${L_IDX}]}"
          # -- Lecture des arguments ...
          while [ ${L_NB_ARG} -le ${L_NB_MAXARG} ]
          do
            [ "${L_OPTMAJ}" = "oui" ] && L_VAL=`echo ${2}|tr a-z A-Z` || L_VAL="$2"
            if [ "${L_VAL:0:1}" = "-" -o -z "${L_VAL}" ]
            then
                # -- Option suivante ou fin de ligne !!
                if [ ${L_NB_ARG} -lt ${L_NB_MINARG} ]
                then
                    L_ERREUR_MSG[6]="L option \"${L_OPT_NOM[${L_IDX}]}\" attend ${L_NB_MINARG} argument(s) a minima"
                    L_ERREUR=6

                fi
                break
            else
                # -- Ici on pourrais valider la concordance des types ...

                # -- Control de la valeur si une liste de valeurs possible a ete defini pour cette option
                if (( ${#L_OPTARGS_CTL} ))
                then
                    # -- Une liste a ete defini, la valeur de l argument courant est-elle presente ?
                    if (( ! `echo "${L_OPTARGS_CTL}"|grep -cw "${L_VAL}"` ))
                    then
                        # -- la valeur n est pas presente dans la liste !!
                        L_ERREUR_MSG[12]="L argument \"${L_VAL}\"  n est pas valide pour l option ${L_OPT_NOM[${L_IDX}]} (Argument attendu : ${L_OPTARGS_CTL})\n"
                        L_ERREUR=12
                    fi
                fi

                # -- Valorisation de la variable d accueil
                if [ ${L_NB_MAXARG} -eq 0 ]
                then
                    # -- Un seul argument est attendu
                    eval ${L_VAR}=\"${L_VAL}\"
                else
                    # -- Plusieurs arguments sont attendu ... On initialise un tableau
                    eval ${L_VAR}[${L_NB_ARG}]=\"${L_VAL}\"
                fi
                shift
            fi
            ((L_NB_ARG++))
          done
      else
          # -- Nous somme en presence d un argument
          # -- On verifier que l argument a ete declare
          if (( ${#L_PARAM_ARGS} ))
          then
              # -- Nom de la variable d acceuille des arguments
              L_VAR=`echo ${L_PARAM_ARGS}|cut -d: -f2`
              [ -z "${L_VAR}" ] && L_VAR="SH_ARGS"
              # -- Les argument doivent il etre transforme en majuscule ?
              [ `echo ${L_PARAM_ARGS}|cut -d: -f1|grep -c "M"` -eq 1 ] && L_VAL=`echo ${1}|tr a-z A-Z` || L_VAL=$1
              # -- la valeur de l argument est-elle presente dans la liste des valeurs possible (si cette liste a ete defini)
              if (( ${#L_PARAM_ARGS_CTL} ))
              then
                  if (( ! `echo "${L_PARAM_ARGS_CTL}"|grep -cw "${L_VAL}"` ))
                  then
                      # -- la valeur n est pas presente dans la liste !!
                      L_ERREUR_MSG[12]="L argument \"${L_VAL}\"  n est pas valide pour ce script (Argument attendu : ${L_PARAM_ARGS_CTL})\n"
                      L_ERREUR=12
                  fi
              fi
              # -- Initialisation de la variable d acceuille en fonction de la taille courante du tableau
              # -- Taille courante du tableau accueillant les arguments moins l arguments par defaut ( On ecrase l argument positionne par defaut )
              eval L_NB_ARG=\$\(\( \${#${L_VAR}[*]} - ${L_PARAM_ARGS_DEF} \)\)
              (( ${L_PARAM_ARGS_DEF} )) && (( L_PARAM_ARGS_DEF-- ))
              # -- Si pas encore initialise alors la taille est 0
              (( ${L_NB_ARG} )) && eval ${L_VAR}[${L_NB_ARG}]=${L_VAL} || eval ${L_VAR}=${L_VAL} 
          else
              # -- Pas de declaration !!
              (( ! ${#L_ERREUR_MSG[11]} )) && L_ERREUR_MSG[11]="L argument suivant a ete dectecte sans declaration : "
              L_ERREUR_MSG[11]="${L_ERREUR_MSG[11]}\"${1}\" "
              L_ERREUR=11 
          fi     
      fi
      shift
    done
fi

# -- Controle des options et arguments obligatoires
# -- ----------------------------------------------
if (( ! ${L_ERREUR} ))
then
    # -- Option obligatoire ...
    for L_TMP in ${L_OPT_OBLIGATOIRE}
    do
      if [ $(( ${L_OPTSET} & 2**${L_TMP#*:} )) -eq 0 ]
      then
          # -- L option obligatoire L_TMP n a pas ete positionnee
          # -- On controle que cette option n est pas une exclusion d une option obligatoire positionnee
          L_PARAM=`echo ${L_OPT_LIGNE[${L_TMP#*:}]}|cut -d: -f6|sed 's/,/ /g'`
          L_VAR=0
          if [ -n "${L_PARAM}" ]
          then
              # -- L option L_TMP pocede une liste d exclusion
              for L_IDX2 in ${L_PARAM}
              do
                eval L_IDX=\${L_POS_${L_IDX2}}
                (( !${L_VAR} )) && L_VAR=$(( ${L_OPTSET} & 2**${L_IDX} ))
              done
          fi
          # -- Si L_VAR est null alors l option L_TMP aurais du etre positionnee
          if [ ${L_VAR} -eq 0 ]
          then
              [ -z "${L_ERREUR_MSG[7]}" ] && L_ERREUR_MSG[7]="Les options suivantes sont requises : "
              L_ERREUR_MSG[7]="${L_ERREUR_MSG[7]}${L_TMP%:*} "
              L_ERREUR=7
          fi
      fi    
    done
    # -- Arguments declare ? ...
    if (( ${#L_PARAM_ARGS} ))
    then
        # -- Nom de la variable d acceuille des arguments
        L_VAR=`echo ${L_PARAM_ARGS}|cut -d: -f2`
        [ -z "${L_VAR}" ] && L_VAR="SH_ARGS"
        # -- Nombre d argument attendu ...
        L_NB_MAXARG=`echo ${L_PARAM_ARGS}|cut -d: -f3`
        # -- Si le nombres d argument n est pas defini alors par defaut on considere qu il peut etre infini
        [ -z "${L_NB_MAXARG}" ] && L_NB_MAXARG=999999
        if [ `echo ${L_NB_MAXARG}|grep -c "/"` -eq 0 ]
        then
            # -- On n a pas trouve le separateur "/" donc pas de minima defini
            # -- l argument est il obligatoire ?
            L_TMP=`echo ${L_PARAM_ARGS}|cut -d: -f1|grep -c "o"`
            (( ${L_TMP} )) && L_NB_MINARG=1 || L_NB_MINARG=0
        else
            L_NB_MINARG=${L_NB_MAXARG%/*}
            L_NB_MAXARG=${L_NB_MAXARG#*/}
            # -- Si L_NB_MAXARG n est pas defini alors on considere qu il peut etre infini
            [ -z "${L_NB_MAXARG}" ] && L_NB_MAXARG=999999
        fi
        [ ${L_NB_MAXARG} -lt 1 ] && L_NB_MAXARG=1
        # -- Nombre d argument soumis ... ( Taille du tableau d arguments )
        eval L_NB_ARG=\${#${L_VAR}[*]}
        if [ ${L_NB_ARG} -lt ${L_NB_MINARG} ]
        then
            L_ERREUR_MSG[13]="Le script ${SH_PROG} attend a minima ${L_NB_MINARG} argument(s)"
            L_ERREUR=13
        fi
        if [ ${L_NB_ARG} -gt ${L_NB_MAXARG} ]
        then
            L_ERREUR_MSG[14]="Trop d arguments passes. Le script ${SH_PROG} attend au maximun ${L_NB_MAXARG} argument(s)"
            L_ERREUR=14
        fi
    fi
fi

# -- Controle des exclusion
# -- ----------------------
for L_TMP in ${L_OPTEXCLUDE}
do
  if [ $(( ${L_OPTSET} & ${L_TMP#*:} )) -eq ${L_TMP#*:} ]
  then
      L_ERREUR_MSG[8]="Les options ${L_TMP%:*} sont mutuellement exclusives"
      L_ERREUR=8
      (( L_ERREUR_NB++ ))
  fi
done

# -- Controle des inclusion
# -- ----------------------
if [ $(( ${L_OPTSET} & ${L_OPTINC} )) -ne 0 ]
then
    # -- Une option exigeant une inclusion a ete positionne
    L_IDX=0
    while [ ${L_IDX} -le ${#L_OPT_NOM[*]} ]
    do
      if [ $(( (2 ** ${L_IDX}) & ${L_OPTSET} & ${L_OPTINC} )) -ne 0 ]
      then
          # -- L option L_IDX a ete positionne est pocedent une liste d inclusion
          if [ $(( ${L_OPTSET} & ${L_OPTINCLUDE[${L_IDX}]#*:} )) -ne ${L_OPTINCLUDE[${L_IDX}]#*:} ]
          then
              L_ERREUR_MSG[9]="L option ${L_OPT_NOM[${L_IDX}]} exige l usage de(s) (l) option(s) ${L_OPTINCLUDE[${L_IDX}]%:*}"
              L_ERREUR=9
          fi
      fi
      (( L_IDX++ ))
    done
fi

# -- Controle des option inconnu
# -- ---------------------------
if [ -n "${L_OPTINCONNU}" ]
then
    L_ERREUR_MSG[10]="Option inconnue(s) detectee(s) : ${L_OPTINCONNU}"
    L_ERREUR=10
fi

# -- Nettoyage
# -- ---------
# -- Suppression des variables tempon
for L_PARAM in ${L_OPT_NOM[*]}
do
  eval unset L_POS_${L_PARAM}
done

# -- Gestion des options par defaut : -h -log -hist -s, -cpt et -dbg
# -- ---------------------------------------------------------------
# -- L option dbg n a pas de traitement particulier elle n apparaitras donc pas ci-dessous.
# -- Creation d un masque binaire pour determiner les options positionnee
L_VAL="${SH_OPTION_h}${SH_OPTION_log}${SH_OPTION_hist}${SH_OPTION_s}${SH_OPTION_cpt}"
if [ ${L_VAL} -ne 0 ]
then
    if (( 2#${L_VAL} & 2#00010 ))   # -- Comparaison binaire bit a bit vrai si l option -s est positionnee
    then
        # -- Option s
        SH_SILENCE="oui"
    fi
    # -- Une option gere par defaut a ete positionnee
    if (( 2#${L_VAL} & 2#10000 ))
    then
        # -- Option h : affichage de l aide
        fct_usage "${SH_DIR}/${SH_PROG}"
        fct_erreur 0
    fi
    if (( 2#${L_VAL} & 2#01000 ))
    then
        # -- Option log
        # -- Recherche du dernier journal
        [ -z "${SH_ARG_LOG}" ] &&  SH_ARG_LOG=`tail -4 ${SH_FICTRC}|grep "fin"|cut -d: -f6|sed 's/(//;s/)//;s/  *//g'`
        L_VAR=`ls ${NC_EXPL_LOG}|grep -c ${SH_ARG_LOG}`
        if (( ${L_VAR} ))
        then
            view ${NC_EXPL_LOG}/*${SH_ARG_LOG}*
        else
            fct_message -color rouge "Le journal d execution de la session ${SH_ARG_LOG} du script ${SH_PROG} n existe plus"
        fi
        fct_erreur 0
    fi
    if (( 2#${L_VAL} & 2#00001 ))
    then
        # -- Option cpt
        # -- Recherche du dernier compte-rendu
        [ -z "${SH_ARG_CPT}" ] &&  SH_ARG_CPT=`tail -4 ${SH_FICTRC}|grep "fin"|cut -d: -f4|sed 's/(//;s/)//;s/  *//g'`
        L_VAR=`ls ${NC_EXPL_CPT}|grep -c ${SH_ARG_CPT}`
        if (( ${L_VAR} ))
        then
            view ${NC_EXPL_CPT}/*${SH_ARG_CPT}*
        else
            fct_message -color rouge "Le compte-rendu de la session ${SH_ARG_CPT} du script ${SH_PROG} n existe plus"
        fi
        fct_erreur 0
    fi
    if (( 2#${L_VAL} & 2#00100 ))
    then
        # -- Option hist
        fct_affiche_ligne entete "Historique des ${SH_ARG_HIST} dernieres executions du script ${SH_PROG}" "Date,18" "Utilisateur(Origine,20:Exec,20)" "Session,16" "Log,3" "Cpt,3" "Code,5" "Parametre,50"
        SH_ARG_HIST=$(( ${SH_ARG_HIST} * 3 ))
        tail -${SH_ARG_HIST} ${SH_FICTRC}|grep "Parametre" | while read L_VAL
        do
          G_TMP=`echo ${L_VAL}|sed 's/ Parametre .*$/:/;s/[^:]//g'`  # Pour assurer la compatibilite ascendante
          G_TMP=$(( 7 - ${#G_TMP} ))             # Nombre de champs 6 ou 8 ?
          L_PARAM=`echo ${L_VAL}|cut -d: -f$(( 8 - ${G_TMP} ))-`
          (( ${G_TMP} )) && L_UORI='' || L_UORI=`echo ${L_VAL}|cut -d: -f4`
          (( ${G_TMP} )) && L_UEXE='' || L_UEXE=`echo ${L_VAL}|cut -d: -f5`
          L_IDX=`echo ${L_VAL}|cut -d: -f$(( 6 - ${G_TMP}))|sed 's/(//;s/)//'`
          L_IDX2=`echo ${L_VAL}|cut -d: -f$1-3`
          L_VAR=`ls ${NC_EXPL_LOG}|grep -c ${L_IDX}`
          L_PARMF=`ls ${NC_EXPL_CPT}|grep -c ${L_IDX}`
          (( ${L_VAR} )) && L_VAR="X" || L_VAR=""
          (( ${L_PARMF} )) && L_PARMF="X" || L_PARMF=""
          L_TMP=`grep ${L_IDX} ${SH_FICTRC}|grep "fin"|cut -d- -f2`
          # -- Si L_TMP est vide, alors il s agit de la session en cours, on n affiche pas le resultat !
          [ -n "${L_TMP}" ] && fct_affiche_ligne "${L_IDX2}" "${L_UORI}" "${L_UEXE}" "${L_IDX}" "${L_VAR}" "${L_PARMF}" "${L_TMP}" "${L_PARAM}"
        done
        fct_affiche_ligne pied
        fct_erreur 0
        fct_erreur 0
    fi
fi

# -- Sortie
# -- ------
if (( ${L_ERREUR} ))
then
    L_IDX=14
    while (( ${L_IDX} ))
    do
      [ -n "${L_ERREUR_MSG[${L_IDX}]}" ] && fct_message -color rouge "${L_ERREUR_MSG[${L_IDX}]}"
      (( L_IDX-- ))
    done
    fct_erreur 254
fi 
return 0
}

typeset -Ffx fct_params