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 )