When using 'interp alias', is there any way of recreating a particular
alias without destroying the associated command? or.. 'updating' an
alias using the returned token?
e.g
proc spud {args} {return spuddata-$args}
interp alias {} a1 {} spud data1
rename a1 somewhere_I_dont_know_about
(The command a1 has possibly been renamed somewhere - outside of my
control.
The alias token still exists as 'a1' though.)
Now I'd like to update the alias (whose name is now divorced from the
command name)
I was hoping to just do:
interp alias {} a1 {} spud newdata
but this simply creates a new alias ::a1 with a new command a1
I can't just delete the alias a1 and recreate it - because I have no
idea where the corresponding command is supposed to go.
Any workarounds?
Cheers,
Julian
Read the man/help page on the trace command. Pay particular attention to
the rename and delete options.
--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
This is one of the subtle ways in which the design of [interp alias]
is broken. You can't [rename] an alias. Searches of clt archives
and other Tcl histories should find more details.
It's a real problem, but one that's really hard to fix (pretty much
needs a rewrite), one which might introduce incompats that would
best come at Tcl 9.0, and one which is fairly rarely encountered,
at least judging by the frequency of complaints about it.
--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|
For example, Tcl Feature Request 524140.
Following the links there to Tcl Bug 707104, it appears to claim this
issue is fixed in Tcl 8.5.
Funny that I remember finding this bug, but I don't remember fixing it.
Thanks - This means maintaining a separate datastructure upon renaming
to point to the actual command.
The whole idea of using interp alias was to keep the required info
built into the comand.
If I have to go looking stuff up somewhere else anyway it rather
defeats the purpose.
I tried storing the destination command in the interp alias data
itself.. but I'm not sure this can be done from within a
'trace add command $cmd rename' procedure.
Actually it crashes my Tclsh.. with
'malformed bucket chain in Tcl_DeleteHashEntry'
Tested and crashed the following script
in tclsh 8.5a7, tclkitsh 8.5b1 & tclkitsh8.4.16 on windows
tclsh8.5a7 on FreeBSD
proc spud {args} {return spuddata-$args}
interp alias {} a1 {} spud data1
trace add command a1 rename [list handle_rename a1]
proc handle_rename {alias args} {
lassign $args oldcmd newcmd _rename
#remove existing alias
interp alias {} $alias {}
#recreate alias with desired token
interp alias {} $alias {} spud "somedata,$newcmd"
#rename the command to the right location leaving alias token intact.
rename $oldcmd $newcmd
}
rename a1 blah
(the crash occurs with or without the 2nd interp alias call, but I
only see the malformed bucket msg with both calls in place)
Cheers,
Julian
Now, to get everything to work for you -- remove the rename inside of the
trace procedure (there is no need for it and this is what is causing your
crashes). Lastly, you do no have to delete the alias and then redefine it --
just redefine it.
neuro...@gmail.com wrote:
> On Nov 8, 3:01 pm, "Gerald W. Lester" <Gerald.Les...@cox.net> wrote:
>> +------------------------------------------------------------------------+- Hide quoted text -
>>
>> - Show quoted text -
>
> Thanks - This means maintaining a separate datastructure upon renaming
> to point to the actual command.
>
> The whole idea of using interp alias was to keep the required info
> built into the comand.
> If I have to go looking stuff up somewhere else anyway it rather
> defeats the purpose.
>
> I tried storing the destination command in the interp alias data
> itself.. but I'm not sure this can be done from within a
> 'trace add command $cmd rename' procedure.
>
> Actually it crashes my Tclsh.. with
> 'malformed bucket chain in Tcl_DeleteHashEntry'
>
>
> Tested and crashed the following script
> in tclsh 8.5a7, tclkitsh 8.5b1 & tclkitsh8.4.16 on windows
> tclsh8.5a7 on FreeBSD
>
>
> proc spud {args} {return spuddata-$args}
> interp alias {} a1 {} spud data1
> trace add command a1 rename [list handle_rename a1]
> proc handle_rename {alias args} {
> lassign $args oldcmd newcmd _rename
> #remove existing alias
> interp alias {} $alias {}
> #recreate alias with desired token
> interp alias {} $alias {} spud "somedata,$newcmd"
> #rename the command to the right location leaving alias token intact.
> rename $oldcmd $newcmd
> }
> rename a1 blah
>
> (the crash occurs with or without the 2nd interp alias call, but I
> only see the malformed bucket msg with both calls in place)
>
> Cheers,
> Julian
>
>
>
Thanks for your help, but I think you need to actually try the code to
see what's going on.
I can't just redefine the alias as you suggest -
in handle_rename,leaving only the line:
interp alias {} $alias {} spud "somedata,$newcmd"
this results in the bizarre situation where the alias exists,
but there no longer appears to be any command to call it with.
ie After 'rename a1 blah' there is an alias a1, but info commands
does not show a1 or blah, and both produce 'invalid command name' when
you try to run them.
A 2nd reason I can't just redefine it, is that it won't handle the
case of a 2nd rename (yes - I want to handle at least 2 renames,
although if I could just rename aliases this wouldn't be quite so
important.)
It won't handle it because if you try to just redefine an alias when
the command & alias-tokens already don't match, then interp alias will
return a new alias token (it prepends :: each time). This would
necessitate extra work (e.g a global array) to keep track of the
changed alias name. Doable I guess.. but ugly.
I believe the rename is required - but I had an error in the script
sorry - it was meant to read.
rename $alias $newcmd
The point of this is that after redefining the alias, we've forced the
command name back to be in sync with the alias, and this may not match
either the $oldcmd or $newcmd passed to handle_rename.
A further anomaly exists in the output of [info command] during traces
anyway:
proc x {} {return xxx}
trace add command x rename [list handle_rename]
proc handle_rename {args} {
lassign $args oldcmd newcmd _rename
puts "$oldcmd-[info commands $oldcmd],$newcmd-[info commands
$newcmd]"
}
rename x y
OUTPUT:
::x-::y,::y-::y
How can [info commands ::x] & [info commands ::y] both return ::y ?
I'd report a bug, but I don't know whether to report 3 or one.
Julian