/* psmlib.psm -- utilites for writing PostScript code with the help of
*   cpp, the C preprocessor
* compiled by [email protected] at Fri Sep 20 23:38:32 CEST 2002
*/

#if USE_A85D
#else
 #if USE_HEXD
 #else
   #define USE_BINARY 1
 #endif
#endif

#if USE_INDEXED2
 #define USE_PALETTE 1
#else
 #if USE_TRANSPARENT8
   #define USE_PALETTE 1
 #endif
#endif

#if USE_NO_BIND
 #define BIND_DEF def
#else
 #define BIND_DEF bind def
#endif


#if NDEBUG
 #define DEBUG(msg)
 #define ASSERT_TRUE_POP(str) pop
 #define ASSERT_FALSE_POP(str) pop
 #define ASSERT_TRUE(what,str)
 #define ASSERT_INT()
 #define INT_EQ eq
 #define INT_NE ne
 #define INT_LE le
 #define INT_GT gt
 #define INT_LT lt
 #define BOOL_BIN(op,message) op
 #define INT_BIN(op,message) op
 #define DEBUGFORCE(msg)
 #define ASSERT_STACK(list,message)
#else
 /-str /stringtype def
 /-aryb /stringtype def % byte array
 /-ary /arraytype def
 /-int /integertype def
 /-bool /booleantype def
 /-dict /dicttype def
 /handleerror.orig /handleerror load def
 /handleerror {
   (%stderr) (w) file
   dup (!!!Fatal: GS error: ) writestring
   dup $error /errorname get write==only
   dup ( in ) writestring
   dup $error /command get write==only
   dup ( at ) writestring
   dup $error /position get write==only
   dup (.\n) writestring
   flushfile flush
   handleerror.orig
   quit
 }bind def
 #define ASSERT_TRUE_POP(str) not{ str InternalError }if
 #define ASSERT_FALSE_POP(str) { str InternalError }if
 #define ASSERT_TRUE(what,str) what not{ str InternalError }if
 #define ASSERT_INT(str) dup type/integertype ne{str InternalError}if
 #define ASSERT_BOOL(str) dup type/booleantype ne{str InternalError}if
 /DumpStack { % - DumpStack -
   (Stack: ) print % from bottom to top
   count 1 sub -1 0{
     index
     dup type /stringtype eq {pop ()}if
     ===only
     ( ) print
   } for
   (.\n) print
 }bind def

 /TypeStack { % <list> TypeStack <bool>
   dup length count 2 sub eq {
     true exch count 2 add 1 index length 1 sub 0 exch 1 exch
     % Stack: ... true ary count(...)+5 0 1 ary.length-1
     {
       % Stack: ... true ary count* i
       2 index exch get 2 copy exch
       % Stack: ... true ary count* ary[i] ary[i] count*
       index type
       % Stack: ... true ary count* ary[i] ary[i] stackitem.type
       ne{
         pop pop pop pop
         % Stack: ...
         false 0 0
         exit
       }if
       pop 1 sub
       % Stack: ... true ary count*-1
     } for
     % Stack: ... true|false ary count*
     pop pop
   }{
     pop false
   }ifelse
   ASSERT_BOOL((TypeStack-bool))
 }bind def
 /InternalError { % <str> FatalError -
   (%stderr) (w) file dup dup
     (Internal muZCat Error: ) writestring
     2 index writestring
     dup (.\n) writestring
     flushfile
     pop
   quit
 }bind def
 /Stderr (%stderr) (w) file def
 #ifdef DEBUGMSG
   #define DEBUG(msg) msg Stderr exch writestring Stderr flushfile
 #else
   #define DEBUG(msg)
 #endif
 #define DEBUGFORCE(msg) msg Stderr exch writestring Stderr flushfile
 #define INT_EQ ASSERT_INT((eq2int)) exch ASSERT_INT((eq1int)) exch eq
 #define INT_NE ASSERT_INT((ne2int)) exch ASSERT_INT((ne1int)) exch ne
 #define INT_LE ASSERT_INT((le2int)) exch ASSERT_INT((le1int)) exch le
 #define INT_GT ASSERT_INT((gt2int)) exch ASSERT_INT((gt1int)) exch gt
 #define INT_LT ASSERT_INT((lt2int)) exch ASSERT_INT((lt1int)) exch lt
 #define BOOL_BIN(op,message) ASSERT_BOOL(message) exch ASSERT_BOOL(message) exch op
 #define INT_BIN(op,message)   ASSERT_INT(message) exch  ASSERT_INT(message) exch op
 #define ASSERT_STACK(list,message) TYPE_STACK(list) not{ DumpStack (assert stack: ) message concatstrings InternalError }if
 #define TYPE_STACK(list) [ list ] TypeStack
