Error in TCL scripting

tcl

I have two tcl files. one is main tcl file(main.tcl) and another one is like helper file(help.tcl) for main tcl file.I want to execute that helperfile from main file while execution of main file.I use the command "source filename" for this.but i got some errors.here i post both tcl files and what is the error occured on execution. Please help me to solve this…

Error
num_nodes is set 4
warning: Please use -channel as shown in tcl/ex/wireless-mitf.tcl
INITIALIZE THE LIST xListHead
Enter Source Node (0 to 4)
0
Enter Destination Node (0 to 4)
3
SORTING LISTS ...DONE!
channel.cc:sendUp - Calc highestAntennaZ_ and distCST_
highestAntennaZ_ = 1.5,  distCST_ = 716.1
ns: proc1: can't read "n0": no such variable
    while executing
"attach-CBR-traffic $n0 $sink1 64 0.07"
    invoked from within
"set inf0_1[attach-CBR-traffic $n0 $sink1 64 0.07]"
    (file "final.tcl" line 1)
    invoked from within
"source.orig final.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel source.orig [list $fileName]"
    invoked from within
"if [$instance_ is_http_url $fileName] {
set buffer [$instance_ read_url $fileName]
uplevel eval $buffer
} else {
uplevel source.orig [list $fileName]
..."
    (procedure "source" line 8)
    invoked from within
"source final.tcl"
    (procedure "proc1" line 6)
    invoked from within
"proc1"

In the file Main.tcl:

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)            CMUPriQueue            ;# interface queue type
set val(ll)             LL                         ;# link layer type
set val(ant)            Antenna/OmniAntenna        ;# antenna model
set val(ifqlen)         340                        ;# max packet in ifq
set val(nn)             4                          ;# number of mobilenodes
set val(rp)             DSR                        ;# routing protocol
set val(x)      630            ;# X axis distance   
set val(y)      570            ;# Y axis distance
set opt(energymodel)    EnergyModel                ;# Initial Energy
set opt(initialenergy)  100                        ;# Initial energy in Joules

set ns [new Simulator]

set nam1 [open nam11.nam w]
$ns namtrace-all-wireless $nam1 $val(x) $val(y)

set trace1 [open trace11.tr w]
$ns trace-all $trace1
$ns use-newtrace

set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)

create-god $val(nn)
Phy/WirelessPhy set Pt_ 0.81

$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) \
        -topoInstance $topo \
        -agentTrace ON \
        -routerTrace ON \
        -macTrace ON \
        -movementTrace ON \
        -rxPower 0.36 \
        -txPower 0.14 \
            -channelType $val(chan) \
        -initialEnergy $opt(initialenergy) \
        -energyModel $opt(energymodel)  \


for { set i 0 } {$i < $val(nn)} { incr i } {
  set n($i) [$ns node]
  $n($i) random-motion 0
  $n($i) color black
  $ns initial_node_pos $n($i) 30
}

for { set i 0 } { $i < $val(nn)} { incr i } {
  $ns at 0.0 "$n($i) color black"
  $ns at 0.0 "$n($i) label-color maroon"
}

$ns at 0.0 "$n(0) setdest 220.00 210 3000"
$ns at 0.0 "$n(1) setdest 320.00 310 3000"
$ns at 0.0 "$n(2) setdest 420.00 110 3000"
$ns at 0.0 "$n(3) setdest 520.00 210 3000"


for {set i 0} {$i<$val(nn)} {incr i} {
  set sink($i) [new Agent/LossMonitor]
  $ns attach-agent $n($i) $sink($i)
}

proc attach-CBR-traffic { node sink size itval} {
  #Get an instance of the simulator
  set ns_ [Simulator instance]
  set udp [new Agent/UDP]
  $ns_ attach-agent $node $udp
  #Create a CBR  agent and attach it to the node
  set cbr [new Application/Traffic/CBR]
  $cbr attach-agent $udp
  $cbr set packetSize_ $size    ;#sub packet size
  $cbr set interval_ $itval
  #Attach CBR source to sink;
  $ns_ connect $udp $sink
  return $cbr
}
set cbr001 [attach-CBR-traffic $n(0) $sink(1) 256 0.082]
$ns at 1.0 "$cbr001 start"
$ns at 1.001 "$cbr001 stop"

set cbr001 [attach-CBR-traffic $n(1) $sink(3) 256 0.082]
$ns at 1.002 "$cbr001 start"
$ns at 1.003 "$cbr001 stop"

# neighbor node calculation
set nbr [open Neighbor w]
puts $nbr "\t\t\t\t\tNeighbor Detail"
puts $nbr "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts $nbr "\tNode\t\tNb node\t\tNode-Xpos\tNode-Ypos\tNb-Xpos\t\tNb-Ypos\t\tDistance(d)"
puts $nbr "\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
close $nbr


