Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

why can't EXPR read a global variable ?

81 views
Skip to first unread message

maura.m...@gmail.com

unread,
May 25, 2006, 7:01:22 PM5/25/06
to
Back to the menu snd its radiobutton children ....
In the following I'm cutting and pasting both my Tcl procs and C
functions that handle this logic ...
I'm almost at the end of this nightmare ... but when I click on AINT
button and then select the alternative
(non default) radiobutton (whose value is 1e12) then the C function
does its job fine at calculating the offset (checked step-by-step and
setting watch/breakpoint by DDD). The C function returns the right
offset in the Tcl buffer but upon retun to the Tcl interpreter I get
the following uexplained error as the variable shift that is claimed
unknown is actually declared GLOBAL at module level (outside any proc),
in the outermost proc, in the proc that uses it .... To be frank I do
not know where else to declare its scope (namespace) :

"Error in Tcl script
Error: can't read "shift": no such variable
OK Skip Message Stack Trace"

The stack contents is as follows:

can't read "shitf": no such variable
while executing
"puts "\n shift: $shitf""
(procedure "change_RZ_hist_aint" line 18)
invoked from within
"change_RZ_hist_aint"
invoked from within
".button_aint.menu invoke active"
("uplevel" body line 1)
invoked from within
"uplevel #0 [list $w invoke active]"
(procedure "tkMenuInvoke" line 47)
invoked from within
"tkMenuInvoke .button_aint.menu 1
"
(command bound to event)

Thnak you in advance for your help.
Maura

*************************************************************************************************
* Tcl stuff
*
*************************************************************************************************
proc mf_ui {root args} { # outermost proc #

global plot
global events_info
global hist_info
global euler_info
global aint
global old_aint
global shift

set aint 1.e10
set old_aint 1.e10
puts "\n AINT: $aint"
.......................................
........................................

button $base.button_undo -text "<<" -command undo_canvas
button $base.button_redo -text ">>" -command redo_canvas
menubutton $base.button_aint -text "AINT" -menu
$base.button_aint.menu -relief raised
set m [menu $base.button_aint.menu -tearoff 1]
$m add radio -label 1.e10 -variable aint -value 1.e10 -command
change_RZ_hist_aint
$m add separator
$m add radio -label 1.e12 -variable aint -value 1.e12
-command change_RZ_hist_aint
button $base.button_asrt -text "1:1" -command ToBeDone

grid $base.button_undo -in $base.frame_undoredo -row 1 -column 1
-sticky nesw
grid $base.button_redo -in $base.frame_undoredo -row 1 -column 2
-sticky nesw
grid $base.button_aint -in $base.frame_undoredo -row 1 -column 3
-sticky nesw
grid $base.button_asrt -in $base.frame_undoredo -row 1 -column 4
-sticky nesw


proc change_RZ_hist_aint {} { # proc that generates the error #

global hist_info
global aint
global old_aint
global shift

if {[catch {check_hist_aint_option} result] != 0} {
tk_messageBox -default ok -type ok -icon error -message "AINT
does not apply to the current histogram"
exit 1
} else {
puts "\n previous AINT value: $old_aint"
puts "\n current AINT value: $aint"
if {$old_aint != $aint} {
delete_hist_bar;
set line [get_hist_bar_shift $old_aint $aint ]
scan $line {%d} shift
puts "\n shift: $shitf"
set hist_info(binmax) [expr $hist_info(binmax) + $shift]
set hist_info(binmin) [expr $hist_info(binmin) + $shift]
if { $ihis == 0 } {
draw_hist_bar 75 621 36 12 $hist_info(binmax)
$hist_info(binmin) $hist_info(max) $hist_info(min)
}
if { $ihis == 1 } {
draw_hist_bar 134 621 51 12 $hist_info(binmax)
$hist_info(binmin) $hist_info(max) $hist_info(min)
}
}
set old_aint $aint
}
}

*************************************************************************************************
* C stuff
*
*************************************************************************************************

Tcl_CreateCommand( interp, "check_hist_aint_option",
check_hist_aint_option_cb,
(ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL );
Tcl_CreateCommand( interp, "get_hist_bar_shift",
get_hist_bar_shift_cb,
(ClientData)NULL,
(Tcl_CmdDeleteProc *)NULL );


/***********************************************************************************************/
/* verify the AINT rescaling option is available for the currently
active histogram */
/*
*/
static int
check_hist_aint_option_cb( ClientData clientData,
Tcl_Interp *interp,
int argc, char *argv[] ) {
int i;

if ( hg.active_ <= 0 ){
Tcl_SetResult( interp,
"Histogram not active !",
TCL_STATIC );
return TCL_ERROR;
}

i = -1;
while ((++i < Length_of_AINT_histo_ID) && (hg.hid_ !=
AINT_histo_ID[i])) ;
if (i >= Length_of_AINT_histo_ID) {
Tcl_SetResult( interp,
"Renormalization option unavailable for the current
histogram !",
TCL_STATIC );
return TCL_ERROR;
}
return TCL_OK;
}

/**********************************************************************************************/
/* Calculates colors_bar shift from ratio of old and new rescaling
factors */
/*
*/
static int
get_hist_bar_shift_cb( ClientData clientData,
Tcl_Interp *interp,
int argc, char *argv[] ) {
double old_norm;
double new_norm;
double Ratio;
double Dshift;
int shift;

if ( argc != 3 ) {
Tcl_SetResult( interp,
"wrong # args: should be \"get_hist_bar_shift
<old_aint> <new_aint>\"",
TCL_STATIC );
return TCL_ERROR;
}
old_norm = strtod( argv[1], NULL );
new_norm = strtod( argv[2], NULL );
Ratio = (double) new_norm/old_norm;
Dshift = (double) log10((double) new_norm/old_norm);
shift = (int) log10((double) new_norm/old_norm);
sprintf( tclres_buffer, "%d", shift);
return TCL_OK;
}


***********
* NOTE *
***********
most of the C lines are redundant and will be dropped. But they were
useful to me to track the data type conversion and make sure the right
data type was returned to the Tcl interpreter.

Alan Anderson

unread,
May 25, 2006, 7:07:17 PM5/25/06
to
"maura.m...@gmail.com" <maura.m...@gmail.com> wrote:

> "Error in Tcl script
> Error: can't read "shift": no such variable
> OK Skip Message Stack Trace"

Run the program and read that error again, letter by letter. You
mistyped it here to say what you thought it says, but what it actually
says will tell you exactly what the problem is.

> The stack contents is as follows:
>
> can't read "shitf": no such variable
> while executing
> "puts "\n shift: $shitf""
> (procedure "change_RZ_hist_aint" line 18)

Notice the actual spelling of the global variable, versus the spelling
you used in the puts command.

Gerald W. Lester

unread,
May 25, 2006, 7:15:37 PM5/25/06
to

Couple problems here:

1) Please read the error message, instead of assuming Tcl is doing something
strange. It looks like you made a typo.

2) There is no such thing as declaring a variable in Tcl. The global
command does not declare a variable, it creates a lookup link from one stack
frame to another stack frame.

