Error processing request

Parameters

CONTENT_LENGTH0
REQUEST_METHODGET
REQUEST_URI/revision/trace?V=60
QUERY_STRINGV=60
CONTENT_TYPE
DOCUMENT_URI/revision/trace
DOCUMENT_ROOT/var/www/nikit/nikit/nginx/../docroot
SCGI1
SERVER_PROTOCOLHTTP/1.1
HTTPSon
REMOTE_ADDR172.70.126.92
REMOTE_PORT52756
SERVER_PORT4443
SERVER_NAMEwiki.tcl-lang.org
HTTP_HOSTwiki.tcl-lang.org
HTTP_CONNECTIONKeep-Alive
HTTP_ACCEPT_ENCODINGgzip, br
HTTP_X_FORWARDED_FOR3.139.90.131
HTTP_CF_RAY87f1890b8fc129e8-ORD
HTTP_X_FORWARDED_PROTOhttps
HTTP_CF_VISITOR{"scheme":"https"}
HTTP_ACCEPT*/*
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
HTTP_CF_CONNECTING_IP3.139.90.131
HTTP_CDN_LOOPcloudflare
HTTP_CF_IPCOUNTRYUS

Body


Error

Unknow state transition: LINE -> END

-code

1

-level

0

-errorstack

INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit trace '''\[http://www.tcl.tk/man/tcl/TclCmd/trace.htm%|%trace\]'''\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ command,\ monitors\ \[variable\]\ accesses\ \[command\]\ definition\ and\ execution.\n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[An\ equation\ solver\]:\ \ \ with\ an\ example\ of\ using\ trace\ to\ update\ dependent\ resources\n\n\ \ \ \[Traces\]:\ \ \ examples\ and\ discussion\n\n\ \ \ \[Tracing\ inappropriate\ variable\ access\]:\ \ \ \n\n\ \ \ \[Whole-Script\ Tracing\]:\ \ \ by\ \[DKF\]\n\n\ \ \ \[An\ example\ of\ data\ objects\]:\ \ \ \[AM\]\ Using\ the\ trace\ command,\ I\ implemented\ an\ idea\ by\ \[George\ Howlett\]\ (the\ author\ of\ \[BLT\])\n\n\n\n**\ Synopsis\ **\n\n\ \ \ \ :\ \ \ '''trace'''\ ''option''\ ''?arg\ arg\ ...?''\n\n\n\n**\ Documentation\ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/trace.htm%|%official\ documentation%|%\]:\ \ \ \n\n\n\n**\ Description\ **\n\nExamples\ of\ what\ to\ do\ with\ `trace`:\n\n\ \ \ *\ Communicate\ between\ parts\ of\ a\ \[GUI\]\ and\ the\ internal\ state\ of\ the\ app.\ (Simplified\ \[MVC\],\ observer).\ In\ general\ Communicate\ between\ different\ parts\ of\ an\ app\ without\ coupling\ them\ strongly.\n\n\ \ \ *\ Compute\ simple\ constraints\ for\ a\ number\ of\ variables\ (\"if\ this\ flag\ is\ on\ and\ that\ one\ is\ on,\ then\ no\ other\ is\ allowed\ to\ be\ set\",\ and\ some\ such).\n\n\ \ \ *\ `\[bind\]`\ \[Canvas\]\ text\ items\ to\ a\ variable,\ effecting\ dynamic\ updates\ \n\n\ \ \ *\ Debug\ -\ call\ a\ proc\ when\ a\ variable\ is\ modified\ (detect\ setting\ from\ wrong\ routine).\n\n\ \ \ *\ Trace\ works\ in\ Itcl\ \[Itcl\ trace\]\ but\ not\ quite\ trivially.\n\n\n\n**\ Order\ of\ Processing\ **\n\n\[JCW\]:\n\n======\nproc\ tellme\ \{id\ a\ e\ op\}\ \{\n\ \ \ \ puts\ \"\ \ \$id\ a=\$a\ e=\$e\ op=\$op\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ax=\[info\ exists\ ::\$a\]\ ex=\[info\ exists\ ::\$\{a\}(\$e)\]\"\n\}\n\nproc\ do\ \{args\}\ \{\n\ \ \ \ puts\ \"<\$args>\"\n\ \ \ \ uplevel\ \$args\n\}\n\ntrace\ var\ a\ wu\ \{tellme\ array\}\ntrace\ var\ a(1)\ wu\ \{tellme\ element\}\n\nputs\ \[trace\ vinfo\ a\]\nputs\ \[trace\ vinfo\ a(1)\]\n\ndo\ set\ a(0)\ zero\ndo\ set\ a(1)\ one\ndo\ set\ a(2)\ two\ndo\ unset\ a(0)\ndo\ unset\ a(2)\ndo\ unset\ a\n\n#\ output\ is:\n#\n#\ \ \ \{wu\ \{tellme\ array\}\}\n#\ \ \ \{wu\ \{tellme\ element\}\}\n#\ \ \ <set\ a(0)\ zero>\n#\ \ \ \ \ array\ a=a\ e=0\ op=w\ ax=1\ ex=1\n#\ \ \ <set\ a(1)\ one>\n#\ \ \ \ \ array\ a=a\ e=1\ op=w\ ax=1\ ex=1\n#\ \ \ \ \ element\ a=a\ e=1\ op=w\ ax=1\ ex=1\n#\ \ \ <set\ a(2)\ two>\n#\ \ \ \ \ array\ a=a\ e=2\ op=w\ ax=1\ ex=1\n#\ \ \ <unset\ a(0)>\n#\ \ \ \ \ array\ a=a\ e=0\ op=u\ ax=1\ ex=0\n#\ \ \ <unset\ a(2)>\n#\ \ \ \ \ array\ a=a\ e=2\ op=u\ ax=1\ ex=0\n#\ \ \ <unset\ a>\n#\ \ \ \ \ array\ a=a\ e=\ op=u\ ax=0\ ex=0\n#\ \ \ \ \ element\ a=a\ e=1\ op=u\ ax=0\ ex=0\n======\n\n\n\n**\ Variable\ Trace\ Arguments\ vs\ Upvar\ **\n\nBe\ careful\ how\ you\ use\ the\ `name1`\ and\ `name2`\ parameters\ provided\ to\ a\ variable\ trace.\nIt's\ tempting\ to\ write\ a\ single\ handler\ which\ tracks\ access\ to\ multiple\ variables\ thus:\n======\nproc\ traceHandler\ \{name\ _\ op\}\ \{\ \ \;#\ we\ ignore\ name2\ for\ a\ non-array\ trace\n\ \ \ \ puts\ \"trace:\ variable\ \{\$name\}\ \$op\"\n\}\nunset\ -nocomplain\ x\ y\ntrace\ add\ variable\ x\ \{write\}\ traceHandler\ntrace\ add\ variable\ y\ \{write\}\ traceHandler\nincr\ x\n#\ \ trace:\ variable\ \{x\}\ write\nincr\ y\n#\ \ trace:\ variable\ \{y\}\ write\n======\n\nSo\ far,\ so\ good.\ \ But\ look\ what\ happens\ when\ the\ variable\ is\ \[https://en.wikipedia.org/wiki/Aliasing_%28computing%29%%|%aliased\]\ with\ `upvar`:\n\n======\nproc\ loop\ \{_var\ first\ limit\ script\}\ \{\ \;#\ http://wiki.tcl.tk/2025\n\ \ \ \ upvar\ 1\ \$_var\ var\n\ \ \ \ for\ \{set\ var\ \$first\}\ \{\$var\ <\ \$limit\}\ \{incr\ var\}\ \{\n\ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \}\n\}\nloop\ x\ 0\ 2\ \{\n\ \ \;#\ no\ loop\ body\ -\ we\ just\ want\ to\ see\ what\ happens\ to\ x\n\}\n#\ \ trace:\ variable\ \{var\}\ write\n#\ \ trace:\ variable\ \{var\}\ write\n#\ \ trace:\ variable\ \{var\}\ write\n======\n\nThe\ trace\ fires\ as\ expected\ ...\ but\ the\ name\ is\ now\ coming\ from\ somebody\ else's\ code.\nThis\ is\ sufficient\ if\ you\ just\ want\ to\ access\ the\ variable\ by\ `\[upvar\]`\ or\ `\[uplevel\]`,\ but\ useless\ for\ identifying\ changes\ to\ different\ variables\ managed\ by\ the\ same\ trace\ handler.\n\nBugs\ stemming\ from\ code\ not\ considering\ this\ behaviour\ can\ lie\ dormant\ for\ a\ very\ long\ time\ and\ be\ mystifying\ when\ they\ arise.\ \ Therefore,\ when\ the\ name\ of\ the\ variable\ matters\ to\ the\ trace\ handler,\ it's\ a\ good\ idea\ (and\ good\ practice\ for\ other\ kinds\ of\ callbacks)\ to\ pass\ that\ name\ explicitly,\ rather\ than\ relying\ on\ the\ arguments\ supplied\ by\ the\ trace:\n\n======\nproc\ traceHandler\ \{name\}\ \{\n\ \ \ \ puts\ \"trace:\ \$name\"\n\}\ntrace\ add\ variable\ x\ \{write\}\ \[lambda\ \{varname\ args\}\ \{traceHandler\ \$varname\}\ x\]\n======\n\n\[PYK\]:\ I\ prefer\ an\ example\ that\ uses\ `\[apply\]`\ directly,\ because\ its\ execution\n\[namespace\]\ can\ be\ specified,\ and\ in\ contrast\ with\ `\[lambda\]`\ (at\ least\ as\ncurrently\ defined\ on\ that\ page),\ its\ `\[uplevel\]`\ is\ still\ the\ context\ that\ntriggered\ the\ trace:\n\n======\ntrace\ add\ variable\ x\ write\ \[\n\ \ \ \ list\ apply\ \[\n\ \ \ \ \ \ \ \ list\ \{varname\ args\}\ \{traceHandler\ \$varname\}\ \[namespace\ current\]\]\ x\]\n======\n\n\[aspect\]:\ \ updated\ the\ \[lambda\]\ page\ to\ more\ prominently\ feature\ the\ Tcllib\ package\ which\ supports\ a\ namespace\ argument.\n\n**\ Local\ Variable\ Traces\ **\n\nOn\ \[comp.lang.tcl\],\ 2004-05,\ \[CLN\]\ answers\ \[Erik\ Leunissen\]'s\ question:\ Erik\nLeunissen\ wrote:\n\n======\n>\ The\ following\ passage\ from\ the\ man\ page\ to\ the\ trace\ command\ is\n>\ mystifying\ to\ me:\n>\ \n>\ \"If\ an\ unset\ occurs\ because\ of\ a\ procedure\ return,\ then\ the\ trace\ will\n>\ be\ invoked\ in\ the\ variable\ context\ of\ the\ procedure\ being\ returned\ to:\n>\ the\ stack\ frame\ of\ the\ returning\ procedure\ will\ no\ longer\ exist.\"\n>\ \n>\ I've\ read\ it\ again\ and\ again\;\ I\ can't\ imagine\ how\ a\ procedure\ return\n>\ affects/causes\ an\ unset.\n>\ ...\n\n\n\ \ \ proc\ foo\ \{\ \}\ \{\ \n\ \ \ \ \ \ set\ x\ 1\n\ \ \ \ \ \ trace\ variable\ x\ u\ \{some\ code\ here\}\n\ \ \ \}\n\nWhen\ foo\ is\ invoked,\ x\ is\ created\ (locally),\ has\ a\ trace\ associated\ with\nit,\ then\ becomes\ unset\ as\ foo\ exits.\n======\n\n\n\n**\ Arrays\ **\n\nNon-array\ variables\ give\ a\ null\ string\ for\ the\ ''name2''\ argument\ \ in\ the\ trace\ninvocation,\ but\ the\ null\ string\ is\ a\ perfectly\ valid\ array\ index\ (it\ is\ also\ a\nvalid\ array\ variable\ name),\ so\ a\ null\ value\ for\ ''name2''\ doesn't\ necessarily\nindicate\ that\ the\ traced\ variable\ is\ scalar.\ \ To\ determine\ whether\ a\ variable\nis\ an\ array,\ use:\n\n======\nif\ \{\[array\ exists\ \$varname\]\}\ \{...\}\n======\n\n\nAll\ of\ the\ following\ operations\ result\ in\ the\ argument\ values\ `a\ \{\}\ u`:\n\n======\nunset\ a\ \;#\ regular\ var\ a\narray\ unset\ a\nunset\ a()\n======\n\nincluding\ a\ null\ index\ string.\ \ `\[array\ exists\]`\ always\ returns\ false\ for\nthe\ first\ two\ cases,\ and\ true\ for\ the\ third\ (even\ if\ the\ null\ index\ was\ the\nonly\ array\ element).\ There\ is\ no\ way\ for\ the\ trace\ to\ be\ sure\ which\ operation\nwas\ performed.\n\n\[Lars\ H\]:\ Hmm...\ might\ this\ be\ a\ sign\ that\ the\ format\ of\ these\ parameter\ lists\nis\ not\ well\ designed?\ An\ alternative\ would\ have\ been\ to\ put\ the\ operation\ first\nand\ the\ variable\ name\ second,\ so\ that\ there\ needn't\ be\ an\ index\ for\ non-array\naccesses.\ Probably\ too\ late\ to\ change\ now,\ though.\ (Adding\ a\ second\ interface\nwhich\ is\ just\ like\ the\ current\ except\ that\ it\ produces\ parameter\ lists\ in\ a\ new\nformat\ is\ possible,\ but\ probably\ seen\ as\ superfluous.)\n\n\n\n**\ Arrays\ and\ Upvar\ **\n\nA\ surprising\ (?)\ result\ that\ is\ documented\ in\ the\ \[upvar\]\ manpage:\n\n===\nIf\ \ otherVar\ \ refers\ \ to\ an\ element\ of\ an\ array,\ then\ variable\ traces\nset\ for\ the\ entire\ array\ will\ not\ be\ invoked\ when\ myVar\ is\ accessed\ (but\ntraces\ on\ the\ particular\ element\ will\ still\ be\ invoked).\n===\n\nThis\ means\ that\ using\ a\ trace\ on\ an\ array\ is\ ''not''\ sufficient\ to\ capture\ all\nthe\ ways\ elements\ can\ be\ accessed.\ \ For\ instance:\n\n======\npackage\ require\ lambda\nunset\ -nocomplain\ a\ x\ y\narray\ set\ a\ \{x\ 1\ y\ 2\}\ntrace\ add\ variable\ a\ \{array\ read\ write\ unset\}\ \[lambda\ args\ \{puts\ \"::a\ trace:\ \$args\"\}\]\n======\n\nAny\ direct\ use\ of\ `a`\ will\ trigger\ the\ trace:\n\n======\n%\ incr\ a(x)\ \ \ \ \;#\ existing\ element\n::a\ trace:\ a\ x\ read\n::a\ trace:\ a\ x\ write\n\ 2\n%\ incr\ a(z)\ \ \ \ \;#\ new\ element\n::a\ trace:\ a\ z\ read\n::a\ trace:\ a\ z\ write\n\ 1\n%\ unset\ a(x)\n::a\ trace:\ a\ x\ unset\n======\n\nso\ far\ so\ good.\ \ But\ throw\ \[upvar\]\ into\ the\ mix:\n\n======\n%\ upvar\ 0\ a(y)\ y\ \ \ \ \;#\ existing\ element\n%\ upvar\ 0\ a(w)\ w\ \ \ \ \;#\ new\ element\n%\ incr\ y\n\ 3\n%\ incr\ w\n\ 1\n%\ unset\ y\n%\ unset\ w\n======\n\nNo\ traces\ were\ fired!\ \ If\ you're\ tracing\ an\ array\ whose\ elements\ might\ be\ \[upvar\]ed,\ beware.\n\n\n**\ What\ about\ a\ \"variable\ create\"\ Trace?\ **\n\n\[male\]\ 2006-01-24:\ I\ wanted\ to\ trace\ the\ creation\ of\ an\narray\ element\ and\ used\ the\ write\ event,\ but\ ...\ the\ write\ event\ is\ fired\ after\nthe\ new\ array\ element\ was\ already\ created!\ What's\ about\ a\ new\ event\ like\n\"create\"?\ Since\ a\ trace\ may\ be\ created\ on\ non-existent\ variables,\ this\ could\ be\nuseful\ not\ only\ for\ arrays.\n\n----\n\n\[Donald\ Arseneau\]:\ Yes,\ write\ traces\ fire\ after\ the\ variable\ has\ already\ been\nset,\ so\ if\ you\ want\ validation\ of\ variables'\ values,\ in\ analogy\ with\ Tk's\n\[entry\ validation\],\ then\ you\ must\ maintain\ shadow\ copies\ of\ the\ previous\nvalues,\ in\ order\ to\ undo\ improper\ settings.\n\n\n\n**\ Triggering\ Traces\ when\ using\ a\ variable\ at\ the\ \[C\]\ level\ **\ \n\nOn\ \[comp.lang.tcl\],\ \[Kevin\ Kenny\]\ answers\ someone\ wanting\ to\ link\ a\ C\ variable\nand\ a\ Tcl\ variable,\ and\ have\ a\ Tcl\ proc\ invoked\ when\ the\ C\ code\ modified\ the\nvariable:\n\n\n\ \ \ \ :\ \ \ Look\ in\ the\ manual\ for\ Tcl_UpdateLinkedVar.\ \ The\ Tcl\ engine\ has\ no\ way\ of\ telling\ that\ you've\ changed\ the\ variable\ in\ C\;\ if\ you\ call\ Tcl_UpdateLinkedVar,\ that\ tells\ it\ your\ value\ has\ changed,\ and\ it\ fires\ the\ traces.\n\n\n\n**\ Simple\ file\ I/O\ in\ traces:\ **\n\n======\ntrace\ var\ stdout\ w\ \{puts\ stdout\ \$stdout\ \;#\}\ntrace\ var\ stdin\ \ r\ \{gets\ stdin\ \ stdin\ \ \ \;#\}\n======\n\nThe\ variables\ are\ named\ like\ the\ file\ handles.\ Little\ demo,\ that\ waits\ for\ninput\ and\ prints\ it\ capitalized:\n\n======\nset\ stdout\ \[string\ toupper\ \$stdin\]\n======\n\n\n\n**\ Managing\ Traces\ **\n\nTraces\ are\ like\ \[widget\]s\ and\ \[image\]s\ in\ that\ they\ are\ resources\ that\ can\ be\nleaked\ and/or\ need\ clean-up.\ \ Counter-intuitive\ results\ sometimes\ arise\ because\ntraces\ are\ additive\ rather\ than\ substitutive\;\ a\ particular\ trace\ can\ fire\ a\nwhole\ chain\ of\ commands.\ \ To\ wipe\ the\ global\ space\ clean\ of\ traces,\n\n======\nforeach\ variable\ \[info\ glob\]\ \{\n\ \ \ \ foreach\ pair\ \[trace\ info\ variable\ ::\$variable\]\ \{\n\ \ \ \ \ \ \ \ foreach\ \{op\ traced_command\}\ \$pair\ \{\}\n\ \ \ \ \ \ \ \ set\ op\ \[string\ range\ \$op\ 0\ 0\]\ \n\ \ \ \ \ \ \ \ trace\ vdelete\ ::\$variable\ \$op\ \$traced_command\n\ \ \ \ \}\n\}\n======\n\n\n**\ Swallowed\ Errors:\ Command\ Delete\ Traces\ **\ \n\n\[PYK\]\ 2015-04-02:\n\nErrors\ are\ ignored\ in\ command\ delete\ traces:\n\n======\nvariable\ var1\ \{1\ one\ 2\ two\}\nproc\ p1\ args\ \{\}\n#intentional\ bad\ code\ here:\ the\ commandPrefix\ doesn't\ have\ the\ right\ command\ signature.\ntrace\ add\ command\ p1\ delete\ \[list\ dict\ unset\ var1\ 1\]\nrename\ p1\ \{\}\nputs\ \$var1\ \;#\ ->\ 1\ one\ 2\ two\n======\n\nThis\ is\ the\ current\ design,\ not\ a\ bug.\ \ Anyone\ have\ any\ info\ on\ the\ rationale?\n\n\n\n\n**\ Traces\ of\ Command\ Executions\ **\n\n\n\n\n***\ step\ traces\ ***\n\n'''enterstep'''\ and\ '''leavestep'''\ traces\ fire\ for\ all\ steps,\n\[recursion%|%recursively%|%\].\ \ When\ this\ is\ undesired,\ the\ depth\ of\ the\nrecursion\ can\ be\ constrained\ by\ having\ the\ trace\ procedure\ look\ at\ `\[info\nlevel\]`.\ \n\n\ \ \ \ :\ \ \ \[http://groups.google.com/d/msg/comp.lang.tcl/d8KWS-VmxDs/rx0aZp7qOdUJ%|%Interesting\ experience\ with\ execution\ traces\],\ \[comp.lang.tcl\],\ 2003-11-24\n\n\n----\n\n\[Donald\ Arseneau\]:\ Another\ tricky\ trap\ is\ that\ errors\ in\ traces\ may\ give\ error\nmessages,\ but\ no\ context\;\ the\ only\ context\ is\ for\ whatever\ triggered\ the\ trace.\nThus,\ if\ you\ ever\ see\ Tk\ error\ messages\ like\ \n\n======\ncan't\ set\ \"xv\":\ invalid\ command\ name\ \"oops\"\n\ \ \ \ while\ executing\n\"incr\ xv\"\n======\n\nthen\ you\ should\ look\ for\ a\ variable\ trace\ on\ the\ xv\ variable.\n\n----\n\n\[Schnexel\]:\ Oh\ the\ tricky\ trace\ traps!\ I\ tried\ to\ automaticly\ update\ a\nderivedData\ array\ by\ setting\ a\ trace\ on\ the\ parentData\ array\ (scenario\nsimplified)...\ Now\ I\ get\ a\ surreal\ result:\n\n======\nset\ bla\ \"What\ happened:\\n\"\n\nnamespace\ eval\ bbb\ \{\n\n\ \ \ \ array\ set\ lala\ \[list\ 1\ v1\ 2\ v2\ 3\ v3\]\n\ \ \ \ trace\ add\ variable\ ::bbb::lala\ \{read\ array\}\ ::bbb::tra\n\ \ \ \ proc\ tra\ args\ \{\n\ \ \ \ \ \ \ \ append\ ::bla\ \"\\n\ (TRACE\ \$args)\"\n\ \ \ \ \ \ \ \ array\ unset\ ::bbb::lala\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;#\ also\ deletes\ trace\ (yet\ the\ \"array\"\ op\ still\ fires)\n\ \ \ \ \ \ \ \ foreach\ \{n\ v\}\ \ \[list\ 1\ trv1\ 2\ trv2\ 3\ trv3\]\ \{\ set\ ::bbb::lala(\$n)\ \$v\ \}\n\ \ \ \ \}\n\}\n\nnamespace\ eval\ aaa\ \{\n\ \ \ \ append\ ::bla\ \"\\n\\\[info\ exists\ ::bbb::lala(1)\\\]==...\"\;\ append\ ::bla\ ...\ \[info\ exists\ ::bbb::lala(1)\]\n\ \ \ \ append\ ::bla\ \"\\n\\\[info\ exists\ ::bbb::lala(1)\\\]==...\"\;\ append\ ::bla\ ...\ \[info\ exists\ ::bbb::lala(1)\]\n\ \ \ \ append\ ::bla\ \"\\n\\\$::bbb::lala(1)==...\"\;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ append\ ::bla\ ...\ \$::bbb::lala(1)\n\}\n\nputs\ \$bla\n======\n\nwhich\ gives\ the\ output\n\n======none\nWhat\ happened:\n\[info\ exists\ ::bbb::lala(1)\]==...\n\ (TRACE\ ::bbb::lala\ 1\ read)\n\ (TRACE\ ::bbb::lala\ \{\}\ array)...0\n\[info\ exists\ ::bbb::lala(1)\]==......1\n\$::bbb::lala(1)==......trv1\n======\n\nSo,\ upon\ first\ read\ access\ of\ lala,\ it\ does\ not\ exist\ anymore,\ whilst\ upon\nsecond\ read\ it\ is\ there.\ Can\ anybody\ make\ sense\ of\ this?\n\n\[Lars\ H\]:\ Regarding\ why\ the\ \"array\"\ op\ fires:\ It\ it\ fires\ at\ the\ very\ `array\nunset\ ::bbb::lala`\ where\ you\ comment\ upon\ this,\ i.e.,\ before\ the\ `\[foreach\]`,\nwhich\ is\ consistent\ with\ the\ `\[trace\]`\ manpage\ (only\ read\ and\ write\ traces\ are\ndisabled\ inside\ a\ read\ or\ write\ trace).\ But\ why\ `\[info\ exists\]`\ reports\ `0`\ I\ don't\nknow...\ Perhaps\ some\ caching\ issue\ (the\ variable\ that\ was\ looked\ up\ is\ not\ the\none\ that\ is\ there\ when\ the\ result\ is\ returned)?\ You'll\ probably\ need\ to\ read\nthe\ source\ to\ find\ out.\n\n\[Schnexel\]:\ Wrrr...\ Here´s\ a\ simpler\ example.\ Array\ trace\ is\ bugged!\n\n======\narray\ set\ ::lala\ \[list\ 1\ v1\ \ 2\ v2\]\narray\ set\ ::lala\ \[list\ 3\ v3\ \ 4\ v4\]\nputs\ \"\\\$::lala==\[array\ get\ ::lala\]\"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;#\ O.K.\n\ntrace\ add\ variable\ ::lala\ read\ ::tra\n\n\nproc\ tra\ args\ \{\n\ \ \ \ puts\ \"\ \ \ \ (TRACE\ \$args)\"\n\ \ \ \ trace\ remove\ variable\ ::lala\ read\ ::tra\n\n\ \ \ \ array\ set\ ::lala\ \ \ \[list\ A\ trvA\ \ B\ trvB\]\n\ \ \ \ puts\ \"\ \ \ \ within\ trace:\ \ \\\$::lala==\[array\ get\ ::lala\]\"\ \;#\ O.K.\n\}\n\nputs\ \"1st\ read\ outside:\ \ \\\$::lala==\[array\ get\ ::lala\]\"\ \ \ \ \ \ \;#\ not\ O.K.\ !\nputs\ \"2nd\ read\ outside:\ \ \\\$::lala==\[array\ get\ ::lala\]\"\ \ \ \ \ \ \;#\ O.K.\n======\n\nOutput:\n\n======none\n\$::lala==4\ v4\ 1\ v1\ 2\ v2\ 3\ v3\nreading\ ::lala\n\ \ \ \ (TRACE\ ::lala\ 4\ read)\n\ \ \ \ within\ trace:\ \ \$::lala==4\ v4\ A\ trvA\ 1\ v1\ B\ trvB\ 2\ v2\ 3\ v3\n1st\ read\ outside:\ \ \$::lala==4\ v4\ 1\ v1\ 2\ v2\ 3\ v3\n2nd\ read\ outside:\ \ \$::lala==4\ v4\ A\ trvA\ 1\ v1\ B\ trvB\ 2\ v2\ 3\ v3\n======\n\n**\ Tracking\ where\ procedures\ were\ defined\ **\n\[DKF\]:\ One\ of\ the\ neat\ things\ about\ Tcl\ is\ that\ you\ can\ attach\ traces\ to\ things\ that\ in\ most\ other\ languages\ would\ be\ completely\ impossible\ to\ track.\ Here's\ how\ to\ find\ out\ where\ procedures\ are\ defined,\ by\ using\ an\ execution\ trace\ on\ \[\['''\[proc\]'''\]\]\ itself.\n======\nproc\ recordDefinitionLocation\ \{call\ code\ result\ op\}\ \{\n\ \ \ \ if\ \{\$code\}\ return\n\ \ \ \ set\ name\ \[uplevel\ 1\ \[list\ namespace\ which\ -command\ \[lindex\ \$call\ 1\]\]\]\n\ \ \ \ set\ location\ \[file\ normalize\ \[uplevel\ 1\ \{info\ script\}\]\]\n\ \ \ \ puts\ stderr\ \"defined\ '\$name'\ in\ '\$location'\"\n\}\ntrace\ add\ execution\ proc\ leave\ recordDefinitionLocation\n======\nTrying\ it\ out…\n===none\n%\ parray\ tcl_platform\n'''defined\ '::parray'\ in\ '/Library/Frameworks/Tcl.framework/Versions/8.6/Resources/Scripts/parray.tcl''''\ntcl_platform(byteOrder)\ \ \ \ \ =\ littleEndian\ntcl_platform(machine)\ \ \ \ \ \ \ =\ x86_64\ntcl_platform(os)\ \ \ \ \ \ \ \ \ \ \ \ =\ Darwin\ntcl_platform(osVersion)\ \ \ \ \ =\ 12.5.0\ntcl_platform(pathSeparator)\ =\ :\ntcl_platform(platform)\ \ \ \ \ \ =\ unix\ntcl_platform(pointerSize)\ \ \ =\ 8\ntcl_platform(threaded)\ \ \ \ \ \ =\ 1\ntcl_platform(user)\ \ \ \ \ \ \ \ \ \ =\ dkf\ntcl_platform(wordSize)\ \ \ \ \ \ =\ 8\n===\nThat\ looks\ correct\ for\ my\ system.\n\n**\ Proposal:\ \ Modify\ `trace\ command\ ...\ enter`\ to\ Act\ as\ a\ Command\ Filter\ **\n\n\[PYK\]\ 2013-12-22:\ The\ result\ of\ a\ command\ run\ as\ a\ trace\ is\ currently\ndiscarded.\ \ It\ could\ instead\ be\ used\ as\ the\ command\ to\ actually\ call.\nFor\ example,\ the\ result\ of\ the\ following\ script\ would\ be\ `12`,\ not\ `21`\n\n======\nproc\ add\ args\ \{\n\ \ \ \ ::tcl::mathop::+\ \{*\}\$args\n\}\n\ntrace\ add\ execution\ add\ enter\ \{apply\ \{\{cmd\ op\}\ \{\n\ \ \ \ set\ args\ \[lassign\ \$cmd\ name\]\n\ \ \ \ foreach\ arg\ \$args\[set\ args\ \{\}\]\ \{\n\ \ \ \ \ \ \ \ if\ \{\$arg\ %\ 2\ ==\ 0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ args\ \$arg\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ return\ \[linsert\ \$args\ 0\ \$name\]\ \n\}\}\}\n\nadd\ 1\ 2\ 3\ 4\ 5\ 6\n======\n***\ Strange\ problem\ I\ had\ with\ trace\ and\ variables\ in\ namespaces***\n\[SVP\]\ 22DEC2016\n\nAn\ interesting\ bug\ I\ have\ to\ fix.\n\nI\ have\ a\ couple\ of\ \"shapescale\"\ widgets\ in\ an\ application.\ These\ are\ pure\ tcl,\ and\ they\ act\ like\ slider\ controls\ but\ with\ a\ non\ rectangular\ shape.\ More\ importantly\ they\ monitor\ their\ variable\ with\ a\ trace,\ so\ when\ ever\ the\ value\ changes\ the\ trace\ proc\ will\ redraw\ the\ widget:\n======\n\ \ proc\ _variableWriteTrace\ \{w\ name1\ name2\ op\}\ \{\n\ \ \ \ variable\ Priv\n\n\ \ \ \ debugcallinfo\ traces\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Array\ element?\n\ \ \ \ variable\ \$name1\n\ \ \ \ if\ \{\$name2\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ set\ name1\ \"\$\{name1\}(\$name2)\"\n\ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Check\ the\ variable\ exists\ before\ we\ go\ reading\ from\ it\n\ \ \ \ debugputs\ traces\ \"\ \ +->Checking\ if\ variable\ \$name1\ exists\ ...\"\n\ \ \ \ if\ \{\[info\ exists\ \$name1\]\}\ \{\n\ \ \ \ \ \ debugputs\ traces\ \"\ \ +->yes\;\ value\ =\ '\[set\ \$name1\]'\"\n\ \ \ \ \ \ set\ Priv(\$w,value)\ \[set\ \$name1\]\n\ \ \ \ \ \ _redrawSlider\ \$w\n\ \ \ \ \}\n\ \ \}\n======\n\nIn\ theory.\n\nBut\ my\ problem\ was\ that\ when\ the\ data\ changed,\ and\ there\ were\ a\ whole\ bunch\ of\ other\ variables\ that\ changed,\ and\ a\ whole\ bunch\ of\ other\ traces\ fired,\ and\ whole\ bunch\ of\ other\ widgets\ were\ updated,\ except\ for\ the\ two\ shapescale\ widgets.\ Well,\ sometimes\ they\ would\ update.\ That\ really\ was\ the\ problem.\n\nNow\ after\ much\ investigation\ I\ found\ the\ following\ behaviour.\ This\ example\ works.\ The\ variableWriteTrace\ proc\ can\ see\ the\ variable\ and\ it's\ value\ and\ it\ redraws\ the\ slider:\n===none\n(System32)\ 51\ %\ set\ ::Gap12::gap12_0(config_volume)\ 7\n\[::ShapeScale|traces\]\ _variableWriteTrace\ w='.pr1.ed.pane.pafr.gap12.tree.config_volume'\ name1='::Gap12::gap12_0'\ name2='config_volume'\ op='write'\n\[::ShapeScale|traces\]\{\ \ +->Checking\ if\ variable\ ::Gap12::gap12_0(config_volume)\ exists\ ...\}\n\[::ShapeScale|traces\]\{\ \ +->yes\;\ value\ =\ '7'\}\n===\n\nBut\ then\ this\ second\ example\ fails.\ And\ this\ is\ the\ important\ one\ because\ the\ proc\ that\ changes\ the\ value\ lives\ in\ another\ namespace\ altogether\ called\ \"Gap12\",\ part\ of\ another\ code\ module:\n===none\n(System32)\ 52\ %\ namespace\ eval\ ::Gap12\ \{\ set\ gap12_0(config_volume)\ 7\ \}\n\[::ShapeScale|traces\]\ _variableWriteTrace\ w='.pr1.ed.pane.pafr.gap12.tree.config_volume'\ name1='gap12_0'\ name2='config_volume'\ op='write'\n\[::ShapeScale|traces\]\{\ \ +->Checking\ if\ variable\ gap12_0(config_volume)\ exists\ ...\}\n===\nSo\ the\ trace\ is\ called,\ but\ without\ the\ namespace\ prefix.\ Hence\ the\ variable\ being\ referenced\ doesn't\ exist,\ and\ so\ the\ value\ has\ changed\ but\ no\ redraw\ happens\ and\ the\ widget\ looses\ synch\ with\ the\ data.\n\nNow\ the\ trace\ info\ tells\ me\ that\ the\ trace\ is\ there.\ I\ can\ also\ see\ a\ second\ unrelated\ trace\ which\ monitors\ for\ project\ data\ changes.\n===none\n(System32)\ 53\ %\ trace\ info\ variable\ ::Gap12::gap12_0(config_volume)\n\{write\ \{::Gap12::_changedDataVariableTrace\ .pr1.ed.pane.pafr.gap12\}\}\ \{write\ \{::ShapeScale::_variableWriteTrace\ .pr1.ed.pane.pafr.gap12.tree.config_volume\}\}\n===\n\nAnd\ this\ is\ the\ code\ that\ sets\ the\ trace:\n===none\n\ \ \ \ \ \ \ \ \ \ \ \ trace\ add\ variable\ \[set\ Priv(\$w,-variable)\]\ write\ \"::ShapeScale::_variableWriteTrace\ \$w\"\n===\n\nAnd\ parray\ shows\ that\ the\ variable\ name\ is\ prefixed\ with\ the\ namespace\ correctly:\n===none\n::ShapeScale::Priv(.pr1.ed.pane.pafr.gap12.tree.config_volume,-variable)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\ ::Gap12::gap12_0(config_volume)\n===\n\nSo\ the\ problem\ is\ that\ despite\ the\ fact\ that\ I\ use\ the\ fully\ qualified\ name\ of\ the\ variable\ in\ the\ trace\ add\ command,\ trace\ will\ still\ call\ the\ handler\ WITHOUT\ the\ namespace\ prefix\ when\ I\ access\ the\ variable\ within\ it's\ own\ namespace\ without\ the\ namespace\ qualification.\ \n\nThis\ seems\ a\ little\ strange\ to\ me?\n\n======\n\n\n<<categories>>\ Tcl\ syntax\ |\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ Command regexp2} CALL {my render trace '''\[http://www.tcl.tk/man/tcl/TclCmd/trace.htm%|%trace\]'''\ a\ \[Tcl\ Commands%|%built-in\]\ \[Tcl\]\ command,\ monitors\ \[variable\]\ accesses\ \[command\]\ definition\ and\ execution.\n\n\n\n**\ See\ Also\ **\n\n\ \ \ \[An\ equation\ solver\]:\ \ \ with\ an\ example\ of\ using\ trace\ to\ update\ dependent\ resources\n\n\ \ \ \[Traces\]:\ \ \ examples\ and\ discussion\n\n\ \ \ \[Tracing\ inappropriate\ variable\ access\]:\ \ \ \n\n\ \ \ \[Whole-Script\ Tracing\]:\ \ \ by\ \[DKF\]\n\n\ \ \ \[An\ example\ of\ data\ objects\]:\ \ \ \[AM\]\ Using\ the\ trace\ command,\ I\ implemented\ an\ idea\ by\ \[George\ Howlett\]\ (the\ author\ of\ \[BLT\])\n\n\n\n**\ Synopsis\ **\n\n\ \ \ \ :\ \ \ '''trace'''\ ''option''\ ''?arg\ arg\ ...?''\n\n\n\n**\ Documentation\ **\n\n\ \ \ \[http://www.tcl.tk/man/tcl/TclCmd/trace.htm%|%official\ documentation%|%\]:\ \ \ \n\n\n\n**\ Description\ **\n\nExamples\ of\ what\ to\ do\ with\ `trace`:\n\n\ \ \ *\ Communicate\ between\ parts\ of\ a\ \[GUI\]\ and\ the\ internal\ state\ of\ the\ app.\ (Simplified\ \[MVC\],\ observer).\ In\ general\ Communicate\ between\ different\ parts\ of\ an\ app\ without\ coupling\ them\ strongly.\n\n\ \ \ *\ Compute\ simple\ constraints\ for\ a\ number\ of\ variables\ (\"if\ this\ flag\ is\ on\ and\ that\ one\ is\ on,\ then\ no\ other\ is\ allowed\ to\ be\ set\",\ and\ some\ such).\n\n\ \ \ *\ `\[bind\]`\ \[Canvas\]\ text\ items\ to\ a\ variable,\ effecting\ dynamic\ updates\ \n\n\ \ \ *\ Debug\ -\ call\ a\ proc\ when\ a\ variable\ is\ modified\ (detect\ setting\ from\ wrong\ routine).\n\n\ \ \ *\ Trace\ works\ in\ Itcl\ \[Itcl\ trace\]\ but\ not\ quite\ trivially.\n\n\n\n**\ Order\ of\ Processing\ **\n\n\[JCW\]:\n\n======\nproc\ tellme\ \{id\ a\ e\ op\}\ \{\n\ \ \ \ puts\ \"\ \ \$id\ a=\$a\ e=\$e\ op=\$op\\\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ ax=\[info\ exists\ ::\$a\]\ ex=\[info\ exists\ ::\$\{a\}(\$e)\]\"\n\}\n\nproc\ do\ \{args\}\ \{\n\ \ \ \ puts\ \"<\$args>\"\n\ \ \ \ uplevel\ \$args\n\}\n\ntrace\ var\ a\ wu\ \{tellme\ array\}\ntrace\ var\ a(1)\ wu\ \{tellme\ element\}\n\nputs\ \[trace\ vinfo\ a\]\nputs\ \[trace\ vinfo\ a(1)\]\n\ndo\ set\ a(0)\ zero\ndo\ set\ a(1)\ one\ndo\ set\ a(2)\ two\ndo\ unset\ a(0)\ndo\ unset\ a(2)\ndo\ unset\ a\n\n#\ output\ is:\n#\n#\ \ \ \{wu\ \{tellme\ array\}\}\n#\ \ \ \{wu\ \{tellme\ element\}\}\n#\ \ \ <set\ a(0)\ zero>\n#\ \ \ \ \ array\ a=a\ e=0\ op=w\ ax=1\ ex=1\n#\ \ \ <set\ a(1)\ one>\n#\ \ \ \ \ array\ a=a\ e=1\ op=w\ ax=1\ ex=1\n#\ \ \ \ \ element\ a=a\ e=1\ op=w\ ax=1\ ex=1\n#\ \ \ <set\ a(2)\ two>\n#\ \ \ \ \ array\ a=a\ e=2\ op=w\ ax=1\ ex=1\n#\ \ \ <unset\ a(0)>\n#\ \ \ \ \ array\ a=a\ e=0\ op=u\ ax=1\ ex=0\n#\ \ \ <unset\ a(2)>\n#\ \ \ \ \ array\ a=a\ e=2\ op=u\ ax=1\ ex=0\n#\ \ \ <unset\ a>\n#\ \ \ \ \ array\ a=a\ e=\ op=u\ ax=0\ ex=0\n#\ \ \ \ \ element\ a=a\ e=1\ op=u\ ax=0\ ex=0\n======\n\n\n\n**\ Variable\ Trace\ Arguments\ vs\ Upvar\ **\n\nBe\ careful\ how\ you\ use\ the\ `name1`\ and\ `name2`\ parameters\ provided\ to\ a\ variable\ trace.\nIt's\ tempting\ to\ write\ a\ single\ handler\ which\ tracks\ access\ to\ multiple\ variables\ thus:\n======\nproc\ traceHandler\ \{name\ _\ op\}\ \{\ \ \;#\ we\ ignore\ name2\ for\ a\ non-array\ trace\n\ \ \ \ puts\ \"trace:\ variable\ \{\$name\}\ \$op\"\n\}\nunset\ -nocomplain\ x\ y\ntrace\ add\ variable\ x\ \{write\}\ traceHandler\ntrace\ add\ variable\ y\ \{write\}\ traceHandler\nincr\ x\n#\ \ trace:\ variable\ \{x\}\ write\nincr\ y\n#\ \ trace:\ variable\ \{y\}\ write\n======\n\nSo\ far,\ so\ good.\ \ But\ look\ what\ happens\ when\ the\ variable\ is\ \[https://en.wikipedia.org/wiki/Aliasing_%28computing%29%%|%aliased\]\ with\ `upvar`:\n\n======\nproc\ loop\ \{_var\ first\ limit\ script\}\ \{\ \;#\ http://wiki.tcl.tk/2025\n\ \ \ \ upvar\ 1\ \$_var\ var\n\ \ \ \ for\ \{set\ var\ \$first\}\ \{\$var\ <\ \$limit\}\ \{incr\ var\}\ \{\n\ \ \ \ \ \ \ \ uplevel\ 1\ \$script\n\ \ \ \ \}\n\}\nloop\ x\ 0\ 2\ \{\n\ \ \;#\ no\ loop\ body\ -\ we\ just\ want\ to\ see\ what\ happens\ to\ x\n\}\n#\ \ trace:\ variable\ \{var\}\ write\n#\ \ trace:\ variable\ \{var\}\ write\n#\ \ trace:\ variable\ \{var\}\ write\n======\n\nThe\ trace\ fires\ as\ expected\ ...\ but\ the\ name\ is\ now\ coming\ from\ somebody\ else's\ code.\nThis\ is\ sufficient\ if\ you\ just\ want\ to\ access\ the\ variable\ by\ `\[upvar\]`\ or\ `\[uplevel\]`,\ but\ useless\ for\ identifying\ changes\ to\ different\ variables\ managed\ by\ the\ same\ trace\ handler.\n\nBugs\ stemming\ from\ code\ not\ considering\ this\ behaviour\ can\ lie\ dormant\ for\ a\ very\ long\ time\ and\ be\ mystifying\ when\ they\ arise.\ \ Therefore,\ when\ the\ name\ of\ the\ variable\ matters\ to\ the\ trace\ handler,\ it's\ a\ good\ idea\ (and\ good\ practice\ for\ other\ kinds\ of\ callbacks)\ to\ pass\ that\ name\ explicitly,\ rather\ than\ relying\ on\ the\ arguments\ supplied\ by\ the\ trace:\n\n======\nproc\ traceHandler\ \{name\}\ \{\n\ \ \ \ puts\ \"trace:\ \$name\"\n\}\ntrace\ add\ variable\ x\ \{write\}\ \[lambda\ \{varname\ args\}\ \{traceHandler\ \$varname\}\ x\]\n======\n\n\[PYK\]:\ I\ prefer\ an\ example\ that\ uses\ `\[apply\]`\ directly,\ because\ its\ execution\n\[namespace\]\ can\ be\ specified,\ and\ in\ contrast\ with\ `\[lambda\]`\ (at\ least\ as\ncurrently\ defined\ on\ that\ page),\ its\ `\[uplevel\]`\ is\ still\ the\ context\ that\ntriggered\ the\ trace:\n\n======\ntrace\ add\ variable\ x\ write\ \[\n\ \ \ \ list\ apply\ \[\n\ \ \ \ \ \ \ \ list\ \{varname\ args\}\ \{traceHandler\ \$varname\}\ \[namespace\ current\]\]\ x\]\n======\n\n\[aspect\]:\ \ updated\ the\ \[lambda\]\ page\ to\ more\ prominently\ feature\ the\ Tcllib\ package\ which\ supports\ a\ namespace\ argument.\n\n**\ Local\ Variable\ Traces\ **\n\nOn\ \[comp.lang.tcl\],\ 2004-05,\ \[CLN\]\ answers\ \[Erik\ Leunissen\]'s\ question:\ Erik\nLeunissen\ wrote:\n\n======\n>\ The\ following\ passage\ from\ the\ man\ page\ to\ the\ trace\ command\ is\n>\ mystifying\ to\ me:\n>\ \n>\ \"If\ an\ unset\ occurs\ because\ of\ a\ procedure\ return,\ then\ the\ trace\ will\n>\ be\ invoked\ in\ the\ variable\ context\ of\ the\ procedure\ being\ returned\ to:\n>\ the\ stack\ frame\ of\ the\ returning\ procedure\ will\ no\ longer\ exist.\"\n>\ \n>\ I've\ read\ it\ again\ and\ again\;\ I\ can't\ imagine\ how\ a\ procedure\ return\n>\ affects/causes\ an\ unset.\n>\ ...\n\n\n\ \ \ proc\ foo\ \{\ \}\ \{\ \n\ \ \ \ \ \ set\ x\ 1\n\ \ \ \ \ \ trace\ variable\ x\ u\ \{some\ code\ here\}\n\ \ \ \}\n\nWhen\ foo\ is\ invoked,\ x\ is\ created\ (locally),\ has\ a\ trace\ associated\ with\nit,\ then\ becomes\ unset\ as\ foo\ exits.\n======\n\n\n\n**\ Arrays\ **\n\nNon-array\ variables\ give\ a\ null\ string\ for\ the\ ''name2''\ argument\ \ in\ the\ trace\ninvocation,\ but\ the\ null\ string\ is\ a\ perfectly\ valid\ array\ index\ (it\ is\ also\ a\nvalid\ array\ variable\ name),\ so\ a\ null\ value\ for\ ''name2''\ doesn't\ necessarily\nindicate\ that\ the\ traced\ variable\ is\ scalar.\ \ To\ determine\ whether\ a\ variable\nis\ an\ array,\ use:\n\n======\nif\ \{\[array\ exists\ \$varname\]\}\ \{...\}\n======\n\n\nAll\ of\ the\ following\ operations\ result\ in\ the\ argument\ values\ `a\ \{\}\ u`:\n\n======\nunset\ a\ \;#\ regular\ var\ a\narray\ unset\ a\nunset\ a()\n======\n\nincluding\ a\ null\ index\ string.\ \ `\[array\ exists\]`\ always\ returns\ false\ for\nthe\ first\ two\ cases,\ and\ true\ for\ the\ third\ (even\ if\ the\ null\ index\ was\ the\nonly\ array\ element).\ There\ is\ no\ way\ for\ the\ trace\ to\ be\ sure\ which\ operation\nwas\ performed.\n\n\[Lars\ H\]:\ Hmm...\ might\ this\ be\ a\ sign\ that\ the\ format\ of\ these\ parameter\ lists\nis\ not\ well\ designed?\ An\ alternative\ would\ have\ been\ to\ put\ the\ operation\ first\nand\ the\ variable\ name\ second,\ so\ that\ there\ needn't\ be\ an\ index\ for\ non-array\naccesses.\ Probably\ too\ late\ to\ change\ now,\ though.\ (Adding\ a\ second\ interface\nwhich\ is\ just\ like\ the\ current\ except\ that\ it\ produces\ parameter\ lists\ in\ a\ new\nformat\ is\ possible,\ but\ probably\ seen\ as\ superfluous.)\n\n\n\n**\ Arrays\ and\ Upvar\ **\n\nA\ surprising\ (?)\ result\ that\ is\ documented\ in\ the\ \[upvar\]\ manpage:\n\n===\nIf\ \ otherVar\ \ refers\ \ to\ an\ element\ of\ an\ array,\ then\ variable\ traces\nset\ for\ the\ entire\ array\ will\ not\ be\ invoked\ when\ myVar\ is\ accessed\ (but\ntraces\ on\ the\ particular\ element\ will\ still\ be\ invoked).\n===\n\nThis\ means\ that\ using\ a\ trace\ on\ an\ array\ is\ ''not''\ sufficient\ to\ capture\ all\nthe\ ways\ elements\ can\ be\ accessed.\ \ For\ instance:\n\n======\npackage\ require\ lambda\nunset\ -nocomplain\ a\ x\ y\narray\ set\ a\ \{x\ 1\ y\ 2\}\ntrace\ add\ variable\ a\ \{array\ read\ write\ unset\}\ \[lambda\ args\ \{puts\ \"::a\ trace:\ \$args\"\}\]\n======\n\nAny\ direct\ use\ of\ `a`\ will\ trigger\ the\ trace:\n\n======\n%\ incr\ a(x)\ \ \ \ \;#\ existing\ element\n::a\ trace:\ a\ x\ read\n::a\ trace:\ a\ x\ write\n\ 2\n%\ incr\ a(z)\ \ \ \ \;#\ new\ element\n::a\ trace:\ a\ z\ read\n::a\ trace:\ a\ z\ write\n\ 1\n%\ unset\ a(x)\n::a\ trace:\ a\ x\ unset\n======\n\nso\ far\ so\ good.\ \ But\ throw\ \[upvar\]\ into\ the\ mix:\n\n======\n%\ upvar\ 0\ a(y)\ y\ \ \ \ \;#\ existing\ element\n%\ upvar\ 0\ a(w)\ w\ \ \ \ \;#\ new\ element\n%\ incr\ y\n\ 3\n%\ incr\ w\n\ 1\n%\ unset\ y\n%\ unset\ w\n======\n\nNo\ traces\ were\ fired!\ \ If\ you're\ tracing\ an\ array\ whose\ elements\ might\ be\ \[upvar\]ed,\ beware.\n\n\n**\ What\ about\ a\ \"variable\ create\"\ Trace?\ **\n\n\[male\]\ 2006-01-24:\ I\ wanted\ to\ trace\ the\ creation\ of\ an\narray\ element\ and\ used\ the\ write\ event,\ but\ ...\ the\ write\ event\ is\ fired\ after\nthe\ new\ array\ element\ was\ already\ created!\ What's\ about\ a\ new\ event\ like\n\"create\"?\ Since\ a\ trace\ may\ be\ created\ on\ non-existent\ variables,\ this\ could\ be\nuseful\ not\ only\ for\ arrays.\n\n----\n\n\[Donald\ Arseneau\]:\ Yes,\ write\ traces\ fire\ after\ the\ variable\ has\ already\ been\nset,\ so\ if\ you\ want\ validation\ of\ variables'\ values,\ in\ analogy\ with\ Tk's\n\[entry\ validation\],\ then\ you\ must\ maintain\ shadow\ copies\ of\ the\ previous\nvalues,\ in\ order\ to\ undo\ improper\ settings.\n\n\n\n**\ Triggering\ Traces\ when\ using\ a\ variable\ at\ the\ \[C\]\ level\ **\ \n\nOn\ \[comp.lang.tcl\],\ \[Kevin\ Kenny\]\ answers\ someone\ wanting\ to\ link\ a\ C\ variable\nand\ a\ Tcl\ variable,\ and\ have\ a\ Tcl\ proc\ invoked\ when\ the\ C\ code\ modified\ the\nvariable:\n\n\n\ \ \ \ :\ \ \ Look\ in\ the\ manual\ for\ Tcl_UpdateLinkedVar.\ \ The\ Tcl\ engine\ has\ no\ way\ of\ telling\ that\ you've\ changed\ the\ variable\ in\ C\;\ if\ you\ call\ Tcl_UpdateLinkedVar,\ that\ tells\ it\ your\ value\ has\ changed,\ and\ it\ fires\ the\ traces.\n\n\n\n**\ Simple\ file\ I/O\ in\ traces:\ **\n\n======\ntrace\ var\ stdout\ w\ \{puts\ stdout\ \$stdout\ \;#\}\ntrace\ var\ stdin\ \ r\ \{gets\ stdin\ \ stdin\ \ \ \;#\}\n======\n\nThe\ variables\ are\ named\ like\ the\ file\ handles.\ Little\ demo,\ that\ waits\ for\ninput\ and\ prints\ it\ capitalized:\n\n======\nset\ stdout\ \[string\ toupper\ \$stdin\]\n======\n\n\n\n**\ Managing\ Traces\ **\n\nTraces\ are\ like\ \[widget\]s\ and\ \[image\]s\ in\ that\ they\ are\ resources\ that\ can\ be\nleaked\ and/or\ need\ clean-up.\ \ Counter-intuitive\ results\ sometimes\ arise\ because\ntraces\ are\ additive\ rather\ than\ substitutive\;\ a\ particular\ trace\ can\ fire\ a\nwhole\ chain\ of\ commands.\ \ To\ wipe\ the\ global\ space\ clean\ of\ traces,\n\n======\nforeach\ variable\ \[info\ glob\]\ \{\n\ \ \ \ foreach\ pair\ \[trace\ info\ variable\ ::\$variable\]\ \{\n\ \ \ \ \ \ \ \ foreach\ \{op\ traced_command\}\ \$pair\ \{\}\n\ \ \ \ \ \ \ \ set\ op\ \[string\ range\ \$op\ 0\ 0\]\ \n\ \ \ \ \ \ \ \ trace\ vdelete\ ::\$variable\ \$op\ \$traced_command\n\ \ \ \ \}\n\}\n======\n\n\n**\ Swallowed\ Errors:\ Command\ Delete\ Traces\ **\ \n\n\[PYK\]\ 2015-04-02:\n\nErrors\ are\ ignored\ in\ command\ delete\ traces:\n\n======\nvariable\ var1\ \{1\ one\ 2\ two\}\nproc\ p1\ args\ \{\}\n#intentional\ bad\ code\ here:\ the\ commandPrefix\ doesn't\ have\ the\ right\ command\ signature.\ntrace\ add\ command\ p1\ delete\ \[list\ dict\ unset\ var1\ 1\]\nrename\ p1\ \{\}\nputs\ \$var1\ \;#\ ->\ 1\ one\ 2\ two\n======\n\nThis\ is\ the\ current\ design,\ not\ a\ bug.\ \ Anyone\ have\ any\ info\ on\ the\ rationale?\n\n\n\n\n**\ Traces\ of\ Command\ Executions\ **\n\n\n\n\n***\ step\ traces\ ***\n\n'''enterstep'''\ and\ '''leavestep'''\ traces\ fire\ for\ all\ steps,\n\[recursion%|%recursively%|%\].\ \ When\ this\ is\ undesired,\ the\ depth\ of\ the\nrecursion\ can\ be\ constrained\ by\ having\ the\ trace\ procedure\ look\ at\ `\[info\nlevel\]`.\ \n\n\ \ \ \ :\ \ \ \[http://groups.google.com/d/msg/comp.lang.tcl/d8KWS-VmxDs/rx0aZp7qOdUJ%|%Interesting\ experience\ with\ execution\ traces\],\ \[comp.lang.tcl\],\ 2003-11-24\n\n\n----\n\n\[Donald\ Arseneau\]:\ Another\ tricky\ trap\ is\ that\ errors\ in\ traces\ may\ give\ error\nmessages,\ but\ no\ context\;\ the\ only\ context\ is\ for\ whatever\ triggered\ the\ trace.\nThus,\ if\ you\ ever\ see\ Tk\ error\ messages\ like\ \n\n======\ncan't\ set\ \"xv\":\ invalid\ command\ name\ \"oops\"\n\ \ \ \ while\ executing\n\"incr\ xv\"\n======\n\nthen\ you\ should\ look\ for\ a\ variable\ trace\ on\ the\ xv\ variable.\n\n----\n\n\[Schnexel\]:\ Oh\ the\ tricky\ trace\ traps!\ I\ tried\ to\ automaticly\ update\ a\nderivedData\ array\ by\ setting\ a\ trace\ on\ the\ parentData\ array\ (scenario\nsimplified)...\ Now\ I\ get\ a\ surreal\ result:\n\n======\nset\ bla\ \"What\ happened:\\n\"\n\nnamespace\ eval\ bbb\ \{\n\n\ \ \ \ array\ set\ lala\ \[list\ 1\ v1\ 2\ v2\ 3\ v3\]\n\ \ \ \ trace\ add\ variable\ ::bbb::lala\ \{read\ array\}\ ::bbb::tra\n\ \ \ \ proc\ tra\ args\ \{\n\ \ \ \ \ \ \ \ append\ ::bla\ \"\\n\ (TRACE\ \$args)\"\n\ \ \ \ \ \ \ \ array\ unset\ ::bbb::lala\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;#\ also\ deletes\ trace\ (yet\ the\ \"array\"\ op\ still\ fires)\n\ \ \ \ \ \ \ \ foreach\ \{n\ v\}\ \ \[list\ 1\ trv1\ 2\ trv2\ 3\ trv3\]\ \{\ set\ ::bbb::lala(\$n)\ \$v\ \}\n\ \ \ \ \}\n\}\n\nnamespace\ eval\ aaa\ \{\n\ \ \ \ append\ ::bla\ \"\\n\\\[info\ exists\ ::bbb::lala(1)\\\]==...\"\;\ append\ ::bla\ ...\ \[info\ exists\ ::bbb::lala(1)\]\n\ \ \ \ append\ ::bla\ \"\\n\\\[info\ exists\ ::bbb::lala(1)\\\]==...\"\;\ append\ ::bla\ ...\ \[info\ exists\ ::bbb::lala(1)\]\n\ \ \ \ append\ ::bla\ \"\\n\\\$::bbb::lala(1)==...\"\;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ append\ ::bla\ ...\ \$::bbb::lala(1)\n\}\n\nputs\ \$bla\n======\n\nwhich\ gives\ the\ output\n\n======none\nWhat\ happened:\n\[info\ exists\ ::bbb::lala(1)\]==...\n\ (TRACE\ ::bbb::lala\ 1\ read)\n\ (TRACE\ ::bbb::lala\ \{\}\ array)...0\n\[info\ exists\ ::bbb::lala(1)\]==......1\n\$::bbb::lala(1)==......trv1\n======\n\nSo,\ upon\ first\ read\ access\ of\ lala,\ it\ does\ not\ exist\ anymore,\ whilst\ upon\nsecond\ read\ it\ is\ there.\ Can\ anybody\ make\ sense\ of\ this?\n\n\[Lars\ H\]:\ Regarding\ why\ the\ \"array\"\ op\ fires:\ It\ it\ fires\ at\ the\ very\ `array\nunset\ ::bbb::lala`\ where\ you\ comment\ upon\ this,\ i.e.,\ before\ the\ `\[foreach\]`,\nwhich\ is\ consistent\ with\ the\ `\[trace\]`\ manpage\ (only\ read\ and\ write\ traces\ are\ndisabled\ inside\ a\ read\ or\ write\ trace).\ But\ why\ `\[info\ exists\]`\ reports\ `0`\ I\ don't\nknow...\ Perhaps\ some\ caching\ issue\ (the\ variable\ that\ was\ looked\ up\ is\ not\ the\none\ that\ is\ there\ when\ the\ result\ is\ returned)?\ You'll\ probably\ need\ to\ read\nthe\ source\ to\ find\ out.\n\n\[Schnexel\]:\ Wrrr...\ Here´s\ a\ simpler\ example.\ Array\ trace\ is\ bugged!\n\n======\narray\ set\ ::lala\ \[list\ 1\ v1\ \ 2\ v2\]\narray\ set\ ::lala\ \[list\ 3\ v3\ \ 4\ v4\]\nputs\ \"\\\$::lala==\[array\ get\ ::lala\]\"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \;#\ O.K.\n\ntrace\ add\ variable\ ::lala\ read\ ::tra\n\n\nproc\ tra\ args\ \{\n\ \ \ \ puts\ \"\ \ \ \ (TRACE\ \$args)\"\n\ \ \ \ trace\ remove\ variable\ ::lala\ read\ ::tra\n\n\ \ \ \ array\ set\ ::lala\ \ \ \[list\ A\ trvA\ \ B\ trvB\]\n\ \ \ \ puts\ \"\ \ \ \ within\ trace:\ \ \\\$::lala==\[array\ get\ ::lala\]\"\ \;#\ O.K.\n\}\n\nputs\ \"1st\ read\ outside:\ \ \\\$::lala==\[array\ get\ ::lala\]\"\ \ \ \ \ \ \;#\ not\ O.K.\ !\nputs\ \"2nd\ read\ outside:\ \ \\\$::lala==\[array\ get\ ::lala\]\"\ \ \ \ \ \ \;#\ O.K.\n======\n\nOutput:\n\n======none\n\$::lala==4\ v4\ 1\ v1\ 2\ v2\ 3\ v3\nreading\ ::lala\n\ \ \ \ (TRACE\ ::lala\ 4\ read)\n\ \ \ \ within\ trace:\ \ \$::lala==4\ v4\ A\ trvA\ 1\ v1\ B\ trvB\ 2\ v2\ 3\ v3\n1st\ read\ outside:\ \ \$::lala==4\ v4\ 1\ v1\ 2\ v2\ 3\ v3\n2nd\ read\ outside:\ \ \$::lala==4\ v4\ A\ trvA\ 1\ v1\ B\ trvB\ 2\ v2\ 3\ v3\n======\n\n**\ Tracking\ where\ procedures\ were\ defined\ **\n\[DKF\]:\ One\ of\ the\ neat\ things\ about\ Tcl\ is\ that\ you\ can\ attach\ traces\ to\ things\ that\ in\ most\ other\ languages\ would\ be\ completely\ impossible\ to\ track.\ Here's\ how\ to\ find\ out\ where\ procedures\ are\ defined,\ by\ using\ an\ execution\ trace\ on\ \[\['''\[proc\]'''\]\]\ itself.\n======\nproc\ recordDefinitionLocation\ \{call\ code\ result\ op\}\ \{\n\ \ \ \ if\ \{\$code\}\ return\n\ \ \ \ set\ name\ \[uplevel\ 1\ \[list\ namespace\ which\ -command\ \[lindex\ \$call\ 1\]\]\]\n\ \ \ \ set\ location\ \[file\ normalize\ \[uplevel\ 1\ \{info\ script\}\]\]\n\ \ \ \ puts\ stderr\ \"defined\ '\$name'\ in\ '\$location'\"\n\}\ntrace\ add\ execution\ proc\ leave\ recordDefinitionLocation\n======\nTrying\ it\ out…\n===none\n%\ parray\ tcl_platform\n'''defined\ '::parray'\ in\ '/Library/Frameworks/Tcl.framework/Versions/8.6/Resources/Scripts/parray.tcl''''\ntcl_platform(byteOrder)\ \ \ \ \ =\ littleEndian\ntcl_platform(machine)\ \ \ \ \ \ \ =\ x86_64\ntcl_platform(os)\ \ \ \ \ \ \ \ \ \ \ \ =\ Darwin\ntcl_platform(osVersion)\ \ \ \ \ =\ 12.5.0\ntcl_platform(pathSeparator)\ =\ :\ntcl_platform(platform)\ \ \ \ \ \ =\ unix\ntcl_platform(pointerSize)\ \ \ =\ 8\ntcl_platform(threaded)\ \ \ \ \ \ =\ 1\ntcl_platform(user)\ \ \ \ \ \ \ \ \ \ =\ dkf\ntcl_platform(wordSize)\ \ \ \ \ \ =\ 8\n===\nThat\ looks\ correct\ for\ my\ system.\n\n**\ Proposal:\ \ Modify\ `trace\ command\ ...\ enter`\ to\ Act\ as\ a\ Command\ Filter\ **\n\n\[PYK\]\ 2013-12-22:\ The\ result\ of\ a\ command\ run\ as\ a\ trace\ is\ currently\ndiscarded.\ \ It\ could\ instead\ be\ used\ as\ the\ command\ to\ actually\ call.\nFor\ example,\ the\ result\ of\ the\ following\ script\ would\ be\ `12`,\ not\ `21`\n\n======\nproc\ add\ args\ \{\n\ \ \ \ ::tcl::mathop::+\ \{*\}\$args\n\}\n\ntrace\ add\ execution\ add\ enter\ \{apply\ \{\{cmd\ op\}\ \{\n\ \ \ \ set\ args\ \[lassign\ \$cmd\ name\]\n\ \ \ \ foreach\ arg\ \$args\[set\ args\ \{\}\]\ \{\n\ \ \ \ \ \ \ \ if\ \{\$arg\ %\ 2\ ==\ 0\}\ \{\n\ \ \ \ \ \ \ \ \ \ \ \ lappend\ args\ \$arg\n\ \ \ \ \ \ \ \ \}\n\ \ \ \ \}\n\ \ \ \ return\ \[linsert\ \$args\ 0\ \$name\]\ \n\}\}\}\n\nadd\ 1\ 2\ 3\ 4\ 5\ 6\n======\n***\ Strange\ problem\ I\ had\ with\ trace\ and\ variables\ in\ namespaces***\n\[SVP\]\ 22DEC2016\n\nAn\ interesting\ bug\ I\ have\ to\ fix.\n\nI\ have\ a\ couple\ of\ \"shapescale\"\ widgets\ in\ an\ application.\ These\ are\ pure\ tcl,\ and\ they\ act\ like\ slider\ controls\ but\ with\ a\ non\ rectangular\ shape.\ More\ importantly\ they\ monitor\ their\ variable\ with\ a\ trace,\ so\ when\ ever\ the\ value\ changes\ the\ trace\ proc\ will\ redraw\ the\ widget:\n======\n\ \ proc\ _variableWriteTrace\ \{w\ name1\ name2\ op\}\ \{\n\ \ \ \ variable\ Priv\n\n\ \ \ \ debugcallinfo\ traces\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Array\ element?\n\ \ \ \ variable\ \$name1\n\ \ \ \ if\ \{\$name2\ !=\ \"\"\}\ \{\n\ \ \ \ \ \ set\ name1\ \"\$\{name1\}(\$name2)\"\n\ \ \ \ \}\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ #\ Check\ the\ variable\ exists\ before\ we\ go\ reading\ from\ it\n\ \ \ \ debugputs\ traces\ \"\ \ +->Checking\ if\ variable\ \$name1\ exists\ ...\"\n\ \ \ \ if\ \{\[info\ exists\ \$name1\]\}\ \{\n\ \ \ \ \ \ debugputs\ traces\ \"\ \ +->yes\;\ value\ =\ '\[set\ \$name1\]'\"\n\ \ \ \ \ \ set\ Priv(\$w,value)\ \[set\ \$name1\]\n\ \ \ \ \ \ _redrawSlider\ \$w\n\ \ \ \ \}\n\ \ \}\n======\n\nIn\ theory.\n\nBut\ my\ problem\ was\ that\ when\ the\ data\ changed,\ and\ there\ were\ a\ whole\ bunch\ of\ other\ variables\ that\ changed,\ and\ a\ whole\ bunch\ of\ other\ traces\ fired,\ and\ whole\ bunch\ of\ other\ widgets\ were\ updated,\ except\ for\ the\ two\ shapescale\ widgets.\ Well,\ sometimes\ they\ would\ update.\ That\ really\ was\ the\ problem.\n\nNow\ after\ much\ investigation\ I\ found\ the\ following\ behaviour.\ This\ example\ works.\ The\ variableWriteTrace\ proc\ can\ see\ the\ variable\ and\ it's\ value\ and\ it\ redraws\ the\ slider:\n===none\n(System32)\ 51\ %\ set\ ::Gap12::gap12_0(config_volume)\ 7\n\[::ShapeScale|traces\]\ _variableWriteTrace\ w='.pr1.ed.pane.pafr.gap12.tree.config_volume'\ name1='::Gap12::gap12_0'\ name2='config_volume'\ op='write'\n\[::ShapeScale|traces\]\{\ \ +->Checking\ if\ variable\ ::Gap12::gap12_0(config_volume)\ exists\ ...\}\n\[::ShapeScale|traces\]\{\ \ +->yes\;\ value\ =\ '7'\}\n===\n\nBut\ then\ this\ second\ example\ fails.\ And\ this\ is\ the\ important\ one\ because\ the\ proc\ that\ changes\ the\ value\ lives\ in\ another\ namespace\ altogether\ called\ \"Gap12\",\ part\ of\ another\ code\ module:\n===none\n(System32)\ 52\ %\ namespace\ eval\ ::Gap12\ \{\ set\ gap12_0(config_volume)\ 7\ \}\n\[::ShapeScale|traces\]\ _variableWriteTrace\ w='.pr1.ed.pane.pafr.gap12.tree.config_volume'\ name1='gap12_0'\ name2='config_volume'\ op='write'\n\[::ShapeScale|traces\]\{\ \ +->Checking\ if\ variable\ gap12_0(config_volume)\ exists\ ...\}\n===\nSo\ the\ trace\ is\ called,\ but\ without\ the\ namespace\ prefix.\ Hence\ the\ variable\ being\ referenced\ doesn't\ exist,\ and\ so\ the\ value\ has\ changed\ but\ no\ redraw\ happens\ and\ the\ widget\ looses\ synch\ with\ the\ data.\n\nNow\ the\ trace\ info\ tells\ me\ that\ the\ trace\ is\ there.\ I\ can\ also\ see\ a\ second\ unrelated\ trace\ which\ monitors\ for\ project\ data\ changes.\n===none\n(System32)\ 53\ %\ trace\ info\ variable\ ::Gap12::gap12_0(config_volume)\n\{write\ \{::Gap12::_changedDataVariableTrace\ .pr1.ed.pane.pafr.gap12\}\}\ \{write\ \{::ShapeScale::_variableWriteTrace\ .pr1.ed.pane.pafr.gap12.tree.config_volume\}\}\n===\n\nAnd\ this\ is\ the\ code\ that\ sets\ the\ trace:\n===none\n\ \ \ \ \ \ \ \ \ \ \ \ trace\ add\ variable\ \[set\ Priv(\$w,-variable)\]\ write\ \"::ShapeScale::_variableWriteTrace\ \$w\"\n===\n\nAnd\ parray\ shows\ that\ the\ variable\ name\ is\ prefixed\ with\ the\ namespace\ correctly:\n===none\n::ShapeScale::Priv(.pr1.ed.pane.pafr.gap12.tree.config_volume,-variable)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\ ::Gap12::gap12_0(config_volume)\n===\n\nSo\ the\ problem\ is\ that\ despite\ the\ fact\ that\ I\ use\ the\ fully\ qualified\ name\ of\ the\ variable\ in\ the\ trace\ add\ command,\ trace\ will\ still\ call\ the\ handler\ WITHOUT\ the\ namespace\ prefix\ when\ I\ access\ the\ variable\ within\ it's\ own\ namespace\ without\ the\ namespace\ qualification.\ \n\nThis\ seems\ a\ little\ strange\ to\ me?\n\n======\n\n\n<<categories>>\ Tcl\ syntax\ |\ Arts\ and\ crafts\ of\ Tcl-Tk\ programming\ |\ Command} CALL {my revision trace} CALL {::oo::Obj6226683 process revision/trace} CALL {::oo::Obj6226681 process}

-errorcode

NONE

-errorinfo

Unknow state transition: LINE -> END
    while executing
"error $msg"
    (class "::Wiki" method "render_wikit" line 6)
    invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
    (class "::Wiki" method "render" line 8)
    invoked from within
"my render $name $C"
    (class "::Wiki" method "revision" line 31)
    invoked from within
"my revision $page"
    (class "::Wiki" method "process" line 56)
    invoked from within
"$server process [string trim $uri /]"

-errorline

4