LCOV - code coverage report
Current view: top level - tests/gpgscm - scheme.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1733 2573 67.4 %
Date: 2016-11-29 15:00:56 Functions: 158 194 81.4 %

          Line data    Source code
       1             : /* T I N Y S C H E M E    1 . 4 1
       2             :  *   Dimitrios Souflis (dsouflis@acm.org)
       3             :  *   Based on MiniScheme (original credits follow)
       4             :  * (MINISCM)               coded by Atsushi Moriwaki (11/5/1989)
       5             :  * (MINISCM)           E-MAIL :  moriwaki@kurims.kurims.kyoto-u.ac.jp
       6             :  * (MINISCM) This version has been modified by R.C. Secrist.
       7             :  * (MINISCM)
       8             :  * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
       9             :  * (MINISCM)
      10             :  * (MINISCM) This is a revised and modified version by Akira KIDA.
      11             :  * (MINISCM)    current version is 0.85k4 (15 May 1994)
      12             :  *
      13             :  */
      14             : 
      15             : #define _SCHEME_SOURCE
      16             : #include "scheme-private.h"
      17             : #ifndef WIN32
      18             : # include <unistd.h>
      19             : #endif
      20             : #ifdef WIN32
      21             : #define snprintf _snprintf
      22             : #endif
      23             : #if USE_DL
      24             : # include "dynload.h"
      25             : #endif
      26             : #if USE_MATH
      27             : # include <math.h>
      28             : #endif
      29             : 
      30             : #include <assert.h>
      31             : #include <limits.h>
      32             : #include <stdint.h>
      33             : #include <float.h>
      34             : #include <ctype.h>
      35             : 
      36             : #if USE_STRCASECMP
      37             : #include <strings.h>
      38             : # ifndef __APPLE__
      39             : #  define stricmp strcasecmp
      40             : # endif
      41             : #endif
      42             : 
      43             : /* Used for documentation purposes, to signal functions in 'interface' */
      44             : #define INTERFACE
      45             : 
      46             : #define TOK_EOF     (-1)
      47             : #define TOK_LPAREN  0
      48             : #define TOK_RPAREN  1
      49             : #define TOK_DOT     2
      50             : #define TOK_ATOM    3
      51             : #define TOK_QUOTE   4
      52             : #define TOK_COMMENT 5
      53             : #define TOK_DQUOTE  6
      54             : #define TOK_BQUOTE  7
      55             : #define TOK_COMMA   8
      56             : #define TOK_ATMARK  9
      57             : #define TOK_SHARP   10
      58             : #define TOK_SHARP_CONST 11
      59             : #define TOK_VEC     12
      60             : 
      61             : #define BACKQUOTE '`'
      62             : #define DELIMITERS  "()\";\f\t\v\n\r "
      63             : 
      64             : /*
      65             :  *  Basic memory allocation units
      66             :  */
      67             : 
      68             : #define banner "TinyScheme 1.41"
      69             : 
      70             : #include <string.h>
      71             : #include <stddef.h>
      72             : #include <stdlib.h>
      73             : 
      74             : #ifdef __APPLE__
      75             : static int stricmp(const char *s1, const char *s2)
      76             : {
      77             :   unsigned char c1, c2;
      78             :   do {
      79             :     c1 = tolower(*s1);
      80             :     c2 = tolower(*s2);
      81             :     if (c1 < c2)
      82             :       return -1;
      83             :     else if (c1 > c2)
      84             :       return 1;
      85             :     s1++, s2++;
      86             :   } while (c1 != 0);
      87             :   return 0;
      88             : }
      89             : #endif /* __APPLE__ */
      90             : 
      91             : #if USE_STRLWR
      92      246272 : static const char *strlwr(char *s) {
      93      246272 :   const char *p=s;
      94     1858434 :   while(*s) {
      95     1365890 :     *s=tolower(*s);
      96     1365890 :     s++;
      97             :   }
      98      246272 :   return p;
      99             : }
     100             : #endif
     101             : 
     102             : #ifndef prompt
     103             : # define prompt "ts> "
     104             : #endif
     105             : 
     106             : #ifndef InitFile
     107             : # define InitFile "init.scm"
     108             : #endif
     109             : 
     110             : #ifndef FIRST_CELLSEGS
     111             : # define FIRST_CELLSEGS 3
     112             : #endif
     113             : 
     114             : enum scheme_types {
     115             :   T_STRING=1,
     116             :   T_NUMBER=2,
     117             :   T_SYMBOL=3,
     118             :   T_PROC=4,
     119             :   T_PAIR=5,
     120             :   T_CLOSURE=6,
     121             :   T_CONTINUATION=7,
     122             :   T_FOREIGN=8,
     123             :   T_CHARACTER=9,
     124             :   T_PORT=10,
     125             :   T_VECTOR=11,
     126             :   T_MACRO=12,
     127             :   T_PROMISE=13,
     128             :   T_ENVIRONMENT=14,
     129             :   T_FOREIGN_OBJECT=15,
     130             :   T_BOOLEAN=16,
     131             :   T_NIL=17,
     132             :   T_EOF_OBJ=18,
     133             :   T_SINK=19,
     134             :   T_LAST_SYSTEM_TYPE=19
     135             : };
     136             : 
     137             : static const char *
     138           2 : type_to_string (enum scheme_types typ)
     139             : {
     140           2 :      switch (typ)
     141             :      {
     142           2 :      case T_STRING: return "string";
     143           0 :      case T_NUMBER: return "number";
     144           0 :      case T_SYMBOL: return "symbol";
     145           0 :      case T_PROC: return "proc";
     146           0 :      case T_PAIR: return "pair";
     147           0 :      case T_CLOSURE: return "closure";
     148           0 :      case T_CONTINUATION: return "continuation";
     149           0 :      case T_FOREIGN: return "foreign";
     150           0 :      case T_CHARACTER: return "character";
     151           0 :      case T_PORT: return "port";
     152           0 :      case T_VECTOR: return "vector";
     153           0 :      case T_MACRO: return "macro";
     154           0 :      case T_PROMISE: return "promise";
     155           0 :      case T_ENVIRONMENT: return "environment";
     156           0 :      case T_FOREIGN_OBJECT: return "foreign object";
     157           0 :      case T_BOOLEAN: return "boolean";
     158           0 :      case T_NIL: return "nil";
     159           0 :      case T_EOF_OBJ: return "eof object";
     160           0 :      case T_SINK: return "sink";
     161             :      }
     162           0 :      assert (! "not reached");
     163             : }
     164             : 
     165             : /* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
     166             : #define ADJ 32
     167             : #define TYPE_BITS 5
     168             : #define T_MASKTYPE      31    /* 0000000000011111 */
     169             : #define T_FINALIZE    2048    /* 0000100000000000 */
     170             : #define T_SYNTAX      4096    /* 0001000000000000 */
     171             : #define T_IMMUTABLE   8192    /* 0010000000000000 */
     172             : #define T_ATOM       16384    /* 0100000000000000 */   /* only for gc */
     173             : #define CLRATOM      49151    /* 1011111111111111 */   /* only for gc */
     174             : #define MARK         32768    /* 1000000000000000 */
     175             : #define UNMARK       32767    /* 0111111111111111 */
     176             : 
     177             : 
     178             : static num num_add(num a, num b);
     179             : static num num_mul(num a, num b);
     180             : static num num_div(num a, num b);
     181             : static num num_intdiv(num a, num b);
     182             : static num num_sub(num a, num b);
     183             : static num num_rem(num a, num b);
     184             : static num num_mod(num a, num b);
     185             : static int num_eq(num a, num b);
     186             : static int num_gt(num a, num b);
     187             : static int num_ge(num a, num b);
     188             : static int num_lt(num a, num b);
     189             : static int num_le(num a, num b);
     190             : 
     191             : #if USE_MATH
     192             : static double round_per_R5RS(double x);
     193             : #endif
     194             : static int is_zero_double(double x);
     195    26552614 : static INLINE int num_is_integer(pointer p) {
     196    26552614 :   return ((p)->_object._number.is_fixnum);
     197             : }
     198             : 
     199             : static num num_zero;
     200             : static num num_one;
     201             : 
     202             : /* macros for cell operations */
     203             : #define typeflag(p)      ((p)->_flag)
     204             : #define type(p)          (typeflag(p)&T_MASKTYPE)
     205             : 
     206      649916 : INTERFACE INLINE int is_string(pointer p)     { return (type(p)==T_STRING); }
     207             : #define strvalue(p)      ((p)->_object._string._svalue)
     208             : #define strlength(p)        ((p)->_object._string._length)
     209             : 
     210             : INTERFACE static int is_list(scheme *sc, pointer p);
     211   145116115 : INTERFACE INLINE int is_vector(pointer p)    { return (type(p)==T_VECTOR); }
     212             : INTERFACE static void fill_vector(pointer vec, pointer obj);
     213             : INTERFACE static pointer vector_elem(pointer vec, int ielem);
     214             : INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
     215     1209996 : INTERFACE INLINE int is_number(pointer p)    { return (type(p)==T_NUMBER); }
     216       71125 : INTERFACE INLINE int is_integer(pointer p) {
     217       71125 :   if (!is_number(p))
     218           0 :       return 0;
     219       71125 :   if (num_is_integer(p) || (double)ivalue(p) == rvalue(p))
     220       71125 :       return 1;
     221           0 :   return 0;
     222             : }
     223             : 
     224           0 : INTERFACE INLINE int is_real(pointer p) {
     225           0 :   return is_number(p) && (!(p)->_object._number.is_fixnum);
     226             : }
     227             : 
     228      255423 : INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
     229       35712 : INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
     230     1090711 : INLINE num nvalue(pointer p)       { return ((p)->_object._number); }
     231    26481021 : INTERFACE long ivalue(pointer p)      { return (num_is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
     232           0 : INTERFACE double rvalue(pointer p)    { return (!num_is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
     233             : #define ivalue_unchecked(p)       ((p)->_object._number.value.ivalue)
     234             : #define rvalue_unchecked(p)       ((p)->_object._number.value.rvalue)
     235             : #define set_num_integer(p)   (p)->_object._number.is_fixnum=1;
     236             : #define set_num_real(p)      (p)->_object._number.is_fixnum=0;
     237       55786 : INTERFACE  long charvalue(pointer p)  { return ivalue_unchecked(p); }
     238             : 
     239      391901 : INTERFACE INLINE int is_port(pointer p)     { return (type(p)==T_PORT); }
     240      141046 : INTERFACE INLINE int is_inport(pointer p)  { return is_port(p) && p->_object._port->kind & port_input; }
     241       71967 : INTERFACE INLINE int is_outport(pointer p) { return is_port(p) && p->_object._port->kind & port_output; }
     242             : 
     243    44363311 : INTERFACE INLINE int is_pair(pointer p)     { return (type(p)==T_PAIR); }
     244             : #define car(p)           ((p)->_object._cons._car)
     245             : #define cdr(p)           ((p)->_object._cons._cdr)
     246      213270 : INTERFACE pointer pair_car(pointer p)   { return car(p); }
     247      103054 : INTERFACE pointer pair_cdr(pointer p)   { return cdr(p); }
     248           0 : INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
     249           0 : INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
     250             : 
     251    23943618 : INTERFACE INLINE int is_symbol(pointer p)   { return (type(p)==T_SYMBOL); }
     252     6979384 : INTERFACE INLINE char *symname(pointer p)   { return strvalue(car(p)); }
     253             : #if USE_PLIST
     254             : SCHEME_EXPORT INLINE int hasprop(pointer p)     { return (is_symbol(p)); }
     255             : #define symprop(p)       cdr(p)
     256             : #endif
     257             : 
     258     9798472 : INTERFACE INLINE int is_syntax(pointer p)   { return (typeflag(p)&T_SYNTAX); }
     259     7149187 : INTERFACE INLINE int is_proc(pointer p)     { return (type(p)==T_PROC); }
     260     1562046 : INTERFACE INLINE int is_foreign(pointer p)  { return (type(p)==T_FOREIGN); }
     261           0 : INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
     262             : #define procnum(p)       ivalue(p)
     263             : static const char *procname(pointer x);
     264             : 
     265     1511732 : INTERFACE INLINE int is_closure(pointer p)  { return (type(p)==T_CLOSURE); }
     266     6748617 : INTERFACE INLINE int is_macro(pointer p)    { return (type(p)==T_MACRO); }
     267     2767060 : INTERFACE INLINE pointer closure_code(pointer p)   { return car(p); }
     268     1383530 : INTERFACE INLINE pointer closure_env(pointer p)    { return cdr(p); }
     269             : 
     270      128202 : INTERFACE INLINE int is_continuation(pointer p)    { return (type(p)==T_CONTINUATION); }
     271             : #define cont_dump(p)     cdr(p)
     272             : 
     273       32856 : INTERFACE INLINE int is_foreign_object(pointer p) { return (type(p)==T_FOREIGN_OBJECT); }
     274       28596 : INTERFACE const foreign_object_vtable *get_foreign_object_vtable(pointer p) {
     275       28596 :   return p->_object._foreign_object._vtable;
     276             : }
     277       28596 : INTERFACE void *get_foreign_object_data(pointer p) {
     278       28596 :   return p->_object._foreign_object._data;
     279             : }
     280             : 
     281             : /* To do: promise should be forced ONCE only */
     282         232 : INTERFACE INLINE int is_promise(pointer p)  { return (type(p)==T_PROMISE); }
     283             : 
     284       41978 : INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
     285             : #define setenvironment(p)    typeflag(p) = T_ENVIRONMENT
     286             : 
     287             : #define is_atom(p)       (typeflag(p)&T_ATOM)
     288             : #define setatom(p)       typeflag(p) |= T_ATOM
     289             : #define clratom(p)       typeflag(p) &= CLRATOM
     290             : 
     291             : #define is_mark(p)       (typeflag(p)&MARK)
     292             : #define setmark(p)       typeflag(p) |= MARK
     293             : #define clrmark(p)       typeflag(p) &= UNMARK
     294             : 
     295       62709 : INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
     296             : /*#define setimmutable(p)  typeflag(p) |= T_IMMUTABLE*/
     297     6956458 : INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
     298             : 
     299             : #define caar(p)          car(car(p))
     300             : #define cadr(p)          car(cdr(p))
     301             : #define cdar(p)          cdr(car(p))
     302             : #define cddr(p)          cdr(cdr(p))
     303             : #define cadar(p)         car(cdr(car(p)))
     304             : #define caddr(p)         car(cdr(cdr(p)))
     305             : #define cdaar(p)         cdr(car(car(p)))
     306             : #define cadaar(p)        car(cdr(car(car(p))))
     307             : #define cadddr(p)        car(cdr(cdr(cdr(p))))
     308             : #define cddddr(p)        cdr(cdr(cdr(cdr(p))))
     309             : 
     310             : #if USE_CHAR_CLASSIFIERS
     311           0 : static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); }
     312           0 : static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); }
     313         617 : static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); }
     314           0 : static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); }
     315           0 : static INLINE int Cislower(int c) { return isascii(c) && islower(c); }
     316             : #endif
     317             : 
     318             : #if USE_ASCII_NAMES
     319             : static const char *charnames[32]={
     320             :  "nul",
     321             :  "soh",
     322             :  "stx",
     323             :  "etx",
     324             :  "eot",
     325             :  "enq",
     326             :  "ack",
     327             :  "bel",
     328             :  "bs",
     329             :  "ht",
     330             :  "lf",
     331             :  "vt",
     332             :  "ff",
     333             :  "cr",
     334             :  "so",
     335             :  "si",
     336             :  "dle",
     337             :  "dc1",
     338             :  "dc2",
     339             :  "dc3",
     340             :  "dc4",
     341             :  "nak",
     342             :  "syn",
     343             :  "etb",
     344             :  "can",
     345             :  "em",
     346             :  "sub",
     347             :  "esc",
     348             :  "fs",
     349             :  "gs",
     350             :  "rs",
     351             :  "us"
     352             : };
     353             : 
     354        1158 : static int is_ascii_name(const char *name, int *pc) {
     355             :   int i;
     356       38214 :   for(i=0; i<32; i++) {
     357       37056 :      if(stricmp(name,charnames[i])==0) {
     358           0 :           *pc=i;
     359           0 :           return 1;
     360             :      }
     361             :   }
     362        1158 :   if(stricmp(name,"del")==0) {
     363           0 :      *pc=127;
     364           0 :      return 1;
     365             :   }
     366        1158 :   return 0;
     367             : }
     368             : 
     369             : #endif
     370             : 
     371             : static int file_push(scheme *sc, const char *fname);
     372             : static void file_pop(scheme *sc);
     373             : static int file_interactive(scheme *sc);
     374             : static INLINE int is_one_of(char *s, int c);
     375             : static int alloc_cellseg(scheme *sc, int n);
     376             : static long binary_decode(const char *s);
     377             : static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
     378             : static pointer _get_cell(scheme *sc, pointer a, pointer b);
     379             : static pointer reserve_cells(scheme *sc, int n);
     380             : static pointer get_consecutive_cells(scheme *sc, int n);
     381             : static pointer find_consecutive_cells(scheme *sc, int n);
     382             : static void finalize_cell(scheme *sc, pointer a);
     383             : static int count_consecutive_cells(pointer x, int needed);
     384             : static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
     385             : static pointer mk_number(scheme *sc, num n);
     386             : static char *store_string(scheme *sc, int len, const char *str, char fill);
     387             : static pointer mk_vector(scheme *sc, int len);
     388             : static pointer mk_atom(scheme *sc, char *q);
     389             : static pointer mk_sharp_const(scheme *sc, char *name);
     390             : static pointer mk_port(scheme *sc, port *p);
     391             : static pointer port_from_filename(scheme *sc, const char *fn, int prop);
     392             : static pointer port_from_file(scheme *sc, FILE *, int prop);
     393             : static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
     394             : static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
     395             : static port *port_rep_from_file(scheme *sc, FILE *, int prop);
     396             : static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
     397             : static void port_close(scheme *sc, pointer p, int flag);
     398             : static void mark(pointer a);
     399             : static void gc(scheme *sc, pointer a, pointer b);
     400             : static int basic_inchar(port *pt);
     401             : static int inchar(scheme *sc);
     402             : static void backchar(scheme *sc, int c);
     403             : static char   *readstr_upto(scheme *sc, char *delim);
     404             : static pointer readstrexp(scheme *sc);
     405             : static INLINE int skipspace(scheme *sc);
     406             : static int token(scheme *sc);
     407             : static void printslashstring(scheme *sc, char *s, int len);
     408             : static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen);
     409             : static void printatom(scheme *sc, pointer l, int f);
     410             : static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
     411             : static pointer mk_closure(scheme *sc, pointer c, pointer e);
     412             : static pointer mk_continuation(scheme *sc, pointer d);
     413             : static pointer reverse(scheme *sc, pointer term, pointer list);
     414             : static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
     415             : static pointer revappend(scheme *sc, pointer a, pointer b);
     416             : static void dump_stack_mark(scheme *);
     417             : static pointer opexe_0(scheme *sc, enum scheme_opcodes op);
     418             : static pointer opexe_1(scheme *sc, enum scheme_opcodes op);
     419             : static pointer opexe_2(scheme *sc, enum scheme_opcodes op);
     420             : static pointer opexe_3(scheme *sc, enum scheme_opcodes op);
     421             : static pointer opexe_4(scheme *sc, enum scheme_opcodes op);
     422             : static pointer opexe_5(scheme *sc, enum scheme_opcodes op);
     423             : static pointer opexe_6(scheme *sc, enum scheme_opcodes op);
     424             : static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
     425             : static void assign_syntax(scheme *sc, char *name);
     426             : static int syntaxnum(pointer p);
     427             : static void assign_proc(scheme *sc, enum scheme_opcodes, char *name);
     428             : 
     429             : #define num_ivalue(n)       (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
     430             : #define num_rvalue(n)       (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
     431             : 
     432       59362 : static num num_add(num a, num b) {
     433             :  num ret;
     434       59362 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum;
     435       59362 :  if(ret.is_fixnum) {
     436       59362 :      ret.value.ivalue= a.value.ivalue+b.value.ivalue;
     437             :  } else {
     438           0 :      ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
     439             :  }
     440       59362 :  return ret;
     441             : }
     442             : 
     443           0 : static num num_mul(num a, num b) {
     444             :  num ret;
     445           0 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum;
     446           0 :  if(ret.is_fixnum) {
     447           0 :      ret.value.ivalue= a.value.ivalue*b.value.ivalue;
     448             :  } else {
     449           0 :      ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
     450             :  }
     451           0 :  return ret;
     452             : }
     453             : 
     454           0 : static num num_div(num a, num b) {
     455             :  num ret;
     456           0 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
     457           0 :  if(ret.is_fixnum) {
     458           0 :      ret.value.ivalue= a.value.ivalue/b.value.ivalue;
     459             :  } else {
     460           0 :      ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
     461             :  }
     462           0 :  return ret;
     463             : }
     464             : 
     465           0 : static num num_intdiv(num a, num b) {
     466             :  num ret;
     467           0 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum;
     468           0 :  if(ret.is_fixnum) {
     469           0 :      ret.value.ivalue= a.value.ivalue/b.value.ivalue;
     470             :  } else {
     471           0 :      ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
     472             :  }
     473           0 :  return ret;
     474             : }
     475             : 
     476       14675 : static num num_sub(num a, num b) {
     477             :  num ret;
     478       14675 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum;
     479       14675 :  if(ret.is_fixnum) {
     480       14675 :      ret.value.ivalue= a.value.ivalue-b.value.ivalue;
     481             :  } else {
     482           0 :      ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
     483             :  }
     484       14675 :  return ret;
     485             : }
     486             : 
     487           0 : static num num_rem(num a, num b) {
     488             :  num ret;
     489             :  long e1, e2, res;
     490           0 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum;
     491           0 :  e1=num_ivalue(a);
     492           0 :  e2=num_ivalue(b);
     493           0 :  res=e1%e2;
     494             :  /* remainder should have same sign as second operand */
     495           0 :  if (res > 0) {
     496           0 :      if (e1 < 0) {
     497           0 :         res -= labs(e2);
     498             :      }
     499           0 :  } else if (res < 0) {
     500           0 :      if (e1 > 0) {
     501           0 :          res += labs(e2);
     502             :      }
     503             :  }
     504           0 :  ret.value.ivalue=res;
     505           0 :  return ret;
     506             : }
     507             : 
     508           0 : static num num_mod(num a, num b) {
     509             :  num ret;
     510             :  long e1, e2, res;
     511           0 :  ret.is_fixnum=a.is_fixnum && b.is_fixnum;
     512           0 :  e1=num_ivalue(a);
     513           0 :  e2=num_ivalue(b);
     514           0 :  res=e1%e2;
     515             :  /* modulo should have same sign as second operand */
     516           0 :  if (res * e2 < 0) {
     517           0 :     res += e2;
     518             :  }
     519           0 :  ret.value.ivalue=res;
     520           0 :  return ret;
     521             : }
     522             : 
     523      340278 : static int num_eq(num a, num b) {
     524             :  int ret;
     525      340278 :  int is_fixnum=a.is_fixnum && b.is_fixnum;
     526      340278 :  if(is_fixnum) {
     527      340278 :      ret= a.value.ivalue==b.value.ivalue;
     528             :  } else {
     529           0 :      ret=num_rvalue(a)==num_rvalue(b);
     530             :  }
     531      340278 :  return ret;
     532             : }
     533             : 
     534             : 
     535        2265 : static int num_gt(num a, num b) {
     536             :  int ret;
     537        2265 :  int is_fixnum=a.is_fixnum && b.is_fixnum;
     538        2265 :  if(is_fixnum) {
     539        2265 :      ret= a.value.ivalue>b.value.ivalue;
     540             :  } else {
     541           0 :      ret=num_rvalue(a)>num_rvalue(b);
     542             :  }
     543        2265 :  return ret;
     544             : }
     545             : 
     546       12350 : static int num_ge(num a, num b) {
     547       12350 :  return !num_lt(a,b);
     548             : }
     549             : 
     550       12399 : static int num_lt(num a, num b) {
     551             :  int ret;
     552       12399 :  int is_fixnum=a.is_fixnum && b.is_fixnum;
     553       12399 :  if(is_fixnum) {
     554       12399 :      ret= a.value.ivalue<b.value.ivalue;
     555             :  } else {
     556           0 :      ret=num_rvalue(a)<num_rvalue(b);
     557             :  }
     558       12399 :  return ret;
     559             : }
     560             : 
     561           0 : static int num_le(num a, num b) {
     562           0 :  return !num_gt(a,b);
     563             : }
     564             : 
     565             : #if USE_MATH
     566             : /* Round to nearest. Round to even if midway */
     567             : static double round_per_R5RS(double x) {
     568             :  double fl=floor(x);
     569             :  double ce=ceil(x);
     570             :  double dfl=x-fl;
     571             :  double dce=ce-x;
     572             :  if(dfl>dce) {
     573             :      return ce;
     574             :  } else if(dfl<dce) {
     575             :      return fl;
     576             :  } else {
     577             :      if(fmod(fl,2.0)==0.0) {       /* I imagine this holds */
     578             :           return fl;
     579             :      } else {
     580             :           return ce;
     581             :      }
     582             :  }
     583             : }
     584             : #endif
     585             : 
     586           0 : static int is_zero_double(double x) {
     587           0 :  return x<DBL_MIN && x>-DBL_MIN;
     588             : }
     589             : 
     590           0 : static long binary_decode(const char *s) {
     591           0 :  long x=0;
     592             : 
     593           0 :  while(*s!=0 && (*s=='1' || *s=='0')) {
     594           0 :      x<<=1;
     595           0 :      x+=*s-'0';
     596           0 :      s++;
     597             :  }
     598             : 
     599           0 :  return x;
     600             : }
     601             : 
     602             : /* Allocate a new cell segment but do not make it available yet.  */
     603             : static int
     604         205 : _alloc_cellseg(scheme *sc, size_t len, void **alloc, pointer *cells)
     605             : {
     606         205 :   int adj = ADJ;
     607             :   void *cp;
     608             : 
     609         205 :   if (adj < sizeof(struct cell))
     610           0 :     adj = sizeof(struct cell);
     611             : 
     612         205 :   cp = sc->malloc(len * sizeof(struct cell) + adj);
     613         205 :   if (cp == NULL)
     614           0 :     return 1;
     615             : 
     616         205 :   *alloc = cp;
     617             : 
     618             :   /* adjust in TYPE_BITS-bit boundary */
     619         205 :   if (((uintptr_t) cp) % adj != 0)
     620         102 :     cp = (void *) (adj * ((uintptr_t) cp / adj + 1));
     621             : 
     622         205 :   *cells = cp;
     623         205 :   return 0;
     624             : }
     625             : 
     626             : /* allocate new cell segment */
     627          52 : static int alloc_cellseg(scheme *sc, int n) {
     628             :      pointer newp;
     629             :      pointer last;
     630             :      pointer p;
     631             :      long i;
     632             :      int k;
     633             : 
     634         206 :      for (k = 0; k < n; k++) {
     635         154 :          if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
     636           0 :               return k;
     637         154 :          i = ++sc->last_cell_seg;
     638         154 :          if (_alloc_cellseg(sc, CELL_SEGSIZE, &sc->alloc_seg[i], &newp)) {
     639           0 :               sc->last_cell_seg--;
     640           0 :               return k;
     641             :          }
     642             :          /* insert new segment in address order */
     643         154 :          sc->cell_seg[i] = newp;
     644         308 :          while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
     645           0 :              p = sc->cell_seg[i];
     646           0 :              sc->cell_seg[i] = sc->cell_seg[i - 1];
     647           0 :              sc->cell_seg[--i] = p;
     648             :          }
     649         154 :          sc->fcells += CELL_SEGSIZE;
     650         154 :          last = newp + CELL_SEGSIZE - 1;
     651      770154 :          for (p = newp; p <= last; p++) {
     652      770000 :               typeflag(p) = 0;
     653      770000 :               cdr(p) = p + 1;
     654      770000 :               car(p) = sc->NIL;
     655             :          }
     656             :          /* insert new cells in address order on free list */
     657         154 :          if (sc->free_cell == sc->NIL || p < sc->free_cell) {
     658          51 :               cdr(last) = sc->free_cell;
     659          51 :               sc->free_cell = newp;
     660             :          } else {
     661         103 :                p = sc->free_cell;
     662      765105 :                while (cdr(p) != sc->NIL && newp > cdr(p))
     663      764899 :                     p = cdr(p);
     664         103 :                cdr(last) = cdr(p);
     665         103 :                cdr(p) = newp;
     666             :          }
     667             :      }
     668          52 :      return n;
     669             : }
     670             : 
     671             : 
     672             : 
     673             : /* Controlling the garbage collector.
     674             :  *
     675             :  * Every time a cell is allocated, the interpreter may run out of free
     676             :  * cells and do a garbage collection.  This is problematic because it
     677             :  * might garbage collect objects that have been allocated, but are not
     678             :  * yet made available to the interpreter.
     679             :  *
     680             :  * Previously, we would plug such newly allocated cells into the list
     681             :  * of newly allocated objects rooted at car(sc->sink), but that
     682             :  * requires allocating yet another cell increasing pressure on the
     683             :  * memory management system.
     684             :  *
     685             :  * A faster alternative is to preallocate the cells needed for an
     686             :  * operation and make sure the garbage collection is not run until all
     687             :  * allocated objects are plugged in.  This can be done with gc_disable
     688             :  * and gc_enable.
     689             :  */
     690             : 
     691             : /* The garbage collector is enabled if the inhibit counter is
     692             :  * zero.  */
     693             : #define GC_ENABLED      0
     694             : 
     695             : /* For now we provide a way to disable this optimization for
     696             :  * benchmarking and because it produces slightly smaller code.  */
     697             : #ifndef USE_GC_LOCKING
     698             : # define USE_GC_LOCKING 1
     699             : #endif
     700             : 
     701             : /* To facilitate nested calls to gc_disable, functions that allocate
     702             :  * more than one cell may define a macro, e.g. foo_allocates.  This
     703             :  * macro can be used to compute the amount of preallocation at the
     704             :  * call site with the help of this macro.  */
     705             : #define gc_reservations(fn) fn ## _allocates
     706             : 
     707             : #if USE_GC_LOCKING
     708             : 
     709             : /* Report a shortage in reserved cells, and terminate the program.  */
     710             : static void
     711           0 : gc_reservation_failure(struct scheme *sc)
     712             : {
     713             : #ifdef NDEBUG
     714             :   fprintf(stderr,
     715             :           "insufficient reservation\n")
     716             : #else
     717           0 :   fprintf(stderr,
     718             :           "insufficient reservation in line %d\n",
     719             :           sc->reserved_lineno);
     720             : #endif
     721           0 :   abort();
     722             : }
     723             : 
     724             : /* Disable the garbage collection and reserve the given number of
     725             :  * cells.  gc_disable may be nested, but the enclosing reservation
     726             :  * must include the reservations of all nested calls.  Note: You must
     727             :  * re-enable the gc before calling Error_X.  */
     728             : static void
     729    42487120 : _gc_disable(struct scheme *sc, size_t reserve, int lineno)
     730             : {
     731    42487120 :   if (sc->inhibit_gc == 0) {
     732    42199748 :     reserve_cells(sc, (reserve));
     733    42199748 :     sc->reserved_cells = (reserve);
     734             : #ifndef NDEBUG
     735             :     (void) lineno;
     736             : #else
     737             :     sc->reserved_lineno = lineno;
     738             : #endif
     739      287372 :   } else if (sc->reserved_cells < (reserve))
     740           0 :     gc_reservation_failure (sc);
     741    42487120 :   sc->inhibit_gc += 1;
     742    42487120 : }
     743             : #define gc_disable(sc, reserve)                 \
     744             :      _gc_disable (sc, reserve, __LINE__)
     745             : 
     746             : /* Enable the garbage collector.  */
     747             : #define gc_enable(sc)                           \
     748             :      do {                                       \
     749             :           assert(sc->inhibit_gc);            \
     750             :           sc->inhibit_gc -= 1;                       \
     751             :      } while (0)
     752             : 
     753             : /* Test whether the garbage collector is enabled.  */
     754             : #define gc_enabled(sc)                          \
     755             :      (sc->inhibit_gc == GC_ENABLED)
     756             : 
     757             : /* Consume a reserved cell.  */
     758             : #define gc_consume(sc)                                                  \
     759             :      do {                                                               \
     760             :           assert(! gc_enabled (sc));                                    \
     761             :           if (sc->reserved_cells == 0)                                       \
     762             :                gc_reservation_failure (sc);                             \
     763             :           sc->reserved_cells -= 1;                                   \
     764             :      } while (0)
     765             : 
     766             : #else /* USE_GC_LOCKING */
     767             : 
     768             : #define gc_disable(sc, reserve) (void) 0
     769             : #define gc_enable(sc)   (void) 0
     770             : #define gc_enabled(sc)  1
     771             : #define gc_consume(sc)  (void) 0
     772             : 
     773             : #endif /* USE_GC_LOCKING */
     774             : 
     775   108386696 : static INLINE pointer get_cell_x(scheme *sc, pointer a, pointer b) {
     776   108386696 :   if (! gc_enabled (sc) || sc->free_cell != sc->NIL) {
     777   108386525 :     pointer x = sc->free_cell;
     778   108386525 :     if (! gc_enabled (sc))
     779   107631222 :          gc_consume (sc);
     780   108386525 :     sc->free_cell = cdr(x);
     781   108386525 :     --sc->fcells;
     782   108386525 :     return (x);
     783             :   }
     784         171 :   assert (gc_enabled (sc));
     785         171 :   return _get_cell (sc, a, b);
     786             : }
     787             : 
     788             : 
     789             : /* get new cell.  parameter a, b is marked by gc. */
     790         171 : static pointer _get_cell(scheme *sc, pointer a, pointer b) {
     791             :   pointer x;
     792             : 
     793         171 :   if(sc->no_memory) {
     794           0 :     return sc->sink;
     795             :   }
     796             : 
     797         171 :   assert (gc_enabled (sc));
     798         171 :   if (sc->free_cell == sc->NIL) {
     799         171 :     const int min_to_be_recovered = sc->last_cell_seg*8;
     800         171 :     gc(sc,a, b);
     801         171 :     if (sc->fcells < min_to_be_recovered
     802         171 :         || sc->free_cell == sc->NIL) {
     803             :       /* if only a few recovered, get more to avoid fruitless gc's */
     804           0 :       if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) {
     805           0 :         sc->no_memory=1;
     806           0 :         return sc->sink;
     807             :       }
     808             :     }
     809             :   }
     810         171 :   x = sc->free_cell;
     811         171 :   sc->free_cell = cdr(x);
     812         171 :   --sc->fcells;
     813         171 :   return (x);
     814             : }
     815             : 
     816             : /* make sure that there is a given number of cells free */
     817    42199748 : static pointer reserve_cells(scheme *sc, int n) {
     818    42199748 :     if(sc->no_memory) {
     819           0 :         return sc->NIL;
     820             :     }
     821             : 
     822             :     /* Are there enough cells available? */
     823    42199748 :     if (sc->fcells < n) {
     824             :         /* If not, try gc'ing some */
     825        9016 :         gc(sc, sc->NIL, sc->NIL);
     826        9016 :         if (sc->fcells < n) {
     827             :             /* If there still aren't, try getting more heap */
     828           1 :             if (!alloc_cellseg(sc,1)) {
     829           0 :                 sc->no_memory=1;
     830           0 :                 return sc->NIL;
     831             :             }
     832             :         }
     833        9016 :         if (sc->fcells < n) {
     834             :             /* If all fail, report failure */
     835           0 :             sc->no_memory=1;
     836           0 :             return sc->NIL;
     837             :         }
     838             :     }
     839    42199748 :     return (sc->T);
     840             : }
     841             : 
     842         102 : static pointer get_consecutive_cells(scheme *sc, int n) {
     843             :   pointer x;
     844             : 
     845         102 :   if(sc->no_memory) { return sc->sink; }
     846             : 
     847             :   /* Are there any cells available? */
     848         102 :   x=find_consecutive_cells(sc,n);
     849         102 :   if (x != sc->NIL) { return x; }
     850             : 
     851             :   /* If not, try gc'ing some */
     852           0 :   gc(sc, sc->NIL, sc->NIL);
     853           0 :   x=find_consecutive_cells(sc,n);
     854           0 :   if (x != sc->NIL) { return x; }
     855             : 
     856             :   /* If there still aren't, try getting more heap */
     857           0 :   if (!alloc_cellseg(sc,1))
     858             :     {
     859           0 :       sc->no_memory=1;
     860           0 :       return sc->sink;
     861             :     }
     862             : 
     863           0 :   x=find_consecutive_cells(sc,n);
     864           0 :   if (x != sc->NIL) { return x; }
     865             : 
     866             :   /* If all fail, report failure */
     867           0 :   sc->no_memory=1;
     868           0 :   return sc->sink;
     869             : }
     870             : 
     871         102 : static int count_consecutive_cells(pointer x, int needed) {
     872         102 :  int n=1;
     873       23766 :  while(cdr(x)==x+1) {
     874       23664 :      x=cdr(x);
     875       23664 :      n++;
     876       23664 :      if(n>needed) return n;
     877             :  }
     878           0 :  return n;
     879             : }
     880             : 
     881         102 : static pointer find_consecutive_cells(scheme *sc, int n) {
     882             :   pointer *pp;
     883             :   int cnt;
     884             : 
     885         102 :   pp=&sc->free_cell;
     886         204 :   while(*pp!=sc->NIL) {
     887         102 :     cnt=count_consecutive_cells(*pp,n);
     888         102 :     if(cnt>=n) {
     889         102 :       pointer x=*pp;
     890         102 :       *pp=cdr(*pp+n-1);
     891         102 :       sc->fcells -= n;
     892         102 :       return x;
     893             :     }
     894           0 :     pp=&cdr(*pp+cnt-1);
     895             :   }
     896           0 :   return sc->NIL;
     897             : }
     898             : 
     899             : /* Free a cell.  This is dangerous.  Only free cells that are not
     900             :  * referenced.  */
     901             : static INLINE void
     902    83738908 : free_cell(scheme *sc, pointer a)
     903             : {
     904    83738908 :   cdr(a) = sc->free_cell;
     905    83738908 :   sc->free_cell = a;
     906    83738908 :   sc->fcells += 1;
     907    83738908 : }
     908             : 
     909             : /* Free a cell and retrieve its content.  This is dangerous.  Only
     910             :  * free cells that are not referenced.  */
     911             : static INLINE void
     912    83335964 : free_cons(scheme *sc, pointer a, pointer *r_car, pointer *r_cdr)
     913             : {
     914    83335964 :   *r_car = car(a);
     915    83335964 :   *r_cdr = cdr(a);
     916    83335964 :   free_cell(sc, a);
     917    83335964 : }
     918             : 
     919             : /* To retain recent allocs before interpreter knows about them -
     920             :    Tehom */
     921             : 
     922      402945 : static void push_recent_alloc(scheme *sc, pointer recent, pointer extra)
     923             : {
     924      402945 :   pointer holder = get_cell_x(sc, recent, extra);
     925      402945 :   typeflag(holder) = T_PAIR | T_IMMUTABLE;
     926      402945 :   car(holder) = recent;
     927      402945 :   cdr(holder) = car(sc->sink);
     928      402945 :   car(sc->sink) = holder;
     929      402945 : }
     930             : 
     931    32955336 : static INLINE void ok_to_freely_gc(scheme *sc)
     932             : {
     933    32955336 :   pointer a = car(sc->sink), next;
     934    32955336 :   car(sc->sink) = sc->NIL;
     935    66313616 :   while (a != sc->NIL)
     936             :     {
     937      402944 :       next = cdr(a);
     938      402944 :       free_cell(sc, a);
     939      402944 :       a = next;
     940             :     }
     941    32955336 : }
     942             : 
     943   107983751 : static pointer get_cell(scheme *sc, pointer a, pointer b)
     944             : {
     945   107983751 :   pointer cell   = get_cell_x(sc, a, b);
     946             :   /* For right now, include "a" and "b" in "cell" so that gc doesn't
     947             :      think they are garbage. */
     948             :   /* Tentatively record it as a pair so gc understands it. */
     949   107983751 :   typeflag(cell) = T_PAIR;
     950   107983751 :   car(cell) = a;
     951   107983751 :   cdr(cell) = b;
     952   107983751 :   if (gc_enabled (sc))
     953      352529 :     push_recent_alloc(sc, cell, sc->NIL);
     954   107983751 :   return cell;
     955             : }
     956             : 
     957         102 : static pointer get_vector_object(scheme *sc, int len, pointer init)
     958             : {
     959         102 :   pointer cells = get_consecutive_cells(sc,len/2+len%2+1);
     960         102 :   if(sc->no_memory) { return sc->sink; }
     961             :   /* Record it as a vector so that gc understands it. */
     962         102 :   typeflag(cells) = (T_VECTOR | T_ATOM);
     963         102 :   ivalue_unchecked(cells)=len;
     964         102 :   set_num_integer(cells);
     965         102 :   fill_vector(cells,init);
     966         102 :   if (gc_enabled (sc))
     967         102 :     push_recent_alloc(sc, cells, sc->NIL);
     968         102 :   return cells;
     969             : }
     970             : 
     971             : #if defined TSGRIND
     972             : static void check_cell_alloced(pointer p, int expect_alloced)
     973             : {
     974             :   /* Can't use putstr(sc,str) because callers have no access to
     975             :      sc.  */
     976             :   if(typeflag(p) & !expect_alloced)
     977             :     {
     978             :       fprintf(stderr,"Cell is already allocated!\n");
     979             :     }
     980             :   if(!(typeflag(p)) & expect_alloced)
     981             :     {
     982             :       fprintf(stderr,"Cell is not allocated!\n");
     983             :     }
     984             : 
     985             : }
     986             : static void check_range_alloced(pointer p, int n, int expect_alloced)
     987             : {
     988             :   int i;
     989             :   for(i = 0;i<n;i++)
     990             :     { (void)check_cell_alloced(p+i,expect_alloced); }
     991             : }
     992             : 
     993             : #endif
     994             : 
     995             : /* Medium level cell allocation */
     996             : 
     997             : /* get new cons cell */
     998   107664883 : pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
     999   107664883 :   pointer x = get_cell(sc,a, b);
    1000             : 
    1001   107664883 :   typeflag(x) = T_PAIR;
    1002   107664883 :   if(immutable) {
    1003     6877228 :     setimmutable(x);
    1004             :   }
    1005   107664883 :   car(x) = a;
    1006   107664883 :   cdr(x) = b;
    1007   107664883 :   return (x);
    1008             : }
    1009             : 
    1010             : /* ========== oblist implementation  ========== */
    1011             : 
    1012             : #ifndef USE_OBJECT_LIST
    1013             : 
    1014             : static int hash_fn(const char *key, int table_size);
    1015             : 
    1016          51 : static pointer oblist_initial_value(scheme *sc)
    1017             : {
    1018          51 :   return mk_vector(sc, 461); /* probably should be bigger */
    1019             : }
    1020             : 
    1021             : /* returns the new symbol */
    1022       42156 : static pointer oblist_add_by_name(scheme *sc, const char *name)
    1023             : {
    1024             : #define oblist_add_by_name_allocates    3
    1025             :   pointer x;
    1026             :   int location;
    1027             : 
    1028       42156 :   gc_disable(sc, gc_reservations (oblist_add_by_name));
    1029       42156 :   x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
    1030       42156 :   typeflag(x) = T_SYMBOL;
    1031       42156 :   setimmutable(car(x));
    1032             : 
    1033       42156 :   location = hash_fn(name, ivalue_unchecked(sc->oblist));
    1034       42156 :   set_vector_elem(sc->oblist, location,
    1035             :                   immutable_cons(sc, x, vector_elem(sc->oblist, location)));
    1036       42156 :   gc_enable(sc);
    1037       42156 :   return x;
    1038             : }
    1039             : 
    1040      263198 : static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
    1041             : {
    1042             :   int location;
    1043             :   pointer x;
    1044             :   char *s;
    1045             : 
    1046      263198 :   location = hash_fn(name, ivalue_unchecked(sc->oblist));
    1047      375203 :   for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) {
    1048      333863 :     s = symname(car(x));
    1049             :     /* case-insensitive, per R5RS section 2. */
    1050      333863 :     if(stricmp(name, s) == 0) {
    1051      221858 :       return car(x);
    1052             :     }
    1053             :   }
    1054       41340 :   return sc->NIL;
    1055             : }
    1056             : 
    1057           0 : static pointer oblist_all_symbols(scheme *sc)
    1058             : {
    1059             :   int i;
    1060             :   pointer x;
    1061           0 :   pointer ob_list = sc->NIL;
    1062             : 
    1063           0 :   for (i = 0; i < ivalue_unchecked(sc->oblist); i++) {
    1064           0 :     for (x  = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) {
    1065           0 :       ob_list = cons(sc, x, ob_list);
    1066             :     }
    1067             :   }
    1068           0 :   return ob_list;
    1069             : }
    1070             : 
    1071             : #else
    1072             : 
    1073             : static pointer oblist_initial_value(scheme *sc)
    1074             : {
    1075             :   return sc->NIL;
    1076             : }
    1077             : 
    1078             : static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
    1079             : {
    1080             :      pointer x;
    1081             :      char    *s;
    1082             : 
    1083             :      for (x = sc->oblist; x != sc->NIL; x = cdr(x)) {
    1084             :         s = symname(car(x));
    1085             :         /* case-insensitive, per R5RS section 2. */
    1086             :         if(stricmp(name, s) == 0) {
    1087             :           return car(x);
    1088             :         }
    1089             :      }
    1090             :      return sc->NIL;
    1091             : }
    1092             : 
    1093             : /* returns the new symbol */
    1094             : static pointer oblist_add_by_name(scheme *sc, const char *name)
    1095             : {
    1096             :   pointer x;
    1097             : 
    1098             :   x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
    1099             :   typeflag(x) = T_SYMBOL;
    1100             :   setimmutable(car(x));
    1101             :   sc->oblist = immutable_cons(sc, x, sc->oblist);
    1102             :   return x;
    1103             : }
    1104             : static pointer oblist_all_symbols(scheme *sc)
    1105             : {
    1106             :   return sc->oblist;
    1107             : }
    1108             : 
    1109             : #endif
    1110             : 
    1111        4421 : static pointer mk_port(scheme *sc, port *p) {
    1112        4421 :   pointer x = get_cell(sc, sc->NIL, sc->NIL);
    1113             : 
    1114        4421 :   typeflag(x) = T_PORT|T_ATOM|T_FINALIZE;
    1115        4421 :   x->_object._port=p;
    1116        4421 :   return (x);
    1117             : }
    1118             : 
    1119        2397 : pointer mk_foreign_func(scheme *sc, foreign_func f) {
    1120        2397 :   pointer x = get_cell(sc, sc->NIL, sc->NIL);
    1121             : 
    1122        2397 :   typeflag(x) = (T_FOREIGN | T_ATOM);
    1123        2397 :   x->_object._ff=f;
    1124        2397 :   return (x);
    1125             : }
    1126             : 
    1127        4260 : pointer mk_foreign_object(scheme *sc, const foreign_object_vtable *vtable, void *data) {
    1128        4260 :   pointer x = get_cell(sc, sc->NIL, sc->NIL);
    1129             : 
    1130        4260 :   typeflag(x) = (T_FOREIGN_OBJECT | T_ATOM | T_FINALIZE);
    1131        4260 :   x->_object._foreign_object._vtable=vtable;
    1132        4260 :   x->_object._foreign_object._data = data;
    1133        4260 :   return (x);
    1134             : }
    1135             : 
    1136      101040 : INTERFACE pointer mk_character(scheme *sc, int c) {
    1137      101040 :   pointer x = get_cell(sc,sc->NIL, sc->NIL);
    1138             : 
    1139      101040 :   typeflag(x) = (T_CHARACTER | T_ATOM);
    1140      101040 :   ivalue_unchecked(x)= c;
    1141      101040 :   set_num_integer(x);
    1142      101040 :   return (x);
    1143             : }
    1144             : 
    1145             : 
    1146             : 
    1147             : #if USE_SMALL_INTEGERS
    1148             : 
    1149             : /* s_save assumes that all opcodes can be expressed as a small
    1150             :  * integer.  */
    1151             : #define MAX_SMALL_INTEGER       OP_MAXDEFINED
    1152             : 
    1153             : static int
    1154          51 : initialize_small_integers(scheme *sc)
    1155             : {
    1156             :   int i;
    1157          51 :   if (_alloc_cellseg(sc, MAX_SMALL_INTEGER, &sc->integer_alloc,
    1158             :                      &sc->integer_cells))
    1159           0 :     return 1;
    1160             : 
    1161        8466 :   for (i = 0; i < MAX_SMALL_INTEGER; i++) {
    1162        8415 :     pointer x = &sc->integer_cells[i];
    1163        8415 :     typeflag(x) = T_NUMBER | T_ATOM | MARK;
    1164        8415 :     ivalue_unchecked(x) = i;
    1165        8415 :     set_num_integer(x);
    1166             :   }
    1167             : 
    1168          51 :   return 0;
    1169             : }
    1170             : 
    1171             : static INLINE pointer
    1172    21009825 : mk_small_integer(scheme *sc, long n)
    1173             : {
    1174             : #define mk_small_integer_allocates      0
    1175    21009825 :   assert(0 <= n && n < MAX_SMALL_INTEGER);
    1176    21009825 :   return &sc->integer_cells[n];
    1177             : }
    1178             : #else
    1179             : 
    1180             : #define mk_small_integer_allocates      1
    1181             : #define mk_small_integer        mk_integer
    1182             : 
    1183             : #endif
    1184             : 
    1185             : /* get number atom (integer) */
    1186      190707 : INTERFACE pointer mk_integer(scheme *sc, long n) {
    1187             :   pointer x;
    1188             : 
    1189             : #if USE_SMALL_INTEGERS
    1190      190707 :   if (0 <= n && n < MAX_SMALL_INTEGER)
    1191      175609 :     return mk_small_integer(sc, n);
    1192             : #endif
    1193             : 
    1194       15098 :   x = get_cell(sc,sc->NIL, sc->NIL);
    1195       15098 :   typeflag(x) = (T_NUMBER | T_ATOM);
    1196       15098 :   ivalue_unchecked(x)= n;
    1197       15098 :   set_num_integer(x);
    1198       15098 :   return (x);
    1199             : }
    1200             : 
    1201             : 
    1202             : 
    1203         255 : INTERFACE pointer mk_real(scheme *sc, double n) {
    1204         255 :   pointer x = get_cell(sc,sc->NIL, sc->NIL);
    1205             : 
    1206         255 :   typeflag(x) = (T_NUMBER | T_ATOM);
    1207         255 :   rvalue_unchecked(x)= n;
    1208         255 :   set_num_real(x);
    1209         255 :   return (x);
    1210             : }
    1211             : 
    1212       44356 : static pointer mk_number(scheme *sc, num n) {
    1213       44356 :  if(n.is_fixnum) {
    1214       44356 :      return mk_integer(sc,n.value.ivalue);
    1215             :  } else {
    1216           0 :      return mk_real(sc,n.value.rvalue);
    1217             :  }
    1218             : }
    1219             : 
    1220             : /* allocate name to string area */
    1221       95095 : static char *store_string(scheme *sc, int len_str, const char *str, char fill) {
    1222             :      char *q;
    1223             : 
    1224       95095 :      q=(char*)sc->malloc(len_str+1);
    1225       95095 :      if(q==0) {
    1226           0 :           sc->no_memory=1;
    1227           0 :           return sc->strbuff;
    1228             :      }
    1229       95095 :      if(str!=0) {
    1230       66734 :           memcpy (q, str, len_str);
    1231       66734 :           q[len_str]=0;
    1232             :      } else {
    1233       28361 :           memset(q, fill, len_str);
    1234       28361 :           q[len_str]=0;
    1235             :      }
    1236       95095 :      return (q);
    1237             : }
    1238             : 
    1239             : /* get new string */
    1240       49040 : INTERFACE pointer mk_string(scheme *sc, const char *str) {
    1241       49040 :      return mk_counted_string(sc,str,strlen(str));
    1242             : }
    1243             : 
    1244       65504 : INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
    1245       65504 :      pointer x = get_cell(sc, sc->NIL, sc->NIL);
    1246       65504 :      typeflag(x) = (T_STRING | T_ATOM | T_FINALIZE);
    1247       65504 :      strvalue(x) = store_string(sc,len,str,0);
    1248       65504 :      strlength(x) = len;
    1249       65504 :      return (x);
    1250             : }
    1251             : 
    1252       28311 : INTERFACE pointer mk_empty_string(scheme *sc, int len, char fill) {
    1253       28311 :      pointer x = get_cell(sc, sc->NIL, sc->NIL);
    1254       28311 :      typeflag(x) = (T_STRING | T_ATOM | T_FINALIZE);
    1255       28311 :      strvalue(x) = store_string(sc,len,0,fill);
    1256       28311 :      strlength(x) = len;
    1257       28311 :      return (x);
    1258             : }
    1259             : 
    1260         102 : INTERFACE static pointer mk_vector(scheme *sc, int len)
    1261         102 : { return get_vector_object(sc,len,sc->NIL); }
    1262             : 
    1263         102 : INTERFACE static void fill_vector(pointer vec, pointer obj) {
    1264             :      int i;
    1265         102 :      int n = ivalue(vec)/2+ivalue(vec)%2;
    1266       23664 :      for(i=0; i < n; i++) {
    1267       23562 :           typeflag(vec+1+i) = T_PAIR;
    1268       23562 :           setimmutable(vec+1+i);
    1269       23562 :           car(vec+1+i)=obj;
    1270       23562 :           cdr(vec+1+i)=obj;
    1271             :      }
    1272         102 : }
    1273             : 
    1274     6942565 : INTERFACE static pointer vector_elem(pointer vec, int ielem) {
    1275     6942565 :      int n=ielem/2;
    1276     6942565 :      if(ielem%2==0) {
    1277     2912629 :           return car(vec+1+n);
    1278             :      } else {
    1279     4029936 :           return cdr(vec+1+n);
    1280             :      }
    1281             : }
    1282             : 
    1283       67590 : INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
    1284       67590 :      int n=ielem/2;
    1285       67590 :      if(ielem%2==0) {
    1286       32506 :           return car(vec+1+n)=a;
    1287             :      } else {
    1288       35084 :           return cdr(vec+1+n)=a;
    1289             :      }
    1290             : }
    1291             : 
    1292             : /* get new symbol */
    1293      255907 : INTERFACE pointer mk_symbol(scheme *sc, const char *name) {
    1294             : #define mk_symbol_allocates     oblist_add_by_name_allocates
    1295             :      pointer x;
    1296             : 
    1297             :      /* first check oblist */
    1298      255907 :      x = oblist_find_by_name(sc, name);
    1299      255907 :      if (x != sc->NIL) {
    1300      218238 :           return (x);
    1301             :      } else {
    1302       37669 :           x = oblist_add_by_name(sc, name);
    1303       37669 :           return (x);
    1304             :      }
    1305             : }
    1306             : 
    1307        3671 : INTERFACE pointer gensym(scheme *sc) {
    1308             :      pointer x;
    1309             :      char name[40];
    1310             : 
    1311       14582 :      for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) {
    1312        7291 :           snprintf(name,40,"gensym-%ld",sc->gensym_cnt);
    1313             : 
    1314             :           /* first check oblist */
    1315        7291 :           x = oblist_find_by_name(sc, name);
    1316             : 
    1317        7291 :           if (x != sc->NIL) {
    1318        3620 :                continue;
    1319             :           } else {
    1320        3671 :                x = oblist_add_by_name(sc, name);
    1321        3671 :                return (x);
    1322             :           }
    1323             :      }
    1324             : 
    1325           0 :      return sc->NIL;
    1326             : }
    1327             : 
    1328             : /* double the size of the string buffer */
    1329          18 : static int expand_strbuff(scheme *sc) {
    1330          18 :   size_t new_size = sc->strbuff_size * 2;
    1331          18 :   char *new_buffer = sc->malloc(new_size);
    1332          18 :   if (new_buffer == 0) {
    1333           0 :     sc->no_memory = 1;
    1334           0 :     return 1;
    1335             :   }
    1336          18 :   memcpy(new_buffer, sc->strbuff, sc->strbuff_size);
    1337          18 :   sc->free(sc->strbuff);
    1338          18 :   sc->strbuff = new_buffer;
    1339          18 :   sc->strbuff_size = new_size;
    1340          18 :   return 0;
    1341             : }
    1342             : 
    1343             : /* make symbol or number atom from string */
    1344      252169 : static pointer mk_atom(scheme *sc, char *q) {
    1345             :      char    c, *p;
    1346      252169 :      int has_dec_point=0;
    1347      252169 :      int has_fp_exp = 0;
    1348             : 
    1349             : #if USE_COLON_HOOK
    1350      252169 :      if((p=strstr(q,"::"))!=0) {
    1351        1260 :           *p=0;
    1352        1260 :           return cons(sc, sc->COLON_HOOK,
    1353             :                           cons(sc,
    1354             :                               cons(sc,
    1355             :                                    sc->QUOTE,
    1356             :                                    cons(sc, mk_atom(sc,p+2), sc->NIL)),
    1357             :                               cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL)));
    1358             :      }
    1359             : #endif
    1360             : 
    1361      250909 :      p = q;
    1362      250909 :      c = *p++;
    1363      250909 :      if ((c == '+') || (c == '-')) {
    1364        3369 :        c = *p++;
    1365        3369 :        if (c == '.') {
    1366           0 :          has_dec_point=1;
    1367           0 :          c = *p++;
    1368             :        }
    1369        3573 :        if (!isdigit(c)) {
    1370        3165 :          return (mk_symbol(sc, strlwr(q)));
    1371             :        }
    1372      247540 :      } else if (c == '.') {
    1373           0 :        has_dec_point=1;
    1374           0 :        c = *p++;
    1375           0 :        if (!isdigit(c)) {
    1376           0 :          return (mk_symbol(sc, strlwr(q)));
    1377             :        }
    1378      247540 :      } else if (!isdigit(c)) {
    1379      241847 :        return (mk_symbol(sc, strlwr(q)));
    1380             :      }
    1381             : 
    1382        8096 :      for ( ; (c = *p) != 0; ++p) {
    1383        2199 :           if (!isdigit(c)) {
    1384         255 :                if(c=='.') {
    1385         255 :                     if(!has_dec_point) {
    1386         255 :                          has_dec_point=1;
    1387         255 :                          continue;
    1388             :                     }
    1389             :                }
    1390           0 :                else if ((c == 'e') || (c == 'E')) {
    1391           0 :                        if(!has_fp_exp) {
    1392           0 :                           has_dec_point = 1; /* decimal point illegal
    1393             :                                                 from now on */
    1394           0 :                           p++;
    1395           0 :                           if ((*p == '-') || (*p == '+') || isdigit(*p)) {
    1396           0 :                              continue;
    1397             :                           }
    1398             :                        }
    1399             :                }
    1400           0 :                return (mk_symbol(sc, strlwr(q)));
    1401             :           }
    1402             :      }
    1403        5897 :      if(has_dec_point) {
    1404         255 :           return mk_real(sc,atof(q));
    1405             :      }
    1406        5642 :      return (mk_integer(sc, atol(q)));
    1407             : }
    1408             : 
    1409             : /* make constant */
    1410        4549 : static pointer mk_sharp_const(scheme *sc, char *name) {
    1411             :      long    x;
    1412             :      char    tmp[STRBUFFSIZE];
    1413             : 
    1414        4549 :      if (!strcmp(name, "t"))
    1415        1183 :           return (sc->T);
    1416        3366 :      else if (!strcmp(name, "f"))
    1417        1795 :           return (sc->F);
    1418        1571 :      else if (*name == 'o') {/* #o (octal) */
    1419         256 :           snprintf(tmp, STRBUFFSIZE, "0%s", name+1);
    1420         256 :           sscanf(tmp, "%lo", (long unsigned *)&x);
    1421         256 :           return (mk_integer(sc, x));
    1422        1315 :      } else if (*name == 'd') {    /* #d (decimal) */
    1423           0 :           sscanf(name+1, "%ld", (long int *)&x);
    1424           0 :           return (mk_integer(sc, x));
    1425        1315 :      } else if (*name == 'x') {    /* #x (hex) */
    1426           2 :           snprintf(tmp, STRBUFFSIZE, "0x%s", name+1);
    1427           2 :           sscanf(tmp, "%lx", (long unsigned *)&x);
    1428           2 :           return (mk_integer(sc, x));
    1429        1313 :      } else if (*name == 'b') {    /* #b (binary) */
    1430           0 :           x = binary_decode(name+1);
    1431           0 :           return (mk_integer(sc, x));
    1432        1313 :      } else if (*name == '\\') { /* #\w (character) */
    1433        1313 :           int c=0;
    1434        1313 :           if(stricmp(name+1,"space")==0) {
    1435           1 :                c=' ';
    1436        1312 :           } else if(stricmp(name+1,"newline")==0) {
    1437         154 :                c='\n';
    1438        1158 :           } else if(stricmp(name+1,"return")==0) {
    1439           0 :                c='\r';
    1440        1158 :           } else if(stricmp(name+1,"tab")==0) {
    1441           0 :                c='\t';
    1442        1158 :      } else if(name[1]=='x' && name[2]!=0) {
    1443           0 :           int c1=0;
    1444           0 :           if(sscanf(name+2,"%x",(unsigned int *)&c1)==1 && c1 < UCHAR_MAX) {
    1445           0 :                c=c1;
    1446             :           } else {
    1447           0 :                return sc->NIL;
    1448             :      }
    1449             : #if USE_ASCII_NAMES
    1450        1158 :           } else if(is_ascii_name(name+1,&c)) {
    1451             :                /* nothing */
    1452             : #endif
    1453        1158 :           } else if(name[2]==0) {
    1454        1158 :                c=name[1];
    1455             :           } else {
    1456           0 :                return sc->NIL;
    1457             :           }
    1458        1313 :           return mk_character(sc,c);
    1459             :      } else
    1460           0 :           return (sc->NIL);
    1461             : }
    1462             : 
    1463             : /* ========== garbage collector ========== */
    1464             : 
    1465             : /*--
    1466             :  *  We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
    1467             :  *  sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
    1468             :  *  for marking.
    1469             :  */
    1470     4382949 : static void mark(pointer a) {
    1471             :      pointer t, q, p;
    1472             : 
    1473     4382949 :      t = (pointer) 0;
    1474     4382949 :      p = a;
    1475   115827141 : E2:  setmark(p);
    1476   115827141 :      if(is_vector(p)) {
    1477             :           int i;
    1478       18374 :           int n = ivalue_unchecked(p)/2+ivalue_unchecked(p)%2;
    1479     4262768 :           for(i=0; i < n; i++) {
    1480             :                /* Vector cells will be treated like ordinary cells */
    1481     4244394 :                mark(p+1+i);
    1482             :           }
    1483             :      }
    1484   115827141 :      if (is_atom(p))
    1485    12085748 :           goto E6;
    1486             :      /* E4: down car */
    1487   103741393 :      q = car(p);
    1488   103741393 :      if (q && !is_mark(q)) {
    1489    55775383 :           setatom(p);  /* a note that we have moved car */
    1490    55775383 :           car(p) = t;
    1491    55775383 :           t = p;
    1492    55775383 :           p = q;
    1493    55775383 :           goto E2;
    1494             :      }
    1495   103741393 : E5:  q = cdr(p); /* down cdr */
    1496   103741393 :      if (q && !is_mark(q)) {
    1497    55668809 :           cdr(p) = t;
    1498    55668809 :           t = p;
    1499    55668809 :           p = q;
    1500    55668809 :           goto E2;
    1501             :      }
    1502             : E6:   /* up.  Undo the link switching from steps E4 and E5. */
    1503   115827141 :      if (!t)
    1504     8765898 :           return;
    1505   111444192 :      q = t;
    1506   111444192 :      if (is_atom(q)) {
    1507    55775383 :           clratom(q);
    1508    55775383 :           t = car(q);
    1509    55775383 :           car(q) = p;
    1510    55775383 :           p = q;
    1511    55775383 :           goto E5;
    1512             :      } else {
    1513    55668809 :           t = cdr(q);
    1514    55668809 :           cdr(q) = p;
    1515    55668809 :           p = q;
    1516    55668809 :           goto E6;
    1517             :      }
    1518             : }
    1519             : 
    1520             : /* garbage collection. parameter a, b is marked. */
    1521        9237 : static void gc(scheme *sc, pointer a, pointer b) {
    1522             :   pointer p;
    1523             :   int i;
    1524             : 
    1525        9237 :   assert (gc_enabled (sc));
    1526             : 
    1527        9237 :   if(sc->gc_verbose) {
    1528           0 :     putstr(sc, "gc...");
    1529             :   }
    1530             : 
    1531             :   /* mark system globals */
    1532        9237 :   mark(sc->oblist);
    1533        9237 :   mark(sc->global_env);
    1534             : 
    1535             :   /* mark current registers */
    1536        9237 :   mark(sc->args);
    1537        9237 :   mark(sc->envir);
    1538        9237 :   mark(sc->code);
    1539        9237 :   dump_stack_mark(sc);
    1540        9237 :   mark(sc->value);
    1541        9237 :   mark(sc->inport);
    1542        9237 :   mark(sc->save_inport);
    1543        9237 :   mark(sc->outport);
    1544        9237 :   mark(sc->loadport);
    1545             : 
    1546             :   /* Mark recent objects the interpreter doesn't know about yet. */
    1547        9237 :   mark(car(sc->sink));
    1548             :   /* Mark any older stuff above nested C calls */
    1549        9237 :   mark(sc->c_nest);
    1550             : 
    1551             :   /* mark variables a, b */
    1552        9237 :   mark(a);
    1553        9237 :   mark(b);
    1554             : 
    1555             :   /* garbage collect */
    1556        9237 :   clrmark(sc->NIL);
    1557        9237 :   sc->fcells = 0;
    1558        9237 :   sc->free_cell = sc->NIL;
    1559             :   /* free-list is kept sorted by address so as to maintain consecutive
    1560             :      ranges, if possible, for use with vectors. Here we scan the cells
    1561             :      (which are also kept sorted by address) downwards to build the
    1562             :      free-list in sorted order.
    1563             :   */
    1564       37333 :   for (i = sc->last_cell_seg; i >= 0; i--) {
    1565       28096 :     p = sc->cell_seg[i] + CELL_SEGSIZE;
    1566   140536192 :     while (--p >= sc->cell_seg[i]) {
    1567   140480000 :       if (is_mark(p)) {
    1568   115737716 :     clrmark(p);
    1569             :       } else {
    1570             :     /* reclaim cell */
    1571    24742284 :         if (typeflag(p) & T_FINALIZE) {
    1572       98491 :           finalize_cell(sc, p);
    1573             :         }
    1574    24742284 :         ++sc->fcells;
    1575    24742284 :         typeflag(p) = 0;
    1576    24742284 :         car(p) = sc->NIL;
    1577    24742284 :         cdr(p) = sc->free_cell;
    1578    24742284 :         sc->free_cell = p;
    1579             :       }
    1580             :     }
    1581             :   }
    1582             : 
    1583        9237 :   if (sc->gc_verbose) {
    1584             :     char msg[80];
    1585           0 :     snprintf(msg,80,"done: %ld cells were recovered.\n", sc->fcells);
    1586           0 :     putstr(sc,msg);
    1587             :   }
    1588        9237 : }
    1589             : 
    1590       98491 : static void finalize_cell(scheme *sc, pointer a) {
    1591       98491 :   if(is_string(a)) {
    1592       92567 :     sc->free(strvalue(a));
    1593        5924 :   } else if(is_port(a)) {
    1594        1664 :     if(a->_object._port->kind&port_file
    1595         446 :        && a->_object._port->rep.stdio.closeit) {
    1596          92 :       port_close(sc,a,port_input|port_output);
    1597        1572 :     } else if (a->_object._port->kind & port_srfi6) {
    1598         385 :       sc->free(a->_object._port->rep.string.start);
    1599             :     }
    1600        1664 :     sc->free(a->_object._port);
    1601        4260 :   } else if(is_foreign_object(a)) {
    1602        4260 :     a->_object._foreign_object._vtable->finalize(sc, a->_object._foreign_object._data);
    1603             :   }
    1604       98491 : }
    1605             : 
    1606             : /* ========== Routines for Reading ========== */
    1607             : 
    1608          49 : static int file_push(scheme *sc, const char *fname) {
    1609          49 :   FILE *fin = NULL;
    1610             : 
    1611          49 :   if (sc->file_i == MAXFIL-1)
    1612           0 :      return 0;
    1613          49 :   fin=fopen(fname,"r");
    1614          49 :   if(fin!=0) {
    1615          49 :     sc->file_i++;
    1616          49 :     sc->load_stack[sc->file_i].kind=port_file|port_input;
    1617          49 :     sc->load_stack[sc->file_i].rep.stdio.file=fin;
    1618          49 :     sc->load_stack[sc->file_i].rep.stdio.closeit=1;
    1619          49 :     sc->nesting_stack[sc->file_i]=0;
    1620          49 :     sc->loadport->_object._port=sc->load_stack+sc->file_i;
    1621             : 
    1622             : #if SHOW_ERROR_LINE
    1623          49 :     sc->load_stack[sc->file_i].rep.stdio.curr_line = 0;
    1624          49 :     if(fname)
    1625          49 :       sc->load_stack[sc->file_i].rep.stdio.filename = store_string(sc, strlen(fname), fname, 0);
    1626             : #endif
    1627             :   }
    1628          49 :   return fin!=0;
    1629             : }
    1630             : 
    1631          49 : static void file_pop(scheme *sc) {
    1632          49 :  if(sc->file_i != 0) {
    1633          49 :    sc->nesting=sc->nesting_stack[sc->file_i];
    1634          49 :    port_close(sc,sc->loadport,port_input);
    1635          49 :    sc->file_i--;
    1636          49 :    sc->loadport->_object._port=sc->load_stack+sc->file_i;
    1637             :  }
    1638          49 : }
    1639             : 
    1640       38992 : static int file_interactive(scheme *sc) {
    1641      112684 :  return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin
    1642       38992 :      && sc->inport->_object._port->kind&port_file;
    1643             : }
    1644             : 
    1645         989 : static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
    1646             :   FILE *f;
    1647             :   char *rw;
    1648             :   port *pt;
    1649         989 :   if(prop==(port_input|port_output)) {
    1650          92 :     rw="a+";
    1651         897 :   } else if(prop==port_output) {
    1652          13 :     rw="w";
    1653             :   } else {
    1654         884 :     rw="r";
    1655             :   }
    1656         989 :   f=fopen(fn,rw);
    1657         989 :   if(f==0) {
    1658          64 :     return 0;
    1659             :   }
    1660         925 :   pt=port_rep_from_file(sc,f,prop);
    1661         925 :   pt->rep.stdio.closeit=1;
    1662             : 
    1663             : #if SHOW_ERROR_LINE
    1664         925 :   if(fn)
    1665         925 :     pt->rep.stdio.filename = store_string(sc, strlen(fn), fn, 0);
    1666             : 
    1667         925 :   pt->rep.stdio.curr_line = 0;
    1668             : #endif
    1669         925 :   return pt;
    1670             : }
    1671             : 
    1672         989 : static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
    1673             :   port *pt;
    1674         989 :   pt=port_rep_from_filename(sc,fn,prop);
    1675         989 :   if(pt==0) {
    1676          64 :     return sc->NIL;
    1677             :   }
    1678         925 :   return mk_port(sc,pt);
    1679             : }
    1680             : 
    1681        1283 : static port *port_rep_from_file(scheme *sc, FILE *f, int prop)
    1682             : {
    1683             :     port *pt;
    1684             : 
    1685        1283 :     pt = (port *)sc->malloc(sizeof *pt);
    1686        1283 :     if (pt == NULL) {
    1687           0 :         return NULL;
    1688             :     }
    1689        1283 :     pt->kind = port_file | prop;
    1690        1283 :     pt->rep.stdio.file = f;
    1691        1283 :     pt->rep.stdio.closeit = 0;
    1692        1283 :     return pt;
    1693             : }
    1694             : 
    1695         358 : static pointer port_from_file(scheme *sc, FILE *f, int prop) {
    1696             :   port *pt;
    1697         358 :   pt=port_rep_from_file(sc,f,prop);
    1698         358 :   if(pt==0) {
    1699           0 :     return sc->NIL;
    1700             :   }
    1701         358 :   return mk_port(sc,pt);
    1702             : }
    1703             : 
    1704           0 : static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
    1705             :   port *pt;
    1706           0 :   pt=(port*)sc->malloc(sizeof(port));
    1707           0 :   if(pt==0) {
    1708           0 :     return 0;
    1709             :   }
    1710           0 :   pt->kind=port_string|prop;
    1711           0 :   pt->rep.string.start=start;
    1712           0 :   pt->rep.string.curr=start;
    1713           0 :   pt->rep.string.past_the_end=past_the_end;
    1714           0 :   return pt;
    1715             : }
    1716             : 
    1717           0 : static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
    1718             :   port *pt;
    1719           0 :   pt=port_rep_from_string(sc,start,past_the_end,prop);
    1720           0 :   if(pt==0) {
    1721           0 :     return sc->NIL;
    1722             :   }
    1723           0 :   return mk_port(sc,pt);
    1724             : }
    1725             : 
    1726             : #define BLOCK_SIZE 256
    1727             : 
    1728         385 : static port *port_rep_from_scratch(scheme *sc) {
    1729             :   port *pt;
    1730             :   char *start;
    1731         385 :   pt=(port*)sc->malloc(sizeof(port));
    1732         385 :   if(pt==0) {
    1733           0 :     return 0;
    1734             :   }
    1735         385 :   start=sc->malloc(BLOCK_SIZE);
    1736         385 :   if(start==0) {
    1737           0 :     return 0;
    1738             :   }
    1739         385 :   memset(start,' ',BLOCK_SIZE-1);
    1740         385 :   start[BLOCK_SIZE-1]='\0';
    1741         385 :   pt->kind=port_string|port_output|port_srfi6;
    1742         385 :   pt->rep.string.start=start;
    1743         385 :   pt->rep.string.curr=start;
    1744         385 :   pt->rep.string.past_the_end=start+BLOCK_SIZE-1;
    1745         385 :   return pt;
    1746             : }
    1747             : 
    1748         385 : static pointer port_from_scratch(scheme *sc) {
    1749             :   port *pt;
    1750         385 :   pt=port_rep_from_scratch(sc);
    1751         385 :   if(pt==0) {
    1752           0 :     return sc->NIL;
    1753             :   }
    1754         385 :   return mk_port(sc,pt);
    1755             : }
    1756             : 
    1757         974 : static void port_close(scheme *sc, pointer p, int flag) {
    1758         974 :   port *pt=p->_object._port;
    1759         974 :   pt->kind&=~flag;
    1760         974 :   if((pt->kind & (port_input|port_output))==0) {
    1761         974 :     if(pt->kind&port_file) {
    1762             : 
    1763             : #if SHOW_ERROR_LINE
    1764             :       /* Cleanup is here so (close-*-port) functions could work too */
    1765         974 :       pt->rep.stdio.curr_line = 0;
    1766             : 
    1767         974 :       if(pt->rep.stdio.filename)
    1768         974 :         sc->free(pt->rep.stdio.filename);
    1769             : #endif
    1770             : 
    1771         974 :       fclose(pt->rep.stdio.file);
    1772             :     }
    1773         974 :     pt->kind=port_free;
    1774             :   }
    1775         974 : }
    1776             : 
    1777             : /* get new character from input file */
    1778     4599330 : static int inchar(scheme *sc) {
    1779             :   int c;
    1780             :   port *pt;
    1781             : 
    1782     4599330 :   pt = sc->inport->_object._port;
    1783     4599330 :   if(pt->kind & port_saw_EOF)
    1784           0 :     { return EOF; }
    1785     4599330 :   c = basic_inchar(pt);
    1786     4599330 :   if(c == EOF && sc->inport == sc->loadport) {
    1787             :     /* Instead, set port_saw_EOF */
    1788        2801 :     pt->kind |= port_saw_EOF;
    1789             : 
    1790             :     /* file_pop(sc); */
    1791        2801 :     return EOF;
    1792             :     /* NOTREACHED */
    1793             :   }
    1794     4596529 :   return c;
    1795             : }
    1796             : 
    1797     4599330 : static int basic_inchar(port *pt) {
    1798     4599330 :   if(pt->kind & port_file) {
    1799     4386179 :     return fgetc(pt->rep.stdio.file);
    1800             :   } else {
    1801      423855 :     if(*pt->rep.string.curr == 0 ||
    1802      210704 :        pt->rep.string.curr == pt->rep.string.past_the_end) {
    1803        2447 :       return EOF;
    1804             :     } else {
    1805      210704 :       return *pt->rep.string.curr++;
    1806             :     }
    1807             :   }
    1808             : }
    1809             : 
    1810             : /* back character to input buffer */
    1811     1257483 : static void backchar(scheme *sc, int c) {
    1812             :   port *pt;
    1813     2514966 :   if(c==EOF) return;
    1814     1255036 :   pt=sc->inport->_object._port;
    1815     1255036 :   if(pt->kind&port_file) {
    1816     1190067 :     ungetc(c,pt->rep.stdio.file);
    1817             :   } else {
    1818       64969 :     if(pt->rep.string.curr!=pt->rep.string.start) {
    1819       64969 :       --pt->rep.string.curr;
    1820             :     }
    1821             :   }
    1822             : }
    1823             : 
    1824         117 : static int realloc_port_string(scheme *sc, port *p)
    1825             : {
    1826         117 :   char *start=p->rep.string.start;
    1827         117 :   size_t old_size = p->rep.string.past_the_end - start;
    1828         117 :   size_t new_size=p->rep.string.past_the_end-start+1+BLOCK_SIZE;
    1829         117 :   char *str=sc->malloc(new_size);
    1830         117 :   if(str) {
    1831         117 :     memset(str,' ',new_size-1);
    1832         117 :     str[new_size-1]='\0';
    1833         117 :     memcpy(str, start, old_size);
    1834         117 :     p->rep.string.start=str;
    1835         117 :     p->rep.string.past_the_end=str+new_size-1;
    1836         117 :     p->rep.string.curr-=start-str;
    1837         117 :     sc->free(start);
    1838         117 :     return 1;
    1839             :   } else {
    1840           0 :     return 0;
    1841             :   }
    1842             : }
    1843             : 
    1844        2061 : INTERFACE void putstr(scheme *sc, const char *s) {
    1845        2061 :   port *pt=sc->outport->_object._port;
    1846        2061 :   if(pt->kind&port_file) {
    1847         195 :     fputs(s,pt->rep.stdio.file);
    1848             :   } else {
    1849        3732 :     for(;*s;s++) {
    1850        1866 :       if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
    1851        1866 :         *pt->rep.string.curr++=*s;
    1852           0 :       } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
    1853           0 :         *pt->rep.string.curr++=*s;
    1854             :       }
    1855             :     }
    1856             :   }
    1857        2061 : }
    1858             : 
    1859       38326 : static void putchars(scheme *sc, const char *s, int len) {
    1860       38326 :   port *pt=sc->outport->_object._port;
    1861       38326 :   if(pt->kind&port_file) {
    1862        1772 :     fwrite(s,1,len,pt->rep.stdio.file);
    1863             :   } else {
    1864       82052 :     for(;len;len--) {
    1865       45498 :       if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
    1866       45384 :         *pt->rep.string.curr++=*s++;
    1867         114 :       } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
    1868         114 :         *pt->rep.string.curr++=*s++;
    1869             :       }
    1870             :     }
    1871             :   }
    1872       38326 : }
    1873             : 
    1874       15008 : INTERFACE void putcharacter(scheme *sc, int c) {
    1875       15008 :   port *pt=sc->outport->_object._port;
    1876       15008 :   if(pt->kind&port_file) {
    1877           0 :     fputc(c,pt->rep.stdio.file);
    1878             :   } else {
    1879       15008 :     if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
    1880       15005 :       *pt->rep.string.curr++=c;
    1881           3 :     } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
    1882           3 :         *pt->rep.string.curr++=c;
    1883             :     }
    1884             :   }
    1885       15008 : }
    1886             : 
    1887             : /* read characters up to delimiter, but cater to character constants */
    1888      255395 : static char *readstr_upto(scheme *sc, char *delim) {
    1889      255395 :   char *p = sc->strbuff;
    1890             : 
    1891     1894991 :   while ((p - sc->strbuff < sc->strbuff_size) &&
    1892     1639596 :          !is_one_of(delim, (*p++ = inchar(sc))));
    1893             : 
    1894      255395 :   if(p == sc->strbuff+2 && p[-2] == '\\') {
    1895          46 :     *p=0;
    1896             :   } else {
    1897      255349 :     backchar(sc,p[-1]);
    1898      255349 :     *--p = '\0';
    1899             :   }
    1900      255395 :   return sc->strbuff;
    1901             : }
    1902             : 
    1903             : /* read string expression "xxx...xxx" */
    1904       13432 : static pointer readstrexp(scheme *sc) {
    1905       13432 :   char *p = sc->strbuff;
    1906             :   int c;
    1907       13432 :   int c1=0;
    1908       13432 :   enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2 } state=st_ok;
    1909             : 
    1910             :   for (;;) {
    1911      239693 :     c=inchar(sc);
    1912      239693 :     if(c == EOF) {
    1913           0 :       return sc->F;
    1914             :     }
    1915      239693 :     if(p-sc->strbuff > (sc->strbuff_size)-1) {
    1916          18 :       ptrdiff_t offset = p - sc->strbuff;
    1917          18 :       if (expand_strbuff(sc) != 0) {
    1918           0 :         return sc->F;
    1919             :       }
    1920          18 :       p = sc->strbuff + offset;
    1921             :     }
    1922      239693 :     switch(state) {
    1923             :         case st_ok:
    1924      239440 :             switch(c) {
    1925             :                 case '\\':
    1926         253 :                     state=st_bsl;
    1927         253 :                     break;
    1928             :                 case '"':
    1929       13432 :                     *p=0;
    1930       13432 :                     return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
    1931             :                 default:
    1932      225755 :                     *p++=c;
    1933      225755 :                     break;
    1934             :             }
    1935      226008 :             break;
    1936             :         case st_bsl:
    1937         253 :             switch(c) {
    1938             :                 case '0':
    1939             :                 case '1':
    1940             :                 case '2':
    1941             :                 case '3':
    1942             :                 case '4':
    1943             :                 case '5':
    1944             :                 case '6':
    1945             :                 case '7':
    1946           0 :                         state=st_oct1;
    1947           0 :                         c1=c-'0';
    1948           0 :                         break;
    1949             :                 case 'x':
    1950             :                 case 'X':
    1951           0 :                     state=st_x1;
    1952           0 :                     c1=0;
    1953           0 :                     break;
    1954             :                 case 'n':
    1955         198 :                     *p++='\n';
    1956         198 :                     state=st_ok;
    1957         198 :                     break;
    1958             :                 case 't':
    1959           0 :                     *p++='\t';
    1960           0 :                     state=st_ok;
    1961           0 :                     break;
    1962             :                 case 'r':
    1963          51 :                     *p++='\r';
    1964          51 :                     state=st_ok;
    1965          51 :                     break;
    1966             :                 case '"':
    1967           4 :                     *p++='"';
    1968           4 :                     state=st_ok;
    1969           4 :                     break;
    1970             :                 default:
    1971           0 :                     *p++=c;
    1972           0 :                     state=st_ok;
    1973           0 :                     break;
    1974             :             }
    1975         253 :             break;
    1976             :         case st_x1:
    1977             :         case st_x2:
    1978           0 :             c=toupper(c);
    1979           0 :             if(c>='0' && c<='F') {
    1980           0 :                 if(c<='9') {
    1981           0 :                     c1=(c1<<4)+c-'0';
    1982             :                 } else {
    1983           0 :                     c1=(c1<<4)+c-'A'+10;
    1984             :                 }
    1985           0 :                 if(state==st_x1) {
    1986           0 :                     state=st_x2;
    1987             :                 } else {
    1988           0 :                     *p++=c1;
    1989           0 :                     state=st_ok;
    1990             :                 }
    1991             :             } else {
    1992           0 :                 return sc->F;
    1993             :             }
    1994           0 :             break;
    1995             :         case st_oct1:
    1996             :         case st_oct2:
    1997           0 :             if (c < '0' || c > '7')
    1998             :             {
    1999           0 :                    *p++=c1;
    2000           0 :                    backchar(sc, c);
    2001           0 :                    state=st_ok;
    2002             :             }
    2003             :             else
    2004             :             {
    2005           0 :                 if (state==st_oct2 && c1 >= 32)
    2006           0 :                     return sc->F;
    2007             : 
    2008           0 :                    c1=(c1<<3)+(c-'0');
    2009             : 
    2010           0 :                 if (state == st_oct1)
    2011           0 :                         state=st_oct2;
    2012             :                 else
    2013             :                 {
    2014           0 :                         *p++=c1;
    2015           0 :                         state=st_ok;
    2016             :                    }
    2017             :             }
    2018           0 :             break;
    2019             : 
    2020             :     }
    2021      226261 :   }
    2022             : }
    2023             : 
    2024             : /* check c is in chars */
    2025     1648182 : static INLINE int is_one_of(char *s, int c) {
    2026     1648182 :      if(c==EOF) return 1;
    2027    18843219 :      while (*s)
    2028    15810836 :           if (*s++ == c)
    2029      263981 :                return (1);
    2030     1384201 :      return (0);
    2031             : }
    2032             : 
    2033             : /* skip white characters */
    2034      615338 : static INLINE int skipspace(scheme *sc) {
    2035      615338 :      int c = 0, curr_line = 0;
    2036             : 
    2037             :      do {
    2038     1254462 :          c=inchar(sc);
    2039             : #if SHOW_ERROR_LINE
    2040     1254462 :          if(c=='\n')
    2041       22803 :            curr_line++;
    2042             : #endif
    2043     1254462 :      } while (isspace(c));
    2044             : 
    2045             : /* record it */
    2046             : #if SHOW_ERROR_LINE
    2047      615338 :      if (sc->load_stack[sc->file_i].kind & port_file)
    2048      581630 :        sc->load_stack[sc->file_i].rep.stdio.curr_line += curr_line;
    2049             : #endif
    2050             : 
    2051      615338 :      if(c!=EOF) {
    2052      614984 :           backchar(sc,c);
    2053      614984 :       return 1;
    2054             :      }
    2055             :      else
    2056         354 :        { return EOF; }
    2057             : }
    2058             : 
    2059             : /* get token */
    2060      615338 : static int token(scheme *sc) {
    2061             :      int c;
    2062      615338 :      c = skipspace(sc);
    2063      615338 :      if(c == EOF) { return (TOK_EOF); }
    2064      614984 :      switch (c=inchar(sc)) {
    2065             :      case EOF:
    2066           0 :           return (TOK_EOF);
    2067             :      case '(':
    2068      156654 :           return (TOK_LPAREN);
    2069             :      case ')':
    2070      156654 :           return (TOK_RPAREN);
    2071             :      case '.':
    2072        4039 :           c=inchar(sc);
    2073        4039 :           if(is_one_of(" \n\t",c)) {
    2074        4039 :                return (TOK_DOT);
    2075             :           } else {
    2076           0 :                backchar(sc,c);
    2077           0 :                backchar(sc,'.');
    2078           0 :                return TOK_ATOM;
    2079             :           }
    2080             :      case '\'':
    2081        3760 :           return (TOK_QUOTE);
    2082             :      case ';':
    2083       16390 :            while ((c=inchar(sc)) != '\n' && c!=EOF)
    2084             :              ;
    2085             : 
    2086             : #if SHOW_ERROR_LINE
    2087       16390 :            if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file)
    2088       16390 :              sc->load_stack[sc->file_i].rep.stdio.curr_line++;
    2089             : #endif
    2090             : 
    2091       16390 :        if(c == EOF)
    2092           0 :          { return (TOK_EOF); }
    2093             :        else
    2094       16390 :          { return (token(sc));}
    2095             :      case '"':
    2096       13432 :           return (TOK_DQUOTE);
    2097             :      case BACKQUOTE:
    2098        2687 :           return (TOK_BQUOTE);
    2099             :      case ',':
    2100        5924 :          if ((c=inchar(sc)) == '@') {
    2101        2053 :                return (TOK_ATMARK);
    2102             :          } else {
    2103        3871 :                backchar(sc,c);
    2104        3871 :                return (TOK_COMMA);
    2105             :          }
    2106             :      case '#':
    2107        4596 :           c=inchar(sc);
    2108        4596 :           if (c == '(') {
    2109           0 :                return (TOK_VEC);
    2110        4596 :           } else if(c == '!') {
    2111          49 :                while ((c=inchar(sc)) != '\n' && c!=EOF)
    2112             :                    ;
    2113             : 
    2114             : #if SHOW_ERROR_LINE
    2115          49 :            if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file)
    2116          49 :              sc->load_stack[sc->file_i].rep.stdio.curr_line++;
    2117             : #endif
    2118             : 
    2119          49 :            if(c == EOF)
    2120           0 :              { return (TOK_EOF); }
    2121             :            else
    2122          49 :              { return (token(sc));}
    2123             :           } else {
    2124        4547 :                backchar(sc,c);
    2125        4547 :                if(is_one_of(" tfodxb\\",c)) {
    2126        4547 :                     return TOK_SHARP_CONST;
    2127             :                } else {
    2128           0 :                     return (TOK_SHARP);
    2129             :                }
    2130             :           }
    2131             :      default:
    2132      250848 :           backchar(sc,c);
    2133      250848 :           return (TOK_ATOM);
    2134             :      }
    2135             : }
    2136             : 
    2137             : /* ========== Routines for Printing ========== */
    2138             : #define   ok_abbrev(x)   (is_pair(x) && cdr(x) == sc->NIL)
    2139             : 
    2140         469 : static void printslashstring(scheme *sc, char *p, int len) {
    2141             :   int i;
    2142         469 :   unsigned char *s=(unsigned char*)p;
    2143         469 :   putcharacter(sc,'"');
    2144       14539 :   for ( i=0; i<len; i++) {
    2145       14070 :     if(*s==0xff || *s=='"' || *s<' ' || *s=='\\') {
    2146           0 :       putcharacter(sc,'\\');
    2147           0 :       switch(*s) {
    2148             :       case '"':
    2149           0 :         putcharacter(sc,'"');
    2150           0 :         break;
    2151             :       case '\n':
    2152           0 :         putcharacter(sc,'n');
    2153           0 :         break;
    2154             :       case '\t':
    2155           0 :         putcharacter(sc,'t');
    2156           0 :         break;
    2157             :       case '\r':
    2158           0 :         putcharacter(sc,'r');
    2159           0 :         break;
    2160             :       case '\\':
    2161           0 :         putcharacter(sc,'\\');
    2162           0 :         break;
    2163             :       default: {
    2164           0 :           int d=*s/16;
    2165           0 :           putcharacter(sc,'x');
    2166           0 :           if(d<10) {
    2167           0 :             putcharacter(sc,d+'0');
    2168             :           } else {
    2169           0 :             putcharacter(sc,d-10+'A');
    2170             :           }
    2171           0 :           d=*s%16;
    2172           0 :           if(d<10) {
    2173           0 :             putcharacter(sc,d+'0');
    2174             :           } else {
    2175           0 :             putcharacter(sc,d-10+'A');
    2176             :           }
    2177             :         }
    2178             :       }
    2179           0 :     } else {
    2180       14070 :       putcharacter(sc,*s);
    2181             :     }
    2182       14070 :     s++;
    2183             :   }
    2184         469 :   putcharacter(sc,'"');
    2185         469 : }
    2186             : 
    2187             : 
    2188             : /* print atoms */
    2189       38326 : static void printatom(scheme *sc, pointer l, int f) {
    2190             :   char *p;
    2191             :   int len;
    2192       38326 :   atom2str(sc,l,f,&p,&len);
    2193       38326 :   putchars(sc,p,len);
    2194       38326 : }
    2195             : 
    2196             : 
    2197             : /* Uses internal buffer unless string pointer is already available */
    2198       38419 : static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen) {
    2199             :      char *p;
    2200             : 
    2201       38419 :      if (l == sc->NIL) {
    2202           0 :           p = "()";
    2203       38419 :      } else if (l == sc->T) {
    2204           0 :           p = "#t";
    2205       38419 :      } else if (l == sc->F) {
    2206           0 :           p = "#f";
    2207       38419 :      } else if (l == sc->EOF_OBJ) {
    2208           0 :           p = "#<EOF>";
    2209       38419 :      } else if (is_port(l)) {
    2210           0 :           p = "#<PORT>";
    2211       38419 :      } else if (is_number(l)) {
    2212         134 :           p = sc->strbuff;
    2213         134 :           if (f <= 1 || f == 10) /* f is the base for numbers if > 1 */ {
    2214         268 :               if(num_is_integer(l)) {
    2215         134 :                    snprintf(p, STRBUFFSIZE, "%ld", ivalue_unchecked(l));
    2216             :               } else {
    2217           0 :                    snprintf(p, STRBUFFSIZE, "%.10g", rvalue_unchecked(l));
    2218             :                    /* r5rs says there must be a '.' (unless 'e'?) */
    2219           0 :                    f = strcspn(p, ".e");
    2220           0 :                    if (p[f] == 0) {
    2221           0 :                         p[f] = '.'; /* not found, so add '.0' at the end */
    2222           0 :                         p[f+1] = '0';
    2223           0 :                         p[f+2] = 0;
    2224             :                    }
    2225             :               }
    2226             :           } else {
    2227           0 :               long v = ivalue(l);
    2228           0 :               if (f == 16) {
    2229           0 :                   if (v >= 0)
    2230           0 :                     snprintf(p, STRBUFFSIZE, "%lx", v);
    2231             :                   else
    2232           0 :                     snprintf(p, STRBUFFSIZE, "-%lx", -v);
    2233           0 :               } else if (f == 8) {
    2234           0 :                   if (v >= 0)
    2235           0 :                     snprintf(p, STRBUFFSIZE, "%lo", v);
    2236             :                   else
    2237           0 :                     snprintf(p, STRBUFFSIZE, "-%lo", -v);
    2238           0 :               } else if (f == 2) {
    2239           0 :                   unsigned long b = (v < 0) ? -v : v;
    2240           0 :                   p = &p[STRBUFFSIZE-1];
    2241           0 :                   *p = 0;
    2242           0 :                   do { *--p = (b&1) ? '1' : '0'; b >>= 1; } while (b != 0);
    2243           0 :                   if (v < 0) *--p = '-';
    2244             :               }
    2245             :           }
    2246       38285 :      } else if (is_string(l)) {
    2247        2169 :           if (!f) {
    2248        1700 :                *pp = strvalue(l);
    2249        1700 :                *plen = strlength(l);
    2250        1700 :                return;
    2251             :           } else { /* Hack, uses the fact that printing is needed */
    2252         469 :                *pp=sc->strbuff;
    2253         469 :                *plen=0;
    2254         469 :                printslashstring(sc, strvalue(l), strlength(l));
    2255         469 :                return;
    2256             :           }
    2257       36116 :      } else if (is_character(l)) {
    2258       35038 :           int c=charvalue(l);
    2259       35038 :           p = sc->strbuff;
    2260       35038 :           if (!f) {
    2261       35038 :                p[0]=c;
    2262       35038 :                p[1]=0;
    2263             :           } else {
    2264           0 :                switch(c) {
    2265             :                case ' ':
    2266           0 :                     p = "#\\space";
    2267           0 :                     break;
    2268             :                case '\n':
    2269           0 :                     p = "#\\newline";
    2270           0 :                     break;
    2271             :                case '\r':
    2272           0 :                     p = "#\\return";
    2273           0 :                     break;
    2274             :                case '\t':
    2275           0 :                     p = "#\\tab";
    2276           0 :                     break;
    2277             :                default:
    2278             : #if USE_ASCII_NAMES
    2279           0 :                     if(c==127) {
    2280           0 :                          p = "#\\del";
    2281           0 :                          break;
    2282           0 :                     } else if(c<32) {
    2283           0 :                          snprintf(p,STRBUFFSIZE, "#\\%s",charnames[c]);
    2284           0 :                          break;
    2285             :                     }
    2286             : #else
    2287             :                     if(c<32) {
    2288             :                       snprintf(p,STRBUFFSIZE,"#\\x%x",c);
    2289             :                       break;
    2290             :                     }
    2291             : #endif
    2292           0 :                     snprintf(p,STRBUFFSIZE,"#\\%c",c);
    2293           0 :                     break;
    2294             :                }
    2295             :           }
    2296        1078 :      } else if (is_symbol(l)) {
    2297        1078 :           p = symname(l);
    2298           0 :      } else if (is_proc(l)) {
    2299           0 :           p = sc->strbuff;
    2300           0 :           snprintf(p,STRBUFFSIZE,"#<%s PROCEDURE %ld>", procname(l),procnum(l));
    2301           0 :      } else if (is_macro(l)) {
    2302           0 :           p = "#<MACRO>";
    2303           0 :      } else if (is_closure(l)) {
    2304           0 :           p = "#<CLOSURE>";
    2305           0 :      } else if (is_promise(l)) {
    2306           0 :           p = "#<PROMISE>";
    2307           0 :      } else if (is_foreign(l)) {
    2308           0 :           p = sc->strbuff;
    2309           0 :           snprintf(p,STRBUFFSIZE,"#<FOREIGN PROCEDURE %ld>", procnum(l));
    2310           0 :      } else if (is_continuation(l)) {
    2311           0 :           p = "#<CONTINUATION>";
    2312           0 :      } else if (is_foreign_object(l)) {
    2313           0 :           p = sc->strbuff;
    2314           0 :           l->_object._foreign_object._vtable->to_string(sc, p, STRBUFFSIZE, l->_object._foreign_object._data);
    2315             :      } else {
    2316           0 :           p = "#<ERROR>";
    2317             :      }
    2318       36250 :      *pp=p;
    2319       36250 :      *plen=strlen(p);
    2320             : }
    2321             : /* ========== Routines for Evaluation Cycle ========== */
    2322             : 
    2323             : /* make closure. c is code. e is environment */
    2324       89113 : static pointer mk_closure(scheme *sc, pointer c, pointer e) {
    2325       89113 :      pointer x = get_cell(sc, c, e);
    2326             : 
    2327       89113 :      typeflag(x) = T_CLOSURE;
    2328       89113 :      car(x) = c;
    2329       89113 :      cdr(x) = e;
    2330       89113 :      return (x);
    2331             : }
    2332             : 
    2333             : /* make continuation. */
    2334        3012 : static pointer mk_continuation(scheme *sc, pointer d) {
    2335        3012 :      pointer x = get_cell(sc, sc->NIL, d);
    2336             : 
    2337        3012 :      typeflag(x) = T_CONTINUATION;
    2338        3012 :      cont_dump(x) = d;
    2339        3012 :      return (x);
    2340             : }
    2341             : 
    2342      152284 : static pointer list_star(scheme *sc, pointer d) {
    2343             :   pointer p, q;
    2344      152284 :   if(cdr(d)==sc->NIL) {
    2345      152284 :     return car(d);
    2346             :   }
    2347           0 :   p=cons(sc,car(d),cdr(d));
    2348           0 :   q=p;
    2349           0 :   while(cdr(cdr(p))!=sc->NIL) {
    2350           0 :     d=cons(sc,car(p),cdr(p));
    2351           0 :     if(cdr(cdr(p))!=sc->NIL) {
    2352           0 :       p=cdr(d);
    2353             :     }
    2354             :   }
    2355           0 :   cdr(p)=car(cdr(p));
    2356           0 :   return q;
    2357             : }
    2358             : 
    2359             : /* reverse list -- produce new list */
    2360        1446 : static pointer reverse(scheme *sc, pointer term, pointer list) {
    2361             : /* a must be checked by gc */
    2362        1446 :      pointer a = list, p = term;
    2363             : 
    2364       13682 :      for ( ; is_pair(a); a = cdr(a)) {
    2365       12236 :           p = cons(sc, car(a), p);
    2366             :      }
    2367        1446 :      return (p);
    2368             : }
    2369             : 
    2370             : /* reverse list --- in-place */
    2371     6995379 : static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
    2372     6995379 :      pointer p = list, result = term, q;
    2373             : 
    2374    31078583 :      while (p != sc->NIL) {
    2375    17087825 :           q = cdr(p);
    2376    17087825 :           cdr(p) = result;
    2377    17087825 :           result = p;
    2378    17087825 :           p = q;
    2379             :      }
    2380     6995379 :      return (result);
    2381             : }
    2382             : 
    2383             : /* append list -- produce new list (in reverse order) */
    2384       23897 : static pointer revappend(scheme *sc, pointer a, pointer b) {
    2385       23897 :     pointer result = a;
    2386       23897 :     pointer p = b;
    2387             : 
    2388       63644 :     while (is_pair(p)) {
    2389       15850 :         result = cons(sc, car(p), result);
    2390       15850 :         p = cdr(p);
    2391             :     }
    2392             : 
    2393       23897 :     if (p == sc->NIL) {
    2394       23897 :         return result;
    2395             :     }
    2396             : 
    2397           0 :     return sc->F;   /* signal an error */
    2398             : }
    2399             : 
    2400             : /* equivalence of atoms */
    2401      144063 : int eqv(pointer a, pointer b) {
    2402      144063 :      if (is_string(a)) {
    2403        1576 :           if (is_string(b))
    2404           0 :                return (strvalue(a) == strvalue(b));
    2405             :           else
    2406        1576 :                return (0);
    2407      142487 :      } else if (is_number(a)) {
    2408        7910 :           if (is_number(b)) {
    2409         167 :                if (num_is_integer(a) == num_is_integer(b))
    2410         167 :                     return num_eq(nvalue(a),nvalue(b));
    2411             :           }
    2412        7743 :           return (0);
    2413      134577 :      } else if (is_character(a)) {
    2414         182 :           if (is_character(b))
    2415         182 :                return charvalue(a)==charvalue(b);
    2416             :           else
    2417           0 :                return (0);
    2418      134395 :      } else if (is_port(a)) {
    2419           0 :           if (is_port(b))
    2420           0 :                return a==b;
    2421             :           else
    2422           0 :                return (0);
    2423      134395 :      } else if (is_proc(a)) {
    2424           0 :           if (is_proc(b))
    2425           0 :                return procnum(a)==procnum(b);
    2426             :           else
    2427           0 :                return (0);
    2428             :      } else {
    2429      134395 :           return (a == b);
    2430             :      }
    2431             : }
    2432             : 
    2433             : /* true or false value macro */
    2434             : /* () is #t in R5RS */
    2435             : #define is_true(p)       ((p) != sc->F)
    2436             : #define is_false(p)      ((p) == sc->F)
    2437             : 
    2438             : /* ========== Environment implementation  ========== */
    2439             : 
    2440             : #if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
    2441             : 
    2442     6942565 : static int hash_fn(const char *key, int table_size)
    2443             : {
    2444     6942565 :   unsigned int hashed = 0;
    2445             :   const char *c;
    2446     6942565 :   int bits_per_int = sizeof(unsigned int)*8;
    2447             : 
    2448    39737702 :   for (c = key; *c; c++) {
    2449             :     /* letters have about 5 bits in them */
    2450    32795137 :     hashed = (hashed<<5) | (hashed>>(bits_per_int-5));
    2451    32795137 :     hashed ^= *c;
    2452             :   }
    2453     6942565 :   return hashed % table_size;
    2454             : }
    2455             : #endif
    2456             : 
    2457             : #ifndef USE_ALIST_ENV
    2458             : 
    2459             : /*
    2460             :  * In this implementation, each frame of the environment may be
    2461             :  * a hash table: a vector of alists hashed by variable name.
    2462             :  * In practice, we use a vector only for the initial frame;
    2463             :  * subsequent frames are too small and transient for the lookup
    2464             :  * speed to out-weigh the cost of making a new vector.
    2465             :  */
    2466             : 
    2467     1557296 : static void new_frame_in_env(scheme *sc, pointer old_env)
    2468             : {
    2469             :   pointer new_frame;
    2470             : 
    2471             :   /* The interaction-environment has about 300 variables in it. */
    2472     1557296 :   if (old_env == sc->NIL) {
    2473          51 :     new_frame = mk_vector(sc, 461);
    2474             :   } else {
    2475     1557245 :     new_frame = sc->NIL;
    2476             :   }
    2477             : 
    2478     1557296 :   gc_disable(sc, 1);
    2479     1557296 :   sc->envir = immutable_cons(sc, new_frame, old_env);
    2480     1557296 :   gc_enable(sc);
    2481     1557296 :   setenvironment(sc->envir);
    2482     1557296 : }
    2483             : 
    2484     2569228 : static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
    2485             :                                         pointer variable, pointer value)
    2486             : {
    2487             : #define new_slot_spec_in_env_allocates  2
    2488             :   pointer slot;
    2489     2569228 :   gc_disable(sc, gc_reservations (new_slot_spec_in_env));
    2490     2569228 :   slot = immutable_cons(sc, variable, value);
    2491             : 
    2492     2569228 :   if (is_vector(car(env))) {
    2493       25434 :     int location = hash_fn(symname(variable), ivalue_unchecked(car(env)));
    2494             : 
    2495       25434 :     set_vector_elem(car(env), location,
    2496             :                     immutable_cons(sc, slot, vector_elem(car(env), location)));
    2497             :   } else {
    2498     2543794 :     car(env) = immutable_cons(sc, slot, car(env));
    2499             :   }
    2500     2569228 :   gc_enable(sc);
    2501     2569228 : }
    2502             : 
    2503    12636412 : static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
    2504             : {
    2505             :   pointer x,y;
    2506             :   int location;
    2507             : 
    2508    26648816 :   for (x = env; x != sc->NIL; x = cdr(x)) {
    2509    26647235 :     if (is_vector(car(x))) {
    2510     6611777 :       location = hash_fn(symname(hdl), ivalue_unchecked(car(x)));
    2511     6611777 :       y = vector_elem(car(x), location);
    2512             :     } else {
    2513    20035458 :       y = car(x);
    2514             :     }
    2515    67741182 :     for ( ; y != sc->NIL; y = cdr(y)) {
    2516    53669890 :               if (caar(y) == hdl) {
    2517    12575943 :                    break;
    2518             :               }
    2519             :          }
    2520    26647235 :          if (y != sc->NIL) {
    2521    12575943 :               break;
    2522             :          }
    2523    14071292 :          if(!all) {
    2524       58888 :            return sc->NIL;
    2525             :          }
    2526             :     }
    2527    12577524 :     if (x != sc->NIL) {
    2528    12575943 :           return car(y);
    2529             :     }
    2530        1581 :     return sc->NIL;
    2531             : }
    2532             : 
    2533             : #else /* USE_ALIST_ENV */
    2534             : 
    2535             : static INLINE void new_frame_in_env(scheme *sc, pointer old_env)
    2536             : {
    2537             :   sc->envir = immutable_cons(sc, sc->NIL, old_env);
    2538             :   setenvironment(sc->envir);
    2539             : }
    2540             : 
    2541             : static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
    2542             :                                         pointer variable, pointer value)
    2543             : {
    2544             :   car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env));
    2545             : }
    2546             : 
    2547             : static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
    2548             : {
    2549             :     pointer x,y;
    2550             :     for (x = env; x != sc->NIL; x = cdr(x)) {
    2551             :          for (y = car(x); y != sc->NIL; y = cdr(y)) {
    2552             :               if (caar(y) == hdl) {
    2553             :                    break;
    2554             :               }
    2555             :          }
    2556             :          if (y != sc->NIL) {
    2557             :               break;
    2558             :          }
    2559             :          if(!all) {
    2560             :            return sc->NIL;
    2561             :          }
    2562             :     }
    2563             :     if (x != sc->NIL) {
    2564             :           return car(y);
    2565             :     }
    2566             :     return sc->NIL;
    2567             : }
    2568             : 
    2569             : #endif /* USE_ALIST_ENV else */
    2570             : 
    2571     2565760 : static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value)
    2572             : {
    2573             : #define new_slot_in_env_allocates       new_slot_spec_in_env_allocates
    2574     2565760 :   new_slot_spec_in_env(sc, sc->envir, variable, value);
    2575     2565760 : }
    2576             : 
    2577        6611 : static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value)
    2578             : {
    2579             :   (void)sc;
    2580        6611 :   cdr(slot) = value;
    2581        6611 : }
    2582             : 
    2583    12569332 : static INLINE pointer slot_value_in_env(pointer slot)
    2584             : {
    2585    12569332 :   return cdr(slot);
    2586             : }
    2587             : 
    2588             : /* ========== Evaluation Cycle ========== */
    2589             : 
    2590             : 
    2591           2 : static pointer _Error_1(scheme *sc, const char *s, pointer a) {
    2592           2 :      const char *str = s;
    2593             : #if USE_ERROR_HOOK
    2594             :      pointer x;
    2595           2 :      pointer hdl=sc->ERROR_HOOK;
    2596             : #endif
    2597             : 
    2598             : #if SHOW_ERROR_LINE
    2599             :      char sbuf[STRBUFFSIZE];
    2600             : 
    2601             :      /* make sure error is not in REPL */
    2602           4 :      if (sc->load_stack[sc->file_i].kind & port_file &&
    2603           2 :          sc->load_stack[sc->file_i].rep.stdio.file != stdin) {
    2604           2 :        int ln = sc->load_stack[sc->file_i].rep.stdio.curr_line;
    2605           2 :        const char *fname = sc->load_stack[sc->file_i].rep.stdio.filename;
    2606             : 
    2607             :        /* should never happen */
    2608           2 :        if(!fname) fname = "<unknown>";
    2609             : 
    2610             :        /* we started from 0 */
    2611           2 :        ln++;
    2612           2 :        snprintf(sbuf, STRBUFFSIZE, "(%s : %i) %s", fname, ln, s);
    2613             : 
    2614           2 :        str = (const char*)sbuf;
    2615             :      }
    2616             : #endif
    2617             : 
    2618             : #if USE_ERROR_HOOK
    2619           2 :      x=find_slot_in_env(sc,sc->envir,hdl,1);
    2620           2 :     if (x != sc->NIL) {
    2621           2 :          if(a!=0) {
    2622           0 :                sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL);
    2623             :          } else {
    2624           2 :                sc->code = sc->NIL;
    2625             :          }
    2626           2 :          sc->code = cons(sc, mk_string(sc, str), sc->code);
    2627           2 :          setimmutable(car(sc->code));
    2628           2 :          sc->code = cons(sc, slot_value_in_env(x), sc->code);
    2629           2 :          sc->op = (int)OP_EVAL;
    2630           2 :          return sc->T;
    2631             :     }
    2632             : #endif
    2633             : 
    2634           0 :     if(a!=0) {
    2635           0 :           sc->args = cons(sc, (a), sc->NIL);
    2636             :     } else {
    2637           0 :           sc->args = sc->NIL;
    2638             :     }
    2639           0 :     sc->args = cons(sc, mk_string(sc, str), sc->args);
    2640           0 :     setimmutable(car(sc->args));
    2641           0 :     sc->op = (int)OP_ERR0;
    2642           0 :     return sc->T;
    2643             : }
    2644             : #define Error_1(sc,s, a) return _Error_1(sc,s,a)
    2645             : #define Error_0(sc,s)    return _Error_1(sc,s,0)
    2646             : 
    2647             : /* Too small to turn into function */
    2648             : # define  BEGIN     do {
    2649             : # define  END  } while (0)
    2650             : 
    2651             : /* Bounce back to Eval_Cycle and execute A.  */
    2652             : #define s_goto(sc,a) BEGIN                                  \
    2653             :     sc->op = (int)(a);                                      \
    2654             :     return sc->T; END
    2655             : 
    2656             : #if USE_THREADED_CODE
    2657             : 
    2658             : /* Do not bounce back to Eval_Cycle but execute A by jumping directly
    2659             :  * to it.  Only applicable if A is part of the same dispatch
    2660             :  * function.  */
    2661             : #define s_thread_to(sc, a)      \
    2662             :      BEGIN                      \
    2663             :      op = (int) (a);            \
    2664             :      goto a;                    \
    2665             :      END
    2666             : 
    2667             : /* Define a label OP and emit a case statement for OP.  For use in the
    2668             :  * dispatch functions.  The slightly peculiar goto that is never
    2669             :  * executed avoids warnings about unused labels.  */
    2670             : #define CASE(OP)        if (0) goto OP; OP: case OP
    2671             : 
    2672             : #else   /* USE_THREADED_CODE */
    2673             : #define s_thread_to(sc, a)      s_goto(sc, a)
    2674             : #define CASE(OP)                case OP
    2675             : #endif  /* USE_THREADED_CODE */
    2676             : 
    2677             : /* Return to the previous frame on the dump stack, setting the current
    2678             :  * value to A.  */
    2679             : #define s_return(sc, a) return _s_return(sc, a, 0)
    2680             : 
    2681             : /* Return to the previous frame on the dump stack, setting the current
    2682             :  * value to A, and re-enable the garbage collector.  */
    2683             : #define s_return_enable_gc(sc, a) return _s_return(sc, a, 1)
    2684             : 
    2685        2804 : static INLINE void dump_stack_reset(scheme *sc)
    2686             : {
    2687        2804 :   sc->dump = sc->NIL;
    2688        2804 : }
    2689             : 
    2690          51 : static INLINE void dump_stack_initialize(scheme *sc)
    2691             : {
    2692          51 :   dump_stack_reset(sc);
    2693          51 : }
    2694             : 
    2695          50 : static void dump_stack_free(scheme *sc)
    2696             : {
    2697          50 :   sc->dump = sc->NIL;
    2698          50 : }
    2699             : 
    2700    20833991 : static pointer _s_return(scheme *sc, pointer a, int enable_gc) {
    2701    20833991 :   pointer dump = sc->dump;
    2702             :   pointer op;
    2703    20833991 :   sc->value = (a);
    2704    20833991 :   if (enable_gc)
    2705      251744 :        gc_enable(sc);
    2706    20833991 :   if (dump == sc->NIL)
    2707           0 :     return sc->NIL;
    2708    20833991 :   free_cons(sc, dump, &op, &dump);
    2709    20833991 :   sc->op = ivalue(op);
    2710             : #ifndef USE_SMALL_INTEGERS
    2711             :   free_cell(sc, op);
    2712             : #endif
    2713    20833991 :   free_cons(sc, dump, &sc->args, &dump);
    2714    20833991 :   free_cons(sc, dump, &sc->envir, &dump);
    2715    20833991 :   free_cons(sc, dump, &sc->code, &sc->dump);
    2716    20833991 :   return sc->T;
    2717             : }
    2718             : 
    2719    20834216 : static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
    2720             : #define s_save_allocates        (4 + mk_small_integer_allocates)
    2721             :     pointer dump;
    2722    20834216 :     gc_disable(sc, gc_reservations (s_save));
    2723    20834216 :     dump = cons(sc, sc->envir, cons(sc, (code), sc->dump));
    2724    20834216 :     dump = cons(sc, (args), dump);
    2725    20834216 :     sc->dump = cons(sc, mk_small_integer(sc, (long)(op)), dump);
    2726    20834216 :     gc_enable(sc);
    2727    20834216 : }
    2728             : 
    2729        9237 : static INLINE void dump_stack_mark(scheme *sc)
    2730             : {
    2731        9237 :   mark(sc->dump);
    2732        9237 : }
    2733             : 
    2734             : #define s_retbool(tf)    s_return(sc,(tf) ? sc->T : sc->F)
    2735             : 
    2736    23151210 : static pointer opexe_0(scheme *sc, enum scheme_opcodes op) {
    2737             :      pointer x, y;
    2738             : 
    2739    23151210 :      switch (op) {
    2740             :      CASE(OP_LOAD):       /* load */
    2741          49 :           if(file_interactive(sc)) {
    2742           0 :                fprintf(sc->outport->_object._port->rep.stdio.file,
    2743           0 :                "Loading %s\n", strvalue(car(sc->args)));
    2744             :           }
    2745          49 :           if (!file_push(sc,strvalue(car(sc->args)))) {
    2746           0 :                Error_1(sc,"unable to open", car(sc->args));
    2747             :           }
    2748             :       else
    2749             :         {
    2750          49 :           sc->args = mk_integer(sc,sc->file_i);
    2751          49 :           s_thread_to(sc,OP_T0LVL);
    2752             :         }
    2753             : 
    2754             :      CASE(OP_T0LVL): /* top level */
    2755             :        /* If we reached the end of file, this loop is done. */
    2756       22273 :        if(sc->loadport->_object._port->kind & port_saw_EOF)
    2757             :      {
    2758        2801 :        if(sc->file_i == 0)
    2759             :          {
    2760        2752 :            sc->args=sc->NIL;
    2761        2752 :            sc->nesting = sc->nesting_stack[0];
    2762        2752 :            s_goto(sc,OP_QUIT);
    2763             :          }
    2764             :        else
    2765             :          {
    2766          49 :            file_pop(sc);
    2767          49 :            s_return(sc,sc->value);
    2768             :          }
    2769             :        /* NOTREACHED */
    2770             :      }
    2771             : 
    2772             :        /* If interactive, be nice to user. */
    2773       19472 :        if(file_interactive(sc))
    2774             :      {
    2775           0 :        sc->envir = sc->global_env;
    2776           0 :        dump_stack_reset(sc);
    2777           0 :        putstr(sc,"\n");
    2778           0 :        putstr(sc,prompt);
    2779             :      }
    2780             : 
    2781             :        /* Set up another iteration of REPL */
    2782       19472 :        sc->nesting=0;
    2783       19472 :        sc->save_inport=sc->inport;
    2784       19472 :        sc->inport = sc->loadport;
    2785       19472 :        s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
    2786       19472 :        s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
    2787       19472 :        s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
    2788       19472 :        s_thread_to(sc,OP_READ_INTERNAL);
    2789             : 
    2790             :      CASE(OP_T1LVL): /* top level */
    2791       19472 :           sc->code = sc->value;
    2792       19472 :           sc->inport=sc->save_inport;
    2793       19472 :           s_thread_to(sc,OP_EVAL);
    2794             : 
    2795             :      CASE(OP_READ_INTERNAL):       /* internal read */
    2796       19472 :           sc->tok = token(sc);
    2797       19472 :           if(sc->tok==TOK_EOF)
    2798         354 :         { s_return(sc,sc->EOF_OBJ); }
    2799       19118 :           s_goto(sc,OP_RDSEXPR);
    2800             : 
    2801             :      CASE(OP_GENSYM):
    2802        3671 :           s_return(sc, gensym(sc));
    2803             : 
    2804             :      CASE(OP_VALUEPRINT): /* print evaluation result */
    2805             :           /* OP_VALUEPRINT is always pushed, because when changing from
    2806             :              non-interactive to interactive mode, it needs to be
    2807             :              already on the stack */
    2808       19471 :        if(sc->tracing) {
    2809           0 :          putstr(sc,"\nGives: ");
    2810             :        }
    2811       19471 :        if(file_interactive(sc)) {
    2812           0 :          sc->print_flag = 1;
    2813           0 :          sc->args = sc->value;
    2814           0 :          s_goto(sc,OP_P0LIST);
    2815             :        } else {
    2816       19471 :          s_return(sc,sc->value);
    2817             :        }
    2818             : 
    2819             :      CASE(OP_EVAL):       /* main part of evaluation */
    2820             : #if USE_TRACING
    2821    23059006 :        if(sc->tracing) {
    2822             :          /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
    2823           0 :          s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
    2824           0 :          sc->args=sc->code;
    2825           0 :          putstr(sc,"\nEval: ");
    2826           0 :          s_goto(sc,OP_P0LIST);
    2827             :        }
    2828             :        /* fall through */
    2829             :      CASE(OP_REAL_EVAL):
    2830             : #endif
    2831    23059006 :           if (is_symbol(sc->code)) {    /* symbol */
    2832    12496799 :                x=find_slot_in_env(sc,sc->envir,sc->code,1);
    2833    12496799 :                if (x != sc->NIL) {
    2834    12496799 :                     s_return(sc,slot_value_in_env(x));
    2835             :                } else {
    2836           0 :                     Error_1(sc,"eval: unbound variable:", sc->code);
    2837             :                }
    2838    10562207 :           } else if (is_pair(sc->code)) {
    2839     9798472 :                if (is_syntax(x = car(sc->code))) {     /* SYNTAX */
    2840     3139510 :                     sc->code = cdr(sc->code);
    2841     3139510 :                     s_goto(sc,syntaxnum(x));
    2842             :                } else {/* first, eval top element and eval arguments */
    2843     6658962 :                     s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
    2844             :                     /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
    2845     6658962 :                     sc->code = car(sc->code);
    2846     6658962 :                     s_thread_to(sc,OP_EVAL);
    2847             :                }
    2848             :           } else {
    2849      763735 :                s_return(sc,sc->code);
    2850             :           }
    2851             : 
    2852             :      CASE(OP_E0ARGS):     /* eval arguments */
    2853     6658962 :           if (is_macro(sc->value)) {    /* macro expansion */
    2854       16908 :                gc_disable(sc, 1 + gc_reservations (s_save));
    2855       16908 :                s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
    2856       16908 :                sc->args = cons(sc,sc->code, sc->NIL);
    2857       16908 :                gc_enable(sc);
    2858       16908 :                sc->code = sc->value;
    2859       16908 :                s_thread_to(sc,OP_APPLY);
    2860             :           } else {
    2861     6642054 :                sc->code = cdr(sc->code);
    2862     6642054 :                s_thread_to(sc,OP_E1ARGS);
    2863             :           }
    2864             : 
    2865             :      CASE(OP_E1ARGS):     /* eval arguments */
    2866    16309099 :           gc_disable(sc, 1);
    2867    16309099 :           sc->args = cons(sc, sc->value, sc->args);
    2868    16309099 :           gc_enable(sc);
    2869    16309099 :           if (is_pair(sc->code)) { /* continue */
    2870     9667050 :                s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
    2871     9667050 :                sc->code = car(sc->code);
    2872     9667050 :                sc->args = sc->NIL;
    2873     9667050 :                s_thread_to(sc,OP_EVAL);
    2874             :           } else {  /* end */
    2875     6642049 :                sc->args = reverse_in_place(sc, sc->NIL, sc->args);
    2876     6642049 :                sc->code = car(sc->args);
    2877     6642049 :                sc->args = cdr(sc->args);
    2878     6642049 :                s_thread_to(sc,OP_APPLY);
    2879             :           }
    2880             : 
    2881             : #if USE_TRACING
    2882             :      CASE(OP_TRACING): {
    2883           0 :        int tr=sc->tracing;
    2884           0 :        sc->tracing=ivalue(car(sc->args));
    2885           0 :        gc_disable(sc, 1);
    2886           0 :        s_return_enable_gc(sc, mk_integer(sc, tr));
    2887             :      }
    2888             : #endif
    2889             : 
    2890             :      CASE(OP_APPLY):      /* apply 'code' to 'args' */
    2891             : #if USE_TRACING
    2892     6886795 :        if(sc->tracing) {
    2893           0 :          s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
    2894           0 :          sc->print_flag = 1;
    2895             :          /*  sc->args=cons(sc,sc->code,sc->args);*/
    2896           0 :          putstr(sc,"\nApply to: ");
    2897           0 :          s_goto(sc,OP_P0LIST);
    2898             :        }
    2899             :        /* fall through */
    2900             :      CASE(OP_REAL_APPLY):
    2901             : #endif
    2902     6886795 :           if (is_proc(sc->code)) {
    2903     5452746 :                s_goto(sc,procnum(sc->code));   /* PROCEDURE */
    2904     1434049 :           } else if (is_foreign(sc->code))
    2905             :             {
    2906             :               /* Keep nested calls from GC'ing the arglist */
    2907       50314 :               push_recent_alloc(sc,sc->args,sc->NIL);
    2908       50314 :                x=sc->code->_object._ff(sc,sc->args);
    2909       50313 :                s_return(sc,x);
    2910     1383735 :           } else if (is_closure(sc->code) || is_macro(sc->code)
    2911         216 :              || is_promise(sc->code)) { /* CLOSURE */
    2912             :         /* Should not accept promise */
    2913             :                /* make environment */
    2914     1383530 :                new_frame_in_env(sc, closure_env(sc->code));
    2915     4688975 :                for (x = car(closure_code(sc->code)), y = sc->args;
    2916     1921915 :                     is_pair(x); x = cdr(x), y = cdr(y)) {
    2917     1921915 :                     if (y == sc->NIL) {
    2918           0 :                          Error_1(sc, "not enough arguments, missing:", x);
    2919             :                     } else {
    2920     1921915 :                          new_slot_in_env(sc, car(x), car(y));
    2921             :                     }
    2922             :                }
    2923     1383530 :                if (x == sc->NIL) {
    2924             :                     /*--
    2925             :                      * if (y != sc->NIL) {
    2926             :                      *   Error_0(sc,"too many arguments");
    2927             :                      * }
    2928             :                      */
    2929      341926 :                } else if (is_symbol(x))
    2930      341926 :                     new_slot_in_env(sc, x, y);
    2931             :                else {
    2932           0 :                     Error_1(sc,"syntax error in closure: not a symbol:", x);
    2933             :                }
    2934     1383530 :                sc->code = cdr(closure_code(sc->code));
    2935     1383530 :                sc->args = sc->NIL;
    2936     1383530 :                s_thread_to(sc,OP_BEGIN);
    2937         205 :           } else if (is_continuation(sc->code)) { /* CONTINUATION */
    2938         205 :                sc->dump = cont_dump(sc->code);
    2939         205 :                s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
    2940             :           } else {
    2941           0 :                Error_1(sc,"illegal function",sc->code);
    2942             :           }
    2943             : 
    2944             :      CASE(OP_DOMACRO):    /* do macro */
    2945       16908 :           sc->code = sc->value;
    2946       16908 :           s_thread_to(sc,OP_EVAL);
    2947             : 
    2948             : #if USE_COMPILE_HOOK
    2949             :      CASE(OP_LAMBDA):     /* lambda */
    2950             :           /* If the hook is defined, apply it to sc->code, otherwise
    2951             :              set sc->value fall through */
    2952             :           {
    2953       74061 :                pointer f=find_slot_in_env(sc,sc->envir,sc->COMPILE_HOOK,1);
    2954       74061 :                if(f==sc->NIL) {
    2955        1530 :                     sc->value = sc->code;
    2956             :                     /* Fallthru */
    2957             :                } else {
    2958       72531 :                     gc_disable(sc, 1 + gc_reservations (s_save));
    2959       72531 :                     s_save(sc,OP_LAMBDA1,sc->args,sc->code);
    2960       72531 :                     sc->args=cons(sc,sc->code,sc->NIL);
    2961       72531 :                     gc_enable(sc);
    2962       72531 :                     sc->code=slot_value_in_env(f);
    2963       72531 :                     s_thread_to(sc,OP_APPLY);
    2964             :                }
    2965             :           }
    2966             : 
    2967             : #else
    2968             :      CASE(OP_LAMBDA):     /* lambda */
    2969             :           sc->value = sc->code;
    2970             :           /* Fallthrough. */
    2971             : #endif
    2972             : 
    2973             :      CASE(OP_LAMBDA1):
    2974       74061 :           gc_disable(sc, 1);
    2975       74061 :           s_return_enable_gc(sc, mk_closure(sc, sc->value, sc->envir));
    2976             : 
    2977             : 
    2978             :      CASE(OP_MKCLOSURE): /* make-closure */
    2979           0 :        x=car(sc->args);
    2980           0 :        if(car(x)==sc->LAMBDA) {
    2981           0 :          x=cdr(x);
    2982             :        }
    2983           0 :        if(cdr(sc->args)==sc->NIL) {
    2984           0 :          y=sc->envir;
    2985             :        } else {
    2986           0 :          y=cadr(sc->args);
    2987             :        }
    2988           0 :        gc_disable(sc, 1);
    2989           0 :        s_return_enable_gc(sc, mk_closure(sc, x, y));
    2990             : 
    2991             :      CASE(OP_QUOTE):      /* quote */
    2992     1066547 :           s_return(sc,car(sc->code));
    2993             : 
    2994             :      CASE(OP_DEF0):  /* define */
    2995       54768 :           if(is_immutable(car(sc->code)))
    2996           0 :             Error_1(sc,"define: unable to alter immutable", car(sc->code));
    2997             : 
    2998       54768 :           if (is_pair(car(sc->code))) {
    2999       52160 :                x = caar(sc->code);
    3000       52160 :                gc_disable(sc, 2);
    3001       52160 :                sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
    3002       52160 :                gc_enable(sc);
    3003             :           } else {
    3004        2608 :                x = car(sc->code);
    3005        2608 :                sc->code = cadr(sc->code);
    3006             :           }
    3007       54768 :           if (!is_symbol(x)) {
    3008           0 :                Error_0(sc,"variable is not a symbol");
    3009             :           }
    3010       54768 :           s_save(sc,OP_DEF1, sc->NIL, x);
    3011       54768 :           s_thread_to(sc,OP_EVAL);
    3012             : 
    3013             :      CASE(OP_DEF1):  /* define */
    3014       54768 :           x=find_slot_in_env(sc,sc->envir,sc->code,0);
    3015       54768 :           if (x != sc->NIL) {
    3016         215 :                set_slot_in_env(sc, x, sc->value);
    3017             :           } else {
    3018       54553 :                new_slot_in_env(sc, sc->code, sc->value);
    3019             :           }
    3020       54768 :           s_return(sc,sc->code);
    3021             : 
    3022             : 
    3023             :      CASE(OP_DEFP):  /* defined? */
    3024          51 :           x=sc->envir;
    3025          51 :           if(cdr(sc->args)!=sc->NIL) {
    3026           0 :                x=cadr(sc->args);
    3027             :           }
    3028          51 :           s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
    3029             : 
    3030             :      CASE(OP_SET0):       /* set! */
    3031        6396 :           if(is_immutable(car(sc->code)))
    3032           0 :                 Error_1(sc,"set!: unable to alter immutable variable",car(sc->code));
    3033        6396 :           s_save(sc,OP_SET1, sc->NIL, car(sc->code));
    3034        6396 :           sc->code = cadr(sc->code);
    3035        6396 :           s_thread_to(sc,OP_EVAL);
    3036             : 
    3037             :      CASE(OP_SET1):       /* set! */
    3038        6396 :           y=find_slot_in_env(sc,sc->envir,sc->code,1);
    3039        6396 :           if (y != sc->NIL) {
    3040        6396 :                set_slot_in_env(sc, y, sc->value);
    3041        6396 :                s_return(sc,sc->value);
    3042             :           } else {
    3043           0 :                Error_1(sc,"set!: unbound variable:", sc->code);
    3044             :           }
    3045             : 
    3046             : 
    3047             :      CASE(OP_BEGIN):      /* begin */
    3048     2247585 :           if (!is_pair(sc->code)) {
    3049         663 :                s_return(sc,sc->code);
    3050             :           }
    3051     2246922 :           if (cdr(sc->code) != sc->NIL) {
    3052      103814 :                s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
    3053             :           }
    3054     2246922 :           sc->code = car(sc->code);
    3055     2246922 :           s_thread_to(sc,OP_EVAL);
    3056             : 
    3057             :      CASE(OP_IF0):        /* if */
    3058      715910 :           s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
    3059      715910 :           sc->code = car(sc->code);
    3060      715910 :           s_thread_to(sc,OP_EVAL);
    3061             : 
    3062             :      CASE(OP_IF1):        /* if */
    3063      715908 :           if (is_true(sc->value))
    3064      203694 :                sc->code = car(sc->code);
    3065             :           else
    3066      512214 :                sc->code = cadr(sc->code);  /* (if #f 1) ==> () because
    3067             :                                             * car(sc->NIL) = sc->NIL */
    3068      715908 :           s_thread_to(sc,OP_EVAL);
    3069             : 
    3070             :      CASE(OP_LET0):       /* let */
    3071      159668 :           sc->args = sc->NIL;
    3072      159668 :           sc->value = sc->code;
    3073      159668 :           sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
    3074      159668 :           s_thread_to(sc,OP_LET1);
    3075             : 
    3076             :      CASE(OP_LET1):       /* let (calculate parameters) */
    3077      342479 :           gc_disable(sc, 1 + (is_pair(sc->code) ? gc_reservations (s_save) : 0));
    3078      342479 :           sc->args = cons(sc, sc->value, sc->args);
    3079      342479 :           if (is_pair(sc->code)) { /* continue */
    3080      183019 :                if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) {
    3081           0 :                     gc_enable(sc);
    3082           0 :                     Error_1(sc, "Bad syntax of binding spec in let :",
    3083             :                             car(sc->code));
    3084             :                }
    3085      183019 :                s_save(sc,OP_LET1, sc->args, cdr(sc->code));
    3086      183019 :                gc_enable(sc);
    3087      183019 :                sc->code = cadar(sc->code);
    3088      183019 :                sc->args = sc->NIL;
    3089      183019 :                s_thread_to(sc,OP_EVAL);
    3090             :           } else {  /* end */
    3091      159460 :                gc_enable(sc);
    3092      159460 :                sc->args = reverse_in_place(sc, sc->NIL, sc->args);
    3093      159460 :                sc->code = car(sc->args);
    3094      159460 :                sc->args = cdr(sc->args);
    3095      159460 :                s_thread_to(sc,OP_LET2);
    3096             :           }
    3097             : 
    3098             :      CASE(OP_LET2):       /* let */
    3099      159460 :           new_frame_in_env(sc, sc->envir);
    3100      501731 :           for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
    3101      182811 :                y != sc->NIL; x = cdr(x), y = cdr(y)) {
    3102      182811 :                new_slot_in_env(sc, caar(x), car(y));
    3103             :           }
    3104      159460 :           if (is_symbol(car(sc->code))) {    /* named let */
    3105       33202 :                for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
    3106       18288 :                     if (!is_pair(x))
    3107           0 :                         Error_1(sc, "Bad syntax of binding in let :", x);
    3108       18288 :                     if (!is_list(sc, car(x)))
    3109           0 :                         Error_1(sc, "Bad syntax of binding in let :", car(x));
    3110       18288 :                     gc_disable(sc, 1);
    3111       18288 :                     sc->args = cons(sc, caar(x), sc->args);
    3112       18288 :                     gc_enable(sc);
    3113             :                }
    3114       14914 :                gc_disable(sc, 2 + gc_reservations (new_slot_in_env));
    3115       14914 :                x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir);
    3116       14914 :                new_slot_in_env(sc, car(sc->code), x);
    3117       14914 :                gc_enable(sc);
    3118       14914 :                sc->code = cddr(sc->code);
    3119       14914 :                sc->args = sc->NIL;
    3120             :           } else {
    3121      144546 :                sc->code = cdr(sc->code);
    3122      144546 :                sc->args = sc->NIL;
    3123             :           }
    3124      159460 :           s_thread_to(sc,OP_BEGIN);
    3125             : 
    3126             :      CASE(OP_LET0AST):    /* let* */
    3127       14255 :           if (car(sc->code) == sc->NIL) {
    3128           0 :                new_frame_in_env(sc, sc->envir);
    3129           0 :                sc->code = cdr(sc->code);
    3130           0 :                s_thread_to(sc,OP_BEGIN);
    3131             :           }
    3132       14255 :           if(!is_pair(car(sc->code)) || !is_pair(caar(sc->code)) || !is_pair(cdaar(sc->code))) {
    3133           0 :                Error_1(sc,"Bad syntax of binding spec in let* :",car(sc->code));
    3134             :           }
    3135       14255 :           s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
    3136       14255 :           sc->code = cadaar(sc->code);
    3137       14255 :           s_thread_to(sc,OP_EVAL);
    3138             : 
    3139             :      CASE(OP_LET1AST):    /* let* (make new frame) */
    3140       14255 :           new_frame_in_env(sc, sc->envir);
    3141       14255 :           s_thread_to(sc,OP_LET2AST);
    3142             : 
    3143             :      CASE(OP_LET2AST):    /* let* (calculate parameters) */
    3144       43266 :           new_slot_in_env(sc, caar(sc->code), sc->value);
    3145       43266 :           sc->code = cdr(sc->code);
    3146       43266 :           if (is_pair(sc->code)) { /* continue */
    3147       29011 :                s_save(sc,OP_LET2AST, sc->args, sc->code);
    3148       29011 :                sc->code = cadar(sc->code);
    3149       29011 :                sc->args = sc->NIL;
    3150       29011 :                s_thread_to(sc,OP_EVAL);
    3151             :           } else {  /* end */
    3152       14255 :                sc->code = sc->args;
    3153       14255 :                sc->args = sc->NIL;
    3154       14255 :                s_thread_to(sc,OP_BEGIN);
    3155             :           }
    3156             :      default:
    3157           0 :           snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
    3158           0 :           Error_0(sc,sc->strbuff);
    3159             :      }
    3160             :      return sc->T;
    3161             : }
    3162             : 
    3163     3928668 : static pointer opexe_1(scheme *sc, enum scheme_opcodes op) {
    3164             :      pointer x, y;
    3165             : 
    3166     3928668 :      switch (op) {
    3167             :      CASE(OP_LET0REC):    /* letrec */
    3168           0 :           new_frame_in_env(sc, sc->envir);
    3169           0 :           sc->args = sc->NIL;
    3170           0 :           sc->value = sc->code;
    3171           0 :           sc->code = car(sc->code);
    3172           0 :           s_thread_to(sc,OP_LET1REC);
    3173             : 
    3174             :      CASE(OP_LET1REC):    /* letrec (calculate parameters) */
    3175           0 :           gc_disable(sc, 1);
    3176           0 :           sc->args = cons(sc, sc->value, sc->args);
    3177           0 :           gc_enable(sc);
    3178           0 :           if (is_pair(sc->code)) { /* continue */
    3179           0 :                if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) {
    3180           0 :                     Error_1(sc, "Bad syntax of binding spec in letrec :",
    3181             :                             car(sc->code));
    3182             :                }
    3183           0 :                s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
    3184           0 :                sc->code = cadar(sc->code);
    3185           0 :                sc->args = sc->NIL;
    3186           0 :                s_goto(sc,OP_EVAL);
    3187             :           } else {  /* end */
    3188           0 :                sc->args = reverse_in_place(sc, sc->NIL, sc->args);
    3189           0 :                sc->code = car(sc->args);
    3190           0 :                sc->args = cdr(sc->args);
    3191           0 :                s_thread_to(sc,OP_LET2REC);
    3192             :           }
    3193             : 
    3194             :      CASE(OP_LET2REC):    /* letrec */
    3195           0 :           for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
    3196           0 :                new_slot_in_env(sc, caar(x), car(y));
    3197             :           }
    3198           0 :           sc->code = cdr(sc->code);
    3199           0 :           sc->args = sc->NIL;
    3200           0 :           s_goto(sc,OP_BEGIN);
    3201             : 
    3202             :      CASE(OP_COND0):      /* cond */
    3203      581578 :           if (!is_pair(sc->code)) {
    3204           0 :                Error_0(sc,"syntax error in cond");
    3205             :           }
    3206      581578 :           s_save(sc,OP_COND1, sc->NIL, sc->code);
    3207      581578 :           sc->code = caar(sc->code);
    3208      581578 :           s_goto(sc,OP_EVAL);
    3209             : 
    3210             :      CASE(OP_COND1):      /* cond */
    3211     1579105 :           if (is_true(sc->value)) {
    3212      581578 :                if ((sc->code = cdar(sc->code)) == sc->NIL) {
    3213           0 :                     s_return(sc,sc->value);
    3214             :                }
    3215      581578 :                if(!sc->code || car(sc->code)==sc->FEED_TO) {
    3216           0 :                     if(!is_pair(cdr(sc->code))) {
    3217           0 :                          Error_0(sc,"syntax error in cond");
    3218             :                     }
    3219           0 :                     gc_disable(sc, 4);
    3220           0 :                     x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
    3221           0 :                     sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
    3222           0 :                     gc_enable(sc);
    3223           0 :                     s_goto(sc,OP_EVAL);
    3224             :                }
    3225      581578 :                s_goto(sc,OP_BEGIN);
    3226             :           } else {
    3227      997527 :                if ((sc->code = cdr(sc->code)) == sc->NIL) {
    3228           0 :                     s_return(sc,sc->NIL);
    3229             :                } else {
    3230      997527 :                     s_save(sc,OP_COND1, sc->NIL, sc->code);
    3231      997527 :                     sc->code = caar(sc->code);
    3232      997527 :                     s_goto(sc,OP_EVAL);
    3233             :                }
    3234             :           }
    3235             : 
    3236             :      CASE(OP_DELAY):      /* delay */
    3237         138 :           gc_disable(sc, 2);
    3238         138 :           x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
    3239         138 :           typeflag(x)=T_PROMISE;
    3240         138 :           s_return_enable_gc(sc,x);
    3241             : 
    3242             :      CASE(OP_AND0):       /* and */
    3243      312539 :           if (sc->code == sc->NIL) {
    3244           0 :                s_return(sc,sc->T);
    3245             :           }
    3246      312539 :           s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
    3247      312539 :           sc->code = car(sc->code);
    3248      312539 :           s_goto(sc,OP_EVAL);
    3249             : 
    3250             :      CASE(OP_AND1):       /* and */
    3251      731170 :           if (is_false(sc->value)) {
    3252      249712 :                s_return(sc,sc->value);
    3253      481458 :           } else if (sc->code == sc->NIL) {
    3254       62827 :                s_return(sc,sc->value);
    3255             :           } else {
    3256      418631 :                s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
    3257      418631 :                sc->code = car(sc->code);
    3258      418631 :                s_goto(sc,OP_EVAL);
    3259             :           }
    3260             : 
    3261             :      CASE(OP_OR0):        /* or */
    3262      147827 :           if (sc->code == sc->NIL) {
    3263           0 :                s_return(sc,sc->F);
    3264             :           }
    3265      147827 :           s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
    3266      147827 :           sc->code = car(sc->code);
    3267      147827 :           s_goto(sc,OP_EVAL);
    3268             : 
    3269             :      CASE(OP_OR1):        /* or */
    3270      415978 :           if (is_true(sc->value)) {
    3271        9409 :                s_return(sc,sc->value);
    3272      406569 :           } else if (sc->code == sc->NIL) {
    3273      138418 :                s_return(sc,sc->value);
    3274             :           } else {
    3275      268151 :                s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
    3276      268151 :                sc->code = car(sc->code);
    3277      268151 :                s_goto(sc,OP_EVAL);
    3278             :           }
    3279             : 
    3280             :      CASE(OP_C0STREAM):   /* cons-stream */
    3281           0 :           s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
    3282           0 :           sc->code = car(sc->code);
    3283           0 :           s_goto(sc,OP_EVAL);
    3284             : 
    3285             :      CASE(OP_C1STREAM):   /* cons-stream */
    3286           0 :           sc->args = sc->value;  /* save sc->value to register sc->args for gc */
    3287           0 :           gc_disable(sc, 3);
    3288           0 :           x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
    3289           0 :           typeflag(x)=T_PROMISE;
    3290           0 :           s_return_enable_gc(sc, cons(sc, sc->args, x));
    3291             : 
    3292             :      CASE(OP_MACRO0):     /* macro */
    3293         867 :           if (is_pair(car(sc->code))) {
    3294         765 :                x = caar(sc->code);
    3295         765 :                gc_disable(sc, 2);
    3296         765 :                sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
    3297         765 :                gc_enable(sc);
    3298             :           } else {
    3299         102 :                x = car(sc->code);
    3300         102 :                sc->code = cadr(sc->code);
    3301             :           }
    3302         867 :           if (!is_symbol(x)) {
    3303           0 :                Error_0(sc,"variable is not a symbol");
    3304             :           }
    3305         867 :           s_save(sc,OP_MACRO1, sc->NIL, x);
    3306         867 :           s_goto(sc,OP_EVAL);
    3307             : 
    3308             :      CASE(OP_MACRO1):     /* macro */
    3309         867 :           typeflag(sc->value) = T_MACRO;
    3310         867 :           x = find_slot_in_env(sc, sc->envir, sc->code, 0);
    3311         867 :           if (x != sc->NIL) {
    3312           0 :                set_slot_in_env(sc, x, sc->value);
    3313             :           } else {
    3314         867 :                new_slot_in_env(sc, sc->code, sc->value);
    3315             :           }
    3316         867 :           s_return(sc,sc->code);
    3317             : 
    3318             :      CASE(OP_CASE0):      /* case */
    3319           0 :           s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
    3320           0 :           sc->code = car(sc->code);
    3321           0 :           s_goto(sc,OP_EVAL);
    3322             : 
    3323             :      CASE(OP_CASE1):      /* case */
    3324           0 :           for (x = sc->code; x != sc->NIL; x = cdr(x)) {
    3325           0 :                if (!is_pair(y = caar(x))) {
    3326           0 :                     break;
    3327             :                }
    3328           0 :                for ( ; y != sc->NIL; y = cdr(y)) {
    3329           0 :                     if (eqv(car(y), sc->value)) {
    3330           0 :                          break;
    3331             :                     }
    3332             :                }
    3333           0 :                if (y != sc->NIL) {
    3334           0 :                     break;
    3335             :                }
    3336             :           }
    3337           0 :           if (x != sc->NIL) {
    3338           0 :                if (is_pair(caar(x))) {
    3339           0 :                     sc->code = cdar(x);
    3340           0 :                     s_goto(sc,OP_BEGIN);
    3341             :                } else {/* else */
    3342           0 :                     s_save(sc,OP_CASE2, sc->NIL, cdar(x));
    3343           0 :                     sc->code = caar(x);
    3344           0 :                     s_goto(sc,OP_EVAL);
    3345             :                }
    3346             :           } else {
    3347           0 :                s_return(sc,sc->NIL);
    3348             :           }
    3349             : 
    3350             :      CASE(OP_CASE2):      /* case */
    3351           0 :           if (is_true(sc->value)) {
    3352           0 :                s_goto(sc,OP_BEGIN);
    3353             :           } else {
    3354           0 :                s_return(sc,sc->NIL);
    3355             :           }
    3356             : 
    3357             :      CASE(OP_PAPPLY):     /* apply */
    3358      152284 :           sc->code = car(sc->args);
    3359      152284 :           sc->args = list_star(sc,cdr(sc->args));
    3360             :           /*sc->args = cadr(sc->args);*/
    3361      152284 :           s_goto(sc,OP_APPLY);
    3362             : 
    3363             :      CASE(OP_PEVAL): /* eval */
    3364        3303 :           if(cdr(sc->args)!=sc->NIL) {
    3365        3303 :                sc->envir=cadr(sc->args);
    3366             :           }
    3367        3303 :           sc->code = car(sc->args);
    3368        3303 :           s_goto(sc,OP_EVAL);
    3369             : 
    3370             :      CASE(OP_CONTINUATION):    /* call-with-current-continuation */
    3371        3012 :           sc->code = car(sc->args);
    3372        3012 :           gc_disable(sc, 2);
    3373        3012 :           sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
    3374        3012 :           gc_enable(sc);
    3375        3012 :           s_goto(sc,OP_APPLY);
    3376             : 
    3377             :      default:
    3378           0 :           snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
    3379           0 :           Error_0(sc,sc->strbuff);
    3380             :      }
    3381             :      return sc->T;
    3382             : }
    3383             : 
    3384             : #if USE_PLIST
    3385             : static pointer
    3386             : get_property(scheme *sc, pointer obj, pointer key)
    3387             : {
    3388             :   pointer x;
    3389             : 
    3390             :   assert (is_symbol(obj));
    3391             :   assert (is_symbol(key));
    3392             : 
    3393             :   for (x = symprop(obj); x != sc->NIL; x = cdr(x)) {
    3394             :     if (caar(x) == key)
    3395             :       break;
    3396             :   }
    3397             : 
    3398             :   if (x != sc->NIL)
    3399             :     return cdar(x);
    3400             : 
    3401             :   return sc->NIL;
    3402             : }
    3403             : 
    3404             : static pointer
    3405             : set_property(scheme *sc, pointer obj, pointer key, pointer value)
    3406             : {
    3407             : #define set_property_allocates  2
    3408             :   pointer x;
    3409             : 
    3410             :   assert (is_symbol(obj));
    3411             :   assert (is_symbol(key));
    3412             : 
    3413             :   for (x = symprop(obj); x != sc->NIL; x = cdr(x)) {
    3414             :     if (caar(x) == key)
    3415             :       break;
    3416             :   }
    3417             : 
    3418             :   if (x != sc->NIL)
    3419             :     cdar(x) = value;
    3420             :   else {
    3421             :     gc_disable(sc, gc_reservations(set_property));
    3422             :     symprop(obj) = cons(sc, cons(sc, key, value), symprop(obj));
    3423             :     gc_enable(sc);
    3424             :   }
    3425             : 
    3426             :   return sc->T;
    3427             : }
    3428             : #endif
    3429             : 
    3430     2216433 : static pointer opexe_2(scheme *sc, enum scheme_opcodes op) {
    3431             :      pointer x;
    3432             :      num v;
    3433             : #if USE_MATH
    3434             :      double dd;
    3435             : #endif
    3436             : 
    3437     2216433 :      switch (op) {
    3438             : #if USE_MATH
    3439             :      CASE(OP_INEX2EX):    /* inexact->exact */
    3440             :           x=car(sc->args);
    3441             :           if(num_is_integer(x)) {
    3442             :                s_return(sc,x);
    3443             :           } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
    3444             :                s_return(sc,mk_integer(sc,ivalue(x)));
    3445             :           } else {
    3446             :                Error_1(sc,"inexact->exact: not integral:",x);
    3447             :           }
    3448             : 
    3449             :      CASE(OP_EXP):
    3450             :           x=car(sc->args);
    3451             :           s_return(sc, mk_real(sc, exp(rvalue(x))));
    3452             : 
    3453             :      CASE(OP_LOG):
    3454             :           x=car(sc->args);
    3455             :           s_return(sc, mk_real(sc, log(rvalue(x))));
    3456             : 
    3457             :      CASE(OP_SIN):
    3458             :           x=car(sc->args);
    3459             :           s_return(sc, mk_real(sc, sin(rvalue(x))));
    3460             : 
    3461             :      CASE(OP_COS):
    3462             :           x=car(sc->args);
    3463             :           s_return(sc, mk_real(sc, cos(rvalue(x))));
    3464             : 
    3465             :      CASE(OP_TAN):
    3466             :           x=car(sc->args);
    3467             :           s_return(sc, mk_real(sc, tan(rvalue(x))));
    3468             : 
    3469             :      CASE(OP_ASIN):
    3470             :           x=car(sc->args);
    3471             :           s_return(sc, mk_real(sc, asin(rvalue(x))));
    3472             : 
    3473             :      CASE(OP_ACOS):
    3474             :           x=car(sc->args);
    3475             :           s_return(sc, mk_real(sc, acos(rvalue(x))));
    3476             : 
    3477             :      CASE(OP_ATAN):
    3478             :           x=car(sc->args);
    3479             :           if(cdr(sc->args)==sc->NIL) {
    3480             :                s_return(sc, mk_real(sc, atan(rvalue(x))));
    3481             :           } else {
    3482             :                pointer y=cadr(sc->args);
    3483             :                s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
    3484             :           }
    3485             : 
    3486             :      CASE(OP_SQRT):
    3487             :           x=car(sc->args);
    3488             :           s_return(sc, mk_real(sc, sqrt(rvalue(x))));
    3489             : 
    3490             :      CASE(OP_EXPT): {
    3491             :           double result;
    3492             :           int real_result=1;
    3493             :           pointer y=cadr(sc->args);
    3494             :           x=car(sc->args);
    3495             :           if (num_is_integer(x) && num_is_integer(y))
    3496             :              real_result=0;
    3497             :           /* This 'if' is an R5RS compatibility fix. */
    3498             :           /* NOTE: Remove this 'if' fix for R6RS.    */
    3499             :           if (rvalue(x) == 0 && rvalue(y) < 0) {
    3500             :              result = 0.0;
    3501             :           } else {
    3502             :              result = pow(rvalue(x),rvalue(y));
    3503             :           }
    3504             :           /* Before returning integer result make sure we can. */
    3505             :           /* If the test fails, result is too big for integer. */
    3506             :           if (!real_result)
    3507             :           {
    3508             :             long result_as_long = (long)result;
    3509             :             if (result != (double)result_as_long)
    3510             :               real_result = 1;
    3511             :           }
    3512             :           if (real_result) {
    3513             :              s_return(sc, mk_real(sc, result));
    3514             :           } else {
    3515             :              s_return(sc, mk_integer(sc, result));
    3516             :           }
    3517             :      }
    3518             : 
    3519             :      CASE(OP_FLOOR):
    3520             :           x=car(sc->args);
    3521             :           s_return(sc, mk_real(sc, floor(rvalue(x))));
    3522             : 
    3523             :      CASE(OP_CEILING):
    3524             :           x=car(sc->args);
    3525             :           s_return(sc, mk_real(sc, ceil(rvalue(x))));
    3526             : 
    3527             :      CASE(OP_TRUNCATE ): {
    3528             :           double rvalue_of_x ;
    3529             :           x=car(sc->args);
    3530             :           rvalue_of_x = rvalue(x) ;
    3531             :           if (rvalue_of_x > 0) {
    3532             :             s_return(sc, mk_real(sc, floor(rvalue_of_x)));
    3533             :           } else {
    3534             :             s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
    3535             :           }
    3536             :      }
    3537             : 
    3538             :      CASE(OP_ROUND):
    3539             :         x=car(sc->args);
    3540             :         if (num_is_integer(x))
    3541             :             s_return(sc, x);
    3542             :         s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
    3543             : #endif
    3544             : 
    3545             :      CASE(OP_ADD):        /* + */
    3546       29681 :        v=num_zero;
    3547       89043 :        for (x = sc->args; x != sc->NIL; x = cdr(x)) {
    3548       59362 :          v=num_add(v,nvalue(car(x)));
    3549             :        }
    3550       29681 :        gc_disable(sc, 1);
    3551       29681 :        s_return_enable_gc(sc, mk_number(sc, v));
    3552             : 
    3553             :      CASE(OP_MUL):        /* * */
    3554           0 :        v=num_one;
    3555           0 :        for (x = sc->args; x != sc->NIL; x = cdr(x)) {
    3556           0 :          v=num_mul(v,nvalue(car(x)));
    3557             :        }
    3558           0 :        gc_disable(sc, 1);
    3559           0 :        s_return_enable_gc(sc, mk_number(sc, v));
    3560             : 
    3561             :      CASE(OP_SUB):        /* - */
    3562       14675 :        if(cdr(sc->args)==sc->NIL) {
    3563           0 :          x=sc->args;
    3564           0 :          v=num_zero;
    3565             :        } else {
    3566       14675 :          x = cdr(sc->args);
    3567       14675 :          v = nvalue(car(sc->args));
    3568             :        }
    3569       29350 :        for (; x != sc->NIL; x = cdr(x)) {
    3570       14675 :          v=num_sub(v,nvalue(car(x)));
    3571             :        }
    3572       14675 :        gc_disable(sc, 1);
    3573       14675 :        s_return_enable_gc(sc, mk_number(sc, v));
    3574             : 
    3575             :      CASE(OP_DIV):        /* / */
    3576           0 :        if(cdr(sc->args)==sc->NIL) {
    3577           0 :          x=sc->args;
    3578           0 :          v=num_one;
    3579             :        } else {
    3580           0 :          x = cdr(sc->args);
    3581           0 :          v = nvalue(car(sc->args));
    3582             :        }
    3583           0 :        for (; x != sc->NIL; x = cdr(x)) {
    3584           0 :          if (!is_zero_double(rvalue(car(x))))
    3585           0 :            v=num_div(v,nvalue(car(x)));
    3586             :          else {
    3587           0 :            Error_0(sc,"/: division by zero");
    3588             :          }
    3589             :        }
    3590           0 :        gc_disable(sc, 1);
    3591           0 :        s_return_enable_gc(sc, mk_number(sc, v));
    3592             : 
    3593             :      CASE(OP_INTDIV):        /* quotient */
    3594           0 :           if(cdr(sc->args)==sc->NIL) {
    3595           0 :                x=sc->args;
    3596           0 :                v=num_one;
    3597             :           } else {
    3598           0 :                x = cdr(sc->args);
    3599           0 :                v = nvalue(car(sc->args));
    3600             :           }
    3601           0 :           for (; x != sc->NIL; x = cdr(x)) {
    3602           0 :                if (ivalue(car(x)) != 0)
    3603           0 :                     v=num_intdiv(v,nvalue(car(x)));
    3604             :                else {
    3605           0 :                     Error_0(sc,"quotient: division by zero");
    3606             :                }
    3607             :           }
    3608           0 :           gc_disable(sc, 1);
    3609           0 :           s_return_enable_gc(sc, mk_number(sc, v));
    3610             : 
    3611             :      CASE(OP_REM):        /* remainder */
    3612           0 :           v = nvalue(car(sc->args));
    3613           0 :           if (ivalue(cadr(sc->args)) != 0)
    3614           0 :                v=num_rem(v,nvalue(cadr(sc->args)));
    3615             :           else {
    3616           0 :                Error_0(sc,"remainder: division by zero");
    3617             :           }
    3618           0 :           gc_disable(sc, 1);
    3619           0 :           s_return_enable_gc(sc, mk_number(sc, v));
    3620             : 
    3621             :      CASE(OP_MOD):        /* modulo */
    3622           0 :           v = nvalue(car(sc->args));
    3623           0 :           if (ivalue(cadr(sc->args)) != 0)
    3624           0 :                v=num_mod(v,nvalue(cadr(sc->args)));
    3625             :           else {
    3626           0 :                Error_0(sc,"modulo: division by zero");
    3627             :           }
    3628           0 :           gc_disable(sc, 1);
    3629           0 :           s_return_enable_gc(sc, mk_number(sc, v));
    3630             : 
    3631             :      CASE(OP_CAR):        /* car */
    3632     1401868 :           s_return(sc,caar(sc->args));
    3633             : 
    3634             :      CASE(OP_CDR):        /* cdr */
    3635      486849 :           s_return(sc,cdar(sc->args));
    3636             : 
    3637             :      CASE(OP_CONS):       /* cons */
    3638      161970 :           cdr(sc->args) = cadr(sc->args);
    3639      161970 :           s_return(sc,sc->args);
    3640             : 
    3641             :      CASE(OP_SETCAR):     /* set-car! */
    3642           0 :        if(!is_immutable(car(sc->args))) {
    3643           0 :          caar(sc->args) = cadr(sc->args);
    3644           0 :          s_return(sc,car(sc->args));
    3645             :        } else {
    3646           0 :          Error_0(sc,"set-car!: unable to alter immutable pair");
    3647             :        }
    3648             : 
    3649             :      CASE(OP_SETCDR):     /* set-cdr! */
    3650           0 :        if(!is_immutable(car(sc->args))) {
    3651           0 :          cdar(sc->args) = cadr(sc->args);
    3652           0 :          s_return(sc,car(sc->args));
    3653             :        } else {
    3654           0 :          Error_0(sc,"set-cdr!: unable to alter immutable pair");
    3655             :        }
    3656             : 
    3657             :      CASE(OP_CHAR2INT): { /* char->integer */
    3658             :           char c;
    3659       28510 :           c=(char)ivalue(car(sc->args));
    3660       28510 :           gc_disable(sc, 1);
    3661       28510 :           s_return_enable_gc(sc, mk_integer(sc, (unsigned char) c));
    3662             :      }
    3663             : 
    3664             :      CASE(OP_INT2CHAR): { /* integer->char */
    3665             :           unsigned char c;
    3666           2 :           c=(unsigned char)ivalue(car(sc->args));
    3667           2 :           gc_disable(sc, 1);
    3668           2 :           s_return_enable_gc(sc, mk_character(sc, (char) c));
    3669             :      }
    3670             : 
    3671             :      CASE(OP_CHARUPCASE): {
    3672             :           unsigned char c;
    3673           0 :           c=(unsigned char)ivalue(car(sc->args));
    3674           0 :           c=toupper(c);
    3675           0 :           gc_disable(sc, 1);
    3676           0 :           s_return_enable_gc(sc, mk_character(sc, (char) c));
    3677             :      }
    3678             : 
    3679             :      CASE(OP_CHARDNCASE): {
    3680             :           unsigned char c;
    3681           0 :           c=(unsigned char)ivalue(car(sc->args));
    3682           0 :           c=tolower(c);
    3683           0 :           gc_disable(sc, 1);
    3684           0 :           s_return_enable_gc(sc, mk_character(sc, (char) c));
    3685             :      }
    3686             : 
    3687             :      CASE(OP_STR2SYM):  /* string->symbol */
    3688         149 :           gc_disable(sc, gc_reservations (mk_symbol));
    3689         149 :           s_return_enable_gc(sc, mk_symbol(sc, strvalue(car(sc->args))));
    3690             : 
    3691             :      CASE(OP_STR2ATOM): /* string->atom */ {
    3692          63 :           char *s=strvalue(car(sc->args));
    3693          63 :           long pf = 0;
    3694          63 :           if(cdr(sc->args)!=sc->NIL) {
    3695             :             /* we know cadr(sc->args) is a natural number */
    3696             :             /* see if it is 2, 8, 10, or 16, or error */
    3697          63 :             pf = ivalue_unchecked(cadr(sc->args));
    3698          63 :             if(pf == 16 || pf == 10 || pf == 8 || pf == 2) {
    3699             :                /* base is OK */
    3700             :             }
    3701             :             else {
    3702           0 :               pf = -1;
    3703             :             }
    3704             :           }
    3705          63 :           if (pf < 0) {
    3706           0 :             Error_1(sc, "string->atom: bad base:", cadr(sc->args));
    3707          63 :           } else if(*s=='#') /* no use of base! */ {
    3708           2 :             s_return(sc, mk_sharp_const(sc, s+1));
    3709             :           } else {
    3710          61 :             if (pf == 0 || pf == 10) {
    3711          61 :               s_return(sc, mk_atom(sc, s));
    3712             :             }
    3713             :             else {
    3714             :               char *ep;
    3715           0 :               long iv = strtol(s,&ep,(int )pf);
    3716           0 :               if (*ep == 0) {
    3717           0 :                 s_return(sc, mk_integer(sc, iv));
    3718             :               }
    3719             :               else {
    3720           0 :                 s_return(sc, sc->F);
    3721             :               }
    3722             :             }
    3723             :           }
    3724             :         }
    3725             : 
    3726             :      CASE(OP_SYM2STR): /* symbol->string */
    3727          78 :           gc_disable(sc, 1);
    3728          78 :           x=mk_string(sc,symname(car(sc->args)));
    3729          78 :           setimmutable(x);
    3730          78 :           s_return_enable_gc(sc, x);
    3731             : 
    3732             :      CASE(OP_ATOM2STR): /* atom->string */ {
    3733          93 :           long pf = 0;
    3734          93 :           x=car(sc->args);
    3735          93 :           if(cdr(sc->args)!=sc->NIL) {
    3736             :             /* we know cadr(sc->args) is a natural number */
    3737             :             /* see if it is 2, 8, 10, or 16, or error */
    3738          93 :             pf = ivalue_unchecked(cadr(sc->args));
    3739          93 :             if(is_number(x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2)) {
    3740             :               /* base is OK */
    3741             :             }
    3742             :             else {
    3743           0 :               pf = -1;
    3744             :             }
    3745             :           }
    3746          93 :           if (pf < 0) {
    3747           0 :             Error_1(sc, "atom->string: bad base:", cadr(sc->args));
    3748          93 :           } else if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
    3749             :             char *p;
    3750             :             int len;
    3751          93 :             atom2str(sc,x,(int )pf,&p,&len);
    3752          93 :             gc_disable(sc, 1);
    3753          93 :             s_return_enable_gc(sc, mk_counted_string(sc, p, len));
    3754             :           } else {
    3755           0 :             Error_1(sc, "atom->string: not an atom:", x);
    3756             :           }
    3757             :         }
    3758             : 
    3759             :      CASE(OP_MKSTRING): { /* make-string */
    3760         209 :           int fill=' ';
    3761             :           int len;
    3762             : 
    3763         209 :           len=ivalue(car(sc->args));
    3764             : 
    3765         209 :           if(cdr(sc->args)!=sc->NIL) {
    3766           2 :                fill=charvalue(cadr(sc->args));
    3767             :           }
    3768         209 :           gc_disable(sc, 1);
    3769         209 :           s_return_enable_gc(sc, mk_empty_string(sc, len, (char) fill));
    3770             :      }
    3771             : 
    3772             :      CASE(OP_STRLEN):  /* string-length */
    3773       33039 :           gc_disable(sc, 1);
    3774       33039 :           s_return_enable_gc(sc, mk_integer(sc, strlength(car(sc->args))));
    3775             : 
    3776             :      CASE(OP_STRREF): { /* string-ref */
    3777             :           char *str;
    3778             :           int index;
    3779             : 
    3780       29600 :           str=strvalue(car(sc->args));
    3781             : 
    3782       29600 :           index=ivalue(cadr(sc->args));
    3783             : 
    3784       29600 :           if(index>=strlength(car(sc->args))) {
    3785           0 :                Error_1(sc,"string-ref: out of bounds:",cadr(sc->args));
    3786             :           }
    3787             : 
    3788       29600 :           gc_disable(sc, 1);
    3789       29600 :           s_return_enable_gc(sc,
    3790             :                              mk_character(sc, ((unsigned char*) str)[index]));
    3791             :      }
    3792             : 
    3793             :      CASE(OP_STRSET): { /* string-set! */
    3794             :           char *str;
    3795             :           int index;
    3796             :           int c;
    3797             : 
    3798        1545 :           if(is_immutable(car(sc->args))) {
    3799           0 :                Error_1(sc,"string-set!: unable to alter immutable string:",car(sc->args));
    3800             :           }
    3801        1545 :           str=strvalue(car(sc->args));
    3802             : 
    3803        1545 :           index=ivalue(cadr(sc->args));
    3804        1545 :           if(index>=strlength(car(sc->args))) {
    3805           0 :                Error_1(sc,"string-set!: out of bounds:",cadr(sc->args));
    3806             :           }
    3807             : 
    3808        1545 :           c=charvalue(caddr(sc->args));
    3809             : 
    3810        1545 :           str[index]=(char)c;
    3811        1545 :           s_return(sc,car(sc->args));
    3812             :      }
    3813             : 
    3814             :      CASE(OP_STRAPPEND): { /* string-append */
    3815             :        /* in 1.29 string-append was in Scheme in init.scm but was too slow */
    3816        8294 :        int len = 0;
    3817             :        pointer newstr;
    3818             :        char *pos;
    3819             : 
    3820             :        /* compute needed length for new string */
    3821       30974 :        for (x = sc->args; x != sc->NIL; x = cdr(x)) {
    3822       22680 :           len += strlength(car(x));
    3823             :        }
    3824        8294 :        gc_disable(sc, 1);
    3825        8294 :        newstr = mk_empty_string(sc, len, ' ');
    3826             :        /* store the contents of the argument strings into the new string */
    3827       39268 :        for (pos = strvalue(newstr), x = sc->args; x != sc->NIL;
    3828       22680 :            pos += strlength(car(x)), x = cdr(x)) {
    3829       22680 :            memcpy(pos, strvalue(car(x)), strlength(car(x)));
    3830             :        }
    3831        8294 :        s_return_enable_gc(sc, newstr);
    3832             :      }
    3833             : 
    3834             :      CASE(OP_SUBSTR): { /* substring */
    3835             :           char *str;
    3836             :           int index0;
    3837             :           int index1;
    3838             :           int len;
    3839             : 
    3840       19808 :           str=strvalue(car(sc->args));
    3841             : 
    3842       19808 :           index0=ivalue(cadr(sc->args));
    3843             : 
    3844       19808 :           if(index0>strlength(car(sc->args))) {
    3845           0 :                Error_1(sc,"substring: start out of bounds:",cadr(sc->args));
    3846             :           }
    3847             : 
    3848       19808 :           if(cddr(sc->args)!=sc->NIL) {
    3849       19804 :                index1=ivalue(caddr(sc->args));
    3850       19804 :                if(index1>strlength(car(sc->args)) || index1<index0) {
    3851           0 :                     Error_1(sc,"substring: end out of bounds:",caddr(sc->args));
    3852             :                }
    3853             :           } else {
    3854           4 :                index1=strlength(car(sc->args));
    3855             :           }
    3856             : 
    3857       19808 :           len=index1-index0;
    3858       19808 :           gc_disable(sc, 1);
    3859       19808 :           x=mk_empty_string(sc,len,' ');
    3860       19808 :           memcpy(strvalue(x),str+index0,len);
    3861       19808 :           strvalue(x)[len]=0;
    3862             : 
    3863       19808 :           s_return_enable_gc(sc, x);
    3864             :      }
    3865             : 
    3866             :      CASE(OP_VECTOR): {   /* vector */
    3867             :           int i;
    3868             :           pointer vec;
    3869           0 :           int len=list_length(sc,sc->args);
    3870           0 :           if(len<0) {
    3871           0 :                Error_1(sc,"vector: not a proper list:",sc->args);
    3872             :           }
    3873           0 :           vec=mk_vector(sc,len);
    3874           0 :           if(sc->no_memory) { s_return(sc, sc->sink); }
    3875           0 :           for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
    3876           0 :                set_vector_elem(vec,i,car(x));
    3877             :           }
    3878           0 :           s_return(sc,vec);
    3879             :      }
    3880             : 
    3881             :      CASE(OP_MKVECTOR): { /* make-vector */
    3882           0 :           pointer fill=sc->NIL;
    3883             :           int len;
    3884             :           pointer vec;
    3885             : 
    3886           0 :           len=ivalue(car(sc->args));
    3887             : 
    3888           0 :           if(cdr(sc->args)!=sc->NIL) {
    3889           0 :                fill=cadr(sc->args);
    3890             :           }
    3891           0 :           vec=mk_vector(sc,len);
    3892           0 :           if(sc->no_memory) { s_return(sc, sc->sink); }
    3893           0 :           if(fill!=sc->NIL) {
    3894           0 :                fill_vector(vec,fill);
    3895             :           }
    3896           0 :           s_return(sc,vec);
    3897             :      }
    3898             : 
    3899             :      CASE(OP_VECLEN):  /* vector-length */
    3900           0 :           gc_disable(sc, 1);
    3901           0 :           s_return_enable_gc(sc, mk_integer(sc, ivalue(car(sc->args))));
    3902             : 
    3903             :      CASE(OP_VECREF): { /* vector-ref */
    3904             :           int index;
    3905             : 
    3906           0 :           index=ivalue(cadr(sc->args));
    3907             : 
    3908           0 :           if(index>=ivalue(car(sc->args))) {
    3909           0 :                Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args));
    3910             :           }
    3911             : 
    3912           0 :           s_return(sc,vector_elem(car(sc->args),index));
    3913             :      }
    3914             : 
    3915             :      CASE(OP_VECSET): {   /* vector-set! */
    3916             :           int index;
    3917             : 
    3918           0 :           if(is_immutable(car(sc->args))) {
    3919           0 :                Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args));
    3920             :           }
    3921             : 
    3922           0 :           index=ivalue(cadr(sc->args));
    3923           0 :           if(index>=ivalue(car(sc->args))) {
    3924           0 :                Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args));
    3925             :           }
    3926             : 
    3927           0 :           set_vector_elem(car(sc->args),index,caddr(sc->args));
    3928           0 :           s_return(sc,car(sc->args));
    3929             :      }
    3930             : 
    3931             :      default:
    3932           0 :           snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
    3933           0 :           Error_0(sc,sc->strbuff);
    3934             :      }
    3935             :      return sc->T;
    3936             : }
    3937             : 
    3938       20231 : static int is_list(scheme *sc, pointer a)
    3939       20231 : { return list_length(sc,a) >= 0; }
    3940             : 
    3941             : /* Result is:
    3942             :    proper list: length
    3943             :    circular list: -1
    3944             :    not even a pair: -2
    3945             :    dotted list: -2 minus length before dot
    3946             : */
    3947     5584770 : int list_length(scheme *sc, pointer a) {
    3948     5584770 :     int i=0;
    3949             :     pointer slow, fast;
    3950             : 
    3951     5584770 :     slow = fast = a;
    3952             :     while (1)
    3953             :     {
    3954     7348558 :         if (fast == sc->NIL)
    3955     1735303 :                 return i;
    3956     5613255 :         if (!is_pair(fast))
    3957           0 :                 return -2 - i;
    3958     5613255 :         fast = cdr(fast);
    3959     5613255 :         ++i;
    3960     5613255 :         if (fast == sc->NIL)
    3961     3849467 :                 return i;
    3962     1763788 :         if (!is_pair(fast))
    3963           0 :                 return -2 - i;
    3964     1763788 :         ++i;
    3965     1763788 :         fast = cdr(fast);
    3966             : 
    3967             :         /* Safe because we would have already returned if `fast'
    3968             :            encountered a non-pair. */
    3969     1763788 :         slow = cdr(slow);
    3970     1763788 :         if (fast == slow)
    3971             :         {
    3972             :             /* the fast pointer has looped back around and caught up
    3973             :                with the slow pointer, hence the structure is circular,
    3974             :                not of finite length, and therefore not a list */
    3975           0 :             return -1;
    3976             :         }
    3977     1763788 :     }
    3978             : }
    3979             : 
    3980     2863615 : static pointer opexe_3(scheme *sc, enum scheme_opcodes op) {
    3981             :      pointer x;
    3982             :      num v;
    3983     2863615 :      int (*comp_func)(num,num)=0;
    3984             : 
    3985     2863615 :      switch (op) {
    3986             :      CASE(OP_NOT):        /* not */
    3987      324199 :           s_retbool(is_false(car(sc->args)));
    3988             :      CASE(OP_BOOLP):       /* boolean? */
    3989           0 :           s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
    3990             :      CASE(OP_EOFOBJP):       /* boolean? */
    3991       35076 :           s_retbool(car(sc->args) == sc->EOF_OBJ);
    3992             :      CASE(OP_NULLP):       /* null? */
    3993       85743 :           s_retbool(car(sc->args) == sc->NIL);
    3994             :      CASE(OP_NUMEQ):      /* = */
    3995             :      CASE(OP_LESS):       /* < */
    3996             :      CASE(OP_GRE):        /* > */
    3997             :      CASE(OP_LEQ):        /* <= */
    3998             :      CASE(OP_GEQ):        /* >= */
    3999      354775 :           switch(op) {
    4000      340111 :                case OP_NUMEQ: comp_func=num_eq; break;
    4001          49 :                case OP_LESS:  comp_func=num_lt; break;
    4002        2265 :                case OP_GRE:   comp_func=num_gt; break;
    4003           0 :                case OP_LEQ:   comp_func=num_le; break;
    4004       12350 :                case OP_GEQ:   comp_func=num_ge; break;
    4005           0 :                default: assert (! "reached");
    4006             :           }
    4007      354775 :           x=sc->args;
    4008      354775 :           v=nvalue(car(x));
    4009      354775 :           x=cdr(x);
    4010             : 
    4011      646890 :           for (; x != sc->NIL; x = cdr(x)) {
    4012      354775 :                if(!comp_func(v,nvalue(car(x)))) {
    4013       62660 :                     s_retbool(0);
    4014             :                }
    4015      292115 :            v=nvalue(car(x));
    4016             :           }
    4017      292115 :           s_retbool(1);
    4018             :      CASE(OP_SYMBOLP):     /* symbol? */
    4019         102 :           s_retbool(is_symbol(car(sc->args)));
    4020             :      CASE(OP_NUMBERP):     /* number? */
    4021      128250 :           s_retbool(is_number(car(sc->args)));
    4022             :      CASE(OP_STRINGP):     /* string? */
    4023      215806 :           s_retbool(is_string(car(sc->args)));
    4024             :      CASE(OP_INTEGERP):     /* integer? */
    4025           1 :           s_retbool(is_integer(car(sc->args)));
    4026             :      CASE(OP_REALP):     /* real? */
    4027           0 :           s_retbool(is_number(car(sc->args))); /* All numbers are real */
    4028             :      CASE(OP_CHARP):     /* char? */
    4029           0 :           s_retbool(is_character(car(sc->args)));
    4030             : #if USE_CHAR_CLASSIFIERS
    4031             :      CASE(OP_CHARAP):     /* char-alphabetic? */
    4032           0 :           s_retbool(Cisalpha(ivalue(car(sc->args))));
    4033             :      CASE(OP_CHARNP):     /* char-numeric? */
    4034           0 :           s_retbool(Cisdigit(ivalue(car(sc->args))));
    4035             :      CASE(OP_CHARWP):     /* char-whitespace? */
    4036         617 :           s_retbool(Cisspace(ivalue(car(sc->args))));
    4037             :      CASE(OP_CHARUP):     /* char-upper-case? */
    4038           0 :           s_retbool(Cisupper(ivalue(car(sc->args))));
    4039             :      CASE(OP_CHARLP):     /* char-lower-case? */
    4040           0 :           s_retbool(Cislower(ivalue(car(sc->args))));
    4041             : #endif
    4042             :      CASE(OP_PORTP):     /* port? */
    4043           0 :           s_retbool(is_port(car(sc->args)));
    4044             :      CASE(OP_INPORTP):     /* input-port? */
    4045           0 :           s_retbool(is_inport(car(sc->args)));
    4046             :      CASE(OP_OUTPORTP):     /* output-port? */
    4047           0 :           s_retbool(is_outport(car(sc->args)));
    4048             :      CASE(OP_PROCP):       /* procedure? */
    4049             :           /*--
    4050             :               * continuation should be procedure by the example
    4051             :               * (call-with-current-continuation procedure?) ==> #t
    4052             :                  * in R^3 report sec. 6.9
    4053             :               */
    4054      127997 :           s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
    4055             :                  || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
    4056             :      CASE(OP_PAIRP):       /* pair? */
    4057      660134 :           s_retbool(is_pair(car(sc->args)));
    4058             :      CASE(OP_LISTP):       /* list? */
    4059           0 :        s_retbool(list_length(sc,car(sc->args)) >= 0);
    4060             : 
    4061             :      CASE(OP_ENVP):        /* environment? */
    4062           0 :           s_retbool(is_environment(car(sc->args)));
    4063             :      CASE(OP_VECTORP):     /* vector? */
    4064       33487 :           s_retbool(is_vector(car(sc->args)));
    4065             :      CASE(OP_EQ):         /* eq? */
    4066      753365 :           s_retbool(car(sc->args) == cadr(sc->args));
    4067             :      CASE(OP_EQV):        /* eqv? */
    4068      144063 :           s_retbool(eqv(car(sc->args), cadr(sc->args)));
    4069             :      default:
    4070           0 :           snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
    4071           0 :           Error_0(sc,sc->strbuff);
    4072             :      }
    4073             :      return sc->T;
    4074             : }
    4075             : 
    4076       69397 : static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
    4077             :      pointer x, y;
    4078             : 
    4079       69397 :      switch (op) {
    4080             :      CASE(OP_FORCE):      /* force */
    4081          16 :           sc->code = car(sc->args);
    4082          16 :           if (is_promise(sc->code)) {
    4083             :                /* Should change type to closure here */
    4084          11 :                s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
    4085          11 :                sc->args = sc->NIL;
    4086          11 :                s_goto(sc,OP_APPLY);
    4087             :           } else {
    4088           5 :                s_return(sc,sc->code);
    4089             :           }
    4090             : 
    4091             :      CASE(OP_SAVE_FORCED):     /* Save forced value replacing promise */
    4092          11 :           memcpy(sc->code,sc->value,sizeof(struct cell));
    4093          11 :           s_return(sc,sc->value);
    4094             : 
    4095             :      CASE(OP_WRITE):      /* write */
    4096             :      CASE(OP_DISPLAY):    /* display */
    4097             :      CASE(OP_WRITE_CHAR): /* write-char */
    4098       37158 :           if(is_pair(cdr(sc->args))) {
    4099       35681 :                if(cadr(sc->args)!=sc->outport) {
    4100       35681 :                     x=cons(sc,sc->outport,sc->NIL);
    4101       35681 :                     s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
    4102       35681 :                     sc->outport=cadr(sc->args);
    4103             :                }
    4104             :           }
    4105       37158 :           sc->args = car(sc->args);
    4106       37158 :           if(op==OP_WRITE) {
    4107         349 :                sc->print_flag = 1;
    4108             :           } else {
    4109       36809 :                sc->print_flag = 0;
    4110             :           }
    4111       37158 :           s_goto(sc,OP_P0LIST);
    4112             : 
    4113             :      CASE(OP_NEWLINE):    /* newline */
    4114         195 :           if(is_pair(sc->args)) {
    4115           0 :                if(car(sc->args)!=sc->outport) {
    4116           0 :                     x=cons(sc,sc->outport,sc->NIL);
    4117           0 :                     s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
    4118           0 :                     sc->outport=car(sc->args);
    4119             :                }
    4120             :           }
    4121         195 :           putstr(sc, "\n");
    4122         195 :           s_return(sc,sc->T);
    4123             : 
    4124             :      CASE(OP_ERR0):  /* error */
    4125           0 :           sc->retcode=-1;
    4126           0 :           if (!is_string(car(sc->args))) {
    4127           0 :                sc->args=cons(sc,mk_string(sc," -- "),sc->args);
    4128           0 :                setimmutable(car(sc->args));
    4129             :           }
    4130           0 :           putstr(sc, "Error: ");
    4131           0 :           putstr(sc, strvalue(car(sc->args)));
    4132           0 :           sc->args = cdr(sc->args);
    4133           0 :           s_thread_to(sc,OP_ERR1);
    4134             : 
    4135             :      CASE(OP_ERR1):  /* error */
    4136           0 :           putstr(sc, " ");
    4137           0 :           if (sc->args != sc->NIL) {
    4138           0 :                s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
    4139           0 :                sc->args = car(sc->args);
    4140           0 :                sc->print_flag = 1;
    4141           0 :                s_goto(sc,OP_P0LIST);
    4142             :           } else {
    4143           0 :                putstr(sc, "\n");
    4144           0 :                if(sc->interactive_repl) {
    4145           0 :                     s_goto(sc,OP_T0LVL);
    4146             :                } else {
    4147           0 :                     return sc->NIL;
    4148             :                }
    4149             :           }
    4150             : 
    4151             :      CASE(OP_REVERSE):   /* reverse */
    4152        1446 :           s_return(sc,reverse(sc, sc->NIL, car(sc->args)));
    4153             : 
    4154             :      CASE(OP_LIST_STAR): /* list* */
    4155           0 :           s_return(sc,list_star(sc,sc->args));
    4156             : 
    4157             :      CASE(OP_APPEND):    /* append */
    4158       23897 :           x = sc->NIL;
    4159       23897 :           y = sc->args;
    4160       23897 :           if (y == x) {
    4161           0 :               s_return(sc, x);
    4162             :           }
    4163             : 
    4164             :           /* cdr() in the while condition is not a typo. If car() */
    4165             :           /* is used (append '() 'a) will return the wrong result.*/
    4166       71691 :           while (cdr(y) != sc->NIL) {
    4167       23897 :               x = revappend(sc, x, car(y));
    4168       23897 :               y = cdr(y);
    4169       23897 :               if (x == sc->F) {
    4170           0 :                   Error_0(sc, "non-list argument to append");
    4171             :               }
    4172             :           }
    4173             : 
    4174       23897 :           s_return(sc, reverse_in_place(sc, car(y), x));
    4175             : 
    4176             : #if USE_PLIST
    4177             :      CASE(OP_SET_SYMBOL_PROPERTY): /* set-symbol-property! */
    4178             :           gc_disable(sc, gc_reservations(set_property));
    4179             :           s_return_enable_gc(sc,
    4180             :                              set_property(sc, car(sc->args),
    4181             :                                           cadr(sc->args), caddr(sc->args)));
    4182             : 
    4183             :      CASE(OP_SYMBOL_PROPERTY):  /* symbol-property */
    4184             :           s_return(sc, get_property(sc, car(sc->args), cadr(sc->args)));
    4185             : #endif /* USE_PLIST */
    4186             :      CASE(OP_QUIT):       /* quit */
    4187        2752 :           if(is_pair(sc->args)) {
    4188           0 :                sc->retcode=ivalue(car(sc->args));
    4189             :           }
    4190        2752 :           return (sc->NIL);
    4191             : 
    4192             :      CASE(OP_GC):         /* gc */
    4193           0 :           gc(sc, sc->NIL, sc->NIL);
    4194           0 :           s_return(sc,sc->T);
    4195             : 
    4196             :      CASE(OP_GCVERB):          /* gc-verbose */
    4197          51 :      {    int  was = sc->gc_verbose;
    4198             : 
    4199          51 :           sc->gc_verbose = (car(sc->args) != sc->F);
    4200          51 :           s_retbool(was);
    4201             :      }
    4202             : 
    4203             :      CASE(OP_NEWSEGMENT): /* new-segment */
    4204           0 :           if (!is_pair(sc->args) || !is_number(car(sc->args))) {
    4205           0 :                Error_0(sc,"new-segment: argument must be a number");
    4206             :           }
    4207           0 :           alloc_cellseg(sc, (int) ivalue(car(sc->args)));
    4208           0 :           s_return(sc,sc->T);
    4209             : 
    4210             :      CASE(OP_OBLIST): /* oblist */
    4211           0 :           s_return(sc, oblist_all_symbols(sc));
    4212             : 
    4213             :      CASE(OP_CURR_INPORT): /* current-input-port */
    4214           0 :           s_return(sc,sc->inport);
    4215             : 
    4216             :      CASE(OP_CURR_OUTPORT): /* current-output-port */
    4217           6 :           s_return(sc,sc->outport);
    4218             : 
    4219             :      CASE(OP_OPEN_INFILE): /* open-input-file */
    4220             :      CASE(OP_OPEN_OUTFILE): /* open-output-file */
    4221             :      CASE(OP_OPEN_INOUTFILE): /* open-input-output-file */ {
    4222         989 :           int prop=0;
    4223             :           pointer p;
    4224         989 :           switch(op) {
    4225         884 :                case OP_OPEN_INFILE:     prop=port_input; break;
    4226          13 :                case OP_OPEN_OUTFILE:    prop=port_output; break;
    4227          92 :                case OP_OPEN_INOUTFILE: prop=port_input|port_output; break;
    4228           0 :                default: assert (! "reached");
    4229             :           }
    4230         989 :           p=port_from_filename(sc,strvalue(car(sc->args)),prop);
    4231         989 :           if(p==sc->NIL) {
    4232          64 :                s_return(sc,sc->F);
    4233             :           }
    4234         925 :           s_return(sc,p);
    4235             :           break;
    4236           0 :      default: assert (! "reached");
    4237             :      }
    4238             : 
    4239             : #if USE_STRING_PORTS
    4240             :      CASE(OP_OPEN_INSTRING): /* open-input-string */
    4241             :      CASE(OP_OPEN_INOUTSTRING): /* open-input-output-string */ {
    4242           0 :           int prop=0;
    4243             :           pointer p;
    4244           0 :           switch(op) {
    4245           0 :                case OP_OPEN_INSTRING:     prop=port_input; break;
    4246           0 :                case OP_OPEN_INOUTSTRING:  prop=port_input|port_output; break;
    4247           0 :                default: assert (! "reached");
    4248             :           }
    4249           0 :           p=port_from_string(sc, strvalue(car(sc->args)),
    4250           0 :                  strvalue(car(sc->args))+strlength(car(sc->args)), prop);
    4251           0 :           if(p==sc->NIL) {
    4252           0 :                s_return(sc,sc->F);
    4253             :           }
    4254           0 :           s_return(sc,p);
    4255             :      }
    4256             :      CASE(OP_OPEN_OUTSTRING): /* open-output-string */ {
    4257             :           pointer p;
    4258         385 :           if(car(sc->args)==sc->NIL) {
    4259         385 :                p=port_from_scratch(sc);
    4260         385 :                if(p==sc->NIL) {
    4261           0 :                     s_return(sc,sc->F);
    4262             :                }
    4263             :           } else {
    4264           0 :                p=port_from_string(sc, strvalue(car(sc->args)),
    4265           0 :                       strvalue(car(sc->args))+strlength(car(sc->args)),
    4266             :                           port_output);
    4267           0 :                if(p==sc->NIL) {
    4268           0 :                     s_return(sc,sc->F);
    4269             :                }
    4270             :           }
    4271         385 :           s_return(sc,p);
    4272             :      }
    4273             :      CASE(OP_GET_OUTSTRING): /* get-output-string */ {
    4274             :           port *p;
    4275             : 
    4276         385 :           if ((p=car(sc->args)->_object._port)->kind&port_string) {
    4277             :                off_t size;
    4278             :                char *str;
    4279             : 
    4280         385 :                size=p->rep.string.curr-p->rep.string.start+1;
    4281         385 :                str=sc->malloc(size);
    4282         385 :                if(str != NULL) {
    4283             :                     pointer s;
    4284             : 
    4285         385 :                     memcpy(str,p->rep.string.start,size-1);
    4286         385 :                     str[size-1]='\0';
    4287         385 :                     s=mk_string(sc,str);
    4288         385 :                     sc->free(str);
    4289         385 :                     s_return(sc,s);
    4290             :                }
    4291             :           }
    4292           0 :           s_return(sc,sc->F);
    4293             :      }
    4294             : #endif
    4295             : 
    4296             :      CASE(OP_CLOSE_INPORT): /* close-input-port */
    4297         820 :           port_close(sc,car(sc->args),port_input);
    4298         820 :           s_return(sc,sc->T);
    4299             : 
    4300             :      CASE(OP_CLOSE_OUTPORT): /* close-output-port */
    4301          13 :           port_close(sc,car(sc->args),port_output);
    4302          13 :           s_return(sc,sc->T);
    4303             : 
    4304             :      CASE(OP_INT_ENV): /* interaction-environment */
    4305           0 :           s_return(sc,sc->global_env);
    4306             : 
    4307             :      CASE(OP_CURR_ENV): /* current-environment */
    4308        1273 :           s_return(sc,sc->envir);
    4309             : 
    4310             :      }
    4311             :      return sc->T;
    4312             : }
    4313             : 
    4314      652446 : static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
    4315             :      pointer x;
    4316             : 
    4317      652446 :      if(sc->nesting!=0) {
    4318           0 :           int n=sc->nesting;
    4319           0 :           sc->nesting=0;
    4320           0 :           sc->retcode=-1;
    4321           0 :           Error_1(sc,"unmatched parentheses:",mk_integer(sc,n));
    4322             :      }
    4323             : 
    4324      652446 :      switch (op) {
    4325             :      /* ========== reading part ========== */
    4326             :      CASE(OP_READ):
    4327           0 :           if(!is_pair(sc->args)) {
    4328           0 :                s_goto(sc,OP_READ_INTERNAL);
    4329             :           }
    4330           0 :           if(!is_inport(car(sc->args))) {
    4331           0 :                Error_1(sc,"read: not an input port:",car(sc->args));
    4332             :           }
    4333           0 :           if(car(sc->args)==sc->inport) {
    4334           0 :                s_goto(sc,OP_READ_INTERNAL);
    4335             :           }
    4336           0 :           x=sc->inport;
    4337           0 :           sc->inport=car(sc->args);
    4338           0 :           x=cons(sc,x,sc->NIL);
    4339           0 :           s_save(sc,OP_SET_INPORT, x, sc->NIL);
    4340           0 :           s_goto(sc,OP_READ_INTERNAL);
    4341             : 
    4342             :      CASE(OP_READ_CHAR): /* read-char */
    4343             :      CASE(OP_PEEK_CHAR): /* peek-char */ {
    4344             :           int c;
    4345       70113 :           if(is_pair(sc->args)) {
    4346       70113 :                if(car(sc->args)!=sc->inport) {
    4347       70113 :                     x=sc->inport;
    4348       70113 :                     x=cons(sc,x,sc->NIL);
    4349       70113 :                     s_save(sc,OP_SET_INPORT, x, sc->NIL);
    4350       70113 :                     sc->inport=car(sc->args);
    4351             :                }
    4352             :           }
    4353       70113 :           c=inchar(sc);
    4354       70113 :           if(c==EOF) {
    4355          39 :                s_return(sc,sc->EOF_OBJ);
    4356             :           }
    4357       70074 :           if(sc->op==OP_PEEK_CHAR) {
    4358       35037 :                backchar(sc,c);
    4359             :           }
    4360       70074 :           s_return(sc,mk_character(sc,c));
    4361             :      }
    4362             : 
    4363             :      CASE(OP_CHAR_READY): /* char-ready? */ {
    4364           0 :           pointer p=sc->inport;
    4365             :           int res;
    4366           0 :           if(is_pair(sc->args)) {
    4367           0 :                p=car(sc->args);
    4368             :           }
    4369           0 :           res=p->_object._port->kind&port_string;
    4370           0 :           s_retbool(res);
    4371             :      }
    4372             : 
    4373             :      CASE(OP_SET_INPORT): /* set-input-port */
    4374       70113 :           sc->inport=car(sc->args);
    4375       70113 :           s_return(sc,sc->value);
    4376             : 
    4377             :      CASE(OP_SET_OUTPORT): /* set-output-port */
    4378       35693 :           sc->outport=car(sc->args);
    4379       35693 :           s_return(sc,sc->value);
    4380             : 
    4381             :      CASE(OP_RDSEXPR):
    4382      437852 :           switch (sc->tok) {
    4383             :           case TOK_EOF:
    4384           0 :                s_return(sc,sc->EOF_OBJ);
    4385             :           /* NOTREACHED */
    4386             :           case TOK_VEC:
    4387           0 :                s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
    4388             :                /* fall through */
    4389             :           case TOK_LPAREN:
    4390      156654 :                sc->tok = token(sc);
    4391      156654 :                if (sc->tok == TOK_RPAREN) {
    4392        1595 :                     s_return(sc,sc->NIL);
    4393      155059 :                } else if (sc->tok == TOK_DOT) {
    4394           0 :                     Error_0(sc,"syntax error: illegal dot expression");
    4395             :                } else {
    4396      155059 :                     sc->nesting_stack[sc->file_i]++;
    4397      155059 :                     s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
    4398      155059 :                     s_thread_to(sc,OP_RDSEXPR);
    4399             :                }
    4400             :           case TOK_QUOTE:
    4401        3760 :                s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
    4402        3760 :                sc->tok = token(sc);
    4403        3760 :                s_thread_to(sc,OP_RDSEXPR);
    4404             :           case TOK_BQUOTE:
    4405        2687 :                sc->tok = token(sc);
    4406        2687 :                if(sc->tok==TOK_VEC) {
    4407           0 :                  s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
    4408           0 :                  sc->tok=TOK_LPAREN;
    4409           0 :                  s_thread_to(sc,OP_RDSEXPR);
    4410             :                } else {
    4411        2687 :                  s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
    4412             :                }
    4413        2687 :                s_thread_to(sc,OP_RDSEXPR);
    4414             :           case TOK_COMMA:
    4415        3871 :                s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
    4416        3871 :                sc->tok = token(sc);
    4417        3871 :                s_thread_to(sc,OP_RDSEXPR);
    4418             :           case TOK_ATMARK:
    4419        2053 :                s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
    4420        2053 :                sc->tok = token(sc);
    4421        2053 :                s_thread_to(sc,OP_RDSEXPR);
    4422             :           case TOK_ATOM:
    4423      250848 :                s_return(sc,mk_atom(sc, readstr_upto(sc, DELIMITERS)));
    4424             :           case TOK_DQUOTE:
    4425       13432 :                x=readstrexp(sc);
    4426       13432 :                if(x==sc->F) {
    4427           0 :                  Error_0(sc,"Error reading string");
    4428             :                }
    4429       13432 :                setimmutable(x);
    4430       13432 :                s_return(sc,x);
    4431             :           case TOK_SHARP: {
    4432           0 :                pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
    4433           0 :                if(f==sc->NIL) {
    4434           0 :                     Error_0(sc,"undefined sharp expression");
    4435             :                } else {
    4436           0 :                     sc->code=cons(sc,slot_value_in_env(f),sc->NIL);
    4437           0 :                     s_goto(sc,OP_EVAL);
    4438             :                }
    4439             :           }
    4440             :           case TOK_SHARP_CONST:
    4441        4547 :                if ((x = mk_sharp_const(sc, readstr_upto(sc, DELIMITERS))) == sc->NIL) {
    4442           0 :                     Error_0(sc,"undefined sharp expression");
    4443             :                } else {
    4444        4547 :                     s_return(sc,x);
    4445             :                }
    4446             :           default:
    4447           0 :                Error_0(sc,"syntax error: illegal token");
    4448             :           }
    4449             :           break;
    4450             : 
    4451             :      CASE(OP_RDLIST): {
    4452      402324 :           gc_disable(sc, 1);
    4453      402324 :           sc->args = cons(sc, sc->value, sc->args);
    4454      402324 :           gc_enable(sc);
    4455      402324 :           sc->tok = token(sc);
    4456      402324 :           if (sc->tok == TOK_EOF)
    4457           0 :                { s_return(sc,sc->EOF_OBJ); }
    4458      402324 :           else if (sc->tok == TOK_RPAREN) {
    4459      151020 :                int c = inchar(sc);
    4460      151020 :                if (c != '\n')
    4461       92847 :                  backchar(sc,c);
    4462             : #if SHOW_ERROR_LINE
    4463       58173 :                else if (sc->load_stack[sc->file_i].kind & port_file)
    4464       58173 :                   sc->load_stack[sc->file_i].rep.stdio.curr_line++;
    4465             : #endif
    4466      151020 :                sc->nesting_stack[sc->file_i]--;
    4467      151020 :                s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
    4468      251304 :           } else if (sc->tok == TOK_DOT) {
    4469        4039 :                s_save(sc,OP_RDDOT, sc->args, sc->NIL);
    4470        4039 :                sc->tok = token(sc);
    4471        4039 :                s_thread_to(sc,OP_RDSEXPR);
    4472             :           } else {
    4473      247265 :                s_save(sc,OP_RDLIST, sc->args, sc->NIL);;
    4474      247265 :                s_thread_to(sc,OP_RDSEXPR);
    4475             :           }
    4476             :      }
    4477             : 
    4478             :      CASE(OP_RDDOT):
    4479        4039 :           if (token(sc) != TOK_RPAREN) {
    4480           0 :                Error_0(sc,"syntax error: illegal dot expression");
    4481             :           } else {
    4482        4039 :                sc->nesting_stack[sc->file_i]--;
    4483        4039 :                s_return(sc,reverse_in_place(sc, sc->value, sc->args));
    4484             :           }
    4485             : 
    4486             :      CASE(OP_RDQUOTE):
    4487        3760 :           gc_disable(sc, 2);
    4488        3760 :           s_return_enable_gc(sc, cons(sc, sc->QUOTE,
    4489             :                                       cons(sc, sc->value, sc->NIL)));
    4490             : 
    4491             :      CASE(OP_RDQQUOTE):
    4492        2687 :           gc_disable(sc, 2);
    4493        2687 :           s_return_enable_gc(sc, cons(sc, sc->QQUOTE,
    4494             :                                       cons(sc, sc->value, sc->NIL)));
    4495             : 
    4496             :      CASE(OP_RDQQUOTEVEC):
    4497           0 :           gc_disable(sc, 5 + 2 * gc_reservations (mk_symbol));
    4498           0 :           s_return_enable_gc(sc,cons(sc, mk_symbol(sc,"apply"),
    4499             :            cons(sc, mk_symbol(sc,"vector"),
    4500             :                  cons(sc,cons(sc, sc->QQUOTE,
    4501             :                   cons(sc,sc->value,sc->NIL)),
    4502             :                   sc->NIL))));
    4503             : 
    4504             :      CASE(OP_RDUNQUOTE):
    4505        3871 :           gc_disable(sc, 2);
    4506        3871 :           s_return_enable_gc(sc, cons(sc, sc->UNQUOTE,
    4507             :                                       cons(sc, sc->value, sc->NIL)));
    4508             : 
    4509             :      CASE(OP_RDUQTSP):
    4510        2053 :           gc_disable(sc, 2);
    4511        2053 :           s_return_enable_gc(sc, cons(sc, sc->UNQUOTESP,
    4512             :                                       cons(sc, sc->value, sc->NIL)));
    4513             : 
    4514             :      CASE(OP_RDVEC):
    4515             :           /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
    4516             :           s_goto(sc,OP_EVAL); Cannot be quoted*/
    4517             :           /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
    4518             :           s_return(sc,x); Cannot be part of pairs*/
    4519             :           /*sc->code=mk_proc(sc,OP_VECTOR);
    4520             :           sc->args=sc->value;
    4521             :           s_goto(sc,OP_APPLY);*/
    4522           0 :           sc->args=sc->value;
    4523           0 :           s_goto(sc,OP_VECTOR);
    4524             : 
    4525             :      /* ========== printing part ========== */
    4526             :      CASE(OP_P0LIST):
    4527       38675 :           if(is_vector(sc->args)) {
    4528           0 :                putstr(sc,"#(");
    4529           0 :                sc->args=cons(sc,sc->args,mk_integer(sc,0));
    4530           0 :                s_thread_to(sc,OP_PVECFROM);
    4531       38675 :           } else if(is_environment(sc->args)) {
    4532           0 :                putstr(sc,"#<ENVIRONMENT>");
    4533           0 :                s_return(sc,sc->T);
    4534       38675 :           } else if (!is_pair(sc->args)) {
    4535       38326 :                printatom(sc, sc->args, sc->print_flag);
    4536       38326 :                s_return(sc,sc->T);
    4537         349 :           } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
    4538           0 :                putstr(sc, "'");
    4539           0 :                sc->args = cadr(sc->args);
    4540           0 :                s_thread_to(sc,OP_P0LIST);
    4541         349 :           } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
    4542           0 :                putstr(sc, "`");
    4543           0 :                sc->args = cadr(sc->args);
    4544           0 :                s_thread_to(sc,OP_P0LIST);
    4545         349 :           } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
    4546           0 :                putstr(sc, ",");
    4547           0 :                sc->args = cadr(sc->args);
    4548           0 :                s_thread_to(sc,OP_P0LIST);
    4549         349 :           } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
    4550           0 :                putstr(sc, ",@");
    4551           0 :                sc->args = cadr(sc->args);
    4552           0 :                s_thread_to(sc,OP_P0LIST);
    4553             :           } else {
    4554         349 :                putstr(sc, "(");
    4555         349 :                s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
    4556         349 :                sc->args = car(sc->args);
    4557         349 :                s_thread_to(sc,OP_P0LIST);
    4558             :           }
    4559             : 
    4560             :      CASE(OP_P1LIST):
    4561        1517 :           if (is_pair(sc->args)) {
    4562        1168 :             s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
    4563        1168 :             putstr(sc, " ");
    4564        1168 :             sc->args = car(sc->args);
    4565        1168 :             s_thread_to(sc,OP_P0LIST);
    4566         349 :           } else if(is_vector(sc->args)) {
    4567           0 :             s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
    4568           0 :             putstr(sc, " . ");
    4569           0 :             s_thread_to(sc,OP_P0LIST);
    4570             :           } else {
    4571         349 :             if (sc->args != sc->NIL) {
    4572           0 :               putstr(sc, " . ");
    4573           0 :               printatom(sc, sc->args, sc->print_flag);
    4574             :             }
    4575         349 :             putstr(sc, ")");
    4576         349 :             s_return(sc,sc->T);
    4577             :           }
    4578             :      CASE(OP_PVECFROM): {
    4579           0 :           int i=ivalue_unchecked(cdr(sc->args));
    4580           0 :           pointer vec=car(sc->args);
    4581           0 :           int len=ivalue_unchecked(vec);
    4582           0 :           if(i==len) {
    4583           0 :                putstr(sc,")");
    4584           0 :                s_return(sc,sc->T);
    4585             :           } else {
    4586           0 :                pointer elem=vector_elem(vec,i);
    4587           0 :                ivalue_unchecked(cdr(sc->args))=i+1;
    4588           0 :                s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
    4589           0 :                sc->args=elem;
    4590           0 :                if (i > 0)
    4591           0 :                    putstr(sc," ");
    4592           0 :                s_thread_to(sc,OP_P0LIST);
    4593             :           }
    4594             :      }
    4595             : 
    4596             :      default:
    4597           0 :           snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
    4598           0 :           Error_0(sc,sc->strbuff);
    4599             : 
    4600             :      }
    4601             :      return sc->T;
    4602             : }
    4603             : 
    4604       73567 : static pointer opexe_6(scheme *sc, enum scheme_opcodes op) {
    4605             :      pointer x, y;
    4606             :      long v;
    4607             : 
    4608       73567 :      switch (op) {
    4609             :      CASE(OP_LIST_LENGTH):     /* length */   /* a.k */
    4610        1036 :           v=list_length(sc,car(sc->args));
    4611        1036 :           if(v<0) {
    4612           0 :                Error_1(sc,"length: not a list:",car(sc->args));
    4613             :           }
    4614        1036 :           gc_disable(sc, 1);
    4615        1036 :           s_return_enable_gc(sc, mk_integer(sc, v));
    4616             : 
    4617             :      CASE(OP_ASSQ):       /* assq */     /* a.k */
    4618           0 :           x = car(sc->args);
    4619           0 :           for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
    4620           0 :                if (!is_pair(car(y))) {
    4621           0 :                     Error_0(sc,"unable to handle non pair element");
    4622             :                }
    4623           0 :                if (x == caar(y))
    4624           0 :                     break;
    4625             :           }
    4626           0 :           if (is_pair(y)) {
    4627           0 :                s_return(sc,car(y));
    4628             :           } else {
    4629           0 :                s_return(sc,sc->F);
    4630             :           }
    4631             : 
    4632             : 
    4633             :      CASE(OP_GET_CLOSURE):     /* get-closure-code */   /* a.k */
    4634           0 :           sc->args = car(sc->args);
    4635           0 :           if (sc->args == sc->NIL) {
    4636           0 :                s_return(sc,sc->F);
    4637           0 :           } else if (is_closure(sc->args)) {
    4638           0 :                gc_disable(sc, 1);
    4639           0 :                s_return_enable_gc(sc, cons(sc, sc->LAMBDA,
    4640             :                                            closure_code(sc->value)));
    4641           0 :           } else if (is_macro(sc->args)) {
    4642           0 :                gc_disable(sc, 1);
    4643           0 :                s_return_enable_gc(sc, cons(sc, sc->LAMBDA,
    4644             :                                            closure_code(sc->value)));
    4645             :           } else {
    4646           0 :                s_return(sc,sc->F);
    4647             :           }
    4648             :      CASE(OP_CLOSUREP):        /* closure? */
    4649             :           /*
    4650             :            * Note, macro object is also a closure.
    4651             :            * Therefore, (closure? <#MACRO>) ==> #t
    4652             :            */
    4653           0 :           s_retbool(is_closure(car(sc->args)));
    4654             :      CASE(OP_MACROP):          /* macro? */
    4655       72531 :           s_retbool(is_macro(car(sc->args)));
    4656             :      default:
    4657           0 :           snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
    4658           0 :           Error_0(sc,sc->strbuff);
    4659             :      }
    4660             :      return sc->T; /* NOTREACHED */
    4661             : }
    4662             : 
    4663             : typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes);
    4664             : 
    4665             : typedef int (*test_predicate)(pointer);
    4666             : 
    4667     2966166 : static int is_any(pointer p) {
    4668             :    (void)p;
    4669     2966166 :    return 1;
    4670             : }
    4671             : 
    4672       71124 : static int is_nonneg(pointer p) {
    4673       71124 :   return ivalue(p)>=0 && is_integer(p);
    4674             : }
    4675             : 
    4676             : /* Correspond carefully with following defines! */
    4677             : static struct {
    4678             :   test_predicate fct;
    4679             :   const char *kind;
    4680             : } tests[]={
    4681             :   {0,0}, /* unused */
    4682             :   {is_any, 0},
    4683             :   {is_string, "string"},
    4684             :   {is_symbol, "symbol"},
    4685             :   {is_port, "port"},
    4686             :   {is_inport,"input port"},
    4687             :   {is_outport,"output port"},
    4688             :   {is_environment, "environment"},
    4689             :   {is_pair, "pair"},
    4690             :   {0, "pair or '()"},
    4691             :   {is_character, "character"},
    4692             :   {is_vector, "vector"},
    4693             :   {is_number, "number"},
    4694             :   {is_integer, "integer"},
    4695             :   {is_nonneg, "non-negative integer"}
    4696             : };
    4697             : 
    4698             : #define TST_NONE 0
    4699             : #define TST_ANY "\001"
    4700             : #define TST_STRING "\002"
    4701             : #define TST_SYMBOL "\003"
    4702             : #define TST_PORT "\004"
    4703             : #define TST_INPORT "\005"
    4704             : #define TST_OUTPORT "\006"
    4705             : #define TST_ENVIRONMENT "\007"
    4706             : #define TST_PAIR "\010"
    4707             : #define TST_LIST "\011"
    4708             : #define TST_CHAR "\012"
    4709             : #define TST_VECTOR "\013"
    4710             : #define TST_NUMBER "\014"
    4711             : #define TST_INTEGER "\015"
    4712             : #define TST_NATURAL "\016"
    4713             : 
    4714             : typedef struct {
    4715             :   dispatch_func func;
    4716             :   char *name;
    4717             :   int min_arity;
    4718             :   int max_arity;
    4719             :   char *arg_tests_encoding;
    4720             : } op_code_info;
    4721             : 
    4722             : #define INF_ARG 0xffff
    4723             : 
    4724             : static op_code_info dispatch_table[]= {
    4725             : #define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
    4726             : #include "opdefines.h"
    4727             :   { 0 }
    4728             : };
    4729             : 
    4730           0 : static const char *procname(pointer x) {
    4731           0 :  int n=procnum(x);
    4732           0 :  const char *name=dispatch_table[n].name;
    4733           0 :  if(name==0) {
    4734           0 :      name="ILLEGAL!";
    4735             :  }
    4736           0 :  return name;
    4737             : }
    4738             : 
    4739             : /* kernel of this interpreter */
    4740        2753 : static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
    4741        2753 :   sc->op = op;
    4742             :   for (;;) {
    4743    32955336 :     op_code_info *pcd=dispatch_table+sc->op;
    4744    32955336 :     if (pcd->name!=0) { /* if built-in function, check arguments */
    4745             :       char msg[STRBUFFSIZE];
    4746     5561292 :       int ok=1;
    4747     5561292 :       int n=list_length(sc,sc->args);
    4748             : 
    4749             :       /* Check number of arguments */
    4750     5561292 :       if(n<pcd->min_arity) {
    4751           0 :         ok=0;
    4752           0 :         snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
    4753             :         pcd->name,
    4754           0 :         pcd->min_arity==pcd->max_arity?"":" at least",
    4755             :         pcd->min_arity);
    4756             :       }
    4757     5561292 :       if(ok && n>pcd->max_arity) {
    4758           0 :         ok=0;
    4759           0 :         snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
    4760             :         pcd->name,
    4761           0 :         pcd->min_arity==pcd->max_arity?"":" at most",
    4762             :         pcd->max_arity);
    4763             :       }
    4764     5561292 :       if(ok) {
    4765     5561292 :         if(pcd->arg_tests_encoding!=0) {
    4766     4697579 :           int i=0;
    4767             :           int j;
    4768     4697579 :           const char *t=pcd->arg_tests_encoding;
    4769     4697579 :           pointer arglist=sc->args;
    4770             :           do {
    4771     6119968 :             pointer arg=car(arglist);
    4772     6119968 :             j=(int)t[0];
    4773     6119968 :             if(j==TST_LIST[0]) {
    4774        2484 :                   if(arg!=sc->NIL && !is_pair(arg)) break;
    4775             :             } else {
    4776     6117484 :               if(!tests[j].fct(arg)) break;
    4777             :             }
    4778             : 
    4779     6116634 :             if(t[1]!=0) {/* last test is replicated as necessary */
    4780       93375 :               t++;
    4781             :             }
    4782     6116634 :             arglist=cdr(arglist);
    4783     6116634 :             i++;
    4784     6116634 :           } while(i<n);
    4785     4697579 :           if(i<n) {
    4786           2 :             ok=0;
    4787           2 :             snprintf(msg, STRBUFFSIZE, "%s: argument %d must be: %s, got: %s",
    4788             :                 pcd->name,
    4789             :                 i+1,
    4790             :                 tests[j].kind,
    4791           2 :                 type_to_string(type(car(arglist))));
    4792             :           }
    4793             :         }
    4794             :       }
    4795     5561292 :       if(!ok) {
    4796           2 :         if(_Error_1(sc,msg,0)==sc->NIL) {
    4797           0 :           return;
    4798             :         }
    4799           2 :         pcd=dispatch_table+sc->op;
    4800             :       }
    4801             :     }
    4802    32955336 :     ok_to_freely_gc(sc);
    4803    32955336 :     if (pcd->func(sc, (enum scheme_opcodes)sc->op) == sc->NIL) {
    4804        2752 :       return;
    4805             :     }
    4806    32952583 :     if(sc->no_memory) {
    4807           0 :       fprintf(stderr,"No memory!\n");
    4808           0 :       exit(1);
    4809             :     }
    4810    32952583 :   }
    4811             : }
    4812             : 
    4813             : /* ========== Initialization of internal keywords ========== */
    4814             : 
    4815         816 : static void assign_syntax(scheme *sc, char *name) {
    4816             :      pointer x;
    4817             : 
    4818         816 :      x = oblist_add_by_name(sc, name);
    4819         816 :      typeflag(x) |= T_SYNTAX;
    4820         816 : }
    4821             : 
    4822        5457 : static void assign_proc(scheme *sc, enum scheme_opcodes op, char *name) {
    4823             :      pointer x, y;
    4824             : 
    4825        5457 :      x = mk_symbol(sc, name);
    4826        5457 :      y = mk_proc(sc,op);
    4827        5457 :      new_slot_in_env(sc, x, y);
    4828        5457 : }
    4829             : 
    4830        5457 : static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
    4831             :      pointer y;
    4832             : 
    4833        5457 :      y = get_cell(sc, sc->NIL, sc->NIL);
    4834        5457 :      typeflag(y) = (T_PROC | T_ATOM);
    4835        5457 :      ivalue_unchecked(y) = (long) op;
    4836        5457 :      set_num_integer(y);
    4837        5457 :      return y;
    4838             : }
    4839             : 
    4840             : /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
    4841     3139510 : static int syntaxnum(pointer p) {
    4842     3139510 :      const char *s=strvalue(car(p));
    4843     3139510 :      switch(strlength(car(p))) {
    4844             :      case 2:
    4845      863737 :           if(s[0]=='i') return OP_IF0;        /* if */
    4846      147827 :           else return OP_OR0;                 /* or */
    4847             :      case 3:
    4848      472207 :           if(s[0]=='a') return OP_AND0;      /* and */
    4849      159668 :           else return OP_LET0;               /* let */
    4850             :      case 4:
    4851      602229 :           switch(s[3]) {
    4852           0 :           case 'e': return OP_CASE0;         /* case */
    4853      581578 :           case 'd': return OP_COND0;         /* cond */
    4854       14255 :           case '*': return OP_LET0AST;       /* let* */
    4855        6396 :           default: return OP_SET0;           /* set! */
    4856             :           }
    4857             :      case 5:
    4858     1072508 :           switch(s[2]) {
    4859        4956 :           case 'g': return OP_BEGIN;         /* begin */
    4860         138 :           case 'l': return OP_DELAY;         /* delay */
    4861         867 :           case 'c': return OP_MACRO0;        /* macro */
    4862     1066547 :           default: return OP_QUOTE;          /* quote */
    4863             :           }
    4864             :      case 6:
    4865      128829 :           switch(s[2]) {
    4866       74061 :           case 'm': return OP_LAMBDA;        /* lambda */
    4867       54768 :           case 'f': return OP_DEF0;          /* define */
    4868           0 :           default: return OP_LET0REC;        /* letrec */
    4869             :           }
    4870             :      default:
    4871           0 :           return OP_C0STREAM;                /* cons-stream */
    4872             :      }
    4873             : }
    4874             : 
    4875             : /* initialization of TinyScheme */
    4876             : #if USE_INTERFACE
    4877         322 : INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
    4878         322 :  return cons(sc,a,b);
    4879             : }
    4880           0 : INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
    4881           0 :  return immutable_cons(sc,a,b);
    4882             : }
    4883             : 
    4884             : static struct scheme_interface vtbl ={
    4885             :   scheme_define,
    4886             :   s_cons,
    4887             :   s_immutable_cons,
    4888             :   reserve_cells,
    4889             :   mk_integer,
    4890             :   mk_real,
    4891             :   mk_symbol,
    4892             :   gensym,
    4893             :   mk_string,
    4894             :   mk_counted_string,
    4895             :   mk_character,
    4896             :   mk_vector,
    4897             :   mk_foreign_func,
    4898             :   mk_foreign_object,
    4899             :   get_foreign_object_vtable,
    4900             :   get_foreign_object_data,
    4901             :   putstr,
    4902             :   putcharacter,
    4903             : 
    4904             :   is_string,
    4905             :   string_value,
    4906             :   is_number,
    4907             :   nvalue,
    4908             :   ivalue,
    4909             :   rvalue,
    4910             :   is_integer,
    4911             :   is_real,
    4912             :   is_character,
    4913             :   charvalue,
    4914             :   is_list,
    4915             :   is_vector,
    4916             :   list_length,
    4917             :   ivalue,
    4918             :   fill_vector,
    4919             :   vector_elem,
    4920             :   set_vector_elem,
    4921             :   is_port,
    4922             :   is_pair,
    4923             :   pair_car,
    4924             :   pair_cdr,
    4925             :   set_car,
    4926             :   set_cdr,
    4927             : 
    4928             :   is_symbol,
    4929             :   symname,
    4930             : 
    4931             :   is_syntax,
    4932             :   is_proc,
    4933             :   is_foreign,
    4934             :   syntaxname,
    4935             :   is_closure,
    4936             :   is_macro,
    4937             :   closure_code,
    4938             :   closure_env,
    4939             : 
    4940             :   is_continuation,
    4941             :   is_promise,
    4942             :   is_environment,
    4943             :   is_immutable,
    4944             :   setimmutable,
    4945             : 
    4946             :   scheme_load_file,
    4947             :   scheme_load_string,
    4948             :   port_from_file
    4949             : };
    4950             : #endif
    4951             : 
    4952           0 : scheme *scheme_init_new() {
    4953           0 :   scheme *sc=(scheme*)malloc(sizeof(scheme));
    4954           0 :   if(!scheme_init(sc)) {
    4955           0 :     free(sc);
    4956           0 :     return 0;
    4957             :   } else {
    4958           0 :     return sc;
    4959             :   }
    4960             : }
    4961             : 
    4962          51 : scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
    4963          51 :   scheme *sc=(scheme*)malloc(sizeof(scheme));
    4964          51 :   if(!scheme_init_custom_alloc(sc,malloc,free)) {
    4965           0 :     free(sc);
    4966           0 :     return 0;
    4967             :   } else {
    4968          51 :     return sc;
    4969             :   }
    4970             : }
    4971             : 
    4972             : 
    4973           0 : int scheme_init(scheme *sc) {
    4974           0 :  return scheme_init_custom_alloc(sc,malloc,free);
    4975             : }
    4976             : 
    4977          51 : int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
    4978          51 :   int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
    4979             :   pointer x;
    4980             : 
    4981          51 :   num_zero.is_fixnum=1;
    4982          51 :   num_zero.value.ivalue=0;
    4983          51 :   num_one.is_fixnum=1;
    4984          51 :   num_one.value.ivalue=1;
    4985             : 
    4986             : #if USE_INTERFACE
    4987          51 :   sc->vptr=&vtbl;
    4988             : #endif
    4989          51 :   sc->gensym_cnt=0;
    4990          51 :   sc->malloc=malloc;
    4991          51 :   sc->free=free;
    4992          51 :   sc->last_cell_seg = -1;
    4993          51 :   sc->sink = &sc->_sink;
    4994          51 :   sc->NIL = &sc->_NIL;
    4995          51 :   sc->T = &sc->_HASHT;
    4996          51 :   sc->F = &sc->_HASHF;
    4997          51 :   sc->EOF_OBJ=&sc->_EOF_OBJ;
    4998             : 
    4999             : #if USE_SMALL_INTEGERS
    5000          51 :   if (initialize_small_integers(sc)) {
    5001           0 :     sc->no_memory=1;
    5002           0 :     return 0;
    5003             :   }
    5004             : #endif
    5005             : 
    5006          51 :   sc->free_cell = &sc->_NIL;
    5007          51 :   sc->fcells = 0;
    5008          51 :   sc->inhibit_gc = GC_ENABLED;
    5009          51 :   sc->reserved_cells = 0;
    5010          51 :   sc->reserved_lineno = 0;
    5011          51 :   sc->no_memory=0;
    5012          51 :   sc->inport=sc->NIL;
    5013          51 :   sc->outport=sc->NIL;
    5014          51 :   sc->save_inport=sc->NIL;
    5015          51 :   sc->loadport=sc->NIL;
    5016          51 :   sc->nesting=0;
    5017          51 :   memset (sc->nesting_stack, 0, sizeof sc->nesting_stack);
    5018          51 :   sc->interactive_repl=0;
    5019          51 :   sc->strbuff = sc->malloc(STRBUFFSIZE);
    5020          51 :   if (sc->strbuff == 0) {
    5021           0 :      sc->no_memory=1;
    5022           0 :      return 0;
    5023             :   }
    5024          51 :   sc->strbuff_size = STRBUFFSIZE;
    5025             : 
    5026          51 :   if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
    5027           0 :     sc->no_memory=1;
    5028           0 :     return 0;
    5029             :   }
    5030          51 :   sc->gc_verbose = 0;
    5031          51 :   dump_stack_initialize(sc);
    5032          51 :   sc->code = sc->NIL;
    5033          51 :   sc->tracing=0;
    5034             : 
    5035             :   /* init sc->NIL */
    5036          51 :   typeflag(sc->NIL) = (T_NIL | T_ATOM | MARK);
    5037          51 :   car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
    5038             :   /* init T */
    5039          51 :   typeflag(sc->T) = (T_BOOLEAN | T_ATOM | MARK);
    5040          51 :   car(sc->T) = cdr(sc->T) = sc->T;
    5041             :   /* init F */
    5042          51 :   typeflag(sc->F) = (T_BOOLEAN | T_ATOM | MARK);
    5043          51 :   car(sc->F) = cdr(sc->F) = sc->F;
    5044             :   /* init EOF_OBJ */
    5045          51 :   typeflag(sc->EOF_OBJ) = (T_EOF_OBJ | T_ATOM | MARK);
    5046          51 :   car(sc->EOF_OBJ) = cdr(sc->EOF_OBJ) = sc->EOF_OBJ;
    5047             :   /* init sink */
    5048          51 :   typeflag(sc->sink) = (T_SINK | T_PAIR | MARK);
    5049          51 :   car(sc->sink) = cdr(sc->sink) = sc->NIL;
    5050             :   /* init c_nest */
    5051          51 :   sc->c_nest = sc->NIL;
    5052             : 
    5053          51 :   sc->oblist = oblist_initial_value(sc);
    5054             :   /* init global_env */
    5055          51 :   new_frame_in_env(sc, sc->NIL);
    5056          51 :   sc->global_env = sc->envir;
    5057             :   /* init else */
    5058          51 :   x = mk_symbol(sc,"else");
    5059          51 :   new_slot_in_env(sc, x, sc->T);
    5060             : 
    5061          51 :   assign_syntax(sc, "lambda");
    5062          51 :   assign_syntax(sc, "quote");
    5063          51 :   assign_syntax(sc, "define");
    5064          51 :   assign_syntax(sc, "if");
    5065          51 :   assign_syntax(sc, "begin");
    5066          51 :   assign_syntax(sc, "set!");
    5067          51 :   assign_syntax(sc, "let");
    5068          51 :   assign_syntax(sc, "let*");
    5069          51 :   assign_syntax(sc, "letrec");
    5070          51 :   assign_syntax(sc, "cond");
    5071          51 :   assign_syntax(sc, "delay");
    5072          51 :   assign_syntax(sc, "and");
    5073          51 :   assign_syntax(sc, "or");
    5074          51 :   assign_syntax(sc, "cons-stream");
    5075          51 :   assign_syntax(sc, "macro");
    5076          51 :   assign_syntax(sc, "case");
    5077             : 
    5078        8517 :   for(i=0; i<n; i++) {
    5079        8466 :     if(dispatch_table[i].name!=0) {
    5080        5457 :       assign_proc(sc, (enum scheme_opcodes)i, dispatch_table[i].name);
    5081             :     }
    5082             :   }
    5083             : 
    5084             :   /* initialization of global pointers to special symbols */
    5085          51 :   sc->LAMBDA = mk_symbol(sc, "lambda");
    5086          51 :   sc->QUOTE = mk_symbol(sc, "quote");
    5087          51 :   sc->QQUOTE = mk_symbol(sc, "quasiquote");
    5088          51 :   sc->UNQUOTE = mk_symbol(sc, "unquote");
    5089          51 :   sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
    5090          51 :   sc->FEED_TO = mk_symbol(sc, "=>");
    5091          51 :   sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
    5092          51 :   sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
    5093          51 :   sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
    5094             : #if USE_COMPILE_HOOK
    5095          51 :   sc->COMPILE_HOOK = mk_symbol(sc, "*compile-hook*");
    5096             : #endif
    5097             : 
    5098          51 :   return !sc->no_memory;
    5099             : }
    5100             : 
    5101          51 : void scheme_set_input_port_file(scheme *sc, FILE *fin) {
    5102          51 :   sc->inport=port_from_file(sc,fin,port_input);
    5103          51 : }
    5104             : 
    5105           0 : void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
    5106           0 :   sc->inport=port_from_string(sc,start,past_the_end,port_input);
    5107           0 : }
    5108             : 
    5109          51 : void scheme_set_output_port_file(scheme *sc, FILE *fout) {
    5110          51 :   sc->outport=port_from_file(sc,fout,port_output);
    5111          51 : }
    5112             : 
    5113           0 : void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
    5114           0 :   sc->outport=port_from_string(sc,start,past_the_end,port_output);
    5115           0 : }
    5116             : 
    5117           0 : void scheme_set_external_data(scheme *sc, void *p) {
    5118           0 :  sc->ext_data=p;
    5119           0 : }
    5120             : 
    5121          50 : void scheme_deinit(scheme *sc) {
    5122             :   int i;
    5123             : 
    5124             : #if SHOW_ERROR_LINE
    5125             :   char *fname;
    5126             : #endif
    5127             : 
    5128          50 :   sc->oblist=sc->NIL;
    5129          50 :   sc->global_env=sc->NIL;
    5130          50 :   dump_stack_free(sc);
    5131          50 :   sc->envir=sc->NIL;
    5132          50 :   sc->code=sc->NIL;
    5133          50 :   sc->args=sc->NIL;
    5134          50 :   sc->value=sc->NIL;
    5135          50 :   if(is_port(sc->inport)) {
    5136           0 :     typeflag(sc->inport) = T_ATOM;
    5137             :   }
    5138          50 :   sc->inport=sc->NIL;
    5139          50 :   sc->outport=sc->NIL;
    5140          50 :   if(is_port(sc->save_inport)) {
    5141           0 :     typeflag(sc->save_inport) = T_ATOM;
    5142             :   }
    5143          50 :   sc->save_inport=sc->NIL;
    5144          50 :   if(is_port(sc->loadport)) {
    5145           0 :     typeflag(sc->loadport) = T_ATOM;
    5146             :   }
    5147          50 :   sc->loadport=sc->NIL;
    5148          50 :   sc->gc_verbose=0;
    5149          50 :   gc(sc,sc->NIL,sc->NIL);
    5150             : 
    5151             : #if USE_SMALL_INTEGERS
    5152          50 :   sc->free(sc->integer_alloc);
    5153             : #endif
    5154             : 
    5155         200 :   for(i=0; i<=sc->last_cell_seg; i++) {
    5156         150 :     sc->free(sc->alloc_seg[i]);
    5157             :   }
    5158          50 :   sc->free(sc->strbuff);
    5159             : 
    5160             : #if SHOW_ERROR_LINE
    5161         100 :   for(i=0; i<=sc->file_i; i++) {
    5162          50 :     if (sc->load_stack[i].kind & port_file) {
    5163           0 :       fname = sc->load_stack[i].rep.stdio.filename;
    5164           0 :       if(fname)
    5165           0 :         sc->free(fname);
    5166             :     }
    5167             :   }
    5168             : #endif
    5169          50 : }
    5170             : 
    5171           0 : void scheme_load_file(scheme *sc, FILE *fin)
    5172           0 : { scheme_load_named_file(sc,fin,0); }
    5173             : 
    5174         306 : void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename) {
    5175         306 :   dump_stack_reset(sc);
    5176         306 :   sc->envir = sc->global_env;
    5177         306 :   sc->file_i=0;
    5178         306 :   sc->load_stack[0].kind=port_input|port_file;
    5179         306 :   sc->load_stack[0].rep.stdio.file=fin;
    5180         306 :   sc->loadport=mk_port(sc,sc->load_stack);
    5181         306 :   sc->retcode=0;
    5182         306 :   if(fin==stdin) {
    5183           0 :     sc->interactive_repl=1;
    5184             :   }
    5185             : 
    5186             : #if SHOW_ERROR_LINE
    5187         306 :   sc->load_stack[0].rep.stdio.curr_line = 0;
    5188         306 :   if(fin!=stdin && filename)
    5189         306 :     sc->load_stack[0].rep.stdio.filename = store_string(sc, strlen(filename), filename, 0);
    5190             :   else
    5191           0 :     sc->load_stack[0].rep.stdio.filename = NULL;
    5192             : #endif
    5193             : 
    5194         306 :   sc->inport=sc->loadport;
    5195         306 :   sc->args = mk_integer(sc,sc->file_i);
    5196         306 :   Eval_Cycle(sc, OP_T0LVL);
    5197         305 :   typeflag(sc->loadport)=T_ATOM;
    5198         305 :   if(sc->retcode==0) {
    5199         305 :     sc->retcode=sc->nesting!=0;
    5200             :   }
    5201             : 
    5202             : #if SHOW_ERROR_LINE
    5203         305 :   sc->free(sc->load_stack[0].rep.stdio.filename);
    5204         305 :   sc->load_stack[0].rep.stdio.filename = NULL;
    5205             : #endif
    5206         305 : }
    5207             : 
    5208        2447 : void scheme_load_string(scheme *sc, const char *cmd) {
    5209        2447 :   dump_stack_reset(sc);
    5210        2447 :   sc->envir = sc->global_env;
    5211        2447 :   sc->file_i=0;
    5212        2447 :   sc->load_stack[0].kind=port_input|port_string;
    5213        2447 :   sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */
    5214        2447 :   sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd);
    5215        2447 :   sc->load_stack[0].rep.string.curr=(char*)cmd;
    5216        2447 :   sc->loadport=mk_port(sc,sc->load_stack);
    5217        2447 :   sc->retcode=0;
    5218        2447 :   sc->interactive_repl=0;
    5219        2447 :   sc->inport=sc->loadport;
    5220        2447 :   sc->args = mk_integer(sc,sc->file_i);
    5221        2447 :   Eval_Cycle(sc, OP_T0LVL);
    5222        2447 :   typeflag(sc->loadport)=T_ATOM;
    5223        2447 :   if(sc->retcode==0) {
    5224        2447 :     sc->retcode=sc->nesting!=0;
    5225             :   }
    5226        2447 : }
    5227             : 
    5228        3468 : void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
    5229             :      pointer x;
    5230             : 
    5231        3468 :      x=find_slot_in_env(sc,envir,symbol,0);
    5232        3468 :      if (x != sc->NIL) {
    5233           0 :           set_slot_in_env(sc, x, value);
    5234             :      } else {
    5235        3468 :           new_slot_spec_in_env(sc, envir, symbol, value);
    5236             :      }
    5237        3468 : }
    5238             : 
    5239             : #if !STANDALONE
    5240           0 : void scheme_register_foreign_func(scheme * sc, scheme_registerable * sr)
    5241             : {
    5242           0 :   scheme_define(sc,
    5243             :                 sc->global_env,
    5244             :                 mk_symbol(sc,sr->name),
    5245             :                 mk_foreign_func(sc, sr->f));
    5246           0 : }
    5247             : 
    5248           0 : void scheme_register_foreign_func_list(scheme * sc,
    5249             :                                        scheme_registerable * list,
    5250             :                                        int count)
    5251             : {
    5252             :   int i;
    5253           0 :   for(i = 0; i < count; i++)
    5254             :     {
    5255           0 :       scheme_register_foreign_func(sc, list + i);
    5256             :     }
    5257           0 : }
    5258             : 
    5259           0 : pointer scheme_apply0(scheme *sc, const char *procname)
    5260           0 : { return scheme_eval(sc, cons(sc,mk_symbol(sc,procname),sc->NIL)); }
    5261             : 
    5262           0 : void save_from_C_call(scheme *sc)
    5263             : {
    5264           0 :   pointer saved_data =
    5265           0 :     cons(sc,
    5266             :          car(sc->sink),
    5267             :          cons(sc,
    5268             :               sc->envir,
    5269             :               sc->dump));
    5270             :   /* Push */
    5271           0 :   sc->c_nest = cons(sc, saved_data, sc->c_nest);
    5272             :   /* Truncate the dump stack so TS will return here when done, not
    5273             :      directly resume pre-C-call operations. */
    5274           0 :   dump_stack_reset(sc);
    5275           0 : }
    5276           0 : void restore_from_C_call(scheme *sc)
    5277             : {
    5278           0 :   car(sc->sink) = caar(sc->c_nest);
    5279           0 :   sc->envir = cadar(sc->c_nest);
    5280           0 :   sc->dump = cdr(cdar(sc->c_nest));
    5281             :   /* Pop */
    5282           0 :   sc->c_nest = cdr(sc->c_nest);
    5283           0 : }
    5284             : 
    5285             : /* "func" and "args" are assumed to be already eval'ed. */
    5286           0 : pointer scheme_call(scheme *sc, pointer func, pointer args)
    5287             : {
    5288           0 :   int old_repl = sc->interactive_repl;
    5289           0 :   sc->interactive_repl = 0;
    5290           0 :   save_from_C_call(sc);
    5291           0 :   sc->envir = sc->global_env;
    5292           0 :   sc->args = args;
    5293           0 :   sc->code = func;
    5294           0 :   sc->retcode = 0;
    5295           0 :   Eval_Cycle(sc, OP_APPLY);
    5296           0 :   sc->interactive_repl = old_repl;
    5297           0 :   restore_from_C_call(sc);
    5298           0 :   return sc->value;
    5299             : }
    5300             : 
    5301           0 : pointer scheme_eval(scheme *sc, pointer obj)
    5302             : {
    5303           0 :   int old_repl = sc->interactive_repl;
    5304           0 :   sc->interactive_repl = 0;
    5305           0 :   save_from_C_call(sc);
    5306           0 :   sc->args = sc->NIL;
    5307           0 :   sc->code = obj;
    5308           0 :   sc->retcode = 0;
    5309           0 :   Eval_Cycle(sc, OP_EVAL);
    5310           0 :   sc->interactive_repl = old_repl;
    5311           0 :   restore_from_C_call(sc);
    5312           0 :   return sc->value;
    5313             : }
    5314             : 
    5315             : 
    5316             : #endif
    5317             : 
    5318             : /* ========== Main ========== */
    5319             : 
    5320             : #if STANDALONE
    5321             : 
    5322             : #if defined(__APPLE__) && !defined (OSX)
    5323             : int main()
    5324             : {
    5325             :      extern MacTS_main(int argc, char **argv);
    5326             :      char**    argv;
    5327             :      int argc = ccommand(&argv);
    5328             :      MacTS_main(argc,argv);
    5329             :      return 0;
    5330             : }
    5331             : int MacTS_main(int argc, char **argv) {
    5332             : #else
    5333             : int main(int argc, char **argv) {
    5334             : #endif
    5335             :   scheme sc;
    5336             :   FILE *fin;
    5337             :   char *file_name=InitFile;
    5338             :   int retcode;
    5339             :   int isfile=1;
    5340             : 
    5341             :   if(argc==1) {
    5342             :     printf(banner);
    5343             :   }
    5344             :   if(argc==2 && strcmp(argv[1],"-?")==0) {
    5345             :     printf("Usage: tinyscheme -?\n");
    5346             :     printf("or:    tinyscheme [<file1> <file2> ...]\n");
    5347             :     printf("followed by\n");
    5348             :     printf("          -1 <file> [<arg1> <arg2> ...]\n");
    5349             :     printf("          -c <Scheme commands> [<arg1> <arg2> ...]\n");
    5350             :     printf("assuming that the executable is named tinyscheme.\n");
    5351             :     printf("Use - as filename for stdin.\n");
    5352             :     return 1;
    5353             :   }
    5354             :   if(!scheme_init(&sc)) {
    5355             :     fprintf(stderr,"Could not initialize!\n");
    5356             :     return 2;
    5357             :   }
    5358             :   scheme_set_input_port_file(&sc, stdin);
    5359             :   scheme_set_output_port_file(&sc, stdout);
    5360             : #if USE_DL
    5361             :   scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext));
    5362             : #endif
    5363             :   argv++;
    5364             :   if(access(file_name,0)!=0) {
    5365             :     char *p=getenv("TINYSCHEMEINIT");
    5366             :     if(p!=0) {
    5367             :       file_name=p;
    5368             :     }
    5369             :   }
    5370             :   do {
    5371             :     if(strcmp(file_name,"-")==0) {
    5372             :       fin=stdin;
    5373             :     } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
    5374             :       pointer args=sc.NIL;
    5375             :       isfile=file_name[1]=='1';
    5376             :       file_name=*argv++;
    5377             :       if(strcmp(file_name,"-")==0) {
    5378             :         fin=stdin;
    5379             :       } else if(isfile) {
    5380             :         fin=fopen(file_name,"r");
    5381             :       }
    5382             :       for(;*argv;argv++) {
    5383             :         pointer value=mk_string(&sc,*argv);
    5384             :         args=cons(&sc,value,args);
    5385             :       }
    5386             :       args=reverse_in_place(&sc,sc.NIL,args);
    5387             :       scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
    5388             : 
    5389             :     } else {
    5390             :       fin=fopen(file_name,"r");
    5391             :     }
    5392             :     if(isfile && fin==0) {
    5393             :       fprintf(stderr,"Could not open file %s\n",file_name);
    5394             :     } else {
    5395             :       if(isfile) {
    5396             :         scheme_load_named_file(&sc,fin,file_name);
    5397             :       } else {
    5398             :         scheme_load_string(&sc,file_name);
    5399             :       }
    5400             :       if(!isfile || fin!=stdin) {
    5401             :         if(sc.retcode!=0) {
    5402             :           fprintf(stderr,"Errors encountered reading %s\n",file_name);
    5403             :         }
    5404             :         if(isfile) {
    5405             :           fclose(fin);
    5406             :         }
    5407             :       }
    5408             :     }
    5409             :     file_name=*argv++;
    5410             :   } while(file_name!=0);
    5411             :   if(argc==1) {
    5412             :     scheme_load_named_file(&sc,stdin,0);
    5413             :   }
    5414             :   retcode=sc.retcode;
    5415             :   scheme_deinit(&sc);
    5416             : 
    5417             :   return retcode;
    5418             : }
    5419             : 
    5420             : #endif
    5421             : 
    5422             : /*
    5423             : Local variables:
    5424             : c-file-style: "k&r"
    5425             : End:
    5426             : */

Generated by: LCOV version 1.11