#f Package d'analyse d'argument :


# 10/10/01 (diam) version 1.0 : refonte complete et utilisation dans stead
# 22/08/00 (diam) intégration à stead et passage en version 0.2
# 16/09/01 (diam) suppression de l'argument arglistName
#        choix automatique args ou argv
# 
# 
package provide parsarg 1.0

package require xtcl

## Parsarg_fullSpec -- extraction d'options en fonction d'une specif complète
# 
# Syntaxe :  Parsarg_fullSpec ?keyValues? clientArrayName specs
# 
# Voir fichier annexe pour doc complete sur la syntaxe des "specs".
# 
#  clientArrayName : nom du tableau des valeurs à positionner
#  specs : description "complète" des options
#  (La liste à analyser (argv ou args) est déterminée automatiquement)
# 
# options :
#  -c
#  -cache  : suppose la spec figée pour la procédure appelante,
#           et mémorise la "compilation" de celle-ci en cache
#           Nom de ce tableau **global** en -cache :
#                ::parsarg_cacheSpec_<parentName>_swa$arg
#
#  -mode <mode> impose un des modes suivants :
#       partial : les options inconnues sont retransmise dans args
#                 et la chaine "--" éventuelles également/
#                 Ceci permet à la procédures appelante de retransmettre
#                 les options qu'elle ne gère pas.
#       normal : options inconnues retransmise, mais "--" est absorbée
#       strict : option inconnue entraine "error", et "--" absorbé
#       fast : en plus de strict, le mode d'option "-flag" n'est pas
#              supporté, et la chaine d'arret "--" n'est pas gèrer
#              (i.e. la liste d'arguments doit être paire)
#              
#       Remarque : 
#           L'analyse s'arrete des qu'une option inconnue est détectée.
#           Il faut donc que les option devant être extrait soient passées
#           **avant** les options destiné à être extrait plus tard.
#         
# 
# Principe : 
#   1 - lecture des options locales à cette proc
#   2 - compilation (i.e. analyse) et mémorisation la la spécif brutte
#       en une spécif standard (i.e non abrégée) dans un tableau de la forme :
#               set swa-level(-type) string
#               set swa-level(-default) "0"
#               set swa-debug(-type) flag
#       ou bien (si option -cache)
#               ::parsarg_cacheSpec_<parentName>_swa-debug(-type) flag
#   3 - analyse de la ligne de commande (args ou argv) et positionnement 
#       du tableau d'option
# 
# 
# Pour debug : pour afficher les tableaux des spec d'option de "MyProc":
#     eval report -v [info vars ::parsarg_cache_MyProc-*]
# 
proc Parsarg_fullSpec {args} {

    # 
    # 1 - Extraction des arguments propre à cette procédure
    # 
    # On peut imposer ici le comportement par défaut de la compilation
    #  - AVEC OU SANS CACHE
    #  - mode nomal ou strict
    # 
    if { ! [info exists ::Parsarg_fullSpec(-setDefault_cache)] } {
        set ::Parsarg_fullSpec(-setDefault_cache) 0
    }
    if { ! [info exists ::Parsarg_fullSpec(-setDefault_mode)] } {
        set ::Parsarg_fullSpec(-setDefault_mode) "normal"
    }
    
    set parsopt(-mode)    "AUTO"
    set parsopt(-cache)   "AUTO"
    # set parsopt(-cache)   1
    # 
    set allowsModes       "partial|normal|strict|fast"
    set i  0
    set argc [llength $args]
    #  on n'examine les options que s'il y en a :  :
    if {"x[string index $args 0]" == "x-"} {
        while {$i < $argc} {
            set arg [lindex $args $i]
            switch -glob -- $arg {
               --       {incr i ; break}
               -c       -
               -cache   { 
                    set parsopt(-cache) 1
               }
               -mode {
                    set parsopt(-mode) [lindex $args [incr i] ]
               }
               -setDefault_mode {
                    set ::Parsarg_fullSpec(-setDefault_mode) \
                                [lindex $args [incr i] ]
                    return
               }
               -setDefault_cache {
                    set ::Parsarg_fullSpec(-setDefault_cache) \
                                [lindex $args [incr i] ]
                    return
               }
               -*       {error "unknow option $arg"}
               default  {break  ;# no more options}
            }
            incr i
        }
    }
    if {$parsopt(-mode) == "AUTO"} {
        set parsopt(-mode) $::Parsarg_fullSpec(-setDefault_mode)
    }
    if {$parsopt(-cache) == "AUTO"} {
        set parsopt(-cache) $::Parsarg_fullSpec(-setDefault_cache)
    }
    if {![regexp "^${allowsModes}\$" $parsopt(-mode)]} {
        error "Option \"-mode $parsopt(-mode)\" invalide,\
                    options autorisées : $allowsModes"
    }
    if {![regexp {^0|1$} $parsopt(-cache)]} {
        error "Option \"-mode $parsopt(-cache)\" invalide,\
                    options autorisées : 0 | 1"
    }
    # report -v parsopt
    # i pointe sur le prochain argument non lu :
    set args [lrange $args $i end]
    if {[llength $args] != 2} {
        puts "!!!!! llength \$args = [llength $args]"
        puts "!!!!! \$args =  $args"
        error "syntaxe: Parsarg_fullSpec ?-keyValues? clientArrayName specs"
    }
    # Affectation des arguments obligatoires
    set clientArrayName [lindex $args 0]
    set specs           [lindex $args 1]
    
    # 
    # 2 - acces simplifiés aux variables à traiter par des upvar
    # 
    upvar $clientArrayName arga
    # La liste à analyser (argv ou args ?) :
    #    Attention : on veut détecter "[info level] == 0" du **parent** !
    if {[info level] == 1} {
        upvar argv argl
    } else {
        upvar args argl
    }
    # Une erreur fréquente d'utilation de parsarg est que la procédure 
    # appelante a oublié d'utilisé le mot clé args :
    if { ![info exists argl] } {
        set msg     "\nVous avez probablement oublié d'utiliser le"
        append  msg "\nmot clé \"args\" dans la procédure "
        append  msg "\"[info level -1]\" ??"
        error   "\n$msg\n\n"
    }
    
    
    # Construction des tableaux globaux mémorisant la spec normalisée
    # Ces tableaux seront de la forme  ::parsarg_cache_myProc-myFlag
    # 
    if {[info level] > 1} {
        set parentProcName [lindex [info level -1] 0]
    } else {
        set parentProcName "TOP_LEVEL"
    }

    if {$parsopt(-cache)} {
        # La spec compilée doit etre mémorisée dans une globale.
        set swBaseName  "::parsarg_cache_$parentProcName"
    } else {
        # Si la spec doit etre recompilée à chaque exécution, il ne faut pas
        # qu'elle soit globale sinon il y a risque d'interaction avec les 
        # valeurs de l'appel précédent.
        set swBaseName  "parsarg_cache_$parentProcName"
    }


    # 
    # 3 - Compilation de la spécif brute d'option (si nécessaire)
    # 
    if {!$parsopt(-cache) || ![llength [info vars $swBaseName ]]} {
        # report  "###### spec NON COMPILÉE INEXISTANTE => ON COMPILE !"
        parsarg_compilSpec $swBaseName $clientArrayName $specs
    } {
        # report  "###### spec DEJA COMPILÉE  => on passe !"
    }
    
    # DEBUG : Exemple d'affichage pour les options d'une proc particulière
    # if {[string match *move* $swBaseName]} {
    #     # report "Affichage des tableaux de spec d'option pour  $swBaseName\n"
    #     eval report -v [info vars $swBaseName*]
    # }
    

    # 
    # 4 - On affecte les valeurs par défaut aux variables sauf si
    #     l'option par défaut est notée "=" ou "parsargs:keep" auquel 
    #     cas on conserve la valeur initiale de la variable
    # 
    parsargSetToDefault $swBaseName
    
    ####################################################################
    # on commence à analyser la liste d'arguments effectivement passés
    # 
    set argc [llength $argl]
    set i 0
    while {$i < $argc} {
    
        # lecture de l'argument à examiner
        set key [lindex $argl $i]
        
        # examen de tous les cas possibles pour cet argument
        #   "--" : est extrait, puis l'extraction est interrompue,
        #   "-*" : examen et traitement du switch.
        #   autre : ce n'est plus une option 
        
        switch -glob -- $key {
        
           --  {
               # Si "-mode partial"  => on conserve "--"
               if {$parsopt(-mode) == "partial"} {incr i -1}
               break
           }
                      
           -*  {
            
               # acces au tableau contenant la spécif de ce switch 
               # eg.   ::parsarg_cache_test_1-debub() 
               upvar 0 $swBaseName$key swa

               # Traitement d'un switch inexistant
               if {![array exists swa]} {
                   # On pourrait traiter ici les switchs collés avant de hurler
                   if {$parsopt(-mode) == "strict"} {
                       # refus de toute option non autorisée
                       report -v swBaseName
                       set msg "unknow option $key"
                       append msg "\n[Parsarg_GetAllowedOptions -d $swBaseName]"
                       error \n\n$msg\n
                   } else {
                       # Cette fausse clé fait partie des arguments résiduelles
                       incr i -1
                       break
                   }
               }
               
               # Si c'est un alias : on redirige l'acces vers le bon switch 
               # en redéfinissant swa pour qu'il représente le switch original
               # e.g.  $swBaseName-v(-alias) = "verboseLevel"
               # 
               if {[info exists swa(-alias)]} {
                   upvar 0 $swBaseName$swa(-alias) swa
               }
               # Tout va bien, le switch existe : AU BOULOT
               if {[string equal $swa(-type) "flag"]} {
                   # traitement d'un switch :
                   
                   # swa(-value) peut être indéfinie si la spécification
                   # est explicite, mais incomplète.
                   if {![info exist swa(-value)]} {
                        set swa(-value) 1  
                   }
                   
                   # ENFIN : le but ultime de ce script (pour le type flag) !
                   uplevel [list set $swa(-variable) $swa(-value)]

                   if [info exists swa(-eval)] {
                      uplevel $swa(-eval)
                   }
                   incr i
                   continue   ;# lecture argument suivant
                   
               }
               
               # Traitement d'une option classique de la forme "-key value"
               # on extrait la valeur :
               set val [lindex $argl [incr i]]
               
               #                
               # ENFIN : le but ultime de ce script (pour option avec valeur) !
               # La variable est filtrée par la procédure de vérification
               # 
               uplevel [list set $swa(-variable)  \
                        [eval [concat $swa(-verifcmd) [list $val]]]]

               # traitement de l'option de clé -eval
               # L'action est exécutée **apres** l'affectation de 
               # l'option traitée (la variable peut donc etre lue par
               # l'action $swa(-eval) )
               if [info exists swa(-eval)] {
                  uplevel  $swa(-eval)
               }
                       
           }
           
           default  {incr i -1; break  ;# no more options}
        }
        incr i
    }
    # i pointe sur le dernier élément exploité.
    set argl [lrange $argl [incr i]  end]

    # si argl représente "argv", on met à jour la globale argc
    if {[info level] == 1} {
        uplevel #0 [list set argc [llength $argl]]
    }
} ;# endproc Parsarg_fullSpec

## parsarg_compilSpec -- compile la spec brute dans un tableau
# 
# Syntaxe :
#    parsarg_compilSpec swBaseName clientArrayName specs
#    
# Arguments :
#    - swBaseName : représente à la fois :
#      - nom de la liste de tous les switchs associés à une procédure
#      - préfixe du nom des tableaux associés à chaque switch.
#    
#    - clientArrayName : nom du tableau d'option fourni par la précédure
#      cliente (par exeple "opt" ou "arga")
#      
#    - spec : le spécif brute de description des options.
# 
# Cette précédure affectue une "compilation"  des specifications brutes
# d'option (spec) en une listes de switchs autorisés et créer un tableau
# associé à chaque switch.
# Par exemple, pour la procédure "myProc" et si l'on souhaite mémoriser
# la spec compilée en cache, on aura création de la liste :
# 
#     ::parsarg_cache_myProc = {-f1 -flag1 -k1 -key1 -key1 ...}
#   
# et des tableaux de la forme :
# 
#     ::parsarg_cache_myProc-f1(-alias) = "-flag1"
#     ::parsarg_cache_myProc-flag1(-default) = "0"
#     ::parsarg_cache_myProc-flag1(-type) = "flag"
#     ::parsarg_cache_myProc-flag1(-value) = "1"
#     ::parsarg_cache_myProc-flag1(-variable) = "arga(-flag1)"
#     ::parsarg_cache_myProc-flag1(-verifcmd) = "Parsarg_veriftype_flag"
# 
# 
proc parsarg_compilSpec { swBaseName clientArrayName specs } {
    
    upvar 1 $swBaseName switches
    
    # if {[string match *xtext_select* $swBaseName]} {
    #     report -v swBaseName $swBaseName clientArrayName switches
    # } 

    set previousSwitch "unknownSwitch"
    set i  [llength $specs]
    if {$i & 1} {
        error "specs doit être une liste paire"
    }
    
    while {$i >= 2} {
       
        set theSpec       [lindex $specs [incr i -1]]
        set theSwitch    -[lindex $specs [incr i -1]]
        
        # On mémorise ce switch dans la liste de tous les switch associés
        # à cette procédure :
        lappend switches $theSwitch
        
        # On rend le tableau d'option accessible par le nom "swa"
        # 
        upvar 1 $swBaseName$theSwitch swa
        
        # 4 - On remplace les specs simplifiées ("-", "flag", ...)
        #     par des specs standards equivalentes :
        #         "flag"  => {-type flag}
        #         "-"     => {-alias <otherSwitch>}
        #         XXX     => {-default XXX}
        #     Nota : 
        #         Le "<= 1" au lieu du "== 1" permet de définir une valeur par
        #         défaut vide par {} au lieu du singleton {""}
        #     
        #
        
        if {[llength $theSpec] <= 1} {

            switch -exact -- $theSpec {
                "-"     {
                    set swa(-alias) $previousSwitch
                    # plus besoin d'aller plus loin : previousSwitch 
                    # est deja traiter
                    continue
                }
                "flag"  {
                    set theSpec {-type flag  -default 0  -value 1}
                }
                "="  -
                "parsargs:keep" {
                    set theSpec {-default parsargs:keep}
                }
                "parsargs:equalSign" {
                    set theSpec {-default parsargs:equalSign}
                }
                default {
                    set theSpec [list  -default [lindex $theSpec 0]]
                }
            }
        }
                
        # 5 - La spec maintenant forcément au format "standard".
        #     (mais pas forcément complète !!!) 
        #     Elle est convertie en tableau
        # 
        # report -v swa theSpec
        array set swa $theSpec
                
        # 6 - On mémorise ce switch pour le prochain alias éventuel (= "-")
        set previousSwitch   $theSwitch 

    }
    
    # Première passe sur toutes les clés connues pour créer les clés secondaires
    # 
    foreach switch $switches   {
             
        upvar 1 $swBaseName$switch swa
        
        # 6 - On completes les options de switch manquantes par des valeurs
        #     par défaut raisonnables :
        # 
        if {![info exists swa(-type)]} {
            if {[info exists swa(-alias)]} {
                set swa(-type) alias
            } elseif {[info exists swa(-values)]} {
                set swa(-type) flagenum
            } else {
                set swa(-type) string
            }
        }
        # Pour les types enum ou flagenum, l'attribut  -values (ne pas 
        # confondre avec -value !) **doit** exister
        if {[regexp {^enum|flagenum$} $swa(-type)]} {
            if { ![info exists swa(-values)] } {
                error "\nl'argument \"-values ... \" indispensable avec le type\
                    \"-type $swa(-type)\" !\n"
            }
            # Tout va bien :  la valeur par défaut est le premier élément de 
            # la liste **sauf** si une autre valeur est spécifiée !
            # Attention, si le premier élement est une liste, c'est le
            # premier sous-élement qu'il faut prendre, car les autres
            # sont des alias comme dans l'exemple :
            #   -values { {forwards f}  {backwards b} }
            # 
            if { ![info exists swa(-default)] } { 
                set swa(-default) [lindex [lindex $swa(-values) 0] 0]
            }

            # on construit la regexp de vérification 
            set swa(-regexp) "^[join $swa(-values) |]\$"
                        
        }
        
    }
    
    # Apres un premier examen des clés, on refait une passe pour compléter.
    # En effet, on doit etre sûr de connaitre toutes les clés principales de 
    # type flagenum avant de créer les flags secondaires associés  
    foreach switch $switches   {
        
        upvar 1 $swBaseName$switch swa
        
        # Si la variable n'est pas précisée : on utilise le tableau 
        # passé en parametre
        if {![info exists swa(-variable)]} {
            set swa(-variable) [set clientArrayName]($switch)
            
            # On complète éventuellement la valeur par défaut des flags
            if {[string equal $swa(-type) flag]} {
                if {![info exist swa(-default)]} {
                    set swa(-default) 0
                }
                if {![info exist swa(-value)]} {
                    set swa(-value) 1
                }
            }
        } else {
            # 
            # Dans la cas ou la variable a été spécifiée, alors ne
            # doit PAS initialisé le flag (car le flag est lié à
            # une autre option !)
            # 
            if {[string equal $swa(-type) flag]} {
                
                if {![info exist swa(-default)]} {
                    set swa(-default) parsargs:keep
                }
                if {![info exist swa(-value)]} {
                    set swa(-value) 1
                }
            }
        }

        if {[string equal $swa(-type) "flagenum"]} {
            # on va contruire les flags associés à cette clé
            # # foreach val $swa(-values) {
            # #     lappend $swBaseName "-$val"
            # #     upvar 1 $swBaseName-$val other_swa
            # #     set other_swa(-type)      flag
            # #     set other_swa(-default)   parsargs:keep
            # #     set other_swa(-value)     $val
            # #     set other_swa(-variable)  $swa(-variable)
            # # }
            # 
            # Exemple de spec : chaque élement de values peut etre une 
            # liste de switch. Le premier détermine la valeur, les autres 
            # sont des alias pour cette valeur.
            # direction {
            #     -type   flagenum
            #     -values { {forwards f}  {backwards b} }
            # }
            foreach vals $swa(-values) {
                set val [lindex $vals 0]
                foreach aliasFlag  $vals  {
                    lappend $swBaseName "-$aliasFlag"
                    upvar 1 $swBaseName-$aliasFlag other_swa
                    set other_swa(-type)      flag
                    set other_swa(-default)   parsargs:keep
                    set other_swa(-value)     $val
                    set other_swa(-variable)  $swa(-variable)
                }
                
            }
        }
        


        # 7 - Construction de la procédure de vérification du type
        #
        # Cette phase de compil doit créer la commande de vérif et la 
        # mémoriser dans la variable d'option '-verifcmd xxx"
        # Cependant, si l'utilisateur utilise son propre type d'option
        # c'est à lui de fournir la procédure de vérification.
        # 
        # Vérification du type (option de clé -type)
        # Plusieurs cas peuvent se présenter :
        # 0 - l'utilisateur fourni la procédure : on n'utilisera qu'elle.
        # 1 - le type n'est pas précisé : on acceptera tout
        # 2 - le type est directement supporté par ce package
        #     (-type enum, -type flagenum, ...)
        # 3 - le type est directement supporter par tcl (string is ...)
        # 4 - l'utilisateur utilise l'option -regexp xxx 
        # 5 - l'utilisateur propose sa procédure de vérification
        #     (de la forme Parsarg_VerifType_<THE_USER_TYPE>)
        #
        # La vérif du type est faite **avant** la modifiction 
        # de l'option traitée
        # 
        
        while {1} {
            
            # Rajouter option "-verifcmd "userVerifProc" !!!
            # # # if {[string length [info proc $swa(-verifcmd)]]} {
            # # #     break
            # # # }
            if {[info exists swa(-verifcmd)] \
                    && [info proc $swa(-verifcmd)] != "" } {
                break
            }
            
            # Si c'est un type alias : on n'a pas de vérifi à faire
            # (elle sera fate sur l'original)
            if {$swa(-type) == "alias"} {
                break
            }
            
            # La commande sera une liste
            set swa(-verifcmd) [list]
            
            if { [lsearch -exact {alnum alpha ascii boolean control digit \
                     double false graph integer lower print punct \
                     space true upper wordchar xdigit } $swa(-type)] != -1} {
                lappend swa(-verifcmd) Parsarg_verifcmd_tcltype $swa(-type)
                break
            }
            if { [info exists swa(-regexp)] } {
                lappend swa(-verifcmd) Parsarg_verifRegexp $swa(-regexp)
                break
            } 
            if { [string equal "string" $swa(-type)]} {
                # il n'y aura rien à vérifier, mais il faut le mémoriser 
                # quand meme pour simplifier l'exploitation ultérieure !
                lappend swa(-verifcmd) Parsarg_verifcmd_string
                break
            } 
            
            # type inconnu : c'est l'utilisateur qui doit proposer sa propre
            # procédure de vérification 
            # exemple :
            #    proc Parsarg_veriftype_color {value} {
            #        ... 
            #        return $validColor
            #    }
            lappend swa(-verifcmd)  Parsarg_veriftype_$swa(-type)
            break
            
        }               
        

    } ;# endforeach

    # On refait une troisième passe maintenant que toutes les clés secondaire
    # sont connu (i.e celle spécifiée indirectement par les type enumflag 
    # ou alias...).
    # 
    foreach switch $switches   {

        
        upvar 1 $swBaseName$switch swa
        
        if {![info exists swa(-variable)] && ($swa(-type) != "alias") } {
            set swa(-variable) [set clientArrayName]($switch)
            
            # si un type flag n'est pas associé à la variable d'un autre
            # switch : on impose l'existence des valeur "on" et "off"
            # 
            # ATTENTION : ne pas initialiser un flag associé à la variable
            # d'une autre clé !
            # 
            if {[string equal $swa(-type) "flag"]} {
                if {![info exists swa(-default)]} {
                    set swa(-default) 0
                }
                if {![info exists swa(-value)]} {
                    set swa(-value) 1
                }
            }
        }
        
        # Enfin, si toujours pas de valeur par défaut spécifiée : on précise
        # explicitement de ne pas modifier la valeur existante
        if {![info exists swa(-default)] && ($swa(-type) != "alias")} {
            set swa(-default) parsargs:keep
        }

        # Toutes les options (sauf les alias) ont une valeur par défaut.
        # Mais il faut remplacer :
        #   - "=" par "parsargs:keep"
        #   - "parsargs:equalSign" par "="
        if { $swa(-type) != "alias" } {
            if { [string equal $swa(-default) "="] } {
                set swa(-default) "parsargs:keep"
            } elseif {[string equal $swa(-default) "parsargs:equalSign"]} {
                set swa(-default) "="
            }
        }
        
    } ;# endforeach
    
    # Une derniere passe de vérification. 
    # (Meme si pas utilisé, à garder commenté pour debug)
    # 
    # report "\nDERNIERE PASSE :"
    # foreach switch $switches   {
    #     
    #     upvar 1 $swBaseName$switch swa
    #     report " pour $swBaseName$switch :"
    #     report -v swa
    #     
    # } ;# endforeach

}

## parsargSetToDefault -- 
# 
# 
proc parsargSetToDefault { swBaseName } {
    
    upvar 1 $swBaseName switches
    # report "Début parsargSetToDefault"
    # report -v swBaseName $swBaseName switches
    foreach keyName $switches  {
        upvar 1  $swBaseName$keyName key
        if {[info exists key(-default)] && \
                    ![regexp -- {parsargs:keep$} $key(-default)]} {
           # report  "Init : [list set $key(-variable) $key(-default) ]"
           uplevel 2 [list set $key(-variable) $key(-default) ]
        }
    }    
}


## Parsarg_GetAllowedOptions - retourne options autorisée (specs complètes)
# 
# Imprime la liste des options autorisées avec les labels éventuels
# 
# Syntaxe :
#   Parsarg_GetAllowedOptions ?options? swBaseName
# 
# argument 
#  swBaseName : nom racine du tableau d'option précompilé
# 
# option :
#  -sort : les options sont affichée dans l'ordre alphabétique qu lieu 
#       de l'ordre donné pas la spec brute.
#  -verbose : affiche toutes les infos sur la specif d'option
#       sinon affiche seulement une ligne d'info.
# 
# ATTENTION : cette procédure ne peut fonctionner qu'apres la compilation
# de la spec !
# 
proc Parsarg_GetAllowedOptions {args} {

    Parsarg_fullSpec opt {
        d -
        debug    flag
        sort     flag
    }
    
    upvar 1 [lindex $args 0] swBaseName

    set msg "options autorisées :\n"
    if {$opt(-sort)} {
        set names [lsort $swBaseName]
    } else {
        set names $swBaseName
    }
    foreach key $names {
        
        # $swBaseName vaudra par exemple parsarg_cache_theClientProc
        # et $swBaseName$sw  vaudra  parsarg_cache_theClientProc-debug
        # upvar 0 $swBaseName swa
        upvar 1 $swBaseName$key swa
        
        append msg "  $key : "
        if {[info exists swa(-alias)]} {
            append msg "  alias pour $swa(-alias)\n"
            continue
        }
        
        if [info exists swa(-label) ] {
            append msg "    $swa(-label)\n"
        } else {
            append msg "    \n"
        }
        
        if {!$opt(-debug)} {
            continue
        }
        
        
        if [info exists swa(-variable) ] {
            append msg "    variable : $swa(-variable)\n"
        }
        if [info exists swa(-default) ] {
            append msg "      default : $swa(-default)\n"
        }
        if [info exists swa(-type) ] {
            append msg "      type : $swa(-type)\n"
        }
        if [info exists swa(-eval) ] {
            append msg "      action : $swa(-eval)\n"
        }
    }
    return $msg
}

## Parsarg_VerifType_integer et cie -- Procédures de vérification de type :
#  
# return une valeut considérée comme correcte (ce qui donne la possibilité 
# à ces procédure de corriger la valeur)
# En cas de probleme, génère une erreur
# 
proc Parsarg_verifRegexp {regexp string} {
    if {![regexp -- $regexp $string]} {
        error "incorrect argument $string: does'nt satisfy pattern $regexp!"
    } else {
        return $string
    }
}
proc Parsarg_verifcmd_tcltype { tcltype string} {
    if {![string is $tcltype $string]} {
        error "should be a valid $tcltype"
    } else {
        return $string
    }
}
proc Parsarg_verifcmd_string {string} {
    return $string
}
#./