3) Variables get created when you assign them a value. No where in what you
posted do you set a value to shift or shitf.

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

maura.m...@gmail.com

unread,
May 26, 2006, 12:18:59 AM5/26/06
to
Thanks. I mistyped the variable in the "puts statement". But everywhere
its name is consistent.

You're right. Nothing is returned to the Tcl interpreter because I
forgot the statement:
Tcl_SetResult( interp, tclres_buffer, TCL_VOLATILE );

in the C routine "get_hist_bar_shift".
Now it works. So I can try to improve its behaviour.

Thank you,
Maura

Donald Arseneau

unread,
May 26, 2006, 2:25:36 AM5/26/06
to
"maura.m...@gmail.com" <maura.m...@gmail.com> writes:

> can't read "shitf": no such variable
> while executing
> "puts "\n shift: $shitf""
> (procedure "change_RZ_hist_aint" line 18)
> invoked from within
> "change_RZ_hist_aint"
> invoked from within
> ".button_aint.menu invoke active"
> ("uplevel" body line 1)
> invoked from within
> "uplevel #0 [list $w invoke active]"
> (procedure "tkMenuInvoke" line 47)
> invoked from within
> "tkMenuInvoke .button_aint.menu 1

that's shitf-ull of errors!


;-)

--
Donald Arseneau as...@triumf.ca

mark anthony

unread,
May 26, 2006, 9:22:42 AM5/26/06
to
on a sidenote use braces:

set hist_info(binmax) [expr $hist_info(binmax) + $shift]
set hist_info(binmin) [expr $hist_info(binmin) + $shift]

vs

set hist_info(binmax) [expr {$hist_info(binmax) + $shift } ]
set hist_info(binmin) [expr {$hist_info(binmin) + $shift } ]

not only it is safer if you get used to them, but it is in fact faster.

and i would move the global variables and global array into an
namespace and make a wrapper like:

histinfo::shift max $shift

looks better imho, but that is just flavour i guess.

sample code for histinfo::shift:

::namespace eval histinfo {
::variable max
::set max 0 ;# default
::variable min
::set min 0 ;# default

## incr varName i
##
## varName - one of { min max }
## i - any number
::proc shift { varName i } {
::return [set $varName [::expr {[set $varName] + $i}]]
}

## set - like the normal set
## set varName ?newValue?
::proc set { varName args } {
::variable $varName
::if {0<[::llength $args]} then {
::set $varName [::lindex $args 0]
}
::return [::set $varName ]
}
}

0 new messages