I am trying to form a rectangle with 2 pairs of Coordinate in TCL - tcl

I am new to TCL and hardware design. I am currently doing a script that could verify all the ports at an edge and make a rectangle box that cover all the ports at an edge.
Since I am new to TCL, I think there is something wrong in the syntax.
The error msg is:
Error: Invalid coordinates '$bbox_coor_x1 [expr $bbox_coor_y2-30]' in list. (NDMUI-100)
Error: Empty or invalid geometry specified for the '-boundary' argument of the command. (NDMUI-337).
Please help me.

Your problem is that variables and commands are not interpolated inside curly braces. Please learn the difference between curlies and double quotes.
For example:
set x 5
set y 10
# Curlies
puts {$x $y}
--> $x $y (literally)
puts {$x [expr $y+1]}
--> $x [expr $y+1] (literally)
# Double quotes
puts "$x $y"
--> 5 10
# List command
puts [list $x $y]
--> 5 10
puts [list $x [expr $y+1]]
--> 5 11
When making a list of lists, like a bbox, anything inside outer-most curlies will interpolate:
puts "{$x $x} {$y $y}"
--> {5 5} {10 10}
One more thing, note that lindex can take multiple indexes. Do this instead of calling lindex twice.
lindex $bbox 0 1

Related

Can be used an expression in the name of variable for reading it in Tcl?

#In Tclsh
% set n 3
3
% set A$n 15
15
% puts $A3
15
But how could I read $A3 as about like ${A{$n}}
Itried:
% puts $[puts \$A$n]
$A3
$
%
I clarify my question date:10Aug2022 (UTC 09.14)
In Bash I can do a deeper indirection as like this:
a=b;b=5;eval echo $`echo $a` # output: 5 is good
How can I do it in Tcl with puts command instead of set command as like this:
set a b;set b 5;eval {puts [puts \$$a]} # it has wrong output: $b rather than 5
Macleod showed that the set command with only one argument is a workaround of a deeper indirection.
That is why the next line is good:
set a b;set b 5;eval puts $[set a] # Output: 5 as required is good
So my question is:
In the above Tcl line how can I replace the set command with puts command and do a deeper indirection in Tcl as like in Bash.
/echo in Bash is as like puts in Tcl/
My question is not for a practical purpose, but for understanding the parsing, substitution in Tcl.
Should work with just:
puts [set A$n]
I have read the Tcl man about substitution process and I have made some experiments.
The puts command unusable for command substitution according to the next examples.
% set x 1; set x [puts 2]; puts "x: >$x<"
x: ><
% set x 1; set x [puts -nonewline 2]; puts "\nx: >$x<"
x: ><
% set x 1; set x [expr 2]; puts "x: >$x<"; # But expr cmd ok of course.
x: >2<
( In Bash the echo command is good for command substitution eg.: a=`echo "apple tree"` )
I checked more type of deeper indirect addressing of variable, here is my experiments:
Now let the names of var is numbers.
% set 1 2; set 2 3; set 3 4; #Here is the chain of var
% puts [set [set [set 1]]]; #Command substitution only
4
% puts [expr $[expr $[expr $[expr 1]]]]; #Command and variable substitution
4
Now let the names of var is alphas and change the expr command to the string trim as a dummy string
expression command.
% set a b; set b c; set c d ; # Here is the chain of var
% puts [set [set [set a]]] ; # Command substitution only
d
# Command and variable substitution:
% puts [eval string trim $[eval string trim $[eval string trim $[string trim a]]]]
d
I would like to know why I had to use eval command unlike in case when the names of var were numbers
and expr command was enough.
In spite of there were deep (indirect) var (and command) substitution was in both two cases .
So it is looks like that deep command substitution controlled by brackets while deep (indirect) var substitution
controlled by eval often.
Likewise in Bash the deep var substituting also happens with eval command, e.g.:
a=b; b=c; c=d # Here is the chain of var
eval echo \$$(eval echo \$$(eval echo \$a))
d

How to pass arguments to tcl scripts when using tclsh [duplicate]

