====== trace ======
Suivre l'accès aux variables
===== Syntaxe =====
trace option ?arg arg ...?
===== Description =====
Cette commande provoque l'exécution de certaines commandes Tcl quand certaines opérations sont appelées. Actuellement, seule la trace de variables est mise en place. Les options valides (qui peuvent être abrégées) sont:
==== variable ====
trace variable name ops command
Provoque l’exécution de la commande //command// à chaque fois que la variable //name// est accédée par un des moyens indiqué par //ops//. //name// peut faire référence à une variable simple, un élément d'un tableau, ou un tableau dans son entier (c'est à dire que //name// peut juste être le nom d'un tableau, sans parenthèses d'index). Si //name// se réfère à un tableau entier, alors //command// est appelée pour chaque manipulation d'un élément du tableau. Si la variable n'existe pas, elle sera créée mais n'aura pas de valeur, donc elle sera visible par les requêtes [[:tcl:namespace#which|namespace which]], mais pas par les requêtes [[:tcl:info#exists|info exists]]. //ops// indique quelles opérations sont suivies, et comprend une ou plusieurs des lettres suivantes:
* **r** Appelle //command// à chaque fois que la variable est lue.
* **w** Appelle //command// à chaque fois que la variable est écrite.
* **u** Appelle //command// à chaque fois que la variable est annulée. Les variables peuvent être annulées explicitement avec la commande [[:tcl:unset]], ou implicitement à la fin des procédures (toutes leurs variables locales sont annulées). Les variables sont aussi annulées quand des interpréteurs sont détruits, mais les commandes de trace ne seront pas appelées parce qu'il n'y aura pas d'interpréteur pour les exécuter.
Quand la trace se déclenche, trois arguments sont ajoutés à la fin de //command//, de telle sorte que la commande est réellement appelée comme suit:
command name1 name2 op
//name1// et //name2// donnent le(s) nom(s) pour la variable accédée:
* si la variable est scalaire, alors //name1// donne le nom de la variable et //name2// est une chaîne vide;
* si la variable est un élément de tableau, //name1// donne le nom du tableau et //name2// l'index dans le tableau;
* si un tableau entier est détruit et que la trace était enregistrée sur la totalité du tableau et non sur un seul élément, alors //name1// donnera le nom du tableau et //name2// une chaîne vide.
//name1// et //name2// ne sont pas nécessairement les mêmes noms que celui utilisé dans la commande trace variable: la commande upvar permet à une procédure de référencer une variable sous un nom différent. Op indique quelle opération est effectuée sur la variable, et est l'une des trois lettres r, w ou u qui sont définies plus haut.
//command// s’exécute dans le même contexte que le code qui a appelé l'opération tracée: si la variable était accédée comme partie d'une procédure Tcl, alors //command// aura accès aux mêmes variables locales que le code de la procédure. Ce contexte peut être différent de celui dans lequel la trace a été créée. Si //command// appelle une procédure (ce qui est le cas normal) alors la procédure devra utiliser [[:tcl:upvar]] ou [[:tcl:uplevel]] si elle souhaite accéder à la variable tracée. Noter aussi que //name1// n'est pas nécessairement le même que le nom utilisé pour définir la trace sur la variable; des différences peuvent se produire si l'accès est fait au travers d'une variable définie par la commande **upvar**.
Pour les traces en lecture et en écriture, //command// peut changer la variable pour modifier le résultat de l'opération tracée. Si //command// modifie la valeur de la variable pendant une trace en lecture ou en écriture, alors la nouvelle valeur sera retournée comme étant le résultat de l'opération tracée. La valeur de retour de //command// est ignorée sauf dans le cas où elle retourne une erreur quelconque; dans ce cas l'opération tracée renvoie aussi une erreur avec le même message d'erreur que celui renvoyé par la commande appelée par trace (ce mécanisme peut être utilisé pour mettre en place des variables en lecture seule, par exemple). Pour les traces en écriture, //command// est appelée après que la valeur de la variable ait été changée; elle peut écrire une nouvelle valeur dans la variable pour forcer la valeur produite par l'opération d'écriture. Pour mettre en place des variables en lecture seule, //command// aura à charge de remettre l'ancienne valeur dans la variable. Pendant que //command// s’exécute durant une trace en lecture ou en écriture, les traces sur la variable sont temporairement désactivées. Cela signifie que les lectures ou les écritures appelées par //command// se produiront directement, sans invoquer //command// (ni aucune autre trace) une nouvelle fois. Cependant, si //command// annule la variable, les traces d'annulation seront appelées.
Quand une trace d'annulation est appelée, la variable a déjà été détruite: elle apparaîtra comme indéfinie et ne possédant pas de traces. Si une annulation de variable se produit à cause d'une fin de procédure, la trace sera appelée dans le contexte de variables de la procédure appelante: le contexte de pile de la procédure qui s'est finie n'existera plus. Les traces ne seront pas désactivées pendant les traces d'annulation, donc si une commande de trace d'annulation crée une nouvelle trace et accède à la variable correspondante, cette commande de trace sera appelée. Les erreurs dans les traces d'annulation sont ignorées.
S'il y a plusieurs traces sur une variable elles seront appelées selon leur ordre de création, les plus récentes en premier. Si une trace renvoie une erreur, les traces suivantes portant sur la même variable ne seront pas appelées. Si un élément de tableau a une trace positionnée, et qu'il y a aussi une trace positionnée sur le tableau dans son ensemble, la trace globale est appelée avant celle qui porte sur l'élément seul.
Une fois créée, la trace reste en effet jusqu'à ce qu'elle soit retirée au moyen de la commande trace [[#vdelete]] décrite ci-dessous, ou bien jusqu'à ce que la variable soit annulée, ou bien jusqu'à ce que l'interpréteur soit détruit. L'annulation de l'élément d'un tableau retirera toutes les traces sur cet élément, mais ne retirera pas les traces sur l'ensemble du tableau. Cette commande retourne une chaîne vide.
==== vdelete ====
trace vdelete name ops command
S'il existe une trace positionnée sur la variable //name// avec les opérations //ops// et la commande //command//, alors la trace est supprimée, de telle sorte que //command// ne sera plus jamais appelée. Retourne une chaîne vide.
==== vinfo ====
trace vinfo name
Retourne une liste contenant un élément pour chaque trace positionnée sur la variable //name//. Chaque élément de la liste est lui-même une liste contenant deux éléments, qui sont les //ops// et //command// associées à la trace. Si //name// n'existe pas ou n'a aucune trace positionnée, le résultat de la commande sera une chaîne vide.
===== Exemples =====
===== Voir aussi =====
{{tag>tcl}}