From: "Brett H. Williams" Date: 2003-04-04T02:59:13+09:00 Subject: Re: Any Hardware/EDA engineers out there? --oyUTqETQ0mS9luUI Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Apr 4, Jim Freeze wrote: > On Friday, 4 April 2003 at 2:03:50 +0900, Brett H. Williams wrote: > > At this time, though, I don't think I'm at liberty to share any of it. Hmmm... > > we do have some simple utilities to parse and communicate with Tcl (so many CAD > > tools use Tcl). I think that could be shared, and we've found it quite useful > > despite its simplicity. > > > Please share > Why not? (attached) It just adds a few things to the Tk* modules, as it seems some of the useful things in them are private. This is primarily used to have tcl configuration files for our Ruby-based CAD tools. So it is not terribly complex. I must make an obligatory disclaimer: I didn't write any of this, coworkers Craig Files and John Bratt did (hence the mix of styles). Perhaps if this is useful to others it could be extended, cleaned up, and made even more useful. A little example of one way we'd use this, rather neutered: def ScanPlan.readCommandsFile(filename, scanplan) # create a class object so it can be reached outside the scope of an # individual object (how it has to be done with Tcl) @@current_scanplan = scanplan # Next, set up tcl configuration commands tcl_code = <<-EOC proc set_constraint {scantype param_name param_value} { ruby "ScanPlan.sp_set_param('$scantype','$param_name','$param_value')" return "$scantype" } # put in any other tcl code you want here... if long could certainly # be read in from a file instead EOC TclUtils.eval(tcl_code) TclUtils.load_file(filename) error = TclUtils.fetchValue("errorInfo") # If load_file had errors, it will print to stderr the error, but nothing # will actually stop our current process. raise "Reading tcl file #{filename} generated errors." unless error.empty? @@current_scanplan = nil end # This is the ruby method that is called by the tcl procedure set_constraint # In such methods we may need to access the class variable which gives # us some context (this tools does things recursively, including reading # multiple tcl configuration file for a given level of hierarchy) def ScanPlan.sp_set_param(scantype, param_name, param_value) ScanPlan.checkNewParam(scantype,param_name,param_value) ScanPlan[scantype,param_name] = param_value return param_value end Note that the same restrictions in communication to and from Tcl apply as when using the Tk modules--make sure each tcl proc and each Ruby method that cross the Tcl/Ruby boundary returns a string and nothing but a string. -- ---------------------------------------------- | -------------------------- Brett Williams | (970) 288-0475 Agilent Technologies | brett_williams@agilent.com ---------------------------------------------- | -------------------------- --oyUTqETQ0mS9luUI Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="TclUtils.rb" # utils that are used to read TCL in ruby # Craig Files 05-13-02 require 'tk' # Need to make tk_split_list public methods in TkComm class TclUtils # returns a ruby array given a tcl list # usage : ruby "list2ruby('$x')" where $x is the list def TclUtils.list2rb (str) a = str.split # go through the string and create a list by matching the # last { with the next } while (loc = a.rindex("{")) # loc is the last { in the string b = a.slice(loc..-1) # b is temporary array loc2 = b.index("}") # loc2 is the first } in b c = b.slice(1..loc2-1) # c represents array between { and } a[loc]=c # set a[loc] to c (loc+1..loc2+loc).each { a.delete_at(loc+1) } # delete all values in c end return a end # returns a ruby hash of the tcl array # NOTE: arg must be global tcl variable # usage : # glob tcl_array # ... put stuff in array # ruby "array2rb('tcl_array'))" def TclUtils.array2rb(arg) v = TkVarAccess.new(arg) return v.value; end # load a TCL script def TclUtils.load_file(file) v = TkVarAccess.new('errorInfo') begin if (FileTest.exists?(file)) # make sure that "file" exists Tk.tk_call('source', file) else puts "Error file: #{file} does not exist" end rescue # print out call stack in the advent something is wrong if v.value == "" puts "ERROR: Possible cause: Ruby method returns nonstring value to tcl" else $stderr.puts v.value end end end # start of extensions def TclUtils.run_command(cmd_name,*args) v = TkVarAccess.new('errorInfo') x = nil begin x = Tk.tk_call(cmd_name, *args) rescue # print out call stack in the advent something is wrong if v.value == "" puts "ERROR: Possible cause: incorrect number of arguments passed to tcl procedure" else $stderr.puts v.value end end return x end def TclUtils.eval(cmd_string) v = TkVarAccess.new('errorInfo') x = nil begin x = Tk.tk_call("eval", cmd_string) rescue # print out call stack in the advent something is wrong if v.value == "" puts "ERROR: Possible cause: who knows? You're using eval..." else $stderr.puts v.value end end return x end def TclUtils.fetchValue(var_name) v = TkVarAccess.new('errorInfo') x = nil begin x = Tk.tk_call("eval", "set tclutilsdummy $#{var_name}") rescue # print out call stack in the advent something is wrong if v.value == "" puts "ERROR: cause unknown." else $stderr.puts v.value end end return x end def TclUtils.set(var_name,value) v = TkVarAccess.new('errorInfo') x = nil begin Tk.tk_call("set",var_name,value) rescue # print out call stack in the advent something is wrong if v.value == "" puts "ERROR: cause unknown." else $stderr.puts v.value end end end end --oyUTqETQ0mS9luUI--