Nodes with different energies in NS2 - mobile

I am working on my project. It is about detection of selfish nodes depending on the energy of the node. Here I have 20 nodes of the same energy, then I added 5 more but with different energies. The program shows that there is an error (as listed at the end of the code).
My code
# Define options
set val(chan) Channel/WirelessChannel ;# channel type
set val(prop) Propagation/TwoRayGround ;# radio-propagation model
set val(netif) Phy/WirelessPhy ;# network interface type
set val(mac) Mac/802_11 ;# MAC type
set val(ifq) Queue/DropTail ;# interface queue type
set val(ll) LL ;# link layer type
set val(ant) Antenna/OmniAntenna ;# antenna model
set val(ifqlen) 100000 ;# max packet in ifq
set val(nn) 20 ;# number of mobilenodes
set val(rp) AODV ;# routing protocol
set val(x) 1000 ;# X dimension of topography
set val(y) 1000 ;# Y dimension of topography
set val(seed) 0.0
set val(cp) "cbr-20"
set val(sc) "setdest-20"
set val(stop) 200.0 ;# time of simulation end
set ns_ [new Simulator]
set tracefile [open aodvnode50.tr w]
#set windowVsTime2 [open win.tr w]
$ns_ trace-all $tracefile
$ns_ use-newtrace
#$ns_ namtrace-all-wireless $namtrace $val(x) $val(y)
# set up topography object
set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)
#Open the NAM trace file
set namfile [open manet.nam w]
$ns_ namtrace-all $namfile
$ns_ namtrace-all-wireless $namfile $val(x) $val(y)
set god_ [create-god $val(nn)]
set chan_1_ [new $val(chan)]
#
# Create nn mobilenodes [$val(nn)] and attach them to the channel.
#
# configure the nodes
$ns_ node-config -adhocRouting $val(rp) \
-llType $val(ll) \
-macType $val(mac) \
-ifqType $val(ifq) \
-ifqLen $val(ifqlen) \
-antType $val(ant) \
-propType $val(prop) \
-phyType $val(netif) \
-channel $chan_1_ \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace ON \
-energyModel "EnergyModel" \
-initialEnergy 100.0 \
-txPower 2.0522 \
-rxPower 0.0591 \
-idlePower 0.00006 \
-sleepPower 0.000003 \
for {set i 0} {$i < $val(nn) } { incr i } {
set node_($i) [$ns_ node]
$node_($i) random-motion 0 ;# disable random motion
}
$ns_ node-config -initialEnergy 500
set node_(20) [$ns_ node]
$ns_ node-config -initialEnergy 20
set node_(21) [$ns_ node]
$ns_ node-config -initialEnergy 30
set node_(22) [$ns_ node]
$ns_ node-config -initialEnergy 100
set node_(23) [$ns_ node]
$ns_ node-config -initialEnergy 100
set node_(24) [$ns_ node]
# 21 connecting to 24 at time 20.48548468411224
#
set udp_(8) [new Agent/UDP]
$ns_ attach-agent $node_(21) $udp_(8)
set null_(8) [new Agent/Null]
$ns_ attach-agent $node_(24) $null_(8)
set cbr_(8) [new Application/Traffic/CBR]
$cbr_(8) set packetSize_ 512
$cbr_(8) set interval_ 1.0
$cbr_(8) set random_ 1
$cbr_(8) set maxpkts_ 10000
$cbr_(8) attach-agent $udp_(8)
$ns_ connect $udp_(8) $null_(8)
$ns_ at 20.48548468411224 "$cbr_(8) start"
#
# 22 connecting to 9 at time 76.258212521792487
#
set udp_(9) [new Agent/UDP]
$ns_ attach-agent $node_(22) $udp_(9)
set null_(9) [new Agent/Null]
$ns_ attach-agent $node_(9) $null_(9)
set cbr_(9) [new Application/Traffic/CBR]
$cbr_(9) set packetSize_ 512
$cbr_(9) set interval_ 1.0
$cbr_(9) set random_ 1
$cbr_(9) set maxpkts_ 10000
$cbr_(9) attach-agent $udp_(9)
$ns_ connect $udp_(9) $null_(9)
$ns_ at 76.258212521792487 "$cbr_(9) start"
puts "Loading connection pattern..."
source $val(cp)
puts "Loading scenario file..."
source $val(sc)
proc finish {} {
global ns_ tracefile namfile
$ns_ flush-trace
close $tracefile
close $namfile
exec nam manet.nam &
exit 0
}
for {set i 0} {$i < $val(nn) } {incr i} {
$ns_ initial_node_pos $node_($i) 20
}
for {set i 0} {$i < $val(nn) } {incr i} {
$ns_ at $val(stop).000000001 "$node_($i) reset";
}
$ns_ at $val(stop) "$ns_ nam-end-wireless $val(stop)"
$ns_ at $val(stop).000000001 "puts \"NS EXITING...\"; $ns_ halt"
puts "Start Simulation..."
$ns_ run
The error
num_nodes is set 20
INITIALIZE THE LIST xListHead
Loading connection pattern...
Loading scenario file...
Start Simulation...
SORTING LISTS ...DONE!
channel.cc:sendUp - Calc highestAntennaZ_ and distCST_
highestAntennaZ_ = 1.5, distCST_ = 550.0
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 24, dst 21, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
MAC_802_11: accessing MAC cache_ array out of range (src 21, dst 24, size 20)!
[suppressing additional MAC cache_ warnings]
NS EXITING...