#~~~~~~~~~~~~~~~~ Calculation of neighbor nodes of all node~~~~~~~~~~~~~~~~~~~
proc distance { n1 n2 nd1 nd2} {
  global c n bnd
  set nbr [open Neighbor a]
  set x1 [expr int([$n1 set X_])]
  set y1 [expr int([$n1 set Y_])]
  set x2 [expr int([$n2 set X_])]
  set y2 [expr int([$n2 set Y_])]
  set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
  if {$d<300} {
    if {$nd2!=$nd1} {
      puts $nbr "\t$nd1\t\t$nd2\t\t$x1\t\t$y1\t\t$x2\t\t$y2\t\t$d"
    }
  }
  close $nbr
}


for {set i 0} {$i <$val(nn)} {incr i} {
  for {set j 0} {$j <$val(nn)} {incr j} {
    $ns at 1.002 "distance $n($i) $n($j) $i $j" 
  }
}

# For Input
set f 1
while {$f} {
  puts "Enter Source Node (0 to 4)"
  gets stdin src
  puts "Enter Destination Node (0 to 4)"
  gets stdin dst
  if {$src>=0 && $src<5 && $dst>=0 && $dst<5 && $src!=$dst} {
    set f 0
    set sd [open srcdst w]
    puts $sd "$src $dst"
    close $sd
  } else {
    puts "\n\t---------Enter Proper Input-------\n"
  }
}

#minimum

proc proc1 {} {
  exec awk -f distance.awk srcdst Neighbor &
  exec awk -f mm.awk snd & 
  exec awk -f mnode.awk min snd &
  exec awk -f final.awk srcdst mnode &
  source final.tcl
}

$ns at 1.5 "proc1"

proc proc2 {} {
  global ns trace1 nam1
  $ns flush-trace
  close $trace1
  close $nam1
  exec nam nam11.nam &
  exit 0
}

$ns at 3.0 "proc2"

$ns run

In the file final.tcl:

set inf0_1[attach-CBR-traffic $n0 $sink1 64 0.07]
$ns at2.1 "$inf0_1 start"
$ns at2.3 "$inf0_1 stop"
$ns at2.1 "$n(0) color green4"
$ns at2.4 "$ns trace-annotate\"Node-0 send data to its neighbor1\""
set inf1_3[attach-CBR-traffic $n1 $sink3 64 0.07]
$ns at2.1 "$inf1_3 start"
$ns at2.3 "$inf1_3 stop"
$ns at2.1 "$n(1) color green4"
$ns at2.4 "$ns trace-annotate\"Node-1 send data to its neighbor3\""

Best Answer

There doesn't seem to be anywhere in your main.tcl file where you source help.tcl. However, in the error message it appears that the file you claim to be help.tcl is actually named final.tcl. Assuming this is what you mean then I can diagnose the error.

The problem is that in your final.tcl file, the first line tries to execute this statement:

set inf0_1 [attach-CBR-traffic $n0 $sink1 64 0.07]
#         ^
#         |
# BTW, unrelated to the error, there is also a missing space here which
# is probably not what you intended. 

The problem with that statement is that the variables n0 and sink1 are undefined.

Updated Answer

OK, there seem to be lots of misconceptions in your understanding of Tcl. I highly recommend reading the documentation of the Tcl language. Fortunately for you, unlike C or Perl or almost any other language, the complete documentation of tcl syntax is only a single page: http://www.tcl.tk/man/tcl/TclCmd/Tcl.htm. Note specifically rule number 8 (variable substitution).

First thing you need to know that's wrong with your script is what the error message tells you: you have not defined the variable n0 anywhere in your program (nor have you defined sink1). There is however a global variable n which happens to be an array. From you comment it looks like this is what you mean when you're trying to access n0. If so, the correct syntax is given in rule number 8: arrays are accessed using the arrayname(index) syntax. Before we go further I'd like to remind you that what Tcl calls arrays are technically associative arrays (in other languages they are sometimes known as hashes or maps) so the index can be a string. Now, having said that, the correct syntax for accessing n is:

set inf0_1 [attach-CBR-traffic $n(0) $sink(1) 64 0.07]
#                                 ^        ^

But this still won't work. If you try this it will still complain about n and sink being undefined. That's because of how tcl scoping rules work. Inside a function, only local variables are visible. Global variables are not available inside functions unless you explicitly ask tcl to import them. To access global variables you have two options:

First, the traditional way: use the global command to import the global variables. You can either do it in the proc that sources the final.tcl file:

proc proc1 {} {
  global n sink
  # ...
  source final.tcl
}

or you can do it in the final.tcl file itself:

global n sink
set inf0_1 [attach-CBR-traffic $n(0) $sink(1) 64 0.07]
# ...

The second method is to access the global variables using the global namespace ::. This way you don't need to import the variables using the global command:

set inf0_1 [attach-CBR-traffic $::n(0) $::sink(1) 64 0.07]

Fixing all the issues I highlighted above should get your code running (assuming I've guessed your intentions correctly). However I strongly suggest reading the tcl man pages and familiarize yourself with tcl to avoid future bugs. At minimum you should understand the syntax rules, the man page for set and the man page for proc:

The following page is also a good introduction to tcl: An Introduction to Tcl Scripting

Related Topic