home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / printing / ghostscrip / source / _gs / c / interp < prev    next >
Encoding:
Text File  |  1991-10-26  |  19.7 KB  |  665 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* interp.c */
  21. /* Ghostscript language interpreter */
  22. #include "memory_.h"
  23. #include "ghost.h"
  24. #include "errors.h"
  25. #include "estack.h"
  26. #include "name.h"
  27. #include "dict.h"
  28. #include "oper.h"
  29. #include "packed.h"
  30. #include "save.h"
  31. #include "stream.h"
  32. #include "store.h"
  33.  
  34. /* Imported procedures */
  35. extern int obj_compare(P2(os_ptr, int));
  36.  
  37. /* Forward references */
  38. private int interp(P1(ref *pref));
  39. private int interp_exit(P1(os_ptr));
  40. private int copy_stack(P3(ref *, uint, ref *));
  41.  
  42. /* Configuration parameters */
  43. #define max_ostack 800
  44. #define max_estack 150
  45. #define max_dstack 20
  46. #define num_clear_dstack 2
  47.  
  48. /* See estack.h for a description of the execution stack. */
  49.  
  50. /* The logic for managing icount and iref below assumes that */
  51. /* there are no control operators which pop and then push */
  52. /* information on the execution stack. */
  53.  
  54. /* Stacks */
  55. #define os_guard_under 10
  56. #define os_guard_over 10
  57. private ref ostack[os_guard_under+max_ostack+os_guard_over];
  58. private ref estack[max_estack];
  59. ref dstack[max_dstack];
  60. os_ptr osp_nargs[os_max_nargs];        /* for checking osp */
  61.  
  62. /* Stack pointers */
  63. os_ptr osbot, osp, ostop;
  64. es_ptr esbot, esp, estop;
  65. ref *dsp, *dstop;
  66.  
  67. /* The object that caused an error */
  68. ref error_object;
  69.  
  70. /* Object related to error handling */
  71. extern ref name_errordict;
  72. extern ref name_ErrorNames;
  73.  
  74. /* Extended types.  The interpreter may replace the type of operators */
  75. /* in procedures with these, to speed up the interpretation loop. */
  76. #define tx_op t_next_index
  77. extern int zadd(P1(os_ptr));
  78. extern int zdup(P1(os_ptr));
  79. extern int zexch(P1(os_ptr));
  80. extern int zifelse(P1(os_ptr));
  81. extern int zle(P1(os_ptr));
  82. extern int zpop(P1(os_ptr));
  83. extern int zsub(P1(os_ptr));
  84. private op_proc_p special_ops[] = {
  85.     zadd, zdup, zexch, zifelse, zle, zpop, zsub
  86. };
  87. enum {
  88.     tx_op_add = tx_op,
  89.     tx_op_dup,
  90.     tx_op_exch,
  91.     tx_op_ifelse,
  92.     tx_op_le,
  93.     tx_op_pop,
  94.     tx_op_sub,
  95.     tx_next_op
  96. };
  97. #define num_special_ops ((int)tx_next_op - tx_op)
  98.  
  99. /* The following is a special "error" code that is used internally */
  100. /* to cause the interpreter to exit. */
  101. #define e_InterpreterExit (-100)
  102.  
  103. /* Initialize the interpreter */
  104. void
  105. interp_init(int ndict)
  106. {    /* Initialize the guard entries on the operand stack */
  107.     /* with objects that have invalid type and attributes. */
  108.     osbot = ostack + os_guard_under;
  109.     osp = osbot - 1, ostop = osbot + (max_ostack-1);
  110.        {    register os_ptr op;
  111.         for ( op = ostack; op < osbot; op++ )
  112.             make_tav(op, -1, 0, index, 0);
  113.        }
  114.        {    register int i;
  115.         for ( i = 1; i < os_max_nargs; i++ )
  116.             osp_nargs[i] = osbot + i - 1;
  117.        }
  118.     esbot = estack, esp = estack - 1, estop = estack + (max_estack-1);
  119.     /* Initialize the dictionary stack to the first ndict */
  120.     /* dictionaries.  ndict is a parameter because during */
  121.     /* initialization, only systemdict exists. */
  122.     dsp = dstack + ndict - 1, dstop = dstack + (max_dstack-1);
  123. }
  124.  
  125. /* Look up an operator during initialization, */
  126. /* changing its type if appropriate. */
  127. void
  128. interp_fix_op(ref *opref)
  129. {    register int i = num_special_ops;
  130.     op_proc_p proc = real_opproc(opref);
  131.     while ( --i >= 0 && proc != special_ops[i] ) ;
  132.     if ( i >= 0 )
  133.       make_tav(opref, tx_op + i, a_executable, opproc,
  134.            (dummy_op_proc_p)proc);
  135. }
  136.  
  137. /* Invoke the interpreter.  If execution completes normally, return 0. */
  138. /* if an error occurs, then if user_errors is true and the error is a */
  139. /* recoverable one (not an overflow condition), let the user handle it; */
  140. /* otherwise, return the error code. */
  141. int
  142. interpret(ref *pref, int user_errors)
  143. {    ref *epref = pref;
  144.     ref erref;
  145.     ref *perrordict, *pErrorNames;
  146.     int code, ccode;
  147.     ref saref;
  148.     /* Push a special exit procedure on the execution stack */
  149.     es_ptr esp0 = ++esp;
  150.     make_oper(esp, 0, (dummy_op_proc_p)interp_exit);
  151. retry:    code = interp(epref);
  152.     if ( code == e_InterpreterExit ) return 0;
  153.     /* Adjust osp in case of operand stack underflow */
  154.     if ( osp < osbot - 1 )
  155.         osp = osbot - 1;
  156.     if ( !user_errors ) return code;
  157.     if ( dict_find(&systemdict, &name_errordict, &perrordict) <= 0 ||
  158.          dict_find(&systemdict, &name_ErrorNames, &pErrorNames) <= 0
  159.        )
  160.         return code;    /* errordict or ErrorNames not found?? */
  161.     switch ( code )
  162.        {
  163.     case e_dictstackoverflow:
  164.         if ( osp + 1 >= ostop ) return e_stackoverflow;
  165.         ccode = copy_stack(dstack, dsp - dstack + 1, &saref);
  166.         if ( ccode < 0 ) return ccode;
  167.         dsp = &dstack[num_clear_dstack - 1];
  168.         *++osp = saref;
  169.         break;
  170.     case e_execstackoverflow:
  171.         if ( osp + 1 >= ostop ) return e_stackoverflow;
  172.         ccode = copy_stack(estack, esp - estack + 1, &saref);
  173.         if ( ccode < 0 ) return ccode;
  174.         esp = esp0;
  175.         *++osp = saref;
  176.         break;
  177.     case e_stackoverflow:
  178.         ccode = copy_stack(ostack, osp - osbot + 1, &saref);
  179.         if ( ccode < 0 ) return ccode;
  180.         osp = osbot;
  181.         *osbot = saref;
  182.         break;
  183.        }
  184.     if ( -code > r_size(pErrorNames) )
  185.         return code;        /* unknown error??? */
  186.     if ( dict_find(perrordict, &pErrorNames->value.refs[-code - 1], &epref) <= 0 )
  187.         return code;        /* error name not in errordict??? */
  188.     erref = *epref;
  189.     epref = &erref;
  190.     /* Push the error object on the operand stack */
  191.     *++osp = error_object;
  192.     goto retry;
  193. }    
  194. private int
  195. interp_exit(os_ptr op)
  196. {    return e_InterpreterExit;
  197. }
  198.  
  199. /* Copy the contents of an overflowed stack into an array. */
  200. private int
  201. copy_stack(ref *stk, uint size, ref *arr)
  202. {    ref *abody = alloc_refs(size, "overflowed stack");
  203.     if ( abody == 0 ) return e_VMerror;
  204.     refcpy_to_new(abody, stk, size);
  205.     make_tasv(arr, t_array, a_all, size, refs, abody);
  206.     return 0;
  207. }
  208.  
  209. /* Main interpreter. */
  210. /* If execution terminates normally, return e_InterpreterExit. */
  211. /* If an error occurs, leave the current object in error_object */
  212. /* and return a (negative) error code. */
  213. #define return_with_error(code, objp)\
  214.   { esp = iesp; osp = iosp; error_object = *(objp); return_error(code); }
  215. private int
  216. interp(ref *pref /* object to interpret */)
  217. {    register ref *iref = pref;
  218.     register int icount = 0;    /* # of consecutive tokens at iref */
  219.     register os_ptr iosp = osp;    /* private copy of osp */
  220.     register es_ptr iesp = esp;    /* private copy of esp */
  221.     int code;
  222.     ref token;        /* token read from file or string, */
  223.                 /* must be declared in this scope */
  224.     register ref *pvalue;
  225.     /* We want to recognize executable arrays here, */
  226.     /* so we push the argument on the estack and enter */
  227.     /* the loop at the bottom. */
  228.     if ( iesp >= estop ) return_with_error (e_execstackoverflow, pref);
  229.     *++iesp = *pref;
  230.     goto bot;
  231.     /* At this point, if icount > 0, iref and icount correspond */
  232.     /* to the top entry on the execution stack: icount is the */
  233.     /* count of sequential entries remaining AFTER the current one. */
  234. #define add1_short(pref) (ref *)((ushort *)(pref) + 1)
  235. #define store_state(ep)\
  236.   ( icount > 0 ? (ep->value.refs = iref + 1, r_set_size(ep, icount)) : 0 )
  237. #define store_state_short(ep)\
  238.   ( icount > 0 ? (ep->value.refs = add1_short(iref), r_set_size(ep, icount)) : 0 )
  239. #define next()\
  240.   if ( --icount > 0 ) { iref++; goto top; } else goto out
  241. #define next_short()\
  242.   if ( --icount <= 0 ) { if ( icount < 0 ) goto up; iesp--; }\
  243.   iref = add1_short(iref); goto top;
  244. top:    /*
  245.      * This is the top of the interpreter loop.
  246.      * iref points to the ref being interpreted.
  247.      * Note that this might be an element of a packed array,
  248.      * not a real ref: we carefully arranged the first 16 bits of
  249.      * a ref and of a packed array element so they could be distinguished
  250.      * from each other.  (See ghost.h and packed.h for more detail.)
  251.      */
  252. #ifdef DEBUG
  253. if ( gs_debug['I'] || gs_debug['i'] &&
  254.      (*(ushort *)iref <= packed_max_full_ref ? r_type(iref) == t_name :
  255.       *(short *)iref < 0)
  256.    )
  257.    {    void debug_print_ref(P1(ref *));
  258.     int edepth = iesp - esbot;
  259.     char depth[10];
  260.     sprintf(depth, "%d", edepth);
  261.     dputs(depth);
  262.     edepth -= strlen(depth);
  263.     do { dputc('.'); } while ( --edepth > 0 );    /* indent */
  264.     dprintf3("%lx(%d)[%d]: ",
  265.          (ulong)iref, icount, (uint)(iosp - osbot + 1));
  266.     debug_print_ref(iref);
  267.     if ( iosp >= osbot )
  268.        {    dputs(" // ");
  269.         debug_print_ref(iosp);
  270.        }
  271.     dputc('\n');
  272.     fflush(dstderr);
  273.    }
  274. #endif
  275. /* Object that have attributes (arrays, dictionaries, files, and strings) */
  276. /* use lit and exec; other objects use plain and plain_exec. */
  277. #define rsa(attrs) (attrs >> (r_type_shift - 2))
  278. #define rsa_execute rsa(a_execute)
  279. #define rsa_executable rsa(a_executable)
  280. #define lit(t) (((t) << 2) + rsa_execute)
  281. #define exec(t) (((t) << 2) + rsa_execute + rsa_executable)
  282. #define nox(t) ((t) << 2)
  283. #define nox_exec(t) (((t) << 2) + rsa_executable)
  284. #define plain(t) ((t) << 2)
  285. #define plain_exec(t) (((t) << 2) + rsa_executable)
  286. sw:    /*
  287.      * We have to populate enough cases of the switch statement to force
  288.      * some compilers to use a dispatch rather than a testing loop.
  289.      * What a nuisance!
  290.      */
  291.     switch ( r_type_xe(iref) )
  292.        {
  293.     /* Access errors. */
  294.     case nox_exec(t_array):
  295.     case nox_exec(t_dictionary):
  296.     case nox_exec(t_file):
  297.     case nox_exec(t_string):
  298.     case nox_exec(t_mixedarray):
  299.     case nox_exec(t_shortarray):
  300.         return_with_error (e_invalidaccess, iref);
  301.     /*
  302.      * Literal objects.  We have to enumerate all the types.
  303.      * In fact, we have to include some extra plain_exec entries
  304.      * just to populate the switch.
  305.      */
  306.     case lit(t_array): case nox(t_array):
  307.     case plain(t_boolean): case plain_exec(t_boolean):
  308.     case lit(t_dictionary): case nox(t_dictionary):
  309.     case lit(t_file): case nox(t_file):
  310.     case plain(t_fontID): case plain_exec(t_fontID):
  311.     case plain(t_integer): case plain_exec(t_integer):
  312.     case plain(t_mark): case plain_exec(t_mark):
  313.     case plain(t_name):
  314.     case plain(t_null):
  315.     case plain(t_oparray):
  316.     case plain(t_operator):
  317.     case plain(t_real): case plain_exec(t_real):
  318.     case plain(t_save): case plain_exec(t_save):
  319.     case lit(t_string): case nox(t_string):
  320.     case lit(t_mixedarray): case nox(t_mixedarray):
  321.     case lit(t_shortarray): case nox(t_shortarray):
  322.     case plain(t_color): case plain_exec(t_color):
  323.     case plain(t_device): case plain_exec(t_device):
  324.         break;
  325.     /* Special operators. */
  326.     case plain_exec(tx_op_add):
  327.         if ( (code = zadd(iosp)) < 0 )
  328.             return_with_error (code, iref);
  329.         iosp--;
  330.         next();
  331.     case plain_exec(tx_op_dup):
  332.         if ( iosp < osp_nargs[1] )
  333.             return_with_error (e_stackunderflow, iref);
  334.         iosp++;
  335.         ref_assign(iosp, iosp - 1);
  336.         next();
  337.     case plain_exec(tx_op_exch):
  338.         if ( iosp < osp_nargs[2] )
  339.             return_with_error (e_stackunderflow, iref);
  340.         ref_assign(&token, iosp);
  341.         ref_assign(iosp, iosp - 1);
  342.         ref_assign(iosp - 1, &token);
  343.         next();
  344.     case plain_exec(tx_op_ifelse):
  345.         if ( r_type(iosp - 2) != t_boolean )
  346.             return_with_error (e_typecheck, iref);
  347.         if ( iesp >= estop )
  348.             return_with_error (e_execstackoverflow, iref);
  349.         store_state(iesp);
  350.         iosp -= 3;
  351.         /* Open code "up" for the array case(s) */
  352.            {    os_ptr whichp =
  353.               (iosp[1].value.index ? iosp + 2 : iosp + 3);
  354.             switch( r_type_xe(whichp) )
  355.                {
  356.             default:
  357.                 ref_assign(iesp + 1, whichp);
  358.                 iref = iesp + 1;
  359.                 icount = 0;
  360.                 goto top;
  361.             case exec(t_array):
  362.             case exec(t_mixedarray):
  363.             case exec(t_shortarray): ;
  364.                }
  365.             iref = whichp->value.refs;
  366.             icount = r_size(whichp);
  367.             if ( --icount <= 0 )    /* <= 1 more elements */
  368.                {    if ( icount < 0 ) goto up;
  369.                }
  370.             else
  371.                {    iesp++;
  372.                 ref_assign(iesp, whichp);
  373.                }
  374.            }
  375.         goto top;
  376.     case plain_exec(tx_op_le):
  377.         code = obj_compare(iosp, 2+1);
  378.         if ( code < 0 )
  379.             return_with_error (code, iref);
  380.         iosp--;
  381.         make_bool(iosp, code);
  382.         next();
  383.     case plain_exec(tx_op_pop):
  384.         if ( iosp < osp_nargs[1] )
  385.             return_with_error (e_stackunderflow, iref);
  386.         iosp--;
  387.         next();
  388.     case plain_exec(tx_op_sub):
  389.         if ( (code = zsub(iosp)) < 0 )
  390.             return_with_error (code, iref);
  391.         iosp--;
  392.         next();
  393.     /* Executable types. */
  394.     case plain_exec(t_null):
  395.         goto bot;
  396.     case plain_exec(t_oparray):
  397.         /* Replace with the definition and go again. */
  398.         pvalue =
  399.           &op_array_table.value.refs[op_index(iref) - op_def_count];
  400. prst:        store_state(iesp);
  401. pr:        if ( iesp >= estop )
  402.             return_with_error (e_execstackoverflow, pvalue);
  403.         ++iesp;
  404.         ref_assign(iesp, pvalue);
  405.         iref = pvalue->value.refs;
  406.         icount = r_size(pvalue) - 1;
  407.         if ( icount <= 0 ) { if ( icount < 0 ) goto up; iesp--; }
  408.         goto top;
  409.     case plain_exec(t_operator):
  410.        {    esp = iesp;        /* save for operator */
  411.         osp = iosp;        /* ditto */
  412.         /* Operator routines take osp as an argument. */
  413.         /* This is just a convenience, since they adjust */
  414.         /* osp themselves to reflect the results. */
  415.         /* Operators that (net) push information on the */
  416.         /* operand stack must check for overflow: */
  417.         /* this normally happens automatically through */
  418.         /* the push macro (in oper.h). */
  419.         /* Operators that do not typecheck their operands */
  420.         /* must check explicitly for stack underflow. */
  421.         code = (*real_opproc(iref))(iosp);
  422.         iosp = osp;
  423.         if ( code != 0 )
  424.            {    /* This might be a control operator that changed */
  425.             /* esp.  Check for this specially. */
  426.             switch ( code )
  427.                {
  428.             case o_check_estack:
  429.                 /* If a control operator popped the estack, */
  430.                 /* we just go to up.  If a control operator */
  431.                 /* pushed something on the estack, we store */
  432.                 /* the state and then go to up.  Otherwise, */
  433.                 /* we can just go on. */
  434.                 if ( esp > iesp ) store_state(iesp);
  435.                 else if ( esp == iesp ) goto bot;
  436.                 iesp = esp;
  437.                 goto up;
  438.             case e_typecheck:
  439.                 /* This might be an operand stack */
  440.                 /* underflow: check the required # of */
  441.                 /* operands now. */
  442.                 if ( iosp < osbot - 1 + op_num_args(iref) )
  443.                     code = e_stackunderflow;
  444.                 /* (falls through) */
  445.             default:
  446.                 return_with_error (code, iref);
  447.                }
  448.            }
  449.         next();            /* just go on */
  450.        }
  451.     case plain_exec(t_name):
  452.         pvalue = iref->value.pname->pvalue;
  453.         if ( !pv_valid(pvalue) )
  454.            {    ref *pdvalue;
  455.             if ( dict_lookup(dstack, dsp, iref, &pdvalue) <= 0 )
  456.                 return_with_error (e_undefined, iref);
  457.             pvalue = pdvalue;
  458.            }
  459.         switch ( r_type_xe(pvalue) )
  460.            {
  461.         case exec(t_array):
  462.         case exec(t_mixedarray):
  463.         case exec(t_shortarray):
  464.             /* This is an executable procedure, execute it. */
  465.             goto prst;
  466.         case plain_exec(t_operator):
  467.            {    /* Shortcut for operators. */
  468.             /* See above for the logic. */
  469.             esp = iesp;
  470.             osp = iosp;
  471.             code = (*real_opproc(pvalue))(iosp);
  472.             iosp = osp;
  473.             if ( code != 0 )
  474.                {    switch ( code )
  475.                    {
  476.                 case o_check_estack:
  477.                    {    if ( esp > iesp )
  478.                       store_state(iesp);
  479.                     else if ( esp == iesp )
  480.                       goto bot;
  481.                     iesp = esp;
  482.                     goto up;
  483.                    }
  484.                 case e_typecheck:
  485.                     if ( iosp < osbot - 1 + op_num_args(pvalue) )
  486.                       code = e_stackunderflow;
  487.                    }
  488.                 return_with_error (code, pvalue);
  489.                }
  490.             next();
  491.            }
  492.         case lit(t_array):
  493.         case plain(t_boolean):
  494.         case plain(t_integer):
  495.         case plain(t_real):
  496.         case lit(t_string):
  497.         case lit(t_mixedarray):
  498.         case lit(t_shortarray):
  499.             /* Just push the value */
  500.             if ( iosp >= ostop )
  501.                 return_with_error (e_stackoverflow, pvalue);
  502.             ++iosp;
  503.             ref_assign(iosp, pvalue);
  504.             next();
  505.         default:        /* handles other literals */
  506.             /* Not a procedure, reinterpret it. */
  507.             store_state(iesp);
  508.             icount = 0;
  509.             iref = pvalue;
  510.             goto top;
  511.            }
  512.     case exec(t_file):
  513.        {    /* Executable file.  Read the next token and interpret it. */
  514.            stream *s;
  515.         code = file_check_read(iref, &s);
  516.         if ( code < 0 ) return_with_error (code, iref);
  517.         osp = iosp;        /* scan_token uses ostack */
  518.         switch ( code = scan_token(s, 0, &token) )
  519.            {
  520.         case 0:            /* read a token */
  521.             store_state(iesp);
  522.             /* Push the file on the e-stack */
  523.             if ( iesp >= estop )
  524.                 return_with_error (e_execstackoverflow, iref);
  525.             ++iesp;
  526.             ref_assign(iesp, iref);
  527.             iref = &token;
  528.             icount = 0;
  529.             goto top;
  530.         case 1:            /* end of file */
  531.             code = file_close(iref, s);
  532.             if ( code < 0 ) return_with_error (code, iref);
  533.             goto bot;
  534.         default:        /* error */
  535.             return_with_error (code, iref);
  536.            }
  537.        }
  538.     case exec(t_string):
  539.        {    /* Executable string.  Read a token and interpret it. */
  540.         stream ss;
  541.         sread_string(&ss, iref->value.bytes, r_size(iref));
  542.         osp = iosp;        /* scan_token uses ostack */
  543.         switch ( code = scan_token(&ss, 1, &token) )
  544.           {
  545.         case 0:            /* read a token */
  546.             store_state(iesp);
  547.             /* Push the updated string back on the e-stack */
  548.             if ( iesp >= estop )
  549.               return_with_error (e_execstackoverflow, iref);
  550.             ++iesp;
  551.             iesp->tas.type_attrs = iref->tas.type_attrs;
  552.             iesp->value.bytes = ss.cptr + 1;
  553.             r_set_size(iesp, ss.cbuf + ss.bsize - ss.cptr - 1);
  554.             iref = &token;
  555.             icount = 0;
  556.             goto top;
  557.         case 1:            /* end of string */
  558.             goto bot;
  559.         default:        /* error */
  560.             return_with_error (code, iref);
  561.           }
  562.        }
  563.     /* Handle packed arrays here by re-dispatching. */
  564.     /* This also picks up some anomalous cases of non-packed arrays. */
  565.     default:
  566.         switch ( *(ushort *)iref >> packed_type_shift )
  567.            {
  568.         case pt_full_ref:
  569.         case pt_full_ref+1:
  570.             if ( iosp >= ostop )
  571.               return_with_error (e_stackoverflow, iref);
  572.             ++iosp;
  573.             /* We know that refs are properly aligned: */
  574.             /* see packed.h for details. */
  575.             ref_assign(iosp, iref);
  576.             next();
  577.         case pt_executable_operator:
  578.            {    uint index = *(ushort *)iref & packed_int_mask;
  579.             op_index_ref(index, &token);
  580.             store_state_short(iesp);
  581.             icount = 0;
  582.             iref = &token;
  583.            }    goto top;
  584.         case pt_integer:
  585.             if ( iosp >= ostop )
  586.               return_with_error (e_stackoverflow, iref);
  587.             ++iosp;
  588.             make_int(iosp, (*(short *)iref & packed_int_mask) +
  589.                     packed_min_intval);
  590.             next_short();
  591.         case pt_literal_name:
  592.         case pt_literal_name+1:
  593.             if ( iosp >= ostop )
  594.               return_with_error (e_stackoverflow, iref);
  595.             ++iosp;
  596.             name_index_ref((uint)*(ushort *)iref &
  597.                          packed_max_name_index,
  598.                        iosp);
  599.             next_short();
  600.         case pt_executable_name:
  601.         case pt_executable_name+1:
  602.            {    ref nref;
  603.             name_index_ref((uint)*(ushort *)iref &
  604.                      packed_max_name_index,
  605.                        &nref);
  606.             pvalue = nref.value.pname->pvalue;
  607.             if ( !pv_valid(pvalue) )
  608.                {    ref *pdvalue;
  609.                 if ( dict_lookup(dstack, dsp, &nref, &pdvalue) <= 0 )
  610.                     return_with_error (e_undefined, &nref);
  611.                 pvalue = pdvalue;
  612.                }
  613.             switch ( r_type_xe(pvalue) )
  614.                {
  615.             case exec(t_array):
  616.             case exec(t_mixedarray):
  617.             case exec(t_shortarray):
  618.                 /* This is an executable procedure, */
  619.                 /* execute it. */
  620.                 store_state_short(iesp);
  621.                 goto pr;
  622.             default:        /* handles other literals */
  623.                 /* Not a procedure, reinterpret it. */
  624.                 store_state_short(iesp);
  625.                 icount = 0;
  626.                 iref = pvalue;
  627.                 goto top;
  628.                }
  629.            }
  630.         /* default can't happen here */
  631.            }
  632.        }
  633.     /* Literal type, just push it. */
  634.     if ( iosp >= ostop ) return_with_error (e_stackoverflow, iref);
  635.     ++iosp;
  636.     ref_assign(iosp, iref);
  637. bot:    next();
  638. out:    /* At most 1 more token in the current procedure. */
  639.     /* (We already decremented icount.) */
  640.     if ( !icount )
  641.        {    /* Pop the execution stack for tail recursion. */
  642.         iesp--;
  643.         iref++;
  644.         goto top;
  645.        }
  646. up:    /* See if there is anything left on the execution stack. */
  647.     switch ( r_type_xe(iesp) )
  648.        {
  649.     default:
  650.         iref = iesp--;
  651.         icount = 0;
  652.         goto top;
  653.     case exec(t_array):
  654.     case exec(t_mixedarray):
  655.     case exec(t_shortarray): ;
  656.        }
  657.     iref = iesp->value.refs;        /* next element of array */
  658.     icount = r_size(iesp) - 1;
  659.     if ( icount <= 0 )        /* <= 1 more elements */
  660.        {    iesp--;            /* pop, or tail recursion */
  661.         if ( icount < 0 ) goto up;
  662.        }
  663.     goto top;
  664. }
  665.