#endif

/* at Sat Sep 21 19:07:59 CEST 2002 */
#if USE_DEBUG2
 #define DEBUG2(x) x
#else
 #define DEBUG2(x)
#endif

/* revised, A85D/read_eod at Sun Sep 22 00:27:13 CEST 2002 */
/* Sample usage:
* { TE_read(===)  % action to do with normal char
*   #if !USE_NO_EOF
*   { TE_read_pop exit } ifelse  % action to do on EOF
*   #endif
* } loop
*/
#if USE_A85D
 #define TE_read_eod a85_getc ASSERT_TRUE(dup 511 eq,(EOD expected)) pop
 #define TE_init /xS 32 def  /xD 0 def  /xC 0 def
 #if USE_NO_EOF
   #define TE_read(true_action) a85_getc true_action
   #define PSM_A85_GETC \
     {27 xS ge{exit}if STDIN read pop \
     dup 122 eq{/xS 27 def/xD 0 def/xC 0 def}{dup 117 gt{ \
     STDIN read{pop}if/xS 54 xS sub def}{dup 33 ge{xS 32 eq{dup/xC exch def/xD -1670420001 def}{dup 117 sub{1 85 \
     7225 614125}xS 28 sub get mul xD add/xD exch def}ifelse/xS xS 1 sub def}if}ifelse}ifelse pop}loop xS 22 eq{511}{xC \
     1868977 mul xD add xS 24 and neg bitshift 23 xS lt{xC 3 mul add}if 255 and/xS xS 3 eq{32}{xS 7 mod 3 \
     eq{22}{xS 8 sub}ifelse}ifelse def}ifelse
   /** TE_readstring(str) <substr> */
   #define TE_readstring(str) dup length 1 sub 0 exch 1 exch{a85_getc 3 copy put pop pop}for
 #else
   #define TE_read(true_action) a85_getc dup 256 INT_LT { true_action }
   #define TE_read_pop pop
   /* #define TE_read_eod TE_read() { ASSERT_TRUE(false,(EOD expected)) } ifelse */
   #define PSM_A85_GETC \
     {27 xS ge{exit}if STDIN read not{511}if \
     dup 122 eq{/xS 27 def/xD 0 def/xC 0 def}{dup 117 gt{ \
     STDIN read{pop}if/xS 54 xS sub def}{dup 33 ge{xS 32 eq{dup/xC exch def/xD -1670420001 def}{dup 117 sub{1 85 \
     7225 614125}xS 28 sub get mul xD add/xD exch def}ifelse/xS xS 1 sub def}if}ifelse}ifelse pop}loop xS 22 eq{511}{xC \
     1868977 mul xD add xS 24 and neg bitshift 23 xS lt{xC 3 mul add}if 255 and/xS xS 3 eq{32}{xS 7 mod 3 \
     eq{22}{xS 8 sub}ifelse}ifelse def}ifelse
 #endif
#endif
#if USE_HEXD
 #define TE_init
 #if USE_NO_EOF
   #define TE_read(true_action) STDIN C readhexstring pop 0 get true_action
   #define TE_read_eod STDIN read pop pop /* read '>' */
   #define TE_readstring(str) STDIN str readhexstring pop
 #else
   #error PostScript op readhexstring cannot detect EOD!
   #define TE_read(true_action) STDIN C readhexstring { 0 get true_action }
   #define TE_read_pop
   #define TE_read_eod
 #endif
#endif
#if USE_BINARY
 #define TE_init
 #define TE_read_eod
 #if USE_NO_EOF
   #define TE_read(true_action) STDIN read pop true_action
   #define TE_readstring(str) STDIN str readstring pop
 #else
   #define TE_read(true_action) STDIN read { true_action }
   #define TE_read_pop
 #endif
#endif