This is the code in TCL that is meant to produce factorial of a number given as parameter by the user.
if {$argc !=1}{
puts stderr "Error! ns called with wrong number of arguments! ($argc)"
exit 1
} else
set f [lindex $argv 0]
proc Factorial {x}{
for {set result 1} {$x>1}{set x [expr $x - 1]}{
set result [expr $result * $x]
}
return $result
}
set res [Factorial $f]
puts "Factorial of $f is $res"
There is a similar SO question, but it does not appear to directly address my problem. I have double-checked the code for syntax errors, but it does not compile successfully in Cygwin via tclsh producing the error:
$ tclsh ext1-1.tcl
extra characters after close-brace
while executing
"if {$argc !=1}{
puts stderr "Error! ns called with wrong number of arguments! ($argc)"
exit 1
} else
set f [lindex $argv 0]
proc Factorial {x}{..."
(file "ext1-1.tcl" line 3)
TCL Code from: NS Simulator for Beginners, Sophia-Antipolis, 2003-2004
Tcl is a little bit more sensitive about whitespace than most languages (though not as much as, say, Python). For instance, you can't add unescaped newlines except between commands as command separators. Another set of rules are that 1) every command must be written in the same manner as a proper list (where the elements are separated by whitespace) and 2) a command invocation must have exactly the number of arguments that the command definition has specified.
Since the invocation must look like a proper list, code like
... {$x>1}{incr x -1} ...
won't work: a list element that starts with an open brace must end with a matching close brace, and there can't be any text immediately following the close brace that matches the initial open brace. (This sounds more complicated than it is, really.)
The number-of-arguments requirement means that
for {set result 1} {$x>1}{incr x -1}{
set result [expr $result * $x]
}
won't work because the for command expects four arguments (start test next body) and it's only getting two, start and a mashup of the rest of other three (and actually not even that, since the mashup is illegal).
To make this work, the arguments need to be separated:
for {set result 1} {$x>1} {incr x -1} {
set result [expr {$result * $x}]
}
Putting in spaces (or tabs, if you want) makes the arguments legal and correct in number.

Cannot evaluating variable within IF and For loop using TCL

In following code in TCL I cannot seem evaluate the variable "a"
I'm evaluating x and y, in the same For Loop I have a IF statement that is checking for a range between x and y.
If valid then I'd like to perform some more calculations within the IF condition.
Every thing is fine up to the IF condition, but I cant seem to evaluate "a".
I'm trying to set "a" to the value of "y" for all the values within the range $min <= $x && $x <= $max
I would kindly request the experts to highlight the mistake.
for {set i 0} {$i < $lenght} {incr i} {
set x [expr ([lindex $cal1 $i])*$offset]
set y [expr ((cal2)/2) ]
if {$min <= $x && $x <= $max } {
puts "is Active"
set a [lindex $y $i]
puts a = $a
}
}
There is a lot that seems problematic in your code.
In the first line, you use the variable lenght. Tcl doesn't care about spelling, but if you don't have such a variable (you might possibly have a length variable instead) you will get an error.
In the invocation expr ([lindex $cal1 $i])*$offset] you have an unnecessary parenthesis but no braces around the expression (the braces aren't mandatory but should be there unless there is a very good reason to omit them). Also: "offset" usually means something you add to, not multiply with, another value. The invocation expr {[lindex $cal1 $i] * $offset}] would be better.
The variable y is used as a list argument to lindex later on, but it's created as a scalar variable. Also, your expression divides a string (or rather, an invalid bareword) with 2. Maybe you meant lappend y [expr {$cal2 / 2}]? If you use lappend, each value will be added to the end of an existing list, or as the first element of a new list if y doesn't exist. This is usually what one wants, but it means that the list y should be reset using set y [list] or set y {} before entering the loop, to get rid of elements added earlier, if any.
puts a = $a won't work, because if there are more than one argument to puts they are expected to be the flag -nonewline and/or a channel id to send the output to. Maybe you meant puts "a = $a".

expected integer but got "floating point number" error

I try to write a very simple program in TCL using list.
Below is the list
list { 1 2 3 4 5 6 1.5 7 }
Below is my code
set sum 0
for {set i 0} {$i < [llength $list]} {incr i} {
incr sum [lindex $list $i]
}
puts $sum
On executing the above program I am getting the below error due to floating point value of 1.5 in the list
expected integer but got "1.5"
(reading increment)
invoked from within
"incr sum [lindex $list $i]"
I searched on internet and could not find anything relevant.
Please advise how do I handle the floating point value?
While using incr command, variable must have value that can be interpreted as a an integer. See tcl wiki.
If variable is a non-integral real number, [incr] could not be used, but [set] could:
set sum 0
for {set i 0} {$i < [llength $list]} {incr i} {
set sum [expr {$sum + [lindex $list $i]}]
}
puts $sum
Omsai's answer should solve your problem, but a cleaner solution is to use foreach:
set sum 0
foreach n $list {
set sum [expr {$sum + $n}]
}
puts $sum
Summing up a list of numeric values can also be done with the ::tcl::mathop::+ command:
::tcl::mathop::+ {*}$list
This looks more complicated that it is. The + command isn't available in the regular namespace, so you need to specify where it comes from (the ::tcl::mathop namespace). The command expects to get each operand as a separate argument, so if they are in a list you need to expand that list using the {*} prefix.
foreach and the various mathop commands are documented here: foreach, mathop.
(Note: the 'Hoodiecrow' mentioned in the comments is me, I used that nick earlier.)
Tcl gives an error if you will try
incr a 1.5
you have to change the logic.
clearly you want to add all the numbers in the list. and answers are easy and many. But i will give you the shortest way:
set l { 1 2 3 4 5 6 1.5 7 }
set sum [expr [join $l +]]
NO LOOPING REQUIRED.

How to define a variable with argument expansion

The following command runs as expected:
lappend {*}{arr 1}
puts [lindex $arr 0]
Now I am trying to make a variable of "{*}{arr 1}" like this:
set X "{*}{arr 1}"
lappend $X
But this does not work, seems $X is taken as one whole value, argument expansion is not effective.
So is it a requirement that argument expansion can not be through variable?
The {*} is a syntactic feature of Tcl (from Tcl 8.5 onwards) just as […], "…" or $ is. You have to write it in the script in order for it to count as argument expansion; otherwise it's just a sequence of three characters.
If you want something like
set X "{*}{arr 1}"
lappend $X
to work, you need to pass it through eval:
set X "{*}{arr 1}"
eval lappend $X
Note that this then means that X actually contains a script fragment; this can have all sort of “interesting” consequences. Try this for size:
set X "{*}{arr 1};puts hiya"
eval lappend $X
Use of eval in modern Tcl is usually a sign that you're going about stuff the wrong way; the key use in old scripts was for doing things similar to that which we'd use {*} for now.
No, within double quotes, { and } actually lose their meaning, so will {*}. Notice that puts "{}" and puts {} are different.
The closest I can think of to do what you're trying to do would be to use something like this:
set X {arr 1}
lappend {*}$X
So if you now execute puts [lindex $arr 0], you get 1 as output.