vho
vho

Reputation: 1141

How to source inside proc?

There is a code which generate the file with one proc:

puts $fh "proc generate \{ fileName\} \{"
puts $fh "[info body generateScriptBody]"
puts $fh "\}"
puts $fh "generate"
close $fh

proc generateScriptBody{} {
    source something1    
    source something2 
    ...
} 

In this case should I source inside proc or there are alternatives?

Upvotes: 0

Views: 1051

Answers (2)

Ralf
Ralf

Reputation: 1295

I just encountered a problem with calling source inside a proc, maybe it's helpful for someone.

I have two test files. This is sourcetest1.tcl which sources sourcetest2.tcl in three different ways:

puts "sourcetest1.tcl"

proc mysource_wrong {script} {
    source $script
}

proc mysource_right {script} {
    uplevel "source sourcetest2.tcl"
}

#source sourcetest2.tcl
#mysource_right sourcetest2.tcl
mysource_wrong sourcetest2.tcl

This is sourcetest2.tcl:

puts "sourcetest2.tcl"

set l {1 2 3}

puts "outside: $l"

proc doit {} {
    global l
    puts "doit: $l"
}

doit

Everything is fine with a direct source and with mysource_right, the output is in both cases:

sourcetest1.tcl
sourcetest2.tcl
outside: 1 2 3
doit: 1 2 3

However, with mysource_wrong, we get the following output:

sourcetest1.tcl
sourcetest2.tcl
outside: 1 2 3
can't read "l": no such variable
    while executing
"puts "doit: $l""
    (procedure "doit" line 3)
    invoked from within
"doit"
    (file "sourcetest2.tcl" line 12)
    invoked from within
"source $script"
    (procedure "mysource_wrong" line 2)
    invoked from within
"mysource_wrong sourcetest2.tcl"
    (file "sourcetest1.tcl" line 13)

My interpretation is that a source inside a proc puts the variable l into the scope of the proc, not into the global scope. This can be avoided by using uplevel like in mysource_right.

Upvotes: 2

Hai Vu
Hai Vu

Reputation: 40763

I don't understand what you are trying to do, but source within a proc is acceptable. If you are looking to write the whole proc into a file, take a look at saveprocs from the TclX package; it will help simplifying your code.

Update

Here is an example of using saveprocs:

package require Tclx

# Generate a proc from body of one or more files
set body [read_file something1]
append body "\n" [read_file something2]
proc generate {fileName} $body

# Write to file
saveprocs generate.tcl generate

In this case, I did away with all the source commands and read the contents directly into the proc's body.

Upvotes: 2

Related Questions