Sharing variables between C Shell and TCL

1.3k views Asked by At

I have a variable which is being used in two separate scripts: a C Shell one and a TCL one. Is there a way to define it just once and access it in both the scripts?

vars.sh

#!/usr/bin/env tcsh
set a=b

run.sh

#!/usr/bin/env tcsh
source vars.sh
echo $a

vars.tcl

#!/usr/bin/env tclsh
set a b

run.tcl

#!/usr/bin/env tclsh
source vars.tcl
puts $a

I do not like to idea of generating two separate files to store the same variables in two different formats. Is there a way to use a single vars file and have the variables available to both C Shell and TCL?

1

There are 1 answers

1
Donal Fellows On BEST ANSWER

The simplest method is to make the variables be environment variables, since those are inherited by a child process from their parent. (On the Tcl side, they're elements in the ::env global array, and on the C shell side, they can be read like any other variable but need to be set via setenv.)

Sharing a single configuration file is much harder, since the two languages use a different syntax. Provided you don't use anything complicated in the way of quoting, you can make Tcl parse the C shell format.

proc loadVariablesFromCshellFile {filename arrayName} {
    upvar 1 $arrayName array
    set f [open $filename]
    while {[gets $f line] >= 0} {
        if {[regexp {^\s*set (\w+)=([""'']?)(.*)\2\s*$} $line -> key quote value]} {
            set array($key) $value
        }
    }
    close $f
}

This isn't complete code, since it doesn't handle substitution of variables inside the value, but it is enough to get you started. (I also hope you're not using that feature; if you are, portability is going to be quite a bit harder to achieve.) Here's how you'd use it:

#!/usr/bin/env tclsh
proc loadVariablesFromCshellFile {filename arrayName} {
    upvar 1 $arrayName array
    set f [open $filename]
    while {[gets $f line] >= 0} {
        if {[regexp {^\s*set (\w+)=([""'']?)(.*)\2\s*$} $line -> key quote value]} {
            set array($key) $value
        }
    }
    close $f
}
loadVariablesFromCshellFile vars.sh myvars
puts $myvars(a)

While it is entirely possible to load the values straight into scalar globals on the Tcl side, I really don't recommend it as it is polluting the global variable space from a source outside the Tcl program, a known piece of poor practice.