hrp@boring.cray.com (Hal Peterson) (07/26/89)
I am using GhostScript 1.3 with the patches supplied by Tony Li and
snoopy's fix to interp.c. My platform is an 8MB Sun 3/50 running
SunOS 3.5. I am compiling with GCC 1.35.
The following short program demonstrates a bug in the implementation
of ifelse:
%!
% find the longest and widest strings in systemdict.
% NOTE: does not work in GhostScript 1.3.
/tempWidest 0 def
/tempLongest 0 def
/tempString 64 string def
systemdict {
pop tempString cvs dup
stringwidth pop round cvi dup tempWidest gt
{ /tempWidest exch def } % def not executed
{ pop }
ifelse
length dup tempLongest gt % length gets typecheck
{ /tempLongest exch def }
{ pop }
ifelse
} forall
The code for ifelse in interp() does not save the context of the proc
on the execution stack. Most of the time this isn't a problem, since
the previous entry on the execution stack was an array; but inside of
the forall there can be a null on the estack, fooling the interpreter
into thinking it's done with the ifelse proc once it has finished the
exch; so the def never gets executed and the ostack is wrong,
resulting in a typecheck from length.
To fix it, I added an s_store_b to the ifelse code, and while I was at
it compressed the two nearly identical cases into one.
--
Hal Peterson Domain: hrp@cray.com
Cray Research Old style: hrp%cray.com@uc.msc.umn.edu
1440 Northland Dr. UUCP: uunet!cray!hrp
Mendota Hts, MN 55120 USA Telephone: +1 612 681 3145
========================================================================
*** interp-DIST.c Wed Jul 5 17:41:44 1989
--- interp.c Tue Jul 25 12:40:22 1989
***************
*** 282,292 ****
store_state(iesp);
iosp -= 3;
/* Open code "up" for the array case(s) */
! if ( iosp[1].value.index ) /* execute iosp[2] */
! { switch( r_type_xe(iosp + 2) )
{
default:
! s_store_b(iesp, 1, iosp, 2);
iref = iesp + 1;
icount = 0;
goto top;
--- 282,296 ----
store_state(iesp);
iosp -= 3;
/* Open code "up" for the array case(s) */
! { int which;
! if (iosp[1].value.index)
! which = 2;
! else
! which = 3;
! switch( r_type_xe(iosp + which) )
{
default:
! s_store_b(iesp, 1, iosp, which);
iref = iesp + 1;
icount = 0;
goto top;
***************
*** 293,321 ****
case exec(t_array): ;
case exec(t_packedarray): ;
}
! iref = iosp[2].value.refs;
! icount = iosp[2].size;
! }
! else /* execute iosp[3] */
! { switch( r_type_xe(iosp + 3) )
! {
! default:
! s_store_b(iesp, 1, iosp, 3);
! iref = iesp + 1;
! icount = 0;
! goto top;
! case exec(t_array): ;
! case exec(t_packedarray): ;
}
! iref = iosp[3].value.refs;
! icount = iosp[3].size;
! }
! if ( --icount <= 0 ) /* <= 1 more elements */
! { if ( icount < 0 ) goto up;
! }
! else
! iesp++;
! goto top;
case plain_exec(tx_op_le):
code = obj_compare(iosp, 2+1);
if ( code < 0 )
--- 297,313 ----
case exec(t_array): ;
case exec(t_packedarray): ;
}
! iref = iosp[which].value.refs;
! icount = iosp[which].size;
! if ( --icount <= 0 ) /* <= 1 more elements */
! { if ( icount < 0 ) goto up;
}
! else
! { iesp++;
! s_store_b(iesp, 0, iosp, which);
! }
! goto top;
! }
case plain_exec(tx_op_le):
code = obj_compare(iosp, 2+1);
if ( code < 0 )