TCL 8.3: syntax error in expression "a eq b" - tcl

I have to run TCL code written for version 8.5 with the interpreter of version 8.3.
I am having problems with eq. Seems 8.3 doesn't recognize it. A simple code:
% expr { "a" eq "b" }
returns an error message like:
syntax error in expression "a eq b"
I am trying to fix this by adding an interp alias before everything like this:
interp alias {} eq {} ==
but seems it has no effect.
Is there any way to make eq an alias for ==? If no, is the only way to get rid of this error is to replace all eq statements by == statements?

The eq and ne operators were introduced in Tcl 8.4. See Changes in Tcl/Tk 8.4 on the Tcler's wiki. There is no way to make "eq" be an alias for "==" within an expression. Your attempt to use the alias command only resulted in creating a command named eq that does whatever the command == does (specifically, fail unless you actually have a command named ==).
If you absolutely must find a way to make this work, in your 8.3 interpreter you can rename expr to be something else (eg: _expr), then create your own expr command that does a string substitution before calling the renamed expr command. This is fraught with peril since you have to make sure to only substitute operators and not the data being compared.

I'm not even sure this code works properly in tcl 8.5
First make sure your expr is between curly brackets:
% expr {"a" eq "b"}
The alias allows you to create an alias for a command, but eq is not a command, it´s a subcommand of the expr command, so you would really need to create your own proc expr args wrapper.
Why do you need to use tcl 8.3? it's a really old version.

