home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / program / gs300sr1 / gs300sr1.exe / ESTACK.H < prev    next >
C/C++ Source or Header  |  1994-07-27  |  6KB  |  133 lines

  1. /* Copyright (C) 1989, 1992, 1993, 1994 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* estack.h */
  20. /* Definitions for the execution stack */
  21. #include "istack.h"
  22.  
  23. /* Define the execution stack pointers. */
  24. typedef s_ptr es_ptr;
  25. typedef const_s_ptr const_es_ptr;
  26. extern ref_stack e_stack;
  27. #define esbot (e_stack.bot)
  28. #define esp (e_stack.p)
  29. #define estop (e_stack.top)
  30.  
  31. /*
  32.  * To improve performance, we cache the currentfile pointer
  33.  * (i.e., `shallow-bind' it in Lisp terminology).  The invariant is as
  34.  * follows: either esfile points to the currentfile slot on the estack
  35.  * (i.e., the topmost slot with an executable file), or it is 0.
  36.  * To maintain the invariant, it is sufficient that whenever a routine
  37.  * pushes or pops anything on the estack, if the object *might* be
  38.  * an executable file, invoke esfile_clear_cache(); alternatively,
  39.  * immediately after pushing an object, invoke esfile_check_cache().
  40.  */
  41. extern ref *esfile;
  42. #define esfile_clear_cache() (esfile = 0)
  43. #define esfile_set_cache(pref) (esfile = (pref))
  44. #define esfile_check_cache()\
  45.   if ( r_has_type_attrs(esp, t_file, a_executable) )\
  46.     esfile_set_cache(esp)
  47.  
  48. /*
  49.  * The execution stack is used for three purposes:
  50.  *
  51.  *    - Procedures being executed are held here.  They always have
  52.  * type = t_array, t_mixedarray, or t_shortarray, with a_executable set.
  53.  * More specifically, the e-stack holds the as yet unexecuted tail of the
  54.  * procedure.
  55.  *
  56.  *    - if, ifelse, etc. push arguments to be executed here.
  57.  * They may be any kind of object whatever.
  58.  *
  59.  *    - Control operators (filenameforall, for, repeat, loop, forall,
  60.  * pathforall, run, stopped, ...) mark the stack by pushing
  61.  * an object with type = t_null, attrs = a_executable, size = es_xxx
  62.  * (see below), and value.opproc = a cleanup procedure that will get called
  63.  * whenever the execution stack is about to get cut back beyond this point
  64.  * (either for normal completion of the operator, or any kind of exit).
  65.  * (Executable null objects can't ever appear on the e-stack otherwise:
  66.  * if a control operator pushes one, it gets popped immediately.)
  67.  * The cleanup procedure is called with esp pointing just BELOW the mark,
  68.  * i.e., the mark has already been popped.
  69.  *
  70.  * The loop operators also push whatever state they need,
  71.  * followed by an operator object that handles continuing the loop.
  72.  *
  73.  * Note that there are many internal looping operators -- for example,
  74.  * all the 'show' operators can behave like loops, since they may call out
  75.  * to BuildChar procedures.
  76.  */
  77.  
  78. /* Macro for marking the execution stack */
  79. #define make_mark_estack(ep, es_idx, proc)\
  80.   make_tasv(ep, t_null, a_executable, es_idx, opproc, proc)
  81. #define push_mark_estack(es_idx, proc)\
  82.   (++esp, make_mark_estack(esp, es_idx, proc))
  83. #define r_is_estack_mark(ep)\
  84.   r_has_type_attrs(ep, t_null, a_executable)
  85. #define estack_mark_index(ep) r_size(ep)
  86.  
  87. /* Macro for pushing an operator on the execution stack */
  88. /* to represent a continuation procedure */
  89. #define make_op_estack(ep, proc)\
  90.   make_oper(ep, 0, proc)
  91. #define push_op_estack(proc)\
  92.   (++esp, make_op_estack(esp, proc))
  93.  
  94. /* Macro to ensure enough room on the execution stack */
  95. #define check_estack(n)\
  96.   if ( esp > estop - (n) )\
  97.     { int es_code_ = ref_stack_extend(&e_stack, n);\
  98.       if ( es_code_ < 0 ) return es_code_;\
  99.     }
  100.  
  101. /* Macro to ensure enough entries on the execution stack */
  102. #define check_esp(n)\
  103.   if ( esp < esbot + ((n) - 1) )\
  104.     { e_stack.requested = (n); return_error(e_ExecStackUnderflow); }
  105.  
  106. /* Define the various kinds of execution stack marks. */
  107. #define es_other 0            /* internal use */
  108. #define es_show 1            /* show operators */
  109. #define es_for 2            /* iteration operators */
  110. #define es_stopped 3            /* stopped operator */
  111.  
  112. /* Pop a given number of elements off the execution stack, */
  113. /* executing cleanup procedures as necessary. */
  114. void    pop_estack(P1(uint));
  115.  
  116. /*
  117.  * The execution stack is implemented as a linked list of blocks;
  118.  * operators that can push or pop an unbounded number of values, or that
  119.  * access the entire o-stack, must take this into account.  These are:
  120.  *    exit  .stop  .instopped  countexecstack  execstack  currentfile
  121.  *    pop_estack(exit, stop, error recovery)
  122.  *    gs_show_find(all the show operators)
  123.  * In addition, for e-stack entries created by control operators, we must
  124.  * ensure that the mark and its data are never separated.  We do this
  125.  * by ensuring that when splitting the top block, at least N items
  126.  * are kept in the new top block above the bottommost retained mark,
  127.  * where N is the largest number of data items associated with a mark.
  128.  * Finally, in order to avoid specific checks for underflowing a block,
  129.  * we put a guard entry at the bottom of each block except the top one
  130.  * that contains a procedure that returns an internal "exec stack block
  131.  * underflow" error.
  132.  */
  133.