Related

TCl Proc to output list or collection

My Question is as follows:
Objective or problem statement : Find the dots in rectangle that are separated by a distance and store it in a list (collection) which will be my final output
Spec:
We start with an x offset and y offset to begin with and then we keep on incrementing in x and y direction till we reach upper right rectangle boundary.
Expected Output
My rect_boundary is {0 0} {112 96} as llx lry urx ury (lower left x, lower right y, upper right x .... cordinates) It can change each time based on procedural argument , rectangle box can be (00) (200 200) I have used this as an example
x offset for first red box = 5
y offset from first red box to boundary = 5
Distance between 1st and 2nd dot = 45, Distance between 2 and 3 = 45 , Distance between 4 and 5 = 45, Distance between 6 and 7 = 45 , so basically all horizontal points are separated by a distance of 45, that will always stay constant.
1 , 2 and 4 form a triangle, so "4 is located exactly in center of 1 and 2 but vertical distance of 45.
Example: 1st point = (5 5 ) , 2nd point = (50 5) so position of "4th point" will be ((5+50/2), 5+45) i.e., (27.5 50)
Position of 5th point on row 2 will be dependent on 4 as their cordinate will be (27.5+45, 50) = (72.5 50)
Now position of 6 and 7 point in rectangle will also be dependent on point 4
Center Point = Box 4 (x, y+45) = (27.5 95) and Box 6 = {(27.5 -45/2) 95) = (5, 95)
i.e Point 6 will be exactly on top of Point 1 = (5, 95)
What I have tried so far and it is giving slightly different output
set output [open "output.txt" w]
proc getPointList {rect_boundary xOffset yOffset } {
global output
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set xIncr 45
set yIncr 45
set x_margin 2
set y_margin 2
set count 0
set list ""
for {set y [expr {$yl +$yOffset}]} {$y <= $yh} {incr y $yIncr} {
for {set x [expr {$xl + $xOffset}]} {$x <= $xh } {incr x $xIncr} {
set point_lookup_window [list [list [expr {$x - $x_margin}] [expr {$y - $y_margin}]] [list [expr {$x + $x_margin}] [expr {$y + $y_margin}]]]
set point_list [index collection [(#some logic_ get_boxes -within $point_lookup_window] 0]
}
incr count
puts $point_list
}
}
set rect_boundary {0 0 111 96}
set xOffset 5
set yOffset 5
getPointList $rect_boundary $xOffset $yOffset
close $output
Note: Rectanglular boundary and offsets will change as they are procedural arguments
Above code gives me equidistant points (have shown dots) as follows, so need the calculation from 2nd row onwards working
Please help expedite and feel free to ask questions.
For each row, you're initializing x at the same value, $xl + $xOffset.
That's what you want for the 1st, 3rd, 5th, ... rows, but x in the even rows should be initialized by an extra half of $xIncr.
I see you're setting a count variable which will keep track of the odd/even rows. You can use this variable to make odd/even rows different.
for {set y [expr {$yl +$yOffset}]} {$y <= $yh} {incr y $yIncr} {
# Define x_start differently on odd/even rows
if {$count % 2 == 0} {
set x_start [expr {$xl + $xOffset}]
} else {
set x_start [expr {$xl + $xOffset + $xIncr/2}]
}
# Iterate x as usual.
for {set x $x_start} {$x <= $xh } {incr x $xIncr} {
...
...
}
incr count
puts $point_list
}

WireGuard: can't ping anything, traffic doesn't go through while handshake successful

I'm trying to setup WireGuard VPN server on a cloud virtual server (Yandex cloud).
Server config:
[Interface]
Address = 10.128.0.19/24
MTU = 1500
SaveConfig = false
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t >
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables ->
ListenPort = 41820
PrivateKey = <cut>
[Peer]
PublicKey = 0fWTvnU+j4D4pXfv0hWtAJDatRj/DxgPH3zwrSbT7js=
AllowedIPs = 10.128.0.201/32
Client config:
[Interface]
PrivateKey = <cut>
Address = 10.128.0.200/32
DNS = 1.1.1.1, 1.0.0.1
[Peer]
PublicKey = g9HF8K1303CwDrYb0ga8/dBe8EY8tb3wlreO0lHA9iI=
AllowedIPs = 0.0.0.0/0
Endpoint = <cut>:41820
PersistentKeepalive = 25
I've enabled the net.ipv4.ip_forward=1 option on the server. The server is on the public cloud compute instance. The client is an Android device in a home network behind NAT.
When I turn on the tunnel, all the communications stops. I can't ping anything from the device. At the same time, I can see successful handshakes in the wg output:
interface: wg0
public key: g9HF8K1303CwDrYb0ga8/dBe8EY8tb3wlreO0lHA9iI=
private key: (hidden)
listening port: 41820
peer: 0fWTvnU+j4D4pXfv0hWtAJDatRj/DxgPH3zwrSbT7js=
endpoint: <cut>:38517
allowed ips: 10.128.0.201/32
latest handshake: 15 seconds ago
transfer: 2.25 KiB received, 124 B sent
I can't ping neither the VPN server internal IP address (10.128.0.19) nor any of public IPs (like 1.1.1.1).
The server's ifconfig output is the following:
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.128.0.19 netmask 255.255.255.0 broadcast 10.128.0.255
inet6 fe80::d20d:1bff:fe98:a801 prefixlen 64 scopeid 0x20<link>
ether d0:0d:1b:98:a8:01 txqueuelen 1000 (Ethernet)
RX packets 16530 bytes 2016056 (2.0 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 12031 bytes 1483606 (1.4 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 177 bytes 14328 (14.3 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 177 bytes 14328 (14.3 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wg0: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1500
inet 10.128.0.19 netmask 255.255.255.0 destination 10.128.0.19
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC)
RX packets 145 bytes 16504 (16.5 KB)
RX errors 54 dropped 0 overruns 0 frame 54
TX packets 11 bytes 472 (472.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
The OS on the server is Ubuntu 20.04.
I tried to set MTU on the client side to 1500 but nothing changed.
What I'm doing wrong?
The issue was in the server's interface IP address. The correct one is
[Interface]
Address = 10.128.0.19/32
The subnet part should be 32 instead of 24 in my case.
After that, the connection works well.
The allowed ip is wrong in the server configuration.
Please change it from:
[Peer]
PublicKey = 0fWTvnU+j4D4pXfv0hWtAJDatRj/DxgPH3zwrSbT7js=
AllowedIPs = 10.128.0.201/32
to:
[Peer]
PublicKey = 0fWTvnU+j4D4pXfv0hWtAJDatRj/DxgPH3zwrSbT7js=
AllowedIPs = 10.128.0.200/32

How to use puts with multiple variable in one argument in Tcl?

I have a series of list like a1, a2, a3, a4, ....
I want to print them in a loop, Thus both a and i are variables. How can I do that?
This doesn't work.
for {set i 1}....
puts $a$i
}
Thanks in advance
Ideally you'd have them in an associative array, but otherwise…
To read from a variable whose name is not constant, use the set command with just one argument instead of the $ syntax. (This use of set predates $.)
for {set i 1} {$i <= 3} {incr i} {
puts [set a$i]
}
However, it would be better to use an array (so the variables would effectively be named a(1), a(2), etc instead of a1, a2, etc). But it does mean a change to the code that creates the variables too.
for {set i 1} {$i <= 3} {incr i} {
puts $a($i)
}
The other realistic option for doing access to variable variables is the upvar command. It's not really recommended in the global namespace, but in a procedure it's very effective.
proc printThree {} {
for {set i 1} {$i <= 3} {incr i} {
upvar 1 a$i vbl
puts $vbl
}
}
This works particularly well when doing more complex operations than just printing the value.
As list:
set a1 [list 1 2 3 4]
set a2 [list 10 20 30 40]
set a3 [list 100 200 300 400]
set a4 [list 1000 2000 3000 4000]
foreach i [list {*}$a1] { puts "\$a$i: [set a$i]" }
# $a1: 1 2 3 4
# $a2: 10 20 30 40
# $a3: 100 200 300 400
# $a4: 1000 2000 3000 4000
As array:
array set a {
1 {1 2 3 4}
2 {10 20 30 40}
3 {100 200 300 400}
4 {1000 2000 3000 4000}
}
parray a
# a(1) = 1 2 3 4
# a(2) = 10 20 30 40
# a(3) = 100 200 300 400
# a(4) = 1000 2000 3000 4000
As dict:
set a [dict create \
a1 {1 2 3 4} \
a2 {10 20 30 40} \
a3 {100 200 300 400} \
a4 {1000 2000 3000 4000}]
dict for {k v} $a { puts "$k: $v" }
# a1: 1 2 3 4
# a2: 10 20 30 40
# a3: 100 200 300 400
# a4: 1000 2000 3000 4000
As matrix:
package require struct::matrix
::struct::matrix xdata
xdata add columns 4
xdata add rows 4
xdata set rect 0 0 {
{1 2 3 4}
{10 20 30 40}
{100 200 300 400}
{1000 2000 3000 4000}
}
join [xdata get rect 0 0 end end] \n
# 1 2 3 4
# 10 20 30 40
# 100 200 300 400
# 1000 2000 3000 4000
#cleanup
xdata destroy

retrieving numerical index from an array in tcl

I'm trying to retrieve a list of numbers from an array (in a txt file) and to do mathematical operations on them then to set them back in a list of the same format.
The txt file looks like this (format is fixed):
1000 2000 3000 4000
I want to read that txt file then to create another list which will be saved in a different text file:
1010 1100 2010 2100 3010 3100 4010 40100 # which is basically adding 10 and 100 to each index.
Here what I've done so far (I'm a very beginner in tcl !)
set zonefile [open "mytxtfile.txt" r]
gets $zonefile
set my_list [gets $zonefile]
puts $my_list
# Check that there is at least one location defined
if { [llength $my_list] == 0 } {
error "No domain are defined in the system parameters workbook"
} else {
puts "OK !"
}
puts [llength my_list]
# this returns 1, which from my understanding means I only have 1 value in my array instead of 4
set c1 [string range $my_list 0 3]
set c2 [string range $my_list 5 8]
set c3 [string range $my_list 10 13]
set c4 [string range $my_list 15 18]
array set domain_list ([lindex $c1 0] [lindex $c2 0])
# I thought this would create an array of 1000 2000 3000 4000 but this doesn't work
Thanks a lot !
I think you're making it more complicated than it needs to be. You don't need to know indexes of elements at all, just use foreach and lappend to build the output array:
set in [open input.txt r]
set a {}
foreach n [split [read $in] " "] {
lappend a [expr {$n + 10}] [expr {$n + 100}]
}
close $in
set out [open output.txt w]
puts $out $a
close $out
If input.txt is:
1000 2000 3000 4000
output.txt will be
1010 1100 2010 2100 3010 3100 4010 4100

Tcl proc to output a list or array

I am new to Tcl arrays. My question is as follows.
I have a rectangle box with two rows R1 and R2. Each of these rows has 8 different values.
I want to return these 16 values (x and y coordinates) either in a text file or as an list output from a proc. I read some earlier posts about Tcl proc cannot output an array unless we use dict.
So, I will try to draw a picture so u can understand my question better.
R1 x1y1 x2y2 ... x8,y8
R2 x9,y9 ... x16, y16
Expected output when I run the proc either on command prompt or in a file with dummy values as an example
$> (1,2) (2,3) (3,4) ....... (7,8)
(9,10) (10,11) ......... (15,16)
So this is what I tried and I am getting the results that I need. But this is hardcoded for two rows. I want to make it able to detect how many rows are there and then accordingly output the number of rows.
proc getPointList {rect_boundary rowOffset colOffset rowIncr colIncr } {
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set list "" ;
for {set y [expr {$yh - $colOffset}]} {$y >= [expr {$yl + $colOffset}]} { incr y $colIncr } {
for {set x [expr {$xl + $rowOffset}]} {$x <= [expr {$xh - $rowOffset}]} { incr x $rowIncr } {
set list "$list $x $y" ;
puts "Value of x is: $x"; puts "\t Value of y is: $y" ;
}
}
return $list
}
set rect_boundary {10 15 100 40} # xl yl xh yh
set rowOffset 5
set colOffset 5
set rowIncr 10
set colIncr 15
Some Logic I need to implement in this code based on yh-yl and xh-xl to calculate height and width of rectangle and accordingly output rows
Command to call the proc
$> getPointList $rect_boundary $rowOffset $colOffset $rowIncr $colIncr
Just for your understanding there are eight x,y points inside the rectangle on a particular row.
x offset is the first x point on a row from the left or roght boundary, thereafter all the points are separated by an increment value which I call rowIncr. Same holds true for column.
Expected output : This is what the above code does but it is hardcoded for two rows. I want to increase and implement the logic if the rows and column are variable.
$> R1: (15 40) (25 40) (35 40) (45 40) (55 40) (65 40) (75 40) (85 40) (95 40)
R2: (15 15) (25 15) (35 15) (45 15) (55 15) (65 15) (75 15) (85 15) (95 15)
Rectangle Image for better clarity as this thing wont let me update pictures
__________________________________________________________________________ (100,40)
| |- 5 |
| . . . . . . . . |
| |- 15 |
|-5-. . --10---. . . . . . |
| |
|_________________________________________________________________________|
(10,15)
For Jerry:
Case1 rowIncr 10 colIncr 20
__________________________________________________________________________ (80,40)
| |- 5 |
| . . . . . . . . |
| |- 20 |
|-5-. . --10---. . . . . . |
| |
|_________________________________________________________________________|
(10,10)
Case2 rowIncr 20 colIncr 35
_________________________________________________ (100,70)
| |- 5 |
| . . . . . |
| |- 35 |
|-5-. . --20---. . . |
| | |-5 |
|________________________________________________|
(10,25)
and so on ...
Okay, I think I now understand what you were trying to do, and I think that your proc would have worked for any number of rows after some fixing:
set output [open "output.txt" w]
proc getPointList {rect_boundary rowOffset colOffset plist} {
global output
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set xpoints [llength [lindex $plist 0]]
set ypoints [llength $plist]
set rowIncr [expr {($xh-$xl-2*$rowOffset)/($xpoints-1)}]
set colIncr [expr {($yh-$yl-2*$colOffset)/($ypoints-1)}]
set count 0
set list ""
for {set y [expr {$yh - $colOffset}]} {$y >= [expr {$yl + $colOffset}]} {incr y -$colIncr} {
for {set x [expr {$xl + $rowOffset}]} {$x <= [expr {$xh - $rowOffset}]} {incr x $rowIncr} {
lappend list "($x,$y)"
}
incr count
puts $output "R$count: [join $list " "]"
set list ""
}
}
set plist {{A B C D E} {A B C D E} {A B C D E} {A B C D E} {A B C D E}}
set rect_boundary {0 0 100 100}
set rowOffset 0
set colOffset 0
getPointList $rect_boundary $rowOffset $colOffset $plist
close $output
I changed the colIncr to put more rows.
In the first loop, I used incr y -$colIncr because this is actually a decrement if you start with the higher y coordinate.
I also changed the output structure to match the one you were looking for. The above snippet returns the coordinates:
R1: (0,100) (25,100) (50,100) (75,100) (100,100)
R2: (0,75) (25,75) (50,75) (75,75) (100,75)
R3: (0,50) (25,50) (50,50) (75,50) (100,50)
R4: (0,25) (25,25) (50,25) (75,25) (100,25)
R5: (0,0) (25,0) (50,0) (75,0) (100,0)
EDIT: Added variable offsets, blank final row and variable columns per row.
proc getPointList {rect_boundary uRowOffset lRowOffset uColOffset lColOffset plist} {
set cordlist $rect_boundary
set xl [lindex $cordlist 0]
set yl [lindex $cordlist 1]
set xh [lindex $cordlist 2]
set yh [lindex $cordlist 3]
set xpoints 0
foreach r $plist {
if {[llength $r] > $xpoints} {set xpoints [llength $r]}
}
set ypoints [llength $plist]
set rowIncr [expr {($xh-$xl-$lRowOffset-$uRowOffset)/($xpoints-1)}]
set colIncr [expr {($yh-$yl-$lColOffset-$uColOffset)/$ypoints}]
set count 0
set list ""
for {set y [expr {$yh - $uColOffset}]} {$y >= [expr {$yl + $lColOffset}]} {incr y -$colIncr} {
set x [expr {$xl + $lRowOffset}]
foreach n [lindex $plist $count] {
lappend list $x $y
incr x $rowIncr
}
incr count
if {$count == $ypoints} {return $list}
}
}
set plist {{A B C D X} {E F G H} {I K L} {M N}}
set qlist 1
foreach n $plist {
set pattern$plist $n
incr qlist
}
set rect_boundary {0 0 100 100}
set upperRowOffset 0
set lowerRowOffset 0
set upperColOffset 0
set lowerColOffset 0
set pointList [getPointList $rect_boundary $upperRowOffset $lowerRowOffset $upperColOffset $lowerColOffset $plist]
set count 1
foreach sub_list $plist {
foreach n $sub_list {
set pattern$count $n
incr count
}
}
set count 1
foreach {a b} $pointList {
set text "pattern$count"
puts "command -point $a,$b -text [set $text]"
incr count
}
It is up to you how to organize the nested lists. In simplest form, return a single list:
set result {x1 y1 x2 y2 ... x16 y16}
Or, you can have a list of two rows:
set result {
{x1 y1 x2 y2 ... x8 y8}
{x9 y9 x10 y10 ... x16 y16}
}
Or, more complex: each pair is a sub-list:
set result {
{ {x1 y1} {x2 y2} ... }
{ {x9 y9} {x10 y10} ... }
}
I don't think you want to use array in this case. FYI, an "array" in TCL is equivalent to a hash in other languages.
Well, with Tcl 8.6
proc parsedata {input} {
lmap a [split $input \n] {
lmap b [split $b \t] {
regexp {x(\d+),?\s*y(\d+)} $b -> c d
list $c $d
}
}
}
Now you can process the data, for example:
foreach line [parsedata $input] {
puts [lmap pair $line {
expr {"([lindex $line 0],[linedex $line 1])"}
}
}

Resources