Tcl 8.3 is rather old, and the recommended path for upgrading from TclPro (as I see you're using from comments) to something less… antediluvian… is to purchase the Tcl Dev Kit from ActiveState, which is at least the spiritual successor and has current support. Nobody supports TclPro any more.
That said…
Now, with Tcl 8.3 the equivalent of the functionality of the eq operator was the string equal command (in 8.4, they actually compile to the same bytecode; one is a short-cut for the other). This means that for this:
if {"a" eq "b"} {...
would be instead written as this:
if {[string equal "a" "b"]} {...
though if you've definitely got a non-integer for one of the arguments, you can just use this:
if {"a" == "b"} {...
There is no mechanism for aliasing operators in any version of Tcl (well, certainly not up to 8.6, which is the current development/beta version).
The Gripping Hand
As Bryan says, you can write your own versions of expr (and if and for and while) that have this extended functionality, but that's a lot of work (i.e., months including all the testing, though you can probably reuse the test suite from Tcl 8.4 to help) and it's just so you can use a version of Tcl that is known to be obsolete. (I have no idea if it has security issues in it, and you can't pay me enough for me to want to try to find out.) You're better off paying for the TDK.

Related

How do I use the ternary operator to add an optional part to an anonymous string in tcl?

I am new to tcl (sorry if the answer is obvious, but reading tutorials and documentation did not help). I have a statement in tcl that says:
startupitem.start "foo
\tbar"
What I would like to do is have the "foo" part become optional, depending on the outcome of
[variant_isset "alice"] using the ternary operator and without using variables.
I've tried several things along the lines
startupitem.start "[variant_isset """alice"""?"""foo\n\t""":""""""] bar"
(of course with all kinds of escapes and combo's or the use of the double quotes inside the double quotes) but I haven't succeeded.
The outcome if the variant_isset expression returns true is that it is equivalent to
startupitem.start "bar"
You might prefer to use the if command (which is very much the command version of the ternary operator), whose result is the result of the body script it evaluates. If there isn't an else clause, the result is the empty string if nothing else is chosen to do:
startupitem.start "[if {[variant_isset alice]} {string cat "foo\n\t"}] bar"
Or you can build a list and then join it:
set items {}
if {[variant_isset alice]} {
lappend items "foo"
}
lappend items bar
startupitem.start [join $items "\n\t"]
This second approach tends to work particularly well when things get complicated.
You want to check out Tcl's expr command, which introduces Tcl's expression sub-language incl. what you call the "ternary" operator ?:
startupitem.start "[expr {[variant_isset "alice"] ? "foo\n\t" : ""}]bar"
If you happen to use a Tcl recent enough, you may want to prefer an outplace string assembly using string cat, rather than inplace:
string cat [expr {[variant_isset "alice"] ? "foo\n\t" : ""}] "bar"

TCL issues with Octal numbers seen after porting from EDK 1.05 to EDK2

I have an EFI Shell tool which uses EDK 1.05 and TCL 8.3 sources. This tool accepts user commands to display PCI-E adapter information and to upgrade firmware on it. I recently ported it to UDK2017. I am using VS2012x86 toolchain to build the tool.
When I run the binary from EFI Shell, TCL reports errors such as these.
can't use invalid octal number as operand of "||"
syntax error in expression "(1<<0)"
syntax error in expression "(0x1<<0)"
I have read about TCL and Octal numbers
Since this issue is not being seen with EDK 1.05 code with the same TCL version, I am wondering if there is any flag I am missing out. I am hoping there is a simple solution to get past this error since there was no change in the TCL version.
Octal Issue
It's hard to be sure, but I suspect with the octal number issue you've got code that's parsing something like 080808 as a number, which is interpreted as octal because of the leading 0 (just like a constant in C or C++) and so can't contain an 8 (or 9). To parse a number definitely as decimal, the scan command is used:
set val 080808
scan $val "%d" parsedVal
# Properly, should check that [scan] has a result of 1, but I probably wouldn't bother
puts "$val -> $parsedVal"
Odd Expression Syntax Error
The other syntax error in expression "(1<<0)" errors are stranger, as those are definitely valid syntax. I've only got versions back to 8.4 on this machine, but…
$ tclsh8.4
% expr (1<<0)
1
The only ways that could be an invalid expression are if it is either in some custom expression language (which would be application-specific; you'll have to read the documentation to figure that out) or if you're using an expression string as a numeric value:
% set val (1<<0)
(1<<0)
% expr {$val + 1}
can't use non-numeric string as operand of "+"
but that wouldn't produce exactly the error you are seeing. Very puzzling indeed!
Use Stack Traces
There is something that might help you figure out what is going on. After an error, the global errorInfo variable has a stack trace generated. For example, after the above erroring expr it has this:
% puts $errorInfo
can't use non-numeric string as operand of "+"
while executing
"expr {$val + 1}"
The good thing is that this tells you exactly what command and where gave you the error; that can make a gigantic difference in your detective work to hunt down your problems.

On tcl tests - how to interpret tcltest::test

I am looking at the tests in TCL source tree and I see this one in compExpr-old.test:
test compExpr-old-14.17 {CompilePrimaryExpr: string primary that looks like var ref} {
expr $
} $
It looks wrong to me: the test runs the script expr $ and expects the return value is "$". Is my interpretation right?
It cannot be right because expr $ is wrong syntactically.
I checked out tcltest.tcl, the definition of tcltest::test is so long, wish someone can help me over here.
I don't know what version of the test suite you are looking at (probably some 8.4 variant?), but when I look at the whole of that test in the Tcl trunk, I see this:
test compExpr-old-14.17 {CompilePrimaryExpr: string primary that looks like var ref} -body {
expr $
} -returnCodes error -match glob -result *
In this case, it is checking that the result is an error and that the value of the result (i.e., the content of the error message) glob matches with *, i.e., is anything (effectively ignoring it). That is, the test checks that an error is obtained from expr $ and otherwise doesn't care.
The test you posted (which uses an older syntax for tcltest) won't pass on modern versions of Tcl. But in 8.4, it did pass; this was an area where Tcl's semantics changed between 8.4 and 8.5:
dkf$ tclsh8.4
% expr $
$
% exit
dkf$ tclsh8.5
% expr $
invalid character "$"
in expression "$"
% exit
Quick guide to Tcltest test cases: The -body describes a scrip to run, the -returnCode can be used to select whether normal results or errors are expected, the -result can be used to say what string to expect as a result of the body script, and -match can be used to pick an alternate matching scheme than the default (exact string equality). There's also -constraints for specifying preconditions on a test, -setup for doing setup code, and -cleanup for cleanup code. The two leading mandatory arguments are the name of the test (which must be unique within a test suite for your own sanity) and a short description of the test, used in reporting of failures.
In the old syntax (used in much of Tcl's test suite because updating it is a ton of boring work), you instead had the same two mandatory arguments, then an optional list of constraints (as for -constraints), then a mandatory body (as for -body), then the mandatory string to match for equality (as for -result). Less flexible, but not too hard to understand.

tcl scripts, struggling with [...] and [expr ...]

I can't understand how assignments and use of variables work in Tcl.
Namely:
If I do something like
set a 5
set b 10
and I do
set c [$a + $b]
Following what internet says:
You obtain the results of a command by placing the command in square
brackets ([]). This is the functional equivalent of the back single
quote (`) in sh programming, or using the return value of a function
in C.
So my statement should set c to 15, right?
If yes, what's the difference with
set c [expr $a + $b]
?
If no, what does that statement do?
Tcl's a really strict language at its core; it always follows the rules. For your case, we can therefore analyse it like this:
set c [$a + $b]
That's three words, set (i.e., the standard “write to a variable” command), c, and what we get from evaluating the contents of the brackets in [$a + $b]. That in turn is a script formed by a single command invocation with another three words, the contents of the a variable (5), +, and the contents of the b variable (10). That the values look like numbers is irrelevant: the rules are the same in all cases.
Since you probably haven't got a command called 5, that will give you an error. On the other hand, if you did this beforehand:
proc 5 {x y} {
return "flarblegarble fleek"
}
then your script would “work”, writing some (clearly defined) utter nonsense words into the c variable. If you want to evaluate a somewhat mathematical expression, you use the expr command; that's it's one job in life, to concatenate all its arguments (with a space between them) and evaluate the result as an expression using the documented little expression language that it understands.
You virtually always want to put braces around the expression, FWIW.
There are other ways to make what you wrote do what you expect, but don't do them. They're slow. OTOH, if you are willing to put the + first, you can make stuff go fast with minimum interference:
# Get extra commands available for Lisp-like math...
namespace path ::tcl::mathop
set c [+ $a $b]
If you're not a fan of Lisp-style prefix math, use expr. It's what most Tcl programmers do, after all.
set c [$a + $b]
Running the above command, you will get invalid command name "5" error message.
For mathematical operations, we should rely on expr only as Tcl treats everything as string.
set c [expr $a + $b]
In this case, the value of a and b is passed and addition is performed.
Here, it is always safe and recommended to brace the expressions as,
set c [expr {$a+$b}]
To avoid any possible surprises in the evaluation.
Update 1 :
In Tcl, everything is based on commands. It can a user-defined proc or existing built-in commands such as lindex. Using a bare-word of string will trigger a command call. Similarly, usage of [ and ] will also trigger the same.
In your case, $a replaced with the value of the variable a and since they are enclosed within square brackets, it triggers command call and since there is no command with the name 5, you are getting the error.

"info command rtExMath" in Tk with vtk

I am new for Tcl/Tk. I am using vtk with Tk command window for running vtk tcl/tk examples. Here is a code which include Tk expression as condition of if and I am not getting it.
if { [info command rtExMath] != "" } {
##Do something related VTK
}
I have explored info of Tk but there is a combination with keyword command and also no any good explanation I found for rtExMath.
Please explain me above.
The info commands command (info command is just an unambiguous prefix) returns a list of all commands, or a list of all commands that match the given glob pattern. In the case you're looking at, the glob pattern is actually going to be a string-equality check (and is even optimised to such internally); there's no glob metacharacters in it. The result of that is that [info command rtExMath] != "" is a condition that is true exactly when the command rtExMath exists.
Tcl itself does not define any command called rtExMath; I conclude that it must be part of some specialist extension or application. However, Googling makes me suspect that it is actually a somewhat-standard name for an instance of the vtkMath class in Vtk, but I don't really know for sure. (I'm guessing that the binding of that class to Tcl was done by SWIG…)