Reputation: 99
I'm using the short syntax of 'if' statement like this:
proc WriteParameter {Parameter Value} {
# Ugly option - WORKS
if {$Parameter eq "Unique"} {
set Register ControlStatus
set Data ${Value}0
set Mask EF
} else {
set Register $Parameter
set Data $Value
set Mask {}
}
# Elegant option - DOESN'T WORK
set Register [expr {$Parameter eq "Unique" ? "ControlStatus" : $Parameter}]
set Data [expr {$Parameter eq "Unique" ? ${Value}0 : $Value}]
set Mask [expr {$Parameter eq "Unique" ? EF : {}}]
puts $Register-$Data-$Mask
return 0
}
set Value 4E20 ;# Merely hexadecimal number
set Parameter Regular
WriteParameter $Parameter $Value
The problem is that in the elegant option, since the 'expr' statement always treats its arguments as integers, 'Data' gets the value of 4e+20, which is merely the scientific notation of 'Value'.
However, I need 'Data' to be 'Value' (for example, to write to an external register).
Any ideas?
Upvotes: 0
Views: 340
Reputation: 137577
The expr
language is rather different to the rest of Tcl. You have to care much more about syntax there. Putting things in "
double quotes"
can help.
set Register [expr {$Parameter eq "Unique" ? "ControlStatus" : $Parameter}]
set Data [expr {$Parameter eq "Unique" ? "${Value}0" : $Value}]
set Mask [expr {$Parameter eq "Unique" ? "EF" : {}}]
However, you might instead be better using if
as that doesn't try to convert the results of its arms to a number (using approximately the rules for C constants) unlike expr
.
set Register [if {$Parameter eq "Unique"} {string cat ControlStatus} {string cat $Parameter}]
set Data [if {$Parameter eq "Unique"} {string cat $Value 0} {string cat $Value}]
set Mask [if {$Parameter eq "Unique"} {string cat EF}]
# We can omit the else clause; the default is an empty string anyway
This depends on string cat
, which was introduced in Tcl 8.6.3 (well, 8.6.2 but that had some bugs in it's I/O subsystem that you really want to avoid). If you're using anything from 8.5 up to 8.6.1, use this instead:
set Register [if {$Parameter eq "Unique"} {return -level 0 ControlStatus} {return -level 0 $Parameter}]
set Data [if {$Parameter eq "Unique"} {return -level 0 ${Value}0} {return -level 0 $Value}]
set Mask [if {$Parameter eq "Unique"} {return -level 0 EF}]
Yes, return -level 0
just gives the value as its result. “Obvious and discoverable”…
If you're on 8.4 or before still (Upgrade, man! You're out of security support!) then you need a little helper procedure:
proc value {value} {return $value}
set Register [if {$Parameter eq "Unique"} {value ControlStatus} {value $Parameter}]
set Data [if {$Parameter eq "Unique"} {value $Value 0} {value $Value}]
set Mask [if {$Parameter eq "Unique"} {value EF}]
The value
procedure above will work with later versions of Tcl too, but it gives less efficient bytecode.
However, for all the above I'd actually do something different:
set Register $Parameter
set Data $Value
set Mask ""
if {$Parameter eq "Unique"} {
set Register ControlStatus
append Data 0
set Mask EF
}
I might also use scan
to parse the value and format
to do the composing of the results back to hex (if necessary). Like that, it'd be much easier to think about the value and not just the representation.
Upvotes: 1