Introduction à Tcl 8.4


par ulis






© ulis, 2006

Licence NOL



INDEX



Les règles de base 5

Avant-goût 5

1. Mot 8

2. Ligne 8

3. Commande 8

4. Commentaire 8

5. Script 8

6. Script global 9

7. Script immédiat 9

8. Type d'une donnée 9

9. Valeur d'une donnée 9

10. Variable 9

11. Nom d'une donnée 10

12. Déclaration/Définition 10

13. Constante chaîne protégée 10

14. Chaîne standard 11

15. Evaluation 11

16. Procédures et environnements 12

17. Environnement d'exécution 12

18. Namespaces (programmation avancée) 13

19. Synthèse 15

Les commandes de base 16

1. set 16

2. puts 16

3. proc 16

4. global 17

5. variable 17

6. upvar 18

7. uplevel 18

8. expr 18

9. eval 19

10. incr 19

11. if 20

12. while 20

13. for 21

14. foreach 21

15. switch 21

16. catch 22

17. error 22

Les commandes de chaînes 24

1. Création d’une chaîne 24

2. Longueur d’une chaîne 24

3. Accès à un caractère dans une chaîne 24

4. Accès à une sous-chaîne 24

5. Recherche du premier index d’une sous-chaîne dans une chaîne 25

6. Recherche du dernier index d’une sous-chaîne dans une chaîne 25

7. Ajout d’une sous-chaîne en fin de chaîne 25

8. Remplacement d’une sous-chaîne dans une chaîne 25

9. Remplacement de sous-chaînes dans une chaîne 26

10. Changement de casse dans une chaîne 26

11. Autres commandes de chaîne 26

Les commandes de listes 27

1. Création d’une liste 27

2. Longueur d’une liste 27

3. Accès à un élément 27

4. Accès à une sous-liste 27

5. Modification d’un élément 28

6. Recherche de l’index d’un élément 28

7. Ajout d’éléments en fin de liste 28

8. Insertion d’éléments dans une liste 28

9. Remplacement d’éléments dans une liste 29

10. Tri d’une liste 29

11. Concaténation de listes 29

12. Création d'un chaîne à partir d'une liste 30

13. Création d'un liste à partir d'une chaîne 30

Les commandes de tableaux 31

1. Collection 31

2. Création d’un tableau, ajout dans un tableau 31

3. Existence d’un tableau 31

4. Nombre d’éléments d’un tableau 31

5. Référencement d’un tableau 32

6. Suppression dans un tableau 32

7. Noms des éléments d’un tableau 32

8. Contenu d’un tableau 32

Les commandes d'entrée-sortie 34

1. Canaux d'entrée-sortie 34

2. Ouverture d'un canal non socket 34

3. Ouverture d'un canal socket 34

4. Lecture d'un fichier ou d'un buffer sur un canal 35

5. Lecture d'une ligne sur un canal 35

6. Ecriture sur un canal 36

Lien utiles 37



Ce document est diffusé suivant la licence NOL (pas d’obligation pour vous ni pour moi).


Tcl est un langage de script inventé par John Ousterhout qui inventa aussi Tk, le Tool Kit graphique associé à Tcl.

Histoire de Tcl/Tk : http://www.tcl.tk/about/history.html



Les règles de base



Avant-goût


Voici un premier exemple commenté pour avoir un avant-goût de ce qu'est Tcl :


Ce petit programme (script) lit un fichier et remplace toutes les tabulations par des blancs.


# ===========================

# transform tabs into spaces

# ===========================

# -----------------

# defining the proc

# parm1: input file name or – (stdin)

# parm2: output file name or – (stdout)

# parm3: tabs size (defaults to 8)

# -----------------

# returns the count of lines

# -----------------


Commentaires. Ils sont introduits par le caractère #.


proc tab2space {ifn ofn {tabs 8}} \


Définition d'une procédure.

Les paramètres sont entre accolades ({}).

{tabs 8} indique que le paramètre tabs a 8 pour valeur par défaut.

L'anti-slash (\) de fin de ligne indique que la ligne logique continue sur la prochaine ligne physique.

La définition d'une procédure a pour structure : proc nom args body.

args et body sont entre accolades pour grouper leurs éléments.


{

# open input file

if {$ifn == "-"} { set ifp stdin } \

else { set ifp [open $ifn r] }


Commande if. Elle a pour structure (simplifiée) : if cond then-body else else-body.

La condition et les deux bodies sont entre accolades pour grouper leurs éléments.

Le dollar ($) devant ifn indique qu'il s'agit d'une variable (et non d'une constante chaîne) et qu'on veut utiliser la valeur de la variable.

Les guillemets (" ") autour de sont obligatoire pour indiquer que le signe == compare des chaînes (et non des nombres).

La commande set permet de donner une valeur à une variable. Ainsi set ifp stdin donne la valeur stdin à la variable ifp.

Dans [open $ifn r] les crochets ([ ]) indiquent qu'il faut évaluer le script immédiat qu'ils contiennent et remplacer l'ensemble de l'expression par la valeur retournée par le script. Ici, le résultat de la commande open.


# open output file

if {$ofn == "-"} { set ofp stdout } \

else { set ofp [open $ofn w] }

# read each line

set count 0

while {![eof $ifp]} \


Commande while. Elle a pour structure while cond body. La condition et le body sont entre accolades pour grouper leurs éléments.



{

set line [gets $ifp]

while {[set p [string first \t $line]] != -1} \


Commande string. Multiforme, elle est très complète. Ici l'opération first permet de retourner l'indice du premier caractère tabulation (\t) dans la chaîne contenue dans line.


{

set n [expr {$p % $tabs}]


Commande expr. Elle permet de faire des calculs. Comme elle analyse elle-même ses arguments, les accolades autour de l'expression empêchent Tcl de le faire de façon anticipée.


if {$n == 0} { set n $tabs }

set beg [string range $line 0 [incr n -1]]


Opération range de la commande string. Elle permet de sélectionner une sous-chaîne.

Commande incr. Elle incrémente la variable d'une certaine valeur et retourne la valeur de la variable.


set end [string range $line 0 [incr n 2] end]

set line "$beg[string repeat " " $n]$end"

}

puts $ofp $line


Commande puts. Elle envoie sur un canal ouvert en sortie une chaîne suivie d'un saut de ligne.


incr count

}

# return count


Commande return. Elle permet de sortir de la procédure en renvoyant un résultat. Ici le nombre de lignes traitées.


return $count

}


# -----------------

# using the proc

# -----------------

package require Tk


Commande package. Elle gère les packages. Ici l'opération require demande le chargement de l'extension Tk qui contient l'interface graphique portable de Tcl.


# get input file name

set ifn [tk_getOpenFile -title "tab2space: input file"]


Commande tk_getOpenFile. Elle fait partie de Tk. Elle ouvre une boîte de dialogue qui permet de choisir un fichier.

Elle peut avoir plusieurs arguments nommés. Ici c'est le titre (option -title) qui est donné.


# exit if no name

if {$ifn == ""} { exit }


Commande exit. Elle permet de terminer l’application.


# show console for result

catch { console show }


Commande console (avec son option show). Elle permet d'afficher une console sur les systèmes non Unixiens.

Commande catch. Elle récupère les erreurs (pour les systèmes Unixiens la commande console n'existe pas).


# call proc

tab2space $ifn - 2


Appel de la procédure avec ses arguments. L'argument - indique que le fichier de sortie est la sortie standard (console).



Voici à nouveau l'exemple mais non commenté :



# ===========================

# transform tabs into spaces

# ===========================

# -----------------

# defining the proc

# -----------------

# parm1: input file name or – (stdin)

# parm2: output file name or – (stdout)

# parm3: tabs size (defaults to 8)

# -----------------

proc tab2space {ifn ofn {tabs 8}} \

{

# open input file

if {$ifn == "-"} { set ifp stdin } \

else { set ifp [open $ifn r] }

# open output file

if {$ofn == "-"} { set ofp stdout } \

else { set ofp [open $ofn w] }

# read each line

set count 0

while {![eof $ifp]} \

{

set line [gets $ifp]

while {[set p [string first \t $line]] != -1} \

{

set n [expr {$p % $tabs}]

if {$n == 0} { set n $tabs }

set beg [string range $line 0 [incr n -1]]

set end [string range $line 0 [incr n 2] end]

set line "$beg[string repeat " " $n]$end"

}

puts $ofp $line

incr count

}

# return count

return $count

}


# -----------------

# using the proc

# -----------------

package require Tk

# get input file name

set ifn [tk_getOpenFile -title "tab2space: input file"]

# exit if no name

if {$ifn == ""} { exit }

# show console for result

catch { console show }

# call proc

tab2space $ifn - 2


1.Mot


Un mot est une suite de caractères qui se termine par un espace, la fin de la ligne ou la fin du script.

Un espace séparateur de mots peut être remplacé par une tabulation.


some words


2.Ligne


Une ligne est une suite de mots qui se termine par un caractère fin de ligne.

Il est possible de continuer une ligne (logique) sur la ligne (physique) suivante en protégeant le caractère fin de ligne par un anti-slash (\).


# this is \

a line


3.Commande


Une commande est une liste d'éléments dont le premier est le nom de la commande et les suivants sont des arguments.


Une commande se termine au premier caractère point-virgule (;), à la fin de la ligne ou à la fin du script qui la contient.

cmd arg1 arg2


Une commande retourne toujours un résultat (même vide).


Il n’y a pas de structure de contrôle : if , while… sont des commandes.

Il n’y a pas de différences entre les commandes définies dans Tcl et les commandes définies dans le script (au moyen de la commande proc) : elles sont évaluées de la même façon.


4.Commentaire


Un commentaire est une suite de mots dont le premier est le caractère dièse (#) et se termine par une fin de ligne.


Un commentaire se termine à la fin de la ligne ou à la fin du script qui le contient.

# this is a comment


Sur sa ligne, un commentaire peut être précédé par des commandes (terminées par des points-virgules).


cmd1 args1; cmd2 args2; # this is a comment


Piège 1 :

Dans ce cas le point-virgule terminant la dernière commande est obligatoire.


Piège 2 :

Voir le piège de la section 14 (Constante chaîne protégée) pour les accolades incluses dans un commentaire qui doivent être appairées ou protégées.


5.Script


Un script Tcl est une suite de commandes et de commentaires.


puts "Hello world!"; # display Hello on the console

exit; # exit from the script


Un script se termine à la fin du fichier qui le contient (script global), à la fin de la constante chaîne qui le contient (corps de procédure ou d’une autre commande), au crochet fermant (script immédiat).


Un script retourne toujours un résultat (même vide). Le résultat d’un script est le résultat de la dernière commande du script qui a été exécutée.


6.Script global


Le script global est inclus dans un fichier. Son exécution par Tcl correspond à l’application.


7.Script immédiat


Un script immédiat est un script entouré par des crochets ([ ]) et qui ne contient pas de fin de ligne (non protégée).


set a [cmd1 args1; cmd2 args2; # comment]


Remarque 1 :

Un script immédiat peut contenir des chaînes de caractères qui contiennent des fins de lignes.


set answer [dialog "choose:

1 – continue

2 – cancel"]


Remarque 2 :

Un script immédiat contenu dans une constante chaîne est considéré comme un tout et équivalent à son résultat.


set answer "choice:\n\t[dialog "choose:

1 – continue

2 – cancel"]"


8.Type d'une donnée


Une donnée peut être de type :

set a 1

set a [list 1 2 3 4 5]

array set {one 1 two 2 three 3 four 4 five 5}


9.Valeur d'une donnée


Scalaire


La valeur d'une donnée de type scalaire est TOUJOURS une chaîne de caractères.


Cette chaîne de caractères peut être interprétée comme une date, un entier, un nombre réel...


Liste


La valeur d'une donnée de type liste est une suite de valeurs scalaires (donc de chaînes de caractères).

Une liste peut être représentée par un chaîne de caractères utilisant des accolades pour le groupage et un espace pour la séparation des items.


En fait, Tcl ne différencie pas les données de type scalaire et les données de type liste, et les considère toutes comme des chaînes de caractères. Par contre, il existe des instructions qui interprètent les données scalaires comme des listes. On en fait un type à part à cause de l'importance des listes dans Tcl (les commandes sont des listes dont le premier élément est le nom de la commande).


set a {1 2 3 4 5}


fournit la même liste que précédemment.


Tableau associatif


Une donnée de type tableau n'a pas de valeur globale mais autant de valeurs scalaires que le tableau contient d’éléments.


10.Variable


Une variable est une donnée qui a un nom et une valeur.

Une donnée nommée de type scalaire est une variable.

Une donnée de type tableau est toujours nommée mais N'est PAS une variable (car un tableau n'a pas de valeur globale).

Les éléments de tableau sont des variables.


11.Nom d'une donnée


Le nom d'une variable permet de la référencer, c'est à dire de retrouver sa valeur.


set b $a


Le $ devant le nom de la variable a indique qu'il s'agit d'un référencement.


Un nom standard est une suite de lettres, de chiffres et de caractères souligné (_).


my_var


Un nom non standard peut contenir n'importe quel caractère sauf des accolades.


my'var


Le nom d'un élément de tableau est le nom du tableau suivi de l’index référençant l'élément et enfermé entre parenthèses.


my_array(name_of_the_element)


Pour référencer une variable dont le nom est standard, on précède son nom par le signe dollar ($).


$my_var

$my_array(name_of_the_element)


Pour référencer une variable dont le nom est non standard, il faut protéger le nom en l’enclosant dans des accolades ({}) et faire précéder l'ensemble par le signe dollar ($).


Piège :

Si l’index d’un élément de tableau est non standard, le nom de cet élément est non standard et doit être protégé.


${my'var}

${my'array(name_of_the_element)}

${my_array(name'of'the'element)}


Dans le cas des variables globales et des variables de namespaces, il existe un nom complet qui permet toujours de référencer –sans ambiguïté– la variable (cf. les namespaces, ci-après).


Piège :

Il n’est pas possible d’obtenir l’ensemble des valeurs d’un tableau en précédant le nom du tableau par un dollar.


12.Déclaration/Définition


Une donnée n’a pas besoin d’être déclarée.

Une donnée est définie dès qu’elle a une valeur.

La commande variable déclare une variable sans la définir (la variable n’a pas de valeur). Elle n’est utilisée que pour les namespaces.


Une valeur scalaire définit une variable scalaire.

La première définition d'un élément déclare un tableau (la variable ne peut plus être scalaire).


set scalar 1; # defining a scalar

set array(element) 1; # defining an array


13.Constante chaîne protégée


Une chaîne protégée est une suite de caractères entre accolades ({...}).


{this is a protected string}


Si la chaîne protégée contient des accolades (ouvrantes ou fermantes), celles-ci doivent être appairées sinon elles doivent être précédées par un anti-slash (\).

Une chaîne peut contenir des sauts de ligne.

Une chaîne protégée n’est jamais interprétée pendant l’évaluation des arguments.


Piège :

Si une chaîne protégée contient un script (cas TRES fréquent), dans ce script les accolades apparaissant dans les commentaires et dans les chaînes standards doivent être (globalement) appairées ou protégées par un anti-slash.


14.Chaîne standard


Une chaîne standard est une suite de caractères entre guillemets ("").


"this is a standard string"


Si la chaîne contient des guillemets, ceux-ci doivent être précédés par un anti-slash (\).

Une chaîne peut contenir des sauts de ligne.

Une chaîne standard est interprétée pendant l’évaluation des arguments. C’est à dire que les références à des variables sont remplacées par la valeur des variables et les script immédiats entre crochets sont remplacées par leur résultat.


set type standard

set s "this is a $type string"


Pour éviter l’interprétation, les signes dollar ($) et les crochets ouvrants ([) peuvent être protégés par un anti-slash (\).


Remarque :

Un script immédiat contenu dans une constante chaîne est considéré comme un tout et équivalent à son résultat. Il peut donc contenir des espaces non protégés et des constantes chaînes.


set answer "choice:\n\t[dialog "choose:

1 – continue

2 – cancel"]"


Piège :

Voir le piège de la section 14 (Constante chaîne protégée) pour les accolades incluses dans une chaîne standard qui doivent être appairées ou protégées.


15.Evaluation


Evaluation d’un script 


Quand un script est évalué, chaque commande est évaluée dans l’ordre d’écriture.

Le résultat d’un script est le résultat de la dernière commande évaluée.


Evaluation d’une commande 


Avant d’évaluer la commande, tous les éléments de la commande sont évalués.

Le nom de la commande peut être lui-même évalué.

Cette évaluation n’a lieu qu’une fois.

Ensuite la commande est invoquée en lui passant les arguments ainsi obtenus.


set _set set

set _a a

set _1 1

$_set $_a $_1


Après évaluation de $_set, $_a et $_1, la commande set a 1 est évaluée.


Evaluation des éléments 


Un élément est une suite de caractères sans espaces non protégés qui peut comporter des références à des variables et des invocations de script immédiats.


set prefix "the result is: "

puts $prefix[compute some result]


Si la suite de caractères contient des espaces non protégés (hors accolades autour d'un nom de variable et hors crochets d'un script immédiat) elle doit être dans une chaîne de caractères.


puts "the result is: [compute some result]"

puts "the result is: ${some result}"


Un élément résultant est obtenu après avoir remplacé dans le texte ou dans la chaîne standard les références à des variables par leur valeur et les scripts entre crochets par leur résultat.

L'élément résultant peut contenir des espaces, mais dans ce cas il demeure un élément unique (les frontières de mot ne changent pas).


Le script

set prefix "the result is: "

set result "this is the result"

puts $prefix$result

renvoie sur la console "the result is: this is the result".


Evaluation d’un script immédiat 


Un script immédiat est évalué comme un script à la différence que les variables et les commandes référençables et/ou définies appartiennent à la procédure ou au script englobant le script immédiat.


set init 10

set x2 [set x1 $init] ; # returns 10


16.Procédures et environnements


Une procédure nommée peut être invoquée (appelée) par son nom. L'invocation d’une procédure initialise les paramètres de la procédure par les arguments de l'invocation avant d'exécuter la procédure.


proc max {n1 n2} \

{

if {$n1 > n2} { set res $n1 } else { set res $n2 }

}

set m [max $m 10]


Invocation


On appelle environnement (ou contexte) d'invocation l'ensemble des variables et commandes visibles au moment de l'invocation.

L’environnement d'invocation des commandes exécutées hors de toute procédure s’appelle l’environnement global.


Exécution


On appelle environnement (ou contexte) d'exécution l'ensemble des variables et commandes visibles à l'intérieur de la procédure quand elle est exécutée suite à une invocation.

Un script immédiat entre crochets est considéré comme une procédure anonyme et est exécuté dans son environnement d’invocation.


17.Environnement d'exécution


Les variables définies dans une procédure sont locales à la procédure.

Les variables définies hors de toute procédure sont globales.

Toutes les procédures sont globales (quand elles sont déclarées en dehors des namespaces, voir plus loin).


Il est possible dans une procédure de référencer :


set max 10

proc check {n} \

{

upvar 1 max lmax

if {$n > $lmax} { error "n exceeds $lmax" }

}


La variable globale max est ajoutée à l'environnement d'exécution de la procédure sous le nom lmax.


set max 10

proc check {n} \

{

global max

if {$n > $max} { error "n exceeds $max" }

}


La variable globale max est ajoutée à l'environnement d'exécution de la procédure (sous son nom).


Il est aussi possible d’exécuter une procédure dans l’environnement d’une procédure appelante (commande uplevel).


set max 11

proc test {} \

{

uplevel 1 { if {$max > 10} { error "$max too big" } }

}

test


Lors de l'exécution de la procédure test, la variable max sera prise dans le contexte englobant la procédure, c'est à dire l'environnement global (où la variable max est définie).


Il est aussi possible d'exécuter une procédure dans son environnement de définition si c'est un namespace (voir ci-dessous).


18.Namespaces (programmation avancée)


Il existe des environnements indépendants des procédures et hiérarchisés. Ils sont nommés namespaces et gérés par la commande namespace.

L’environnement global est considéré comme le premier namespace et a un nom vide.

Les variables et commandes d’un namespace peuvent être référencées par ::namespace::name.

(En toute logique une variable ou commande globale devrait être référencée par ::::name. La raison a permis de les référencer par ::name.)


Un namespace contient des définitions de variables et de commandes et définit un contexte d'exécution pour les commandes qui y sont définies.


Déclaration/Définition


Les variables du namespace peuvent être déclarées par la commande variable.


namespace eval ::ns \

{

variable a

proc b {c} \

{

variable a

...

}

}


La variable a de la procédure b EST la variable a définie dans le namespace.


Cette même commande permet de définir la valeur de la variable déclarée.


namespace eval ::ns \

{

variable a 0

...

}


Pour ajouter à son environnement d'exécution des variables du namespace, une procédure définie dans un namespace utilise aussi la commande variable.


Il est possible de définir une variable ou une procédure d'un namespace en précédant son nom dans la définition par le nom du namespace.


namespace eval ::ns {}

set ::ns::a 0

proc ::ns::b {c} { ... }


C'est équivalent à l'exemple précédent.


Référence et invocation


Il est possible de référencer une variable ou d’évaluer une procédure définie dans un namespace en précédant son nom par le nom du namespace.


puts $::ns::a

puts [::ns::b ...]


Environnements


Une procédure définie dans un namespace et invoquée hors de son namespace est quand même exécutée dans le contexte de son namespace (c'est ce qui permet de référencer les variables du namespace déclarées par la commande variable dans la procédure).


namespace eval ::ns \

{

variable a

proc b {c} \

{

variable a

...

}

}

namespace eval ::ns2 \

{

set a 1

set b [::ns::b $a]

}


Lors de l'invocation de la procédure ::ns::b dans le namespace ::ns2, la variable a dont la valeur est passée en argument est la variable a du namespace d'invocation ::ns2.

Mais pendant l'exécution de la procédure ::ns::b, la variable a définie par variable a et référencée dans la procédure est la variable a du namespace ::ns où est définie la procédure.


En résumé : une procédure définie dans un namespace peut être invoquée partout et ses arguments sont évalués normalement (dans le contexte d'invocation), mais son contexte d'exécution reste son namespace de définition.


Il est possible de garder le namespace de déclaration de la procédure comme contexte d'invocation au moyen de la commande namespace code.


Noms relatifs/absolus


Pour référencer une variable d'un namespace défini au même niveau que la référence, il suffit de faire précéder le nom de la variable par le nom du namespace suivi de ::.


namespace eval ns { variable a }

set ns::a 1


Ce nom est relatif au namespace courant (ou à l'environnement global qui est le père de tous les namespaces).


Un nom relatif à l'environnement global est dit absolu car il est sans ambigüité et peut être utilisé dans toutes les circonstances. Tous les noms commençant par :: sont des noms absolus.


namespace eval ::ns1 { variable a }

namespace eval ::ns2 { set ::ns1::a 1 }



19.Synthèse


Un script Tcl est une suite de commandes.

Une commande est composée d’un mot-clef suivi d’arguments.

Les arguments peuvent être :


# a Tcl script example

set fn myscript.tcl ;# the file name

set fp [open $fn] ;# opening the file

set script [read $fp] ;# reading the file

close $fp ;# closing the file


Le script, les références à une variable, les chaînes standards et les script immédiats entre crochets sont évalués et remplacés par leur valeur ou résultat.


$ remplace la variable par sa valeur.

[] remplacent la commande par son résultat.

"" encadrent une chaîne standard qui est évaluée.

{} encadrent une chaîne protégée (non évaluée).

\ enlève toute signification particulière au caractère qui suit.

# introduit un commentaire (si en début d’instruction).


A une invocation et à une exécution sont associés des environnements qui comprennent les variables et les commandes visibles lors de cette invocation ou de cette exécution. Ces environnements sont manipulables.




Les commandes de base



1.set


La commande set permet de modifier et de référencer une variable.


set varName ?value?


varName est le nom d’une variable ou un élément de tableau.


value est une chaîne de caractères ou une liste.


Modifier :

set varName value

set arrName(element) value


Référencer :

set varName

set arrName(element)


Résultat équivalent avec :

$varName

$arrName(element)


2.puts


La commande puts permet d’écrire son argument suivi d’un caractère saut de ligne sur un canal.


puts ?-nonewline? ?channel? string


nonewline permet de supprimer le caractère saut de ligne.


channel est le canal d’écriture (stdout, résultat d’un open...)

En l'absence de canal l'écriture est faite sur stdout (sortie standard, c’est à dire la console).


string est la chaîne qui est écrite.


puts $var1


3.proc


La commande proc permet de définir une procédure.

Une procédure peut recevoir des arguments et retourne un résultat.


proc name parms body


name est le nom de la procédure.


parms est une liste (qui peut être vide) de paramètres décrivant les arguments reçus par la procédure lors de son invocation (appel).


Chaque élément de la liste correspond à un argument obligatoire s’il n’a pas de valeur par défaut et s’il est différents de args situé en dernière position.

Si le dernier élément de la liste est args il sera remplacé par la liste des derniers arguments qui n’auront pas été décrits dans les paramètres.


parm1 {parm2 default2} args


default2 est la valeur par défaut du paramètre parm2.

args représentent la liste des arguments suivants parm2 (la liste peut être vide).


body est un script qui peut référencer les éléments de la liste des paramètres

Lors de son exécution, une instruction return retourne à la commande suivant l’appel de la procédure. Si l’instruction return est suivie d’une valeur, c’est cette valeur qui sera le résultat de l’appel.


Le script body peut référencer de façon simple :


Le script peut toujours référencer des variables globales ou de namespaces si elles sont référencées par leur nom absolu (commençant par ::).


Il est licite :


Une procédure définie dans une procédure englobante est connue dans le namespace contenant la déclaration de la procédure englobante (à moins de préfixer le nom par un nom de namespace).


Il vaut mieux mettre sagement le script entre accolades.


On peut supprimer une procédure au moyen de l’instruction rename.


proc getFile (fileName) \

{

set fp [open $fileName]

set res [read $fp]

close $fp

return $res

}


4.global


La commande global redéclare dans l’environnement local une variable globale.


global varName ?varName-n?...


varName (respectivement varName-n) est le nom d’une variable globale (donc déclarée en dehors d’une procédure) qui va être connue au niveau local (dans une procédure).


set max 10

proc compute {args} { global max ; ... }


Remarque :

On peut référencer une variable globale depuis n'importe quel environnement en préfixant son nom par ::.


proc a {} { set ::v 1; set b $::v; ... }


5.variable


La commande variable utilisée hors d'une procédure déclare une variable dans le namespace courant.

La commande variable utilisée dans une procédure redéclare dans l’environnement local une variable du namespace courant.


variable ?varName-1 value-1?... varName-n ?value-n?


varName-1 (respectivement varName-n) est le nom d’une variable définie dans le namespace courant.

value-1 (respectivement value-n) est la valeur donnée à la variable varName-1 (respectivement varName-n) .


variable max 10

proc compute {args} { variable max ; ... }


Remarque 1 :

La commande variable utilisée dans le script global (hors procédure) définit une variable globale.

La commande variable utilisée dans une procédure globale référence une variable globale.

En effet le script global et les procédures globales sont dans le namespace global.


Remarque 2 :

On peut référencer une variable d'un namespace depuis n'importe quel environnement en utilisant son nom absolu.

proc a {} { set ::v 1; set b $::v; ... }


6.upvar


La commande upvar redéclare dans l’environnement local une variable d’un environnement appelant.


upvar ?level? varName localName ?varName-n localName-n?...


level indique l’environnement visé.

0 environnement de la procédure

1 environnement de la procédure appelante

...

#0 environnement global

#1 environnement de la première procédure

...


Par défaut level vaut 1.

Pour éviter toute ambiguïté avec l’argument qui suit et pour des raisons de performance, il vaut mieux toujours indiquer level.


varName (respectivement varName-n) est le nom d’une variable d’un environnement englobant (déclarée en dehors d’une procédure) qu’on veut connaître au niveau local (dans une procédure).


set max 10

proc compute {args} { upvar 1 max mx ; ... }


7.uplevel


La commande uplevel exécute un script dans un environnement appelant.


uplevel ?level? arg ?arg ?...


level indique l’environnement visé.

0 environnement de la procédure

1 environnement de la procédure appelante

...

#0 environnement global

#1 environnement de la première procédure

...


Par défaut level vaut 1.

Pour éviter toute ambiguïté avec l’argument qui suit et pour des raisons de performance, il vaut mieux toujours indiquer level.


Les différents arg sont concaténés avec la commande concat pour former le script exécuté.


Piège :

La commande concat transforme une liste en une suite d’éléments. Il faut donc protéger par [list …] les arguments que l’on veut conserver sous forme de liste et les constantes chaîne vides.



8.expr


La commande expr évalue une expression.


expr exp


set sum [expr {$a + $b}]


La syntaxe est proche des expressions en C.

La commande a son propre analyseur syntaxique et c’est pourquoi il vaut souvent mieux mettre l’expression entre accolades pour éviter l’évaluation anticipée par Tcl.


Il vaut mieux mettre sagement l’expression entre accolades.


Fonctions arithmétiques :

int() double() abs() ceil() cos() log() …


Opérateurs arithmétiques :

+ - * / %


Opérateurs booléens :

&& || == != < > <= >= 


Opérateur ternaire :

? : 


Les constantes chaînes de caractères doivent être entre guillemets.

Les nombres peuvent être entiers ou flottants (syntaxe C). Ils sont contenus dans des chaînes (sans guillemets).

La valeur booléenne faux est 0 et la valeur vrai est 1 (il y en a d’autres).

Le résultat d’une expression est toujours une chaîne, même si elle représente un nombre.


9.eval


La commande eval évalue un script. Elle est équivalente à uplevel 0.

Pour évaluer le script elle concatène (comme la commande concat) en une chaîne de caractères la liste des arguments (déjà évalués) et évalue le script résultant.

Il y a donc deux niveaux d’évaluation :


eval arg-1 ?... arg-n ?


eval $cmd $opts $args


Piège :

Les deux niveaux d’évaluation et le passage d’une liste à une chaîne peuvent entraîner des phénomènes subtils et difficiles à analyser.

set str "a string"

eval puts $msg

ici eval va essayer d’interpréter : "puts a string"

a sera considéré comme le canal sur lequel écrire et string comme la chaîne à écrire.


Remarque :

puts $msg

ne pose aucun problème.


Piège :

La commande concat transforme une liste en une suite d’éléments. Il faut donc protéger par [list …] les arguments que l’on veut conserver sous forme de liste et les constantes chaîne vides.



10.incr


La commande incr permet d’incrémenter un nombre entier.


incr varName ?value?


varName est un NOM de variable.

La commande retourne la valeur de la variable après l’avoir modifiée.


value est un nombre entier.

Par défaut la valeur est 1.


incr n –1


Piège :

set n 1

incr $n

est équivalent à :

incr 1

et occasionne une erreur si la variable de nom "1" n’est pas définie (c’est rare qu’elle le soit).


11.if


La commande if implémente la structure de contrôle if.


if exp exp-script ?elseif exp1 exp1-script?… ??else? else-script ?


exp est une expression booléenne dont la syntaxe suit celle de la commande expr.


exp_script est un script qui est exécuté si exp a pour valeur vrai (1).


exp1 est une expression booléenne qui est évaluée si exp a pour valeur faux (0).


exp1_script est un script qui est exécuté si exp1 a pour valeur vrai (1).


else-script est un script qui est exécuté si toutes les expressions booléennes précédentes sont fausses.


if {$x < $y} { set x $y } else { set y 0 }

if {$type != "std"} { error "unknown type: $type" }


Il vaut mieux mettre sagement les expressions et les scripts entre accolades.


12.while


La commande while implémente la structure de contrôle while.


while exp script 


exp est une expression booléenne dont la syntaxe suit celle de la commande expr.


script est un script qui est exécuté tant que exp a pour valeur vrai (1).


Les commandes continue et break situées dans script permettent de passer à l’itération suivante ou de sortir immédiatement de la boucle.


set fact 10

set res 1

set n 1

while {$n <= $fact} \

{

incr n 

set res [expr {$res * $n}]

}


Il vaut mieux mettre sagement l’expression et le script entre accolades.


Piège :

l’expression, sans espace, peut être écrite sans les accolades :

while $n<=$fact { script }

c’est équivalent à :

while 1<=1 { script }

(car les arguments sont interprétés avant l’appel de la commande while)

c’est une boucle infinie.


Equivalent de do :

while 1 { script }


13.for


La commande for implémente la structure de contrôle for.


for init-script exp next-script script


Equivalent sémantique :

init-script

while {exp} { script; next-script }


init-script est le script d’initialisation de la boucle.


exp est l’expression de contrôle de la boucle : la boucle est exécutée tant que sa valeur est vrai.


next-script est le script d’avancement exécuté après chaque itération de la boucle.


script est le script principal exécuté à chaque itération de la boucle.


Les commandes continue et break situées dans script permettent de passer à l’itération suivante ou de sortir immédiatement de la boucle.


set max 10

for {set i 0} {$i < $max} {incr i} { puts $i }


Il vaut mieux mettre sagement l’expression et le script entre accolades.


14.foreach


La commande foreach est une boucle for spécialisée pour les listes.


foreach varName list script

foreach {varName-1 ... varName-n} list script

(il existe une forme plus complexe)


varName est le nom d’une variable qui n’a pas besoin d’être déjà définie.


list est une liste de valeurs.


script est le script exécuté pour chaque valeur de la liste.


Les commandes continue et break situées dans script permettent de passer à l’itération suivante ou de sortir immédiatement de la boucle.


Dans la deuxième forme, les n variables varName-1 ... varName-n reçoivent les n valeurs suivantes de la liste.


set list {one two three four}

foreach i $list { puts $i }


Il vaut mieux mettre sagement le script entre accolades.


15.switch


La commande switch permet de choisir un script parmi n à partir d’une valeur.


switch ?opts? ?--? value { value-1 script-1 ... value-n script-n ?default default-script ? }

(il existe une forme plus complexe)


opts permet de définir le type de comparaison :

-exact comparaison directe

-glob comparaison semblable à celle de la commande glob (*, ? comme sous DOS)

-regexp comparaison semblable à celle de la commande regexp (expressions UNIX)


-- indique la fin des options (utile si la valeur suivante commence par un tiret).


value-1 (respectivement value-n) est une chaîne de caractères comparée à value.


script-1 (respectivement script-n) est le script exécuté si la comparaison d’égalité entre value-1 (respectivement value-n) et value retourne vrai.


default-script est le script exécuté si aucune comparaison ne retourne vrai.


Un seul script est exécuté.

Si est script est réduit à un tiret (-) c’est le script suivant qui est exécuté.


switch –exact -- $op \

{

+ -

- { return compute $op $a $b}

0 { set a 0; set b 0; return 0 }

}


Il vaut mieux mettre sagement le script entre accolades.


Piège :

Surtout ne pas insérer de commentaires à l’extérieur des scripts, ils seraient considérés comme un ensemble de couples valeur-script.

Par exemple :

switch # { # commentaire }

essaiera d’exécuter commentaire.


16.catch


La commande catch permet de récupérer une erreur et le message associé.

La commande


catch script ?varName?


script est le script à exécuter.


varName est le nom de la variable qui recevra :







set rc [catch { set i $max } msg]

if {$rc == 1} \

{

# error

puts "error: $msg"

} \

else \

{

# no error

puts "result: $msg"

}


Il vaut mieux mettre sagement le script entre accolades.


17.error


La commande error permet de signaler une erreur en lui associant un message.


error msg


msg est une chaîne de caractères contenant le message associé à l’erreur.


error "unknown type $type"


Remarque :

Cette erreur pourra être interceptée par la commande catch.



Les commandes de chaînes



1.Création d’une chaîne


La commande set permet de créer (entre autre) une chaîne.


Les différentes chaînes sont les chaînes protégées et les chaînes standards.


- chaîne protégée (pas d’interprétation) :

set prot {this is a protected string}


- chaîne standard (interprétation) :

set curr "current path : [pwd]"


Remarques :

Tout ce qui n’est pas un tableau est une chaîne.

Une variable créée sous forme de chaîne, et traitée entre-temps comme une liste, garde sa représentation de chaîne.

Une variable crée comme une liste a comme représentation de chaîne tous ses éléments séparés par un espace.


2.Longueur d’une chaîne


La commande string length retourne le nombre de caractères d’une chaîne.


string length string


string ne doit pas être un tableau.


La commande

string length "string"

retourne 6.


3.Accès à un caractère dans une chaîne


La commande string index permet d’accéder à un caractère d’une chaîne.


string index string index


string est une chaîne.


index indique le rang du caractère :

0 premier caractère 

1 deuxième caractère 

...

end dernier caractère 

end-1 avant-dernier caractère 

...


La commande

string index "string" 1

retourne le caractère "t".


4.Accès à une sous-chaîne


La commande string range permet d’accéder à une sous-chaîne.


string range string index1 index2


string est une chaîne.


index1 et index2 indiquent le rang dans la chaîne du premier caractère et le rang dans la chaîne du dernier caractère de la sous-chaîne .


La commande

string range "string" end-1 end

retourne la sous-chaîne "ng".


5.Recherche du premier index d’une sous-chaîne dans une chaîne


La commande string first permet de retrouver l’index de la première sous-chaîne trouvée dans une chaîne.

Elle retourne l’index de la sous-chaîne si elle est trouvée, sinon elle retourne –1.


string first string-1 string-2


string-1 est la sous-chaîne à rechercher dans la chaîne.


string-2 est une chaîne.


if {[string first \n $string] == -1} { error "new line not found" }


6.Recherche du dernier index d’une sous-chaîne dans une chaîne


La commande string last permet de retrouver l’index de la dernière sous-chaîne trouvée dans une chaîne.

Elle retourne l’index de la sous-chaîne si elle est trouvée, sinon elle retourne –1.


string last substring string


substring est la sous-chaîne à rechercher dans la chaîne.


string est une chaîne.


La commande

string last " " $string

retourne l’index du dernier caractère espace dans la chaîne contenue dans la variable string.


7.Ajout d’une sous-chaîne en fin de chaîne


La commande append permet d’ajouter une sous-chaîne à la fin de la chaîne.


append varName substring


varName est le NOM d’une variable contenant une chaîne.


substring est une sous-chaîne à ajouter en fin de la chaîne.


Piège :

Contrairement aux autres commandes de chaîne, append a pour premier argument un NOM de variable.


La commande

append "one two three four" " five six"

retourne la chaîne "one two three four five six".

8.Remplacement d’une sous-chaîne dans une chaîne


La commande string replace permet de remplacer une sous-chaîne positionnée dans une chaîne par une autre sous-chaîne.


string replace string first last ?substring?


string est une chaîne.


first, last sont les index définissant la sous-chaîne qui va être remplacée.


substring est la sous-chaîne à insérer.

Si elle est absente, la sous-chaîne définie par first et last n’est pas remplacée mais supprimée.


La commande

string replace "one two three four" 0 2 "first"

retourne la chaîne "first two three four five six".


9.Remplacement de sous-chaînes dans une chaîne


La commande string map permet de remplacer dans une chaîne certaines sous-chaînes par d’autres sous-chaînes.


string map ?-nocase? charMap string


Si l’option –nocase est présente, les comparaisons se font sans différencier majuscules et minuscules.


charMap est une liste de sous-chaînes appairées : les impaires sont les sous-chaînes recherchées et remplacées, les paires sont les sous-chaînes qui remplacent la sous-chaîne qui précède dans la liste.


string est une chaîne.


La commande

string map {one 1 two 2 three 3 four 4} "one two three four"

retourne la chaîne "1 2 3 4".


10.Changement de casse dans une chaîne


Les commandes string tolower, string toupper et string totitle permettent de modifier la casse des caractères d’une chaîne.

tolower passe les caractères en minuscules.

toupper passe les caractères en majuscules.

totitle passe le premier caractère du premier mot en majuscule et les autres caractères en minuscules.


string tolower string

string toupper string

string totitle string


La commande

string totitle "THIS IS A STRING"

retourne la chaîne "This is a string".


11.Autres commandes de chaîne


encoding

convertit les caractères d’une chaîne suivant les différents encodages

format

formatte une chaîne suivant une spécification (cf. printf)

regexp

détermine si une chaîne est conforme à une expression régulière

regsub

substitue dans une chaîne suivant une expression régulière

scan

scanne une chaîne suivant une spécification (cf. scanf)

string bytelength

retourne la longueur en octets d’un caractère (suivant l’encodage)

string compare

compare deux chaînes

string equal

détermine si deux chaînes sont égales

string is

détermine le type de donnée que représente une chaîne

string match

détermine si une chaîne correspond à une expression

string repeat

crée une chaîne en répétant une sous-chaîne

string trim

supprime certains caractères aux deux extrémités d’une chaîne

string trimleft

supprime certains caractères à gauche d’une chaîne

string trimright

supprime certains caractères à droite d’une chaîne

string wordend

retourne l’index de la fin d’un mot dans une chaîne

string wordstart

retourne l’index du début d’un mot dans une chaîne

subst

évalue une chaîne




Les commandes de listes



1.Création d’une liste


La commande list permet de créer une liste.


list ?string-1 ... string-n?


string-n est le nième élément de la liste.


set l [list one two three four]


Toute chaîne de caractères peut être considérée par Tcl comme une liste de mots séparés par des espaces.


set l "one two three four"

set l {one two three four}


2.Longueur d’une liste


La commande llength retourne le nombre d’élément d’une liste.


llength list


list est une liste.


La commande

llength [list one two three four]

retourne 4.


3.Accès à un élément


La commande lindex permet d’accéder à un élément d’une liste.


lindex list index


list est une liste.


index indique le rang de l’élément :

0 premier élément

1 deuxième élément

...

end dernier élément

end-1 avant-dernier élément

...


La commande

lindex [list one two three four] 1

retourne "two".


4.Accès à une sous-liste


La commande lrange permet d’accéder à une sous-liste.


lrange list index1 index2


list est une liste.


index1 et index2 indiquent le rang dans la liste du premier élément et le rang dans la liste du dernier élément de la sous-liste.


La commande

lrange [list one two three four] end-1 end

retourne la liste {three four}.


5.Modification d’un élément


La commande lset (nouveauté pour Tcl 8.4) permet de modifier un élément dans une liste.

Elle retourne la liste modifiée.


lset listName ?index?... value

lset listName {?index?...} value

(les deux formes sont équivalentes)


listName est le NOM d’une liste.

index est un index dans la liste.

value est la valeur à donner à l’élément sélectionné.


Si index est absent ou vide, la commande est équivalente à set listName value : la liste prend la valeur value.

La commande

lset myList {1 2 3 4}

lset myList {} {1 2 3 4}

retourne la liste {1 2 3 4}.


S’il y a plusieurs index, la commande :

set myList {{a b} {b c} {c d}}

lset myList 2 0 ""

retourne la liste {{a b} {b c} {{} d}}.

myList est considéré comme le nom d’une liste, l’élément d’index 2 est sélectionné, considéré comme une sous-liste puis l’élément 0 de cette sous-liste est sélectionné puis remplacé par "" .


6.Recherche de l’index d’un élément


La commande lsearch permet de retrouver l’index d’un élément dans une liste.

Elle retourne l’index de l’élément si il est trouvé, sinon elle retourne –1.


lsearch list value


list est une liste.


value est la chaîne de caractères à rechercher parmi les éléments de la liste.


if {[lsearch $list $item] == -1} { error "item not found" }


7.Ajout d’éléments en fin de liste


La commande lappend permet d’ajouter un ou des éléments à la fin de la liste.

Elle retourne la liste modifiée.


lappend listName string-1 ?... string-n?


listName est le NOM d’un liste.


string-n est la n-ième chaîne de caractères à ajouter en fin de liste.


La commande

set l [list one two three four]

lappend l five six

retourne la liste {one two three four five six}.


8.Insertion d’éléments dans une liste


La commande linsert permet d’insérer un ou des éléments à partir d’un certain rang dans une liste.

Elle retourne la liste modifiée.


linsert list index string-1 ?... string-n?


list est une liste.


index est le rang où seront insérés les nouveaux éléments.


string-n est la n-ième chaîne de caractères à insérer dans la liste.


La commande

linsert {one two three four} 0 zero

retourne la liste {zero one two three four}.


9.Remplacement d’éléments dans une liste


La commande lreplace permet de remplacer un ou des éléments à partir d’un certain rang dans une liste.

Elle retourne la liste modifiée.


lreplace list index1 index2  ?string-1 ... string-n?


list est une liste.


index1 et index2 indiquent le rang dans la liste du premier élément et le rang dans la liste du dernier élément de la sous-liste qui sera remplacée.


string-n est la n-ième chaîne de caractères à insérer dans la liste à partir de index1.

S’il n’y a pas d’élément à insérer, cela revient à une suppression.


La commande

lreplace {one two three four} 1 end others

retourne la liste {one others}.


10.Tri d’une liste


La commande lsort retourne une liste triée.


lsort ?opts? list


opts est une liste d’options :

-ascii séquence de comparaison ascii

-dictionary comparaison de type dictionnaire

-integer comparaison de type entiers

-real comparaison de type flottants

-command cmd commande de comparaison de deux éléments

-increasing tri en ordre croissant

-decreasing tri en ordre décroissant

-index index tri de sous-listes, index est l’index de la clef dans la sous-liste

-unique supprime les éléments en double


list est une liste.


La commande

lsort {one two three four}

retourne la liste (suivant le tri standard) {four one three two}.



11.Concaténation de listes


La commande concat permet de créer une liste en concaténant des listes.

Les éléments de chaque liste sont ajoutés à la liste résultante.


concat ?list-1...list-n ?


list-1, ..., list-n sont les listes.


La commande

concat a b {c d e} {f {g h}}

retourne la liste {a b c d e f {g h}}.


Piège :

La commande concat transforme une liste en une suite d’éléments. Il faut donc protéger par [list …] les arguments que l’on veut conserver sous forme de liste et les constantes chaîne vides.


12.Création d'un chaîne à partir d'une liste


La commande join permet de créer une chaîne à partir d'une liste et d'une sous-chaîne servant de séparateur.


join list ?separ?


list est une liste.


separ est une chaîne de caractères qui sera utilisée comme séparateur.

Si separ est absent, le séparateur sera un espace.


La commande

join {a b c d} ,

retourne la chaîne "a,b,c,d".


13.Création d'un liste à partir d'une chaîne


La commande split permet de créer une liste à partir d'une chaîne et d'une sous-chaîne servant de séparateur.


split string ?separ?


string est une chaîne de caractères.


separ est une chaîne de caractères dont chacun sera un séparateur.

Si separ est absent, les séparateurs seront les caractères espace, tabulation et saut de ligne.


La commande

split {a:b,c:d} :,

retourne la liste {a b c d}.




Les commandes de tableaux



1.Collection


Ce que Tcl appelle tableaux (array) sont en fait des tableaux associatifs ou collections : un ensemble de valeurs accessibles à partir d’un nom.


2.Création d’un tableau, ajout dans un tableau


La commande array set crée un tableau en l’initialisant.


array set varName paired-list


varName ne doit pas être le nom d’une variable scalaire.


paired-list doit être une liste avec un nombre pair d’éléments. Les éléments pairs sont les noms des éléments du tableau, les éléments impairs sont les valeurs des éléments du tableau.


array set dirs {root / home ~ current .}


Si la variable existe déjà et est un tableau, array set ajoute les éléments de sa liste aux autres éléments du tableau.

Si un élément existe déjà, il est modifié.


On peut aussi créer un tableau en créant son premier élément.


set dir(root) /


Si la variable existe déjà et est un tableau, set ajoute l’élément aux autres éléments du tableau.

Si l’élément existe déjà, il est modifié.


Une variable scalaire ne peut pas être transformée en tableau.

De même un tableau ne peut pas être transformée en variable scalaire.


3.Existence d’un tableau


La commande array exists permet de tester l’existence d’un tableau.


array exists varName


varName est le nom à tester.


if {![array exists dirs]} { set dirs(root) / }


4.Nombre d’éléments d’un tableau


La commande array size permet de connaître le nombre d’éléments d’un tableau.


array size arrayName


arrayName est le nom du tableau.


La commande

array size dirs

retourne le nombre d’éléments du tableau dirs.




5.Référencement d’un tableau


Pour référencer un élément d’un tableau on accole, au nom du tableau, le nom de l’élément entre parenthèses.


set dirs(selected) [pwd]

puts $dirs(selected)

foreach dir {root home current selected} { puts $dirs($dir) }


Il n’est pas possible de référencer un tableau en son entier.


Les commandes

array set nums {1 0.5 2 0.25 3 0.5 4 1.0}

set sum [array_add $nums]

occasionnent une erreur car $nums est illicite.


Pour passer un tableau à une procédure on passe le nom du tableau et on utilise la commande upvar qui rend visible, au niveau de la procédure, une variable du contexte appelant.


proc array_add {arrayName} \

{

upvar $arrayName array

set sum 0.0

foreach key [array names array] \

{ set sum [expr {$sum + $array($key)}] }

return $sum

}

array set nums {1 0.5 2 0.25 3 0.5 4 1.0}

set sum [array_add nums]


6.Suppression dans un tableau


La commande array unset permet de supprimer un tableau ou des éléments d’un tableau.


array unset arrayName ?pattern?


arrayName doit être le nom d’un tableau.


pattern est une expression régulière telles que celles utilisées par l’option match de la commande string.

Si pattern est une chaîne vide, le tableau entier est supprimé.

Sinon, toutes les éléments correspondant à pattern sont supprimés.


Après la commande

array unset dirs cur*

tous les éléments du tableau dirs dont les noms commencent par "cur" sont supprimés.


7.Noms des éléments d’un tableau


La commande array names permet de retrouver tout ou partie des noms des éléments d’un tableau.


array names arrayName ?pattern ?


arrayName doit être le nom d’un tableau.


pattern est une expression régulière telles que celles utilisées par l’option match de la commande string.

Si pattern est une chaîne vide, tous les noms sont retournés.

Sinon, seuls les noms correspondant à pattern sont retournés.


La commande

array names dirs

retourne les noms de tous les éléments du tableau dirs.


8.Contenu d’un tableau


La commande array get permet d’accéder au contenu d’un tableau. C’est le symétrique de array set).

Elle retourne une liste pairée. Les éléments pairs sont les noms des éléments du tableau, les éléments impairs sont les valeurs des éléments du tableau.


array get arrayName ?pattern ?


arrayName doit être le nom d’un tableau.


pattern est une expression régulière telles que celles utilisées par l’option match de la commande string.

Si pattern est une chaîne vide, tous les noms sont retournés.

Sinon, seuls les noms correspondant à pattern sont retournés.


La commande

array get dirs

retourne une liste contenant chaque valeur contenue dans la liste, précédée du nom correspondant (cf. l’exemple de array set).


Piège :

Dans la liste retournée par array get les noms des éléments NE SONT PAS dans l’ordre d’insertion mais dans l’ordre d’accès à la table de hashing utilisée.

De plus il n’y a AUCUN MOYEN de les garder dans un certain ordre.


Pour obtenir une liste triée des éléments d’un tableau il faut passer par les listes.


foreach name [lsort [array names dirs]] \

{ puts "$name\t$dirs($name)" }




Les commandes d'entrée-sortie



1.Canaux d'entrée-sortie


Tcl permet de lire et d'écrire vers des canaux d'entré-sortie.

Ceux-ci sont des identifiants (handles) et permettent d'accéder à des périphériques (:COM1, /dev/ttyS0...), des fichiers, des pipe-lines (pipes) ou des sockets.


2.Ouverture d'un canal non socket


La commande open permet d'obtenir l'identifiant (handle) d'un canal vers un périphérique, un fichier ou un pipe-line.

L'accès peut se faire en différents modes.


open name ?access ?permissions??


name est le nom du périphérique, du fichier ou un pipe-line.

Un pipe-line est décrit sous la forme "|cmd ?args?" cmd est le nom d'une commande externe (commande de l'OS) et args est la suite des arguments et/ou redirections tels que fourni au shell.


access

r ouverture en lecture, le fichier doit exister (valeur par défaut)

r+ ouverture en lecture-écriture, le fichier doit exister

w ouverture en écriture, tronque un fichier existant, sinon le crée

w+ ouverture en lecture-écriture, tronque un fichier existant, sinon le crée

a ouverture en ajout, crée le fichier s'il n'existe pas

a+ ouverture en lecture et en ajout, crée le fichier s'il n'existe pas


Remarque:

Il n'y a pas d'option b (pour binaire). Il faut utiliser la commande fconfigure avec l'option ­translation binary.


permissions est un entier interprété comme sous UNIX (valeur par défaut 0666).


Les commandes suivantes

open /dev/ttyS0

open myFile

open [list |ps –f $user | grep $cmd]

retournent un identifiant vers le canal ouvert.


3.Ouverture d'un canal socket


La commande socket permet soit de définir un socket serveur, soit d'obtenir l'identifiant d'un canal vers un socket.client.


canal serveur


socket -server cmd ?-myaddr server_addr ? server_port


Lors d'une connexion au canal socket serveur Tcl créera automatiquement un nouveau canal socket et exécutera la commande cmd channel client_addr client_port .


channel sera l'identifiant du nouveau canal socket,

client_addr sera l'adresse réseau du client,

client_port sera le numéro de port IP du socket client.


server_addr est l'adresse réseau sur laquelle le socket serveur acceptera des connexions (utile seulement si le serveur a plusieurs adresses réseau).

Si l'option est absente, le socket serveur acceptera des connexions pour toutes les adresses réseau du serveur.


server_port est le port IP sur lequel le socket serveur acceptera des connexions.


proc connection {channel addr port} { ... }

socket -server connection 1234


canal client


socket ?options? server_addr server_port


options sont des options parmi :

-myaddr addr

Cette option est utile si le client a plusieurs adresses réseau. Dans ce cas addr précise l'adresse réseau à utiliser.

-myport port

port précise le numéro de port IP à utiliser du côté client. En l'absence de cette option, le numéro sera choisi par IP.

-async

Si cette option est précisée, le canal socket est en mode asynchrone.


server_addr et server_port sont l'adresse réseau et le port IP du socket serveur auquel on veut se connecter.


La commande

set channel [socket localhost 1234]

retourne l'identifiant du canal socket établi avec le serveur local à l'écoute du port 1234.


4.Lecture d'un fichier ou d'un buffer sur un canal


La commande read retourne le contenu d'un fichier ou d'un buffer.


read ?-nonewline? channel

read channel count


L'option –nonewline a pour effet de supprimer le saut de ligne en fin de fichier (s'il y en a un).


channel est l'identifiant d'un canal ouvert en lecture ou en lecture-écriture.


Dans la première forme la commande retourne tous les caractères disponibles sur le canal channel.

Dans la deuxième forme la commande retourne count caractères sur le canal channel (ou moins si Tcl rencontre une condition de fin de fichier).


Si le canal est en mode non bloquant, la commande read retourne immédiatement avec tous les caractères disponibles.


Les séquences de fin de ligne sont transformées suivant l'option –translation de fconfigure.


set text [read $channel]


5.Lecture d'une ligne sur un canal


La commande gets retourne une ligne (sans la séquence de fin de ligne).


gets channel ?varName?


channel est l'identifiant d'un canal ouvert en lecture ou en lecture-écriture.


varName est le nom d'une variable qui recevra la ligne.

Si le nom est présent, la commande retourne le nombre de caractères mis dans la variable (ou –1 en cas de fin de fichier).

S'il est omis, la commande retourne la ligne ou une chaîne vide.


En mode non bloquant le commande retourne une ligne vide s'il n'y a pas de ligne complète disponible.

En cas de fin de fichier avant la fin de ligne :


Remarque :

Les commandes eof et fblocked permettent de distinguer les différents cas où une ligne vide est retournée.


set count [gets $channel line]

if {$count > -1} { ... }


6.Ecriture sur un canal


La commande puts permet d'écrire une chaîne de caractères sur un canal.


puts ?-nonewline? ?channel? string


L'option –nonewline empêche la commande d'ajouter une séquence de fin de ligne après la chaîne de caractères.


channel est l'identifiant d'un canal ouvert en écriture ou en lecture-écriture.

Si le canal n'est pas spécifié les caractères sont envoyés sur stdout.


string est la chaîne de caractères à écrire sur le canal.


Les séquences de fin de ligne sont transformées suivant l'option –translation de fconfigure.


Les caractères sont bufferisés. La commande flush permet de forcer l'écriture immédiate sur le canal.


Pour utiliser le mode non bloquant, il faut utiliser la commande vwait pour activer la boucle de traitement des évènements de Tcl.

En mode non bloquant la commande puts retourne immédiatement. Dans ce cas il est préférable d'utiliser fileevent pour savoir quand écrire à nouveau avec puts.


set ::fp [open $::fn w]

fconfigure $::fp -blocking 0

proc write_line {} \

{

puts $::fp [create_line]

if {[incr ::count] == $::max} \

{

close $::fp

set ::ended 1

}

}

fileevent $::fp writable write_line

vwait ::ended

(après écriture du fichier le script est quitté)




Lien utiles




wiki francophone 

http://wfr.tcl.tk


wiki international

http://www.tcl.tk


forum francophone

http://groups.google.com/group/fr.comp.lang.tcl


forum international 

http://groups.google.com/group/comp.lang.tcl


tcltk.free.fr 

http://tcltk.free.fr


ulis’ code 

http://perso.wanadoo.fr/maurice.ulis/tcl