# compute provides some preprocessing capabilities for expr. # It will add a "$" sign to anything in the expression that # is a variable in the uplevel context, if it doesn't already # have one. It maps ' to " in the final translation, to insure # string comparisons are done in a string context, It maps # "and" to &&; "or" to ||; "not" to !; "<>" to !=; "true", "on" # and "yes" to 1 and "false", "off" and "no" to 0. It also # maps "pi" to 3.1415926535 # glennj: no need to map {true on yes false off no} since those # are already valid truth values. proc compute { args } { # puts "expr $args" set exp "" set id "" regsub "''" [ string trim $args ] "@@@" args while 1 { regexp "(\[^a-zA-Z_'\]*)(\[a-zA-Z0-9_'\]*)(.*)" $args -> head id tail if ![ string length $id ] { set exp "$exp$head" break } set dollar "" if ![ string equal [ string index $id 0 ] "'" ] { if ![ string equal [info commands $id] "" ] { set id "\[ $id" regexp {[^\(]*\(([^\)]*)\)(.*)} $tail -> params tail set tail " $params \]$tail" } elseif [ uplevel info exists $id ] { set dollar "\$" } } append exp "$head$dollar$id" set args $tail } regsub -all "'" $exp "\"" exp set map "@@@ ' and && or || not ! <> != true 1 false 0 on 1 off 0 yes 1 no 0 pi 3.1415926535" foreach { from to } $map { regsub $from $exp $to exp } # as of tcl 8.3, more efficient to replace foreach look with: # set exp [string map $map $exp] set exp [ uplevel subst \{$exp\} ] return [ expr $exp ] }