1 /* T I N Y S C H E M E 1 . 3 3
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.
8 * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
10 * (MINISCM) This is a revised and modified version by Akira KIDA.
11 * (MINISCM) current version is 0.85k4 (15 May 1994)
15 #define _SCHEME_SOURCE
16 #include "scheme-private.h"
29 #define stricmp strcasecmp
34 void dump_protect(scheme *sc);
39 static void memleakcheck(scheme *sc);
42 /* Used for documentation purposes, to signal functions in 'interface' */
57 #define TOK_SHARP_CONST 11
60 # define BACKQUOTE '`'
63 * Basic memory allocation units
66 #define banner "TinyScheme 1.33"
72 #endif /* __APPLE__ */
78 static const char *strlwr(char *s) {
89 #endif /* __AMIGA__ */
96 # define InitFile "init.scm"
99 #ifndef FIRST_CELLSEGS
100 # define FIRST_CELLSEGS 3
118 T_LAST_SYSTEM_TYPE=14
121 /* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
124 #define T_MASKTYPE 31 /* 0000000000011111 */
125 #if USE_CUSTOM_FINALIZE
126 #define T_CUSTFIN 2048 /* 0000100000000000 */
128 #define T_SYNTAX 4096 /* 0001000000000000 */
129 #define T_IMMUTABLE 8192 /* 0010000000000000 */
130 #define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
131 #define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
132 #define MARK 32768 /* 1000000000000000 */
133 #define UNMARK 32767 /* 0111111111111111 */
136 enum scheme_opcodes {
137 #define _OP_DEF(A,B,C,D,E,OP) OP,
138 #include "opdefines.h"
143 static num num_add(num a, num b);
144 static num num_mul(num a, num b);
145 static num num_div(num a, num b);
146 static num num_intdiv(num a, num b);
147 static num num_sub(num a, num b);
148 static num num_rem(num a, num b);
149 static num num_mod(num a, num b);
150 static int num_eq(num a, num b);
151 static int num_gt(num a, num b);
152 static int num_ge(num a, num b);
153 static int num_lt(num a, num b);
154 static int num_le(num a, num b);
157 static double round_per_R5RS(double x);
159 static int is_zero_double(double x);
164 /* macros for cell operations */
165 #define typeflag(p) ((p)->_flag)
166 #define type(p) (typeflag(p)&T_MASKTYPE)
168 INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); }
169 #define strvalue(p) ((p)->_object._string._svalue)
170 #define strlength(p) ((p)->_object._string._length)
172 INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); }
173 INTERFACE static void fill_vector(pointer vec, pointer obj);
174 INTERFACE static pointer vector_elem(pointer vec, int ielem);
175 INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
176 INTERFACE INLINE int is_number(pointer p) { return (type(p)==T_NUMBER); }
177 INTERFACE INLINE int is_integer(pointer p) {
178 return ((p)->_object._number.is_fixnum);
180 INTERFACE INLINE int is_real(pointer p) {
181 return (!(p)->_object._number.is_fixnum);
184 INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
185 INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
186 INLINE num nvalue(pointer p) { return ((p)->_object._number); }
187 INTERFACE long ivalue(pointer p) { return (is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
188 INTERFACE double rvalue(pointer p) { return (!is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
189 #define ivalue_unchecked(p) ((p)->_object._number.value.ivalue)
190 #define rvalue_unchecked(p) ((p)->_object._number.value.rvalue)
191 #define set_integer(p) (p)->_object._number.is_fixnum=1;
192 #define set_real(p) (p)->_object._number.is_fixnum=0;
193 INTERFACE long charvalue(pointer p) { return ivalue_unchecked(p); }
195 INTERFACE INLINE int is_port(pointer p) { return (type(p)==T_PORT); }
196 #define is_inport(p) (type(p)==T_PORT && p->_object._port->kind&port_input)
197 #define is_outport(p) (type(p)==T_PORT && p->_object._port->kind&port_output)
199 INTERFACE INLINE int is_pair(pointer p) { return (type(p)==T_PAIR); }
200 #define car(p) ((p)->_object._cons._car)
201 #define cdr(p) ((p)->_object._cons._cdr)
202 INTERFACE pointer pair_car(pointer p) { return car(p); }
203 INTERFACE pointer pair_cdr(pointer p) { return cdr(p); }
204 INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
205 INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
207 INTERFACE INLINE int is_symbol(pointer p) { return (type(p)==T_SYMBOL); }
208 INTERFACE INLINE char *symname(pointer p) { return strvalue(car(p)); }
210 SCHEME_EXPORT INLINE int hasprop(pointer p) { return (typeflag(p)&T_SYMBOL); }
211 #define symprop(p) cdr(p)
214 INTERFACE INLINE foreign_func ffvalue(pointer p)
215 { return (!is_foreign(p) ? NULL : p->_object._ff); }
217 INTERFACE INLINE int is_syntax(pointer p) { return (typeflag(p)&T_SYNTAX); }
218 INTERFACE INLINE int is_proc(pointer p) { return (type(p)==T_PROC); }
219 INTERFACE INLINE int is_foreign(pointer p) { return (type(p)==T_FOREIGN); }
220 INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
221 #define procnum(p) ivalue(p)
222 static const char *procname(pointer x);
224 INTERFACE INLINE int is_closure(pointer p) { return (type(p)==T_CLOSURE); }
225 INTERFACE INLINE int is_macro(pointer p) { return (type(p)==T_MACRO); }
226 INTERFACE INLINE pointer closure_code(pointer p) { return car(p); }
227 INTERFACE INLINE pointer closure_env(pointer p) { return cdr(p); }
229 INTERFACE INLINE int is_continuation(pointer p) { return (type(p)==T_CONTINUATION); }
230 #define cont_dump(p) cdr(p)
232 /* To do: promise should be forced ONCE only */
233 INTERFACE INLINE int is_promise(pointer p) { return (type(p)==T_PROMISE); }
235 INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
236 #define setenvironment(p) typeflag(p) = T_ENVIRONMENT
238 #define is_atom(p) (typeflag(p)&T_ATOM)
239 #define setatom(p) typeflag(p) |= T_ATOM
240 #define clratom(p) typeflag(p) &= CLRATOM
242 #define is_mark(p) (typeflag(p)&MARK)
243 #define setmark(p) typeflag(p) |= MARK
244 #define clrmark(p) typeflag(p) &= UNMARK
245 #define is_free(p) (0==typeflag(p))
247 #if USE_CUSTOM_FINALIZE
248 #define is_custfin(p) (typeflag(p)&T_CUSTFIN)
249 #define setcustfin(p) (typeflag(p)|=T_CUSTFIN)
250 #define clrcustfin(p) (typeflag(p)&=(~T_CUSTFIN))
254 INTERFACE INLINE pointer protect(scheme *sc, pointer p)
257 list_add(&sc->protect, &p->plist);
261 INTERFACE INLINE pointer unprotect(scheme *sc, pointer p)
266 list_remove(&p->plist);
269 #define init_pref(p) ((p)->pref = 0)
274 #if USE_CUSTOM_FINALIZE
275 INTERFACE INLINE void ifc_setcustfin(pointer p)
281 INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
282 /*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/
283 INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
285 #define caar(p) car(car(p))
286 #define cadr(p) car(cdr(p))
287 #define cdar(p) cdr(car(p))
288 #define cddr(p) cdr(cdr(p))
289 #define cadar(p) car(cdr(car(p)))
290 #define caddr(p) car(cdr(cdr(p)))
291 #define cadaar(p) car(cdr(car(car(p))))
292 #define cadddr(p) car(cdr(cdr(cdr(p))))
293 #define cddddr(p) cdr(cdr(cdr(cdr(p))))
295 #if USE_CHAR_CLASSIFIERS
296 static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); }
297 static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); }
298 static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); }
299 static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); }
300 static INLINE int Cislower(int c) { return isascii(c) && islower(c); }
304 static const char *charnames[32]={
339 static int is_ascii_name(const char *name, int *pc) {
341 for(i=0; i<32; i++) {
342 if(stricmp(name,charnames[i])==0) {
347 if(stricmp(name,"del")==0) {
356 static int file_push(scheme *sc, const char *fname);
357 static void file_pop(scheme *sc);
358 static int file_interactive(scheme *sc);
359 static INLINE int is_one_of(const char *s, int c);
360 static void nomem(scheme *sc);
361 static int alloc_cellseg(scheme *sc, int n);
362 static long binary_decode(const char *s);
363 static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
364 static pointer _get_cell(scheme *sc, pointer a, pointer b);
365 static pointer get_consecutive_cells(scheme *sc, int n);
366 static pointer find_consecutive_cells(scheme *sc, int n);
367 static void finalize_cell(scheme *sc, pointer a);
368 static int count_consecutive_cells(pointer x, int needed);
369 static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
370 static pointer mk_number(scheme *sc, num n);
371 static pointer mk_empty_string(scheme *sc, int len, char fill);
372 static char *store_string(scheme *sc, int len, const char *str, char fill);
373 static pointer mk_vector(scheme *sc, int len);
374 static pointer mk_atom(scheme *sc, char *q);
375 static pointer mk_sharp_const(scheme *sc, char *name);
376 static pointer mk_port(scheme *sc, port *p);
377 static pointer port_from_filename(scheme *sc, const char *fn, int prop);
378 static pointer port_from_file(scheme *sc, FILE *, int prop);
379 static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
380 static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
381 static port *port_rep_from_file(scheme *sc, FILE *, int prop);
382 static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
383 static void port_close(scheme *sc, pointer p, int flag);
384 static void mark(pointer a);
385 static void gc(scheme *sc, pointer a, pointer b);
386 static int basic_inchar(port *pt);
387 static int inchar(scheme *sc);
388 static void backchar(scheme *sc, int c);
389 static char *readstr_upto(scheme *sc, const char *delim);
390 static pointer readstrexp(scheme *sc);
391 static INLINE void skipspace(scheme *sc);
392 static int token(scheme *sc);
393 static void printslashstring(scheme *sc, char *s, int len);
394 static void atom2str(scheme *sc, pointer l, int f, const char **pp, int *plen);
395 static void printatom(scheme *sc, pointer l, int f);
396 static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
397 static pointer mk_closure(scheme *sc, pointer c, pointer e);
398 static pointer mk_continuation(scheme *sc, pointer d);
399 static pointer reverse(scheme *sc, pointer a);
400 static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
401 static pointer append(scheme *sc, pointer a, pointer b);
402 static int list_length(scheme *sc, pointer a);
403 static int eqv(pointer a, pointer b);
404 static void dump_stack_mark(scheme *);
405 static pointer opexe_0(scheme *sc, enum scheme_opcodes op);
406 static pointer opexe_1(scheme *sc, enum scheme_opcodes op);
407 static pointer opexe_2(scheme *sc, enum scheme_opcodes op);
408 static pointer opexe_3(scheme *sc, enum scheme_opcodes op);
409 static pointer opexe_4(scheme *sc, enum scheme_opcodes op);
410 static pointer opexe_5(scheme *sc, enum scheme_opcodes op);
411 static pointer opexe_6(scheme *sc, enum scheme_opcodes op);
413 static pointer opexe_ghul(scheme *sc, enum scheme_opcodes op);
415 static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
416 static void assign_syntax(scheme *sc, const char *name);
417 static int syntaxnum(pointer p);
418 static void assign_proc(scheme *sc, enum scheme_opcodes, const char *name);
420 #define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
421 #define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
423 static void nomem(scheme *sc)
428 static num num_add(num a, num b) {
430 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
432 ret.value.ivalue= a.value.ivalue+b.value.ivalue;
434 ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
439 static num num_mul(num a, num b) {
441 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
443 ret.value.ivalue= a.value.ivalue*b.value.ivalue;
445 ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
450 static num num_div(num a, num b) {
452 ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
454 ret.value.ivalue= a.value.ivalue/b.value.ivalue;
456 ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
461 static num num_intdiv(num a, num b) {
463 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
465 ret.value.ivalue= a.value.ivalue/b.value.ivalue;
467 ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
472 static num num_sub(num a, num b) {
474 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
476 ret.value.ivalue= a.value.ivalue-b.value.ivalue;
478 ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
483 static num num_rem(num a, num b) {
486 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
490 if(res*e1<0) { /* remainder should have same sign as first operand */
498 ret.value.ivalue=res;
502 static num num_mod(num a, num b) {
505 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
509 if(res*e2<0) { /* modulo should have same sign as second operand */
517 ret.value.ivalue=res;
521 static int num_eq(num a, num b) {
523 int is_fixnum=a.is_fixnum && b.is_fixnum;
525 ret= a.value.ivalue==b.value.ivalue;
527 ret=num_rvalue(a)==num_rvalue(b);
533 static int num_gt(num a, num b) {
535 int is_fixnum=a.is_fixnum && b.is_fixnum;
537 ret= a.value.ivalue>b.value.ivalue;
539 ret=num_rvalue(a)>num_rvalue(b);
544 static int num_ge(num a, num b) {
548 static int num_lt(num a, num b) {
550 int is_fixnum=a.is_fixnum && b.is_fixnum;
552 ret= a.value.ivalue<b.value.ivalue;
554 ret=num_rvalue(a)<num_rvalue(b);
559 static int num_le(num a, num b) {
564 /* Round to nearest. Round to even if midway */
565 static double round_per_R5RS(double x) {
575 if(fmod(fl,2.0)==0.0) { /* I imagine this holds */
584 static int is_zero_double(double x) {
585 return x<DBL_MIN && x>-DBL_MIN;
588 static long binary_decode(const char *s) {
591 while(*s!=0 && (*s=='1' || *s=='0')) {
600 /* allocate new cell segment */
601 static int alloc_cellseg(scheme *sc, int n) {
608 unsigned int adj=ADJ;
610 if(adj<sizeof(struct cell)) {
611 adj=sizeof(struct cell);
614 for (k = 0; k < n; k++) {
615 if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
617 cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj);
620 i = ++sc->last_cell_seg ;
621 sc->alloc_seg[i] = cp;
622 /* adjust in TYPE_BITS-bit boundary */
623 if(((long)cp)%adj!=0) {
624 cp=(char*)(adj*((long)cp/adj+1));
626 /* insert new segment in address order */
628 sc->cell_seg[i] = newp;
629 while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
631 sc->cell_seg[i] = sc->cell_seg[i - 1];
632 sc->cell_seg[--i] = p;
634 sc->fcells += CELL_SEGSIZE;
635 last = newp + CELL_SEGSIZE - 1;
636 for (p = newp; p <= last; p++) {
641 /* insert new cells in address order on free list */
642 if (sc->free_cell == sc->NIL || p < sc->free_cell) {
643 cdr(last) = sc->free_cell;
644 sc->free_cell = newp;
647 while (cdr(p) != sc->NIL && newp > cdr(p))
656 static INLINE pointer get_cell(scheme *sc, pointer a, pointer b) {
657 if (sc->free_cell != sc->NIL) {
658 pointer x = sc->free_cell;
662 sc->free_cell = cdr(x);
666 return _get_cell (sc, a, b);
670 /* get new cell. parameter a, b is marked by gc. */
671 static pointer _get_cell(scheme *sc, pointer a, pointer b) {
678 if (sc->free_cell == sc->NIL) {
680 if (sc->fcells < sc->last_cell_seg*8
681 || sc->free_cell == sc->NIL) {
682 /* if only a few recovered, get more to avoid fruitless gc's */
683 if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) {
693 sc->free_cell = cdr(x);
698 static pointer get_consecutive_cells(scheme *sc, int n) {
705 /* Are there any cells available? */
706 x=find_consecutive_cells(sc,n);
708 /* If not, try gc'ing some */
709 gc(sc, sc->NIL, sc->NIL);
710 x=find_consecutive_cells(sc,n);
712 /* If there still aren't, try getting more heap */
713 if (!alloc_cellseg(sc,1)) {
718 x=find_consecutive_cells(sc,n);
720 /* If all fail, report failure */
728 static int count_consecutive_cells(pointer x, int needed) {
733 if(n>needed) return n;
738 static pointer find_consecutive_cells(scheme *sc, int n) {
743 while(*pp!=sc->NIL) {
744 cnt=count_consecutive_cells(*pp,n);
756 /* get new cons cell */
757 pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
758 pointer x = get_cell(sc,a, b);
760 typeflag(x) = T_PAIR;
769 /* ========== oblist implementation ========== */
771 #ifndef USE_OBJECT_LIST
773 static int hash_fn(const char *key, int table_size);
775 static pointer oblist_initial_value(scheme *sc)
777 return mk_vector(sc, 461); /* probably should be bigger */
780 /* returns the new symbol */
781 static pointer oblist_add_by_name(scheme *sc, const char *name)
786 x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
787 typeflag(x) = T_SYMBOL;
788 setimmutable(car(x));
790 location = hash_fn(name, ivalue_unchecked(sc->oblist));
791 set_vector_elem(sc->oblist, location,
792 immutable_cons(sc, x, vector_elem(sc->oblist, location)));
796 static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
802 location = hash_fn(name, ivalue_unchecked(sc->oblist));
803 for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) {
805 /* case-insensitive, per R5RS section 2. */
806 if(stricmp(name, s) == 0) {
813 static pointer oblist_all_symbols(scheme *sc)
817 pointer ob_list = sc->NIL;
819 for (i = 0; i < ivalue_unchecked(sc->oblist); i++) {
820 for (x = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) {
821 ob_list = cons(sc, x, ob_list);
829 static pointer oblist_initial_value(scheme *sc)
834 static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
839 for (x = sc->oblist; x != sc->NIL; x = cdr(x)) {
841 /* case-insensitive, per R5RS section 2. */
842 if(stricmp(name, s) == 0) {
849 /* returns the new symbol */
850 static pointer oblist_add_by_name(scheme *sc, const char *name)
854 x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
855 typeflag(x) = T_SYMBOL;
856 setimmutable(car(x));
857 sc->oblist = immutable_cons(sc, x, sc->oblist);
860 static pointer oblist_all_symbols(scheme *sc)
867 static pointer mk_port(scheme *sc, port *p) {
868 pointer x = get_cell(sc, sc->NIL, sc->NIL);
870 typeflag(x) = T_PORT|T_ATOM;
875 pointer mk_foreign_func(scheme *sc, foreign_func f) {
876 pointer x = get_cell(sc, sc->NIL, sc->NIL);
878 typeflag(x) = (T_FOREIGN | T_ATOM);
883 INTERFACE pointer mk_character(scheme *sc, int c) {
884 pointer x = get_cell(sc,sc->NIL, sc->NIL);
886 typeflag(x) = (T_CHARACTER | T_ATOM);
887 ivalue_unchecked(x)= c;
892 /* get number atom (integer) */
893 INTERFACE pointer mk_integer(scheme *sc, long num) {
894 pointer x = get_cell(sc,sc->NIL, sc->NIL);
896 typeflag(x) = (T_NUMBER | T_ATOM);
897 ivalue_unchecked(x)= num;
902 INTERFACE pointer mk_real(scheme *sc, double n) {
903 pointer x = get_cell(sc,sc->NIL, sc->NIL);
905 typeflag(x) = (T_NUMBER | T_ATOM);
906 rvalue_unchecked(x)= n;
911 static pointer mk_number(scheme *sc, num n) {
913 return mk_integer(sc,n.value.ivalue);
915 return mk_real(sc,n.value.rvalue);
919 /* allocate name to string area */
920 static char *store_string(scheme *sc, int len_str, const char *str, char fill) {
923 q=(char*)sc->malloc(len_str+1);
931 memset(q, fill, len_str);
938 INTERFACE pointer mk_string(scheme *sc, const char *str) {
939 return mk_counted_string(sc,str,strlen(str));
942 INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
943 pointer x = get_cell(sc, sc->NIL, sc->NIL);
945 strvalue(x) = store_string(sc,len,str,0);
946 typeflag(x) = (T_STRING | T_ATOM);
951 static pointer mk_empty_string(scheme *sc, int len, char fill) {
952 pointer x = get_cell(sc, sc->NIL, sc->NIL);
954 strvalue(x) = store_string(sc,len,0,fill);
955 typeflag(x) = (T_STRING | T_ATOM);
960 INTERFACE static pointer mk_vector(scheme *sc, int len) {
961 pointer x=get_consecutive_cells(sc,len/2+len%2+1);
962 typeflag(x) = (T_VECTOR | T_ATOM);
963 ivalue_unchecked(x)=len;
965 fill_vector(x,sc->NIL);
969 INTERFACE static void fill_vector(pointer vec, pointer obj) {
971 int num=ivalue(vec)/2+ivalue(vec)%2;
972 for(i=0; i<num; i++) {
973 typeflag(vec+1+i) = T_PAIR;
974 setimmutable(vec+1+i);
980 INTERFACE static pointer vector_elem(pointer vec, int ielem) {
989 INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
992 return car(vec+1+n)=a;
994 return cdr(vec+1+n)=a;
999 INTERFACE pointer mk_symbol(scheme *sc, const char *name) {
1002 /* first check oblist */
1003 x = oblist_find_by_name(sc, name);
1007 x = oblist_add_by_name(sc, name);
1012 INTERFACE pointer gensym(scheme *sc) {
1016 for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) {
1017 sprintf(name,"gensym-%ld",sc->gensym_cnt);
1019 /* first check oblist */
1020 x = oblist_find_by_name(sc, name);
1025 x = oblist_add_by_name(sc, name);
1033 /* make symbol or number atom from string */
1034 static pointer mk_atom(scheme *sc, char *q) {
1036 int has_dec_point=0;
1040 if((p=strstr(q,"::"))!=0) {
1042 return cons(sc, sc->COLON_HOOK,
1046 cons(sc, mk_atom(sc,p+2), sc->NIL)),
1047 cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL)));
1053 if ((c == '+') || (c == '-')) {
1060 return (mk_symbol(sc, strlwr(q)));
1062 } else if (c == '.') {
1066 return (mk_symbol(sc, strlwr(q)));
1068 } else if (!isdigit(c)) {
1069 return (mk_symbol(sc, strlwr(q)));
1072 for ( ; (c = *p) != 0; ++p) {
1075 if(!has_dec_point) {
1080 else if ((c == 'e') || (c == 'E')) {
1082 has_dec_point = 1; /* decimal point illegal
1085 if ((*p == '-') || (*p == '+') || isdigit(*p)) {
1090 return (mk_symbol(sc, strlwr(q)));
1094 return mk_real(sc,atof(q));
1096 return (mk_integer(sc, atol(q)));
1100 static pointer mk_sharp_const(scheme *sc, char *name) {
1104 if (!strcmp(name, "t"))
1106 else if (!strcmp(name, "f"))
1108 else if (*name == 'o') {/* #o (octal) */
1109 sprintf(tmp, "0%s", name+1);
1110 sscanf(tmp, "%lo", &x);
1111 return (mk_integer(sc, x));
1112 } else if (*name == 'd') { /* #d (decimal) */
1113 sscanf(name+1, "%ld", &x);
1114 return (mk_integer(sc, x));
1115 } else if (*name == 'x') { /* #x (hex) */
1116 sprintf(tmp, "0x%s", name+1);
1117 sscanf(tmp, "%lx", &x);
1118 return (mk_integer(sc, x));
1119 } else if (*name == 'b') { /* #b (binary) */
1120 x = binary_decode(name+1);
1121 return (mk_integer(sc, x));
1122 } else if (*name == '\\') { /* #\w (character) */
1124 if(stricmp(name+1,"space")==0) {
1126 } else if(stricmp(name+1,"newline")==0) {
1128 } else if(stricmp(name+1,"return")==0) {
1130 } else if(stricmp(name+1,"tab")==0) {
1132 } else if(name[1]=='x' && name[2]!=0) {
1134 if(sscanf(name+2,"%x",&c1)==1 && c1<256) {
1140 } else if(is_ascii_name(name+1,&c)) {
1143 } else if(name[2]==0) {
1148 return mk_character(sc,c);
1153 /* ========== garbage collector ========== */
1156 * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
1157 * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
1160 static void mark(pointer a) {
1168 int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2;
1169 for(i=0; i<num; i++) {
1170 /* Vector cells will be treated like ordinary cells */
1178 if (q && !is_mark(q)) {
1179 setatom(p); /* a note that we have moved car */
1185 E5: q = cdr(p); /* down cdr */
1186 if (q && !is_mark(q)) {
1192 E6: /* up. Undo the link switching from steps E4 and E5. */
1211 static void protected_mark(scheme *sc)
1216 list_for_each(&sc->protect, elem) {
1217 p = list_entry(elem, struct cell, plist);
1221 static void unprotect_all(scheme *sc)
1224 sc->ignore_protect = 1;
1229 elem = sc->protect.next;
1230 while (elem != &sc->protect) {
1231 p = list_entry(elem, struct cell, plist);
1239 /* garbage collection. parameter a, b is marked. */
1240 static void gc(scheme *sc, pointer a, pointer b) {
1244 if(sc->gc_verbose) {
1245 putstr(sc, "gc...");
1248 /* mark system globals */
1250 mark(sc->global_env);
1252 /* mark current registers */
1256 dump_stack_mark(sc);
1259 mark(sc->save_inport);
1263 /* mark variables a, b */
1268 /* mark protected */
1269 if (!sc->ignore_protect) {
1274 /* garbage collect */
1277 sc->free_cell = sc->NIL;
1278 /* free-list is kept sorted by address so as to maintain consecutive
1279 ranges, if possible, for use with vectors. Here we scan the cells
1280 (which are also kept sorted by address) downwards to build the
1281 free-list in sorted order.
1283 for (i = sc->last_cell_seg; i >= 0; i--) {
1284 p = sc->cell_seg[i] + CELL_SEGSIZE;
1285 while (--p >= sc->cell_seg[i]) {
1290 if (typeflag(p) != 0) {
1291 finalize_cell(sc, p);
1296 cdr(p) = sc->free_cell;
1302 if (sc->gc_verbose) {
1304 sprintf(msg,"done: %ld cells were recovered.\n", sc->fcells);
1309 static void finalize_cell(scheme *sc, pointer a) {
1311 sc->free(strvalue(a));
1312 } else if(is_port(a)) {
1313 if(a->_object._port->kind&port_file
1314 && a->_object._port->rep.stdio.closeit) {
1315 port_close(sc,a,port_input|port_output);
1317 sc->free(a->_object._port);
1318 } else if(is_custfin(a) && sc->custom_finalize) {
1319 sc->custom_finalize(sc, (pointer)ffvalue(a));
1323 /* ========== Routines for Reading ========== */
1325 static int file_push(scheme *sc, const char *fname) {
1326 FILE *fin = file_open_in_include_dir(fname);
1327 /*printf("load %s...\n", fname);*/
1330 sc->load_stack[sc->file_i].kind=port_file|port_input;
1331 sc->load_stack[sc->file_i].rep.stdio.file=fin;
1332 sc->load_stack[sc->file_i].rep.stdio.closeit=1;
1333 #if USE_FILE_AND_LINE
1334 sc->load_stack[sc->file_i].rep.stdio.name = strdup(fname);
1335 sc->load_stack[sc->file_i].rep.stdio.line = 0;
1337 sc->nesting_stack[sc->file_i]=0;
1338 sc->loadport->_object._port=sc->load_stack+sc->file_i;
1343 static void file_pop(scheme *sc) {
1344 sc->nesting=sc->nesting_stack[sc->file_i];
1346 port_close(sc,sc->loadport,port_input);
1348 sc->loadport->_object._port=sc->load_stack+sc->file_i;
1349 if(file_interactive(sc)) {
1355 static int file_interactive(scheme *sc) {
1356 return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin
1357 && sc->inport->_object._port->kind&port_file;
1360 static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
1364 if(prop==(port_input|port_output)) {
1366 } else if(prop==port_output) {
1375 pt=port_rep_from_file(sc,f,prop);
1376 pt->rep.stdio.closeit=1;
1380 static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
1382 pt=port_rep_from_filename(sc,fn,prop);
1386 return mk_port(sc,pt);
1389 static port *port_rep_from_file(scheme *sc, FILE *f, int prop) {
1392 pt=(port*)sc->malloc(sizeof(port));
1396 if(prop==(port_input|port_output)) {
1398 } else if(prop==port_output) {
1403 pt->kind=port_file|prop;
1404 pt->rep.stdio.file=f;
1405 pt->rep.stdio.closeit=0;
1409 static pointer port_from_file(scheme *sc, FILE *f, int prop) {
1411 pt=port_rep_from_file(sc,f,prop);
1415 return mk_port(sc,pt);
1418 static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
1420 pt=(port*)sc->malloc(sizeof(port));
1424 pt->kind=port_string|prop;
1425 pt->rep.string.start=start;
1426 pt->rep.string.curr=start;
1427 pt->rep.string.past_the_end=past_the_end;
1431 static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
1433 pt=port_rep_from_string(sc,start,past_the_end,prop);
1437 return mk_port(sc,pt);
1440 static void port_close(scheme *sc, pointer p, int flag) {
1441 port *pt=p->_object._port;
1443 if((pt->kind & (port_input|port_output))==0) {
1444 if(pt->kind&port_file) {
1445 fclose(pt->rep.stdio.file);
1446 #if USE_FILE_AND_LINE
1447 if (pt->rep.stdio.name) {
1448 free(pt->rep.stdio.name);
1456 /* get new character from input file */
1457 static int inchar(scheme *sc) {
1461 pt=sc->inport->_object._port;
1463 if(c==EOF && sc->inport==sc->loadport && sc->file_i!=0) {
1465 if(sc->nesting!=0 || sc->tok==TOK_COMMENT) {
1470 #if USE_FILE_AND_LINE
1472 pt->rep.stdio.line++;
1477 static int basic_inchar(port *pt) {
1478 if(pt->kind&port_file) {
1479 int ch = fgetc(pt->rep.stdio.file);
1482 if(*pt->rep.string.curr==0
1483 || pt->rep.string.curr==pt->rep.string.past_the_end) {
1486 return *pt->rep.string.curr++;
1491 /* back character to input buffer */
1492 static void backchar(scheme *sc, int c) {
1495 pt=sc->inport->_object._port;
1496 if(pt->kind&port_file) {
1497 ungetc(c,pt->rep.stdio.file);
1498 #if USE_FILE_AND_LINE
1500 pt->rep.stdio.line--;
1503 if(pt->rep.string.curr!=pt->rep.string.start) {
1504 --pt->rep.string.curr;
1509 INTERFACE void putstr(scheme *sc, const char *s) {
1510 port *pt=sc->outport->_object._port;
1511 if(pt->kind&port_file) {
1512 fputs(s,pt->rep.stdio.file);
1515 if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
1516 *pt->rep.string.curr++=*s;
1522 static void putchars(scheme *sc, const char *s, int len) {
1523 port *pt=sc->outport->_object._port;
1524 if(pt->kind&port_file) {
1525 fwrite(s,1,len,pt->rep.stdio.file);
1528 if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
1529 *pt->rep.string.curr++=*s++;
1535 INTERFACE void putcharacter(scheme *sc, int c) {
1536 port *pt=sc->outport->_object._port;
1537 if(pt->kind&port_file) {
1538 fputc(c,pt->rep.stdio.file);
1540 if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
1541 *pt->rep.string.curr++=c;
1546 /* read characters up to delimiter, but cater to character constants */
1547 static char *readstr_upto(scheme *sc, const char *delim) {
1548 char *p = sc->strbuff;
1550 while (!is_one_of(delim, (*p++ = inchar(sc))));
1551 if(p==sc->strbuff+2 && p[-2]=='\\') {
1560 /* read string expression "xxx...xxx" */
1561 static pointer readstrexp(scheme *sc) {
1562 char *p = sc->strbuff;
1565 enum { st_ok, st_bsl, st_x1, st_x2} state=st_ok;
1569 if(c==EOF || (p-sc->strbuff)>(int)(sizeof(sc->strbuff)-1)) {
1580 return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
1618 if(c>='0' && c<='F') {
1622 c1=(c1<<4)+c-'A'+10;
1638 /* check c is in chars */
1639 static INLINE int is_one_of(const char *s, int c) {
1640 if(c==EOF) return 1;
1647 /* skip white characters */
1648 static INLINE void skipspace(scheme *sc) {
1650 while (isspace(c=inchar(sc)))
1658 static int token(scheme *sc) {
1661 switch (c=inchar(sc)) {
1665 return (TOK_LPAREN);
1667 return (TOK_RPAREN);
1670 if(is_one_of(" \n\t",c)) {
1680 while ((c=inchar(sc)) != '\n' && c!=EOF)
1684 return (TOK_DQUOTE);
1686 return (TOK_BQUOTE);
1688 if ((c=inchar(sc)) == '@')
1689 return (TOK_ATMARK);
1698 } else if(c == '!') {
1699 while ((c=inchar(sc)) != '\n' && c!=EOF)
1704 if(is_one_of(" tfodxb\\",c)) {
1705 return TOK_SHARP_CONST;
1716 /* ========== Routines for Printing ========== */
1717 #define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL)
1719 static void printslashstring(scheme *sc, char *p, int len) {
1721 unsigned char *s=(unsigned char*)p;
1722 putcharacter(sc,'"');
1723 for ( i=0; i<len; i++) {
1724 if(*s==0xff || *s=='"' || *s<' ' || *s=='\\') {
1725 putcharacter(sc,'\\');
1728 putcharacter(sc,'"');
1731 putcharacter(sc,'n');
1734 putcharacter(sc,'t');
1737 putcharacter(sc,'r');
1740 putcharacter(sc,'\\');
1744 putcharacter(sc,'x');
1746 putcharacter(sc,d+'0');
1748 putcharacter(sc,d-10+'A');
1752 putcharacter(sc,d+'0');
1754 putcharacter(sc,d-10+'A');
1759 putcharacter(sc,*s);
1763 putcharacter(sc,'"');
1768 static void printatom(scheme *sc, pointer l, int f) {
1771 atom2str(sc,l,f,&p,&len);
1776 /* Uses internal buffer unless string pointer is already available */
1777 static void atom2str(scheme *sc, pointer l, int f, const char **pp, int *plen) {
1782 } else if (l == sc->T) {
1784 } else if (l == sc->F) {
1786 } else if (l == sc->EOF_OBJ) {
1788 } else if (is_port(l)) {
1789 strcpy(sc->strbuff, "#<PORT>");
1791 } else if (is_number(l)) {
1793 sprintf(sc->strbuff, "%ld", ivalue_unchecked(l));
1795 sprintf(sc->strbuff, "%.10g", rvalue_unchecked(l));
1798 } else if (is_string(l)) {
1801 } else { /* Hack, uses the fact that printing is needed */
1804 printslashstring(sc, strvalue(l), strlength(l));
1807 } else if (is_character(l)) {
1815 sprintf(sc->strbuff,"#\\space"); break;
1817 sprintf(sc->strbuff,"#\\newline"); break;
1819 sprintf(sc->strbuff,"#\\return"); break;
1821 sprintf(sc->strbuff,"#\\tab"); break;
1825 strcpy(sc->strbuff,"#\\del"); break;
1827 strcpy(sc->strbuff,"#\\"); strcat(sc->strbuff,charnames[c]); break;
1831 sprintf(sc->strbuff,"#\\x%x",c); break;
1834 sprintf(sc->strbuff,"#\\%c",c); break;
1838 } else if (is_symbol(l)) {
1840 } else if (is_proc(l)) {
1841 sprintf(sc->strbuff, "#<%s PROCEDURE %ld>", procname(l),procnum(l));
1843 } else if (is_macro(l)) {
1845 } else if (is_closure(l)) {
1847 } else if (is_promise(l)) {
1849 } else if (is_foreign(l)) {
1850 sprintf(sc->strbuff, "#<FOREIGN PROCEDURE %ld>", procnum(l));
1852 } else if (is_continuation(l)) {
1853 p = "#<CONTINUATION>";
1860 /* ========== Routines for Evaluation Cycle ========== */
1862 /* make closure. c is code. e is environment */
1863 static pointer mk_closure(scheme *sc, pointer c, pointer e) {
1864 pointer x = get_cell(sc, c, e);
1866 typeflag(x) = T_CLOSURE;
1872 /* make continuation. */
1873 static pointer mk_continuation(scheme *sc, pointer d) {
1874 pointer x = get_cell(sc, sc->NIL, d);
1876 typeflag(x) = T_CONTINUATION;
1881 static pointer list_star(scheme *sc, pointer d) {
1883 if(cdr(d)==sc->NIL) {
1886 p=cons(sc,car(d),cdr(d));
1888 while(cdr(cdr(p))!=sc->NIL) {
1889 d=cons(sc,car(p),cdr(p));
1890 if(cdr(cdr(p))!=sc->NIL) {
1898 /* reverse list -- produce new list */
1899 static pointer reverse(scheme *sc, pointer a) {
1900 /* a must be checked by gc */
1901 pointer p = sc->NIL;
1903 for ( ; is_pair(a); a = cdr(a)) {
1904 p = cons(sc, car(a), p);
1909 /* reverse list --- in-place */
1910 static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
1911 pointer p = list, result = term, q;
1913 while (p != sc->NIL) {
1922 /* append list -- produce new list */
1923 static pointer append(scheme *sc, pointer a, pointer b) {
1928 while (a != sc->NIL) {
1938 /* equivalence of atoms */
1939 static int eqv(pointer a, pointer b) {
1942 return (strvalue(a) == strvalue(b));
1945 } else if (is_number(a)) {
1947 return num_eq(nvalue(a),nvalue(b));
1950 } else if (is_character(a)) {
1951 if (is_character(b))
1952 return charvalue(a)==charvalue(b);
1955 } else if (is_port(a)) {
1960 } else if (is_proc(a)) {
1962 return procnum(a)==procnum(b);
1965 } else if (is_foreign(a)) {
1967 return (a->_object._ff == b->_object._ff);
1974 /* true or false value macro */
1975 /* () is #t in R5RS */
1976 #define is_true(p) ((p) != sc->F)
1977 #define is_false(p) ((p) == sc->F)
1979 /* ========== Environment implementation ========== */
1981 #if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
1983 static int hash_fn(const char *key, int table_size)
1985 unsigned int hashed = 0;
1987 int bits_per_int = sizeof(unsigned int)*8;
1989 for (c = key; *c; c++) {
1990 /* letters have about 5 bits in them */
1991 hashed = (hashed<<5) | (hashed>>(bits_per_int-5));
1994 return hashed % table_size;
1998 #ifndef USE_ALIST_ENV
2001 * In this implementation, each frame of the environment may be
2002 * a hash table: a vector of alists hashed by variable name.
2003 * In practice, we use a vector only for the initial frame;
2004 * subsequent frames are too small and transient for the lookup
2005 * speed to out-weigh the cost of making a new vector.
2008 static void new_frame_in_env(scheme *sc, pointer old_env)
2012 /* The interaction-environment has about 300 variables in it. */
2013 if (old_env == sc->NIL) {
2014 new_frame = mk_vector(sc, 461);
2016 new_frame = sc->NIL;
2019 sc->envir = immutable_cons(sc, new_frame, old_env);
2020 setenvironment(sc->envir);
2023 static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
2024 pointer variable, pointer value)
2026 pointer slot = immutable_cons(sc, variable, value);
2028 if (is_vector(car(env))) {
2029 int location = hash_fn(symname(variable), ivalue_unchecked(car(env)));
2031 set_vector_elem(car(env), location,
2032 immutable_cons(sc, slot, vector_elem(car(env), location)));
2034 car(env) = immutable_cons(sc, slot, car(env));
2038 static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
2040 pointer x,y=sc->NIL;
2043 for (x = env; x != sc->NIL; x = cdr(x)) {
2044 if (is_vector(car(x))) {
2045 location = hash_fn(symname(hdl), ivalue_unchecked(car(x)));
2046 y = vector_elem(car(x), location);
2050 for ( ; y != sc->NIL; y = cdr(y)) {
2051 if (caar(y) == hdl) {
2068 #else /* USE_ALIST_ENV */
2070 static INLINE void new_frame_in_env(scheme *sc, pointer old_env)
2072 sc->envir = immutable_cons(sc, sc->NIL, old_env);
2073 setenvironment(sc->envir);
2076 static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
2077 pointer variable, pointer value)
2079 car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env));
2082 static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
2085 for (x = env; x != sc->NIL; x = cdr(x)) {
2086 for (y = car(x); y != sc->NIL; y = cdr(y)) {
2087 if (caar(y) == hdl) {
2104 #endif /* USE_ALIST_ENV else */
2106 static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value)
2108 new_slot_spec_in_env(sc, sc->envir, variable, value);
2111 static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value)
2116 static INLINE pointer slot_value_in_env(pointer slot)
2121 /* ========== Evaluation Cycle ========== */
2124 static pointer _Error_1(scheme *sc, const char *s, pointer a) {
2127 pointer hdl=sc->ERROR_HOOK;
2129 x=find_slot_in_env(sc,sc->envir,hdl,1);
2132 sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL);
2136 sc->code = cons(sc, mk_string(sc, (s)), sc->code);
2137 setimmutable(car(sc->code));
2138 sc->code = cons(sc, slot_value_in_env(x), sc->code);
2139 sc->op = (int)OP_EVAL;
2145 sc->args = cons(sc, (a), sc->NIL);
2149 sc->args = cons(sc, mk_string(sc, (s)), sc->args);
2150 setimmutable(car(sc->args));
2151 sc->op = (int)OP_ERR0;
2154 #define Error_1(sc,s, a) return _Error_1(sc,s,a)
2155 #define Error_0(sc,s) return _Error_1(sc,s,0)
2157 /* Too small to turn into function */
2159 # define END } while (0)
2160 #define s_goto(sc,a) BEGIN \
2161 sc->op = (int)(a); \
2164 #define s_return(sc,a) return _s_return(sc,a)
2166 #ifndef USE_SCHEME_STACK
2168 /* this structure holds all the interpreter's registers */
2169 struct dump_stack_frame {
2170 enum scheme_opcodes op;
2176 #define STACK_GROWTH 3
2178 static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code)
2180 long nframes = (long)sc->dump;
2181 struct dump_stack_frame *next_frame;
2183 /* enough room for the next frame? */
2184 if (nframes >= sc->dump_size) {
2185 sc->dump_size += STACK_GROWTH;
2186 /* alas there is no sc->realloc */
2187 sc->dump_base = realloc(sc->dump_base,
2188 sizeof(struct dump_stack_frame) * sc->dump_size);
2190 next_frame = (struct dump_stack_frame *)sc->dump_base + nframes;
2191 next_frame->op = op;
2192 next_frame->args = args;
2193 next_frame->envir = sc->envir;
2194 next_frame->code = code;
2195 sc->dump = (pointer)(nframes+1);
2198 static pointer _s_return(scheme *sc, pointer a)
2200 long nframes = (long)sc->dump;
2201 struct dump_stack_frame *frame;
2208 frame = (struct dump_stack_frame *)sc->dump_base + nframes;
2210 sc->args = frame->args;
2211 sc->envir = frame->envir;
2212 sc->code = frame->code;
2213 sc->dump = (pointer)nframes;
2217 static INLINE void dump_stack_reset(scheme *sc)
2219 /* in this implementation, sc->dump is the number of frames on the stack */
2220 sc->dump = (pointer)0;
2223 static INLINE void dump_stack_initialize(scheme *sc)
2226 sc->dump_base = NULL;
2227 dump_stack_reset(sc);
2230 static void dump_stack_free(scheme *sc)
2232 free(sc->dump_base);
2233 sc->dump_base = NULL;
2234 sc->dump = (pointer)0;
2238 static INLINE void dump_stack_mark(scheme *sc)
2240 long nframes = (long)sc->dump;
2242 for(i=0; i<nframes; i++) {
2243 struct dump_stack_frame *frame;
2244 frame = (struct dump_stack_frame *)sc->dump_base + i;
2253 static INLINE void dump_stack_reset(scheme *sc)
2258 static INLINE void dump_stack_initialize(scheme *sc)
2260 dump_stack_reset(sc);
2263 static void dump_stack_free(scheme *sc)
2268 static pointer _s_return(scheme *sc, pointer a) {
2270 if(sc->dump==sc->NIL) return sc->NIL;
2271 sc->op = ivalue(car(sc->dump));
2272 sc->args = cadr(sc->dump);
2273 sc->envir = caddr(sc->dump);
2274 sc->code = cadddr(sc->dump);
2275 sc->dump = cddddr(sc->dump);
2279 static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
2280 sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump));
2281 sc->dump = cons(sc, (args), sc->dump);
2282 sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump);
2285 static INLINE void dump_stack_mark(scheme *sc)
2291 #define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F)
2293 static pointer opexe_0(scheme *sc, enum scheme_opcodes op) {
2297 case OP_LOAD: /* load */
2298 if(file_interactive(sc)) {
2299 fprintf(sc->outport->_object._port->rep.stdio.file,
2300 "Loading %s\n", strvalue(car(sc->args)));
2302 if (!file_push(sc,strvalue(car(sc->args)))) {
2303 Error_1(sc,"unable to open", car(sc->args));
2305 s_goto(sc,OP_T0LVL);
2307 case OP_T0LVL: /* top level */
2308 if(file_interactive(sc)) {
2312 dump_stack_reset(sc);
2313 sc->envir = sc->global_env;
2314 sc->save_inport=sc->inport;
2315 sc->inport = sc->loadport;
2316 s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
2317 s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
2318 s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
2319 if (file_interactive(sc)) {
2322 s_goto(sc,OP_READ_INTERNAL);
2324 case OP_T1LVL: /* top level */
2325 sc->code = sc->value;
2326 sc->inport=sc->save_inport;
2329 case OP_READ_INTERNAL: /* internal read */
2330 sc->tok = token(sc);
2331 if(sc->tok==TOK_EOF) {
2332 if(sc->inport==sc->loadport) {
2336 s_return(sc,sc->EOF_OBJ);
2339 s_goto(sc,OP_RDSEXPR);
2342 s_return(sc, gensym(sc));
2344 case OP_VALUEPRINT: /* print evaluation result */
2345 /* OP_VALUEPRINT is always pushed, because when changing from
2346 non-interactive to interactive mode, it needs to be
2347 already on the stack */
2349 putstr(sc,"\nGives: ");
2351 if(file_interactive(sc)) {
2353 sc->args = sc->value;
2354 s_goto(sc,OP_P0LIST);
2356 s_return(sc,sc->value);
2359 case OP_EVAL: /* main part of evaluation */
2362 /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
2363 s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
2365 putstr(sc,"\nEval: ");
2366 s_goto(sc,OP_P0LIST);
2371 if (is_symbol(sc->code)) { /* symbol */
2372 x=find_slot_in_env(sc,sc->envir,sc->code,1);
2374 s_return(sc,slot_value_in_env(x));
2376 Error_1(sc,"eval: unbound variable:", sc->code);
2378 } else if (is_pair(sc->code)) {
2379 if (is_syntax(x = car(sc->code))) { /* SYNTAX */
2380 sc->code = cdr(sc->code);
2381 s_goto(sc,syntaxnum(x));
2382 } else {/* first, eval top element and eval arguments */
2383 s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
2384 /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
2385 sc->code = car(sc->code);
2389 s_return(sc,sc->code);
2392 case OP_E0ARGS: /* eval arguments */
2393 if (is_macro(sc->value)) { /* macro expansion */
2394 s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
2395 sc->args = cons(sc,sc->code, sc->NIL);
2396 sc->code = sc->value;
2397 s_goto(sc,OP_APPLY);
2399 sc->code = cdr(sc->code);
2400 s_goto(sc,OP_E1ARGS);
2403 case OP_E1ARGS: /* eval arguments */
2404 sc->args = cons(sc, sc->value, sc->args);
2405 if (is_pair(sc->code)) { /* continue */
2406 s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
2407 sc->code = car(sc->code);
2411 sc->args = reverse_in_place(sc, sc->NIL, sc->args);
2412 sc->code = car(sc->args);
2413 sc->args = cdr(sc->args);
2414 s_goto(sc,OP_APPLY);
2420 sc->tracing=ivalue(car(sc->args));
2421 s_return(sc,mk_integer(sc,tr));
2425 case OP_APPLY: /* apply 'code' to 'args' */
2428 s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
2430 /* sc->args=cons(sc,sc->code,sc->args);*/
2431 putstr(sc,"\nApply to: ");
2432 s_goto(sc,OP_P0LIST);
2437 if (is_proc(sc->code)) {
2438 s_goto(sc,procnum(sc->code)); /* PROCEDURE */
2439 } else if (is_foreign(sc->code)) {
2440 x=sc->code->_object._ff(sc,sc->args);
2442 } else if (is_closure(sc->code) || is_macro(sc->code)
2443 || is_promise(sc->code)) { /* CLOSURE */
2444 /* Should not accept promise */
2445 /* make environment */
2446 new_frame_in_env(sc, closure_env(sc->code));
2447 for (x = car(closure_code(sc->code)), y = sc->args;
2448 is_pair(x); x = cdr(x), y = cdr(y)) {
2450 Error_0(sc,"not enough arguments");
2452 new_slot_in_env(sc, car(x), car(y));
2457 * if (y != sc->NIL) {
2458 * Error_0(sc,"too many arguments");
2461 } else if (is_symbol(x))
2462 new_slot_in_env(sc, x, y);
2464 Error_1(sc,"syntax error in closure: not a symbol:", x);
2466 sc->code = cdr(closure_code(sc->code));
2468 s_goto(sc,OP_BEGIN);
2469 } else if (is_continuation(sc->code)) { /* CONTINUATION */
2470 sc->dump = cont_dump(sc->code);
2471 s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
2473 Error_0(sc,"illegal function");
2476 case OP_DOMACRO: /* do macro */
2477 sc->code = sc->value;
2480 case OP_LAMBDA: /* lambda */
2481 s_return(sc,mk_closure(sc, sc->code, sc->envir));
2483 case OP_MKCLOSURE: /* make-closure */
2485 if(car(x)==sc->LAMBDA) {
2488 if(cdr(sc->args)==sc->NIL) {
2493 s_return(sc,mk_closure(sc, x, y));
2495 case OP_QUOTE: /* quote */
2497 s_return(sc,car(sc->code));
2499 case OP_DEF0: /* define */
2500 if (is_pair(car(sc->code))) {
2502 sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
2505 sc->code = cadr(sc->code);
2507 if (!is_symbol(x)) {
2508 Error_0(sc,"variable is not a symbol");
2510 s_save(sc,OP_DEF1, sc->NIL, x);
2513 case OP_DEF1: /* define */
2514 x=find_slot_in_env(sc,sc->envir,sc->code,0);
2516 set_slot_in_env(sc, x, sc->value);
2518 new_slot_in_env(sc, sc->code, sc->value);
2520 s_return(sc,sc->code);
2523 case OP_DEFP: /* defined? */
2525 if(cdr(sc->args)!=sc->NIL) {
2528 s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
2530 case OP_SET0: /* set! */
2531 s_save(sc,OP_SET1, sc->NIL, car(sc->code));
2532 sc->code = cadr(sc->code);
2535 case OP_SET1: /* set! */
2536 y=find_slot_in_env(sc,sc->envir,sc->code,1);
2538 set_slot_in_env(sc, y, sc->value);
2539 s_return(sc,sc->value);
2541 Error_1(sc,"set!: unbound variable:", sc->code);
2545 case OP_BEGIN: /* begin */
2546 if (!is_pair(sc->code)) {
2547 s_return(sc,sc->code);
2549 if (cdr(sc->code) != sc->NIL) {
2550 s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
2552 sc->code = car(sc->code);
2555 case OP_IF0: /* if */
2556 s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
2557 sc->code = car(sc->code);
2560 case OP_IF1: /* if */
2561 if (is_true(sc->value))
2562 sc->code = car(sc->code);
2564 sc->code = cadr(sc->code); /* (if #f 1) ==> () because
2565 * car(sc->NIL) = sc->NIL */
2568 case OP_LET0: /* let */
2570 sc->value = sc->code;
2571 sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
2574 case OP_LET1: /* let (calculate parameters) */
2575 sc->args = cons(sc, sc->value, sc->args);
2576 if (is_pair(sc->code)) { /* continue */
2577 s_save(sc,OP_LET1, sc->args, cdr(sc->code));
2578 sc->code = cadar(sc->code);
2582 sc->args = reverse_in_place(sc, sc->NIL, sc->args);
2583 sc->code = car(sc->args);
2584 sc->args = cdr(sc->args);
2588 case OP_LET2: /* let */
2589 new_frame_in_env(sc, sc->envir);
2590 for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
2591 y != sc->NIL; x = cdr(x), y = cdr(y)) {
2592 new_slot_in_env(sc, caar(x), car(y));
2594 if (is_symbol(car(sc->code))) { /* named let */
2595 for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
2597 sc->args = cons(sc, caar(x), sc->args);
2599 x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir);
2600 new_slot_in_env(sc, car(sc->code), x);
2601 sc->code = cddr(sc->code);
2604 sc->code = cdr(sc->code);
2607 s_goto(sc,OP_BEGIN);
2609 case OP_LET0AST: /* let* */
2610 if (car(sc->code) == sc->NIL) {
2611 new_frame_in_env(sc, sc->envir);
2612 sc->code = cdr(sc->code);
2613 s_goto(sc,OP_BEGIN);
2615 s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
2616 sc->code = cadaar(sc->code);
2619 case OP_LET1AST: /* let* (make new frame) */
2620 new_frame_in_env(sc, sc->envir);
2621 s_goto(sc,OP_LET2AST);
2623 case OP_LET2AST: /* let* (calculate parameters) */
2624 new_slot_in_env(sc, caar(sc->code), sc->value);
2625 sc->code = cdr(sc->code);
2626 if (is_pair(sc->code)) { /* continue */
2627 s_save(sc,OP_LET2AST, sc->args, sc->code);
2628 sc->code = cadar(sc->code);
2632 sc->code = sc->args;
2634 s_goto(sc,OP_BEGIN);
2637 sprintf(sc->strbuff, "%d: illegal operator", sc->op);
2638 Error_0(sc,sc->strbuff);
2643 static pointer opexe_1(scheme *sc, enum scheme_opcodes op) {
2647 case OP_LET0REC: /* letrec */
2648 new_frame_in_env(sc, sc->envir);
2650 sc->value = sc->code;
2651 sc->code = car(sc->code);
2652 s_goto(sc,OP_LET1REC);
2654 case OP_LET1REC: /* letrec (calculate parameters) */
2655 sc->args = cons(sc, sc->value, sc->args);
2656 if (is_pair(sc->code)) { /* continue */
2657 s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
2658 sc->code = cadar(sc->code);
2662 sc->args = reverse_in_place(sc, sc->NIL, sc->args);
2663 sc->code = car(sc->args);
2664 sc->args = cdr(sc->args);
2665 s_goto(sc,OP_LET2REC);
2668 case OP_LET2REC: /* letrec */
2669 for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
2670 new_slot_in_env(sc, caar(x), car(y));
2672 sc->code = cdr(sc->code);
2674 s_goto(sc,OP_BEGIN);
2676 case OP_COND0: /* cond */
2677 if (!is_pair(sc->code)) {
2678 Error_0(sc,"syntax error in cond");
2680 s_save(sc,OP_COND1, sc->NIL, sc->code);
2681 sc->code = caar(sc->code);
2684 case OP_COND1: /* cond */
2685 if (is_true(sc->value)) {
2686 if ((sc->code = cdar(sc->code)) == sc->NIL) {
2687 s_return(sc,sc->value);
2689 if(car(sc->code)==sc->FEED_TO) {
2690 if(!is_pair(cdr(sc->code))) {
2691 Error_0(sc,"syntax error in cond");
2693 x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
2694 sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
2697 s_goto(sc,OP_BEGIN);
2699 if ((sc->code = cdr(sc->code)) == sc->NIL) {
2700 s_return(sc,sc->NIL);
2702 s_save(sc,OP_COND1, sc->NIL, sc->code);
2703 sc->code = caar(sc->code);
2708 case OP_DELAY: /* delay */
2709 x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
2710 typeflag(x)=T_PROMISE;
2713 case OP_AND0: /* and */
2714 if (sc->code == sc->NIL) {
2717 s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
2718 sc->code = car(sc->code);
2721 case OP_AND1: /* and */
2722 if (is_false(sc->value)) {
2723 s_return(sc,sc->value);
2724 } else if (sc->code == sc->NIL) {
2725 s_return(sc,sc->value);
2727 s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
2728 sc->code = car(sc->code);
2732 case OP_OR0: /* or */
2733 if (sc->code == sc->NIL) {
2736 s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
2737 sc->code = car(sc->code);
2740 case OP_OR1: /* or */
2741 if (is_true(sc->value)) {
2742 s_return(sc,sc->value);
2743 } else if (sc->code == sc->NIL) {
2744 s_return(sc,sc->value);
2746 s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
2747 sc->code = car(sc->code);
2751 case OP_C0STREAM: /* cons-stream */
2752 s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
2753 sc->code = car(sc->code);
2756 case OP_C1STREAM: /* cons-stream */
2757 sc->args = sc->value; /* save sc->value to register sc->args for gc */
2758 x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
2759 typeflag(x)=T_PROMISE;
2760 s_return(sc,cons(sc, sc->args, x));
2762 case OP_MACRO0: /* macro */
2763 if (is_pair(car(sc->code))) {
2765 sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
2768 sc->code = cadr(sc->code);
2770 if (!is_symbol(x)) {
2771 Error_0(sc,"variable is not a symbol");
2773 s_save(sc,OP_MACRO1, sc->NIL, x);
2776 case OP_MACRO1: /* macro */
2777 typeflag(sc->value) = T_MACRO;
2778 x = find_slot_in_env(sc, sc->envir, sc->code, 0);
2780 set_slot_in_env(sc, x, sc->value);
2782 new_slot_in_env(sc, sc->code, sc->value);
2784 s_return(sc,sc->code);
2786 case OP_CASE0: /* case */
2787 s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
2788 sc->code = car(sc->code);
2791 case OP_CASE1: /* case */
2792 for (x = sc->code; x != sc->NIL; x = cdr(x)) {
2793 if (!is_pair(y = caar(x))) {
2796 for ( ; y != sc->NIL; y = cdr(y)) {
2797 if (eqv(car(y), sc->value)) {
2806 if (is_pair(caar(x))) {
2808 s_goto(sc,OP_BEGIN);
2810 s_save(sc,OP_CASE2, sc->NIL, cdar(x));
2815 s_return(sc,sc->NIL);
2818 case OP_CASE2: /* case */
2819 if (is_true(sc->value)) {
2820 s_goto(sc,OP_BEGIN);
2822 s_return(sc,sc->NIL);
2825 case OP_PAPPLY: /* apply */
2826 sc->code = car(sc->args);
2827 sc->args = list_star(sc,cdr(sc->args));
2828 /*sc->args = cadr(sc->args);*/
2829 s_goto(sc,OP_APPLY);
2831 case OP_PEVAL: /* eval */
2832 if(cdr(sc->args)!=sc->NIL) {
2833 sc->envir=cadr(sc->args);
2835 sc->code = car(sc->args);
2838 case OP_CONTINUATION: /* call-with-current-continuation */
2839 sc->code = car(sc->args);
2840 sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
2841 s_goto(sc,OP_APPLY);
2844 sprintf(sc->strbuff, "%d: illegal operator", sc->op);
2845 Error_0(sc,sc->strbuff);
2850 static pointer opexe_2(scheme *sc, enum scheme_opcodes op) {
2859 case OP_INEX2EX: /* inexact->exact */
2863 } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
2864 s_return(sc,mk_integer(sc,ivalue(x)));
2866 Error_1(sc,"inexact->exact: not integral:",x);
2871 s_return(sc, mk_real(sc, exp(rvalue(x))));
2875 s_return(sc, mk_real(sc, log(rvalue(x))));
2879 s_return(sc, mk_real(sc, sin(rvalue(x))));
2883 s_return(sc, mk_real(sc, cos(rvalue(x))));
2887 s_return(sc, mk_real(sc, tan(rvalue(x))));
2891 s_return(sc, mk_real(sc, asin(rvalue(x))));
2895 s_return(sc, mk_real(sc, acos(rvalue(x))));
2899 if(cdr(sc->args)==sc->NIL) {
2900 s_return(sc, mk_real(sc, atan(rvalue(x))));
2902 pointer y=cadr(sc->args);
2903 s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
2908 s_return(sc, mk_real(sc, sqrt(rvalue(x))));
2912 if(cdr(sc->args)==sc->NIL) {
2913 Error_0(sc,"expt: needs two arguments");
2915 pointer y=cadr(sc->args);
2916 s_return(sc, mk_real(sc, pow(rvalue(x),
2922 s_return(sc, mk_real(sc, floor(rvalue(x))));
2926 s_return(sc, mk_real(sc, ceil(rvalue(x))));
2928 case OP_TRUNCATE : {
2929 double rvalue_of_x ;
2931 rvalue_of_x = rvalue(x) ;
2932 if (rvalue_of_x > 0) {
2933 s_return(sc, mk_real(sc, floor(rvalue_of_x)));
2935 s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
2941 s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
2944 case OP_ADD: /* + */
2946 for (x = sc->args; x != sc->NIL; x = cdr(x)) {
2947 v=num_add(v,nvalue(car(x)));
2949 s_return(sc,mk_number(sc, v));
2951 case OP_MUL: /* * */
2953 for (x = sc->args; x != sc->NIL; x = cdr(x)) {
2954 v=num_mul(v,nvalue(car(x)));
2956 s_return(sc,mk_number(sc, v));
2958 case OP_SUB: /* - */
2959 if(cdr(sc->args)==sc->NIL) {
2964 v = nvalue(car(sc->args));
2966 for (; x != sc->NIL; x = cdr(x)) {
2967 v=num_sub(v,nvalue(car(x)));
2969 s_return(sc,mk_number(sc, v));
2971 case OP_DIV: /* / */
2972 if(cdr(sc->args)==sc->NIL) {
2977 v = nvalue(car(sc->args));
2979 for (; x != sc->NIL; x = cdr(x)) {
2980 if (!is_zero_double(rvalue(car(x))))
2981 v=num_div(v,nvalue(car(x)));
2983 Error_0(sc,"/: division by zero");
2986 s_return(sc,mk_number(sc, v));
2988 case OP_INTDIV: /* quotient */
2989 if(cdr(sc->args)==sc->NIL) {
2994 v = nvalue(car(sc->args));
2996 for (; x != sc->NIL; x = cdr(x)) {
2997 if (ivalue(car(x)) != 0)
2998 v=num_intdiv(v,nvalue(car(x)));
3000 Error_0(sc,"quotient: division by zero");
3003 s_return(sc,mk_number(sc, v));
3005 case OP_REM: /* remainder */
3006 v = nvalue(car(sc->args));
3007 if (ivalue(cadr(sc->args)) != 0)
3008 v=num_rem(v,nvalue(cadr(sc->args)));
3010 Error_0(sc,"remainder: division by zero");
3012 s_return(sc,mk_number(sc, v));
3014 case OP_MOD: /* modulo */
3015 v = nvalue(car(sc->args));
3016 if (ivalue(cadr(sc->args)) != 0)
3017 v=num_mod(v,nvalue(cadr(sc->args)));
3019 Error_0(sc,"modulo: division by zero");
3021 s_return(sc,mk_number(sc, v));
3023 case OP_CAR: /* car */
3024 s_return(sc,caar(sc->args));
3026 case OP_CDR: /* cdr */
3027 s_return(sc,cdar(sc->args));
3029 case OP_CONS: /* cons */
3030 cdr(sc->args) = cadr(sc->args);
3031 s_return(sc,sc->args);
3033 case OP_SETCAR: /* set-car! */
3034 if(!is_immutable(car(sc->args))) {
3035 caar(sc->args) = cadr(sc->args);
3036 s_return(sc,car(sc->args));
3038 Error_0(sc,"set-car!: unable to alter immutable pair");
3041 case OP_SETCDR: /* set-cdr! */
3042 if(!is_immutable(car(sc->args))) {
3043 cdar(sc->args) = cadr(sc->args);
3044 s_return(sc,car(sc->args));
3046 Error_0(sc,"set-cdr!: unable to alter immutable pair");
3049 case OP_CHAR2INT: { /* char->integer */
3051 c=(char)ivalue(car(sc->args));
3052 s_return(sc,mk_integer(sc,(unsigned char)c));
3055 case OP_INT2CHAR: { /* integer->char */
3057 c=(unsigned char)ivalue(car(sc->args));
3058 s_return(sc,mk_character(sc,(char)c));
3061 case OP_CHARUPCASE: {
3063 c=(unsigned char)ivalue(car(sc->args));
3065 s_return(sc,mk_character(sc,(char)c));
3068 case OP_CHARDNCASE: {
3070 c=(unsigned char)ivalue(car(sc->args));
3072 s_return(sc,mk_character(sc,(char)c));
3075 case OP_STR2SYM: /* string->symbol */
3076 s_return(sc,mk_symbol(sc,strvalue(car(sc->args))));
3078 case OP_STR2ATOM: /* string->atom */ {
3079 char *s=strvalue(car(sc->args));
3081 s_return(sc, mk_sharp_const(sc, s+1));
3083 s_return(sc, mk_atom(sc, s));
3087 case OP_SYM2STR: /* symbol->string */
3088 x=mk_string(sc,symname(car(sc->args)));
3091 case OP_ATOM2STR: /* atom->string */
3093 if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
3096 atom2str(sc,x,0,&p,&len);
3097 s_return(sc,mk_counted_string(sc,p,len));
3099 Error_1(sc, "atom->string: not an atom:", x);
3102 case OP_MKSTRING: { /* make-string */
3106 len=ivalue(car(sc->args));
3108 if(cdr(sc->args)!=sc->NIL) {
3109 fill=charvalue(cadr(sc->args));
3111 s_return(sc,mk_empty_string(sc,len,(char)fill));
3114 case OP_STRLEN: /* string-length */
3115 s_return(sc,mk_integer(sc,strlength(car(sc->args))));
3117 case OP_STRREF: { /* string-ref */
3121 str=strvalue(car(sc->args));
3123 index=ivalue(cadr(sc->args));
3125 if(index>=strlength(car(sc->args))) {
3126 Error_1(sc,"string-ref: out of bounds:",cadr(sc->args));
3129 s_return(sc,mk_character(sc,((unsigned char*)str)[index]));
3132 case OP_STRSET: { /* string-set! */
3137 if(is_immutable(car(sc->args))) {
3138 Error_1(sc,"string-set!: unable to alter immutable string:",car(sc->args));
3140 str=strvalue(car(sc->args));
3142 index=ivalue(cadr(sc->args));
3143 if(index>=strlength(car(sc->args))) {
3144 Error_1(sc,"string-set!: out of bounds:",cadr(sc->args));
3147 c=charvalue(caddr(sc->args));
3150 s_return(sc,car(sc->args));
3153 case OP_STRAPPEND: { /* string-append */
3154 /* in 1.29 string-append was in Scheme in init.scm but was too slow */
3159 /* compute needed length for new string */
3160 for (x = sc->args; x != sc->NIL; x = cdr(x)) {
3161 len += strlength(car(x));
3163 newstr = mk_empty_string(sc, len, ' ');
3164 /* store the contents of the argument strings into the new string */
3165 for (pos = strvalue(newstr), x = sc->args; x != sc->NIL;
3166 pos += strlength(car(x)), x = cdr(x)) {
3167 memcpy(pos, strvalue(car(x)), strlength(car(x)));
3169 s_return(sc, newstr);
3172 case OP_SUBSTR: { /* substring */
3178 str=strvalue(car(sc->args));
3180 index0=ivalue(cadr(sc->args));
3182 if(index0>strlength(car(sc->args))) {
3183 Error_1(sc,"substring: start out of bounds:",cadr(sc->args));
3186 if(cddr(sc->args)!=sc->NIL) {
3187 index1=ivalue(caddr(sc->args));
3188 if(index1>strlength(car(sc->args)) || index1<index0) {
3189 Error_1(sc,"substring: end out of bounds:",caddr(sc->args));
3192 index1=strlength(car(sc->args));
3196 x=mk_empty_string(sc,len,' ');
3197 memcpy(strvalue(x),str+index0,len);
3203 case OP_VECTOR: { /* vector */
3206 int len=list_length(sc,sc->args);
3208 Error_1(sc,"vector: not a proper list:",sc->args);
3210 vec=mk_vector(sc,len);
3211 for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
3212 set_vector_elem(vec,i,car(x));
3217 case OP_MKVECTOR: { /* make-vector */
3218 pointer fill=sc->NIL;
3222 len=ivalue(car(sc->args));
3224 if(cdr(sc->args)!=sc->NIL) {
3225 fill=cadr(sc->args);
3227 vec=mk_vector(sc,len);
3229 fill_vector(vec,fill);
3234 case OP_VECLEN: /* vector-length */
3235 s_return(sc,mk_integer(sc,ivalue(car(sc->args))));
3237 case OP_VECREF: { /* vector-ref */
3240 index=ivalue(cadr(sc->args));
3242 if(index>=ivalue(car(sc->args))) {
3243 Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args));
3246 s_return(sc,vector_elem(car(sc->args),index));
3249 case OP_VECSET: { /* vector-set! */
3252 if(is_immutable(car(sc->args))) {
3253 Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args));
3256 index=ivalue(cadr(sc->args));
3257 if(index>=ivalue(car(sc->args))) {
3258 Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args));
3261 set_vector_elem(car(sc->args),index,caddr(sc->args));
3262 s_return(sc,car(sc->args));
3266 sprintf(sc->strbuff, "%d: illegal operator", sc->op);
3267 Error_0(sc,sc->strbuff);
3272 static int list_length(scheme *sc, pointer a) {
3275 for (x = a, v = 0; is_pair(x); x = cdr(x)) {
3284 static pointer opexe_3(scheme *sc, enum scheme_opcodes op) {
3287 int (*comp_func)(num,num)=0;
3290 case OP_NOT: /* not */
3291 s_retbool(is_false(car(sc->args)));
3292 case OP_BOOLP: /* boolean? */
3293 s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
3294 case OP_EOFOBJP: /* boolean? */
3295 s_retbool(car(sc->args) == sc->EOF_OBJ);
3296 case OP_NULLP: /* null? */
3297 s_retbool(car(sc->args) == sc->NIL);
3298 case OP_NUMEQ: /* = */
3299 case OP_LESS: /* < */
3300 case OP_GRE: /* > */
3301 case OP_LEQ: /* <= */
3302 case OP_GEQ: /* >= */
3304 case OP_NUMEQ: comp_func=num_eq; break;
3305 case OP_LESS: comp_func=num_lt; break;
3306 case OP_GRE: comp_func=num_gt; break;
3307 case OP_LEQ: comp_func=num_le; break;
3308 case OP_GEQ: comp_func=num_ge; break;
3315 for (; x != sc->NIL; x = cdr(x)) {
3316 if(!comp_func(v,nvalue(car(x)))) {
3322 case OP_SYMBOLP: /* symbol? */
3323 s_retbool(is_symbol(car(sc->args)));
3324 case OP_NUMBERP: /* number? */
3325 s_retbool(is_number(car(sc->args)));
3326 case OP_STRINGP: /* string? */
3327 s_retbool(is_string(car(sc->args)));
3328 case OP_INTEGERP: /* integer? */
3329 s_retbool(is_integer(car(sc->args)));
3330 case OP_REALP: /* real? */
3331 s_retbool(is_number(car(sc->args))); /* All numbers are real */
3332 case OP_CHARP: /* char? */
3333 s_retbool(is_character(car(sc->args)));
3334 #if USE_CHAR_CLASSIFIERS
3335 case OP_CHARAP: /* char-alphabetic? */
3336 s_retbool(Cisalpha(ivalue(car(sc->args))));
3337 case OP_CHARNP: /* char-numeric? */
3338 s_retbool(Cisdigit(ivalue(car(sc->args))));
3339 case OP_CHARWP: /* char-whitespace? */
3340 s_retbool(Cisspace(ivalue(car(sc->args))));
3341 case OP_CHARUP: /* char-upper-case? */
3342 s_retbool(Cisupper(ivalue(car(sc->args))));
3343 case OP_CHARLP: /* char-lower-case? */
3344 s_retbool(Cislower(ivalue(car(sc->args))));
3346 case OP_PORTP: /* port? */
3347 s_retbool(is_port(car(sc->args)));
3348 case OP_INPORTP: /* input-port? */
3349 s_retbool(is_inport(car(sc->args)));
3350 case OP_OUTPORTP: /* output-port? */
3351 s_retbool(is_outport(car(sc->args)));
3352 case OP_PROCP: /* procedure? */
3354 * continuation should be procedure by the example
3355 * (call-with-current-continuation procedure?) ==> #t
3356 * in R^3 report sec. 6.9
3358 s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
3359 || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
3360 case OP_PAIRP: /* pair? */
3361 s_retbool(is_pair(car(sc->args)));
3362 case OP_LISTP: { /* list? */
3364 slow = fast = car(sc->args);
3366 if (!is_pair(fast)) s_retbool(fast == sc->NIL);
3368 if (!is_pair(fast)) s_retbool(fast == sc->NIL);
3372 /* the fast pointer has looped back around and caught up
3373 with the slow pointer, hence the structure is circular,
3374 not of finite length, and therefore not a list */
3379 case OP_ENVP: /* environment? */
3380 s_retbool(is_environment(car(sc->args)));
3381 case OP_VECTORP: /* vector? */
3382 s_retbool(is_vector(car(sc->args)));
3383 case OP_EQ: /* eq? */
3384 s_retbool(car(sc->args) == cadr(sc->args));
3385 case OP_EQV: /* eqv? */
3386 s_retbool(eqv(car(sc->args), cadr(sc->args)));
3388 sprintf(sc->strbuff, "%d: illegal operator", sc->op);
3389 Error_0(sc,sc->strbuff);
3394 static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
3398 case OP_FORCE: /* force */
3399 sc->code = car(sc->args);
3400 if (is_promise(sc->code)) {
3401 /* Should change type to closure here */
3402 s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
3404 s_goto(sc,OP_APPLY);
3406 s_return(sc,sc->code);
3409 case OP_SAVE_FORCED: /* Save forced value replacing promise */
3410 memcpy(sc->code,sc->value,sizeof(struct cell));
3411 s_return(sc,sc->value);
3413 case OP_WRITE: /* write */
3414 case OP_DISPLAY: /* display */
3415 case OP_WRITE_CHAR: /* write-char */
3416 if(is_pair(cdr(sc->args))) {
3417 if(cadr(sc->args)!=sc->outport) {
3418 x=cons(sc,sc->outport,sc->NIL);
3419 s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
3420 sc->outport=cadr(sc->args);
3423 sc->args = car(sc->args);
3429 s_goto(sc,OP_P0LIST);
3431 case OP_NEWLINE: /* newline */
3432 if(is_pair(sc->args)) {
3433 if(car(sc->args)!=sc->outport) {
3434 x=cons(sc,sc->outport,sc->NIL);
3435 s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
3436 sc->outport=car(sc->args);
3442 case OP_ERR0: /* error */
3444 if (!is_string(car(sc->args))) {
3445 sc->args=cons(sc,mk_string(sc," -- "),sc->args);
3446 setimmutable(car(sc->args));
3448 putstr(sc, "Error: ");
3449 #if USE_FILE_AND_LINE
3452 pt=sc->inport->_object._port;
3453 if(pt->kind&port_file &&
3454 pt->rep.stdio.name) {
3456 putstr(sc, pt->rep.stdio.name);
3457 putstr(sc, " line ");
3458 snprintf(linestr, sizeof(linestr), "%d", pt->rep.stdio.line);
3459 putstr(sc, linestr);
3464 putstr(sc, strvalue(car(sc->args)));
3465 sc->args = cdr(sc->args);
3468 case OP_ERR1: /* error */
3470 if (sc->args != sc->NIL) {
3471 s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
3472 sc->args = car(sc->args);
3474 s_goto(sc,OP_P0LIST);
3477 if(sc->interactive_repl) {
3478 s_goto(sc,OP_T0LVL);
3484 case OP_REVERSE: /* reverse */
3485 s_return(sc,reverse(sc, car(sc->args)));
3487 case OP_LIST_STAR: /* list* */
3488 s_return(sc,list_star(sc,sc->args));
3490 case OP_APPEND: /* append */
3491 if(sc->args==sc->NIL) {
3492 s_return(sc,sc->NIL);
3495 if(cdr(sc->args)==sc->NIL) {
3496 s_return(sc,sc->args);
3498 for (y = cdr(sc->args); y != sc->NIL; y = cdr(y)) {
3499 x=append(sc,x,car(y));
3504 case OP_PUT: /* put */
3505 if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
3506 Error_0(sc,"illegal use of put");
3508 for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
3514 cdar(x) = caddr(sc->args);
3516 symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)),
3517 symprop(car(sc->args)));
3520 case OP_GET: /* get */
3521 if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
3522 Error_0(sc,"illegal use of get");
3524 for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
3530 s_return(sc,cdar(x));
3532 s_return(sc,sc->NIL);
3534 #endif /* USE_PLIST */
3535 case OP_QUIT: /* quit */
3536 if(is_pair(sc->args)) {
3537 sc->retcode=ivalue(car(sc->args));
3541 case OP_GC: /* gc */
3542 gc(sc, sc->NIL, sc->NIL);
3545 case OP_GCVERB: /* gc-verbose */
3546 { int was = sc->gc_verbose;
3548 sc->gc_verbose = (car(sc->args) != sc->F);
3552 case OP_NEWSEGMENT: /* new-segment */
3553 if (!is_pair(sc->args) || !is_number(car(sc->args))) {
3554 Error_0(sc,"new-segment: argument must be a number");
3556 alloc_cellseg(sc, (int) ivalue(car(sc->args)));
3559 case OP_OBLIST: /* oblist */
3560 s_return(sc, oblist_all_symbols(sc));
3562 case OP_CURR_INPORT: /* current-input-port */
3563 s_return(sc,sc->inport);
3565 case OP_CURR_OUTPORT: /* current-output-port */
3566 s_return(sc,sc->outport);
3568 case OP_OPEN_INFILE: /* open-input-file */
3569 case OP_OPEN_OUTFILE: /* open-output-file */
3570 case OP_OPEN_INOUTFILE: /* open-input-output-file */ {
3574 case OP_OPEN_INFILE: prop=port_input; break;
3575 case OP_OPEN_OUTFILE: prop=port_output; break;
3576 case OP_OPEN_INOUTFILE: prop=port_input|port_output; break;
3579 p=port_from_filename(sc,strvalue(car(sc->args)),prop);
3586 #if USE_STRING_PORTS
3587 case OP_OPEN_INSTRING: /* open-input-string */
3588 case OP_OPEN_OUTSTRING: /* open-output-string */
3589 case OP_OPEN_INOUTSTRING: /* open-input-output-string */ {
3593 case OP_OPEN_INSTRING: prop=port_input; break;
3594 case OP_OPEN_OUTSTRING: prop=port_output; break;
3595 case OP_OPEN_INOUTSTRING: prop=port_input|port_output; break;
3598 p=port_from_string(sc, strvalue(car(sc->args)),
3599 strvalue(car(sc->args))+strlength(car(sc->args)), prop);
3607 case OP_CLOSE_INPORT: /* close-input-port */
3608 port_close(sc,car(sc->args),port_input);
3611 case OP_CLOSE_OUTPORT: /* close-output-port */
3612 port_close(sc,car(sc->args),port_output);
3615 case OP_INT_ENV: /* interaction-environment */
3616 s_return(sc,sc->global_env);
3618 case OP_CURR_ENV: /* current-environment */
3619 s_return(sc,sc->envir);
3626 static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
3629 if(sc->nesting!=0) {
3633 Error_1(sc,"unmatched parentheses:",mk_integer(sc,n));
3637 /* ========== reading part ========== */
3639 if(!is_pair(sc->args)) {
3640 s_goto(sc,OP_READ_INTERNAL);
3642 if(!is_inport(car(sc->args))) {
3643 Error_1(sc,"read: not an input port:",car(sc->args));
3645 if(car(sc->args)==sc->inport) {
3646 s_goto(sc,OP_READ_INTERNAL);
3649 sc->inport=car(sc->args);
3650 x=cons(sc,x,sc->NIL);
3651 s_save(sc,OP_SET_INPORT, x, sc->NIL);
3652 s_goto(sc,OP_READ_INTERNAL);
3654 case OP_READ_CHAR: /* read-char */
3655 case OP_PEEK_CHAR: /* peek-char */ {
3657 if(is_pair(sc->args)) {
3658 if(car(sc->args)!=sc->inport) {
3660 x=cons(sc,x,sc->NIL);
3661 s_save(sc,OP_SET_INPORT, x, sc->NIL);
3662 sc->inport=car(sc->args);
3667 s_return(sc,sc->EOF_OBJ);
3669 if(sc->op==OP_PEEK_CHAR) {
3672 s_return(sc,mk_character(sc,c));
3675 case OP_CHAR_READY: /* char-ready? */ {
3676 pointer p=sc->inport;
3678 if(is_pair(sc->args)) {
3681 res=p->_object._port->kind&port_string;
3685 case OP_SET_INPORT: /* set-input-port */
3686 sc->inport=car(sc->args);
3687 s_return(sc,sc->value);
3689 case OP_SET_OUTPORT: /* set-output-port */
3690 sc->outport=car(sc->args);
3691 s_return(sc,sc->value);
3696 if(sc->inport==sc->loadport) {
3700 s_return(sc,sc->EOF_OBJ);
3703 * Commented out because we now skip comments in the scanner
3707 while ((c=inchar(sc)) != '\n' && c!=EOF)
3710 sc->tok = token(sc);
3712 s_goto(sc,OP_RDSEXPR);
3716 s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
3719 sc->tok = token(sc);
3720 if (sc->tok == TOK_RPAREN) {
3721 s_return(sc,sc->NIL);
3722 } else if (sc->tok == TOK_DOT) {
3723 Error_0(sc,"syntax error: illegal dot expression");
3725 sc->nesting_stack[sc->file_i]++;
3726 s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
3727 s_goto(sc,OP_RDSEXPR);
3730 s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
3731 sc->tok = token(sc);
3732 s_goto(sc,OP_RDSEXPR);
3734 sc->tok = token(sc);
3735 if(sc->tok==TOK_VEC) {
3736 s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
3738 s_goto(sc,OP_RDSEXPR);
3740 s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
3742 s_goto(sc,OP_RDSEXPR);
3744 s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
3745 sc->tok = token(sc);
3746 s_goto(sc,OP_RDSEXPR);
3748 s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
3749 sc->tok = token(sc);
3750 s_goto(sc,OP_RDSEXPR);
3752 s_return(sc,mk_atom(sc, readstr_upto(sc, "();\t\n\r ")));
3756 Error_0(sc,"Error reading string");
3761 pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
3763 Error_0(sc,"undefined sharp expression");
3765 sc->code=cons(sc,slot_value_in_env(f),sc->NIL);
3769 case TOK_SHARP_CONST:
3770 if ((x = mk_sharp_const(sc, readstr_upto(sc, "();\t\n\r "))) == sc->NIL) {
3771 Error_0(sc,"undefined sharp expression");
3776 Error_0(sc,"syntax error: illegal token");
3781 sc->args = cons(sc, sc->value, sc->args);
3782 sc->tok = token(sc);
3783 if (sc->tok == TOK_COMMENT) {
3785 while ((c=inchar(sc)) != '\n' && c!=EOF)
3787 sc->tok = token(sc);
3789 if (sc->tok == TOK_RPAREN) {
3791 /* inchar() may pop the file, so decrement the nesting stack
3792 * now. Otherwise if files end in RPAREN you'll get a mysterious
3793 * "mismatched parentheseis: -1" error. */
3794 sc->nesting_stack[sc->file_i]--;
3796 if (c != '\n' && c != EOF) backchar(sc,c);
3797 s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
3798 } else if (sc->tok == TOK_DOT) {
3799 s_save(sc,OP_RDDOT, sc->args, sc->NIL);
3800 sc->tok = token(sc);
3801 s_goto(sc,OP_RDSEXPR);
3803 s_save(sc,OP_RDLIST, sc->args, sc->NIL);;
3804 s_goto(sc,OP_RDSEXPR);
3809 if (token(sc) != TOK_RPAREN) {
3810 Error_0(sc,"syntax error: illegal dot expression");
3812 sc->nesting_stack[sc->file_i]--;
3813 s_return(sc,reverse_in_place(sc, sc->value, sc->args));
3817 s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)));
3820 s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL)));
3822 case OP_RDQQUOTEVEC:
3823 s_return(sc,cons(sc, mk_symbol(sc,"apply"),
3824 cons(sc, mk_symbol(sc,"vector"),
3825 cons(sc,cons(sc, sc->QQUOTE,
3826 cons(sc,sc->value,sc->NIL)),
3830 s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL)));
3833 s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL)));
3836 /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
3837 s_goto(sc,OP_EVAL); Cannot be quoted*/
3838 /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
3839 s_return(sc,x); Cannot be part of pairs*/
3840 /*sc->code=mk_proc(sc,OP_VECTOR);
3842 s_goto(sc,OP_APPLY);*/
3844 s_goto(sc,OP_VECTOR);
3846 /* ========== printing part ========== */
3848 if(is_vector(sc->args)) {
3850 sc->args=cons(sc,sc->args,mk_integer(sc,0));
3851 s_goto(sc,OP_PVECFROM);
3852 } else if(is_environment(sc->args)) {
3853 putstr(sc,"#<ENVIRONMENT>");
3855 } else if (!is_pair(sc->args)) {
3856 printatom(sc, sc->args, sc->print_flag);
3858 } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
3860 sc->args = cadr(sc->args);
3861 s_goto(sc,OP_P0LIST);
3862 } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
3864 sc->args = cadr(sc->args);
3865 s_goto(sc,OP_P0LIST);
3866 } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
3868 sc->args = cadr(sc->args);
3869 s_goto(sc,OP_P0LIST);
3870 } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
3872 sc->args = cadr(sc->args);
3873 s_goto(sc,OP_P0LIST);
3876 s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
3877 sc->args = car(sc->args);
3878 s_goto(sc,OP_P0LIST);
3882 if (is_pair(sc->args)) {
3883 s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
3885 sc->args = car(sc->args);
3886 s_goto(sc,OP_P0LIST);
3887 } else if(is_vector(sc->args)) {
3888 s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
3890 s_goto(sc,OP_P0LIST);
3892 if (sc->args != sc->NIL) {
3894 printatom(sc, sc->args, sc->print_flag);
3900 int i=ivalue_unchecked(cdr(sc->args));
3901 pointer vec=car(sc->args);
3902 int len=ivalue_unchecked(vec);
3907 pointer elem=vector_elem(vec,i);
3908 ivalue_unchecked(cdr(sc->args))=i+1;
3909 s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
3912 s_goto(sc,OP_P0LIST);
3917 sprintf(sc->strbuff, "%d: illegal operator", sc->op);
3918 Error_0(sc,sc->strbuff);
3924 static pointer opexe_6(scheme *sc, enum scheme_opcodes op) {
3929 case OP_LIST_LENGTH: /* length */ /* a.k */
3930 v=list_length(sc,car(sc->args));
3932 Error_1(sc,"length: not a list:",car(sc->args));
3934 s_return(sc,mk_integer(sc, v));
3936 case OP_ASSQ: /* assq */ /* a.k */
3938 for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
3939 if (!is_pair(car(y))) {
3940 Error_0(sc,"unable to handle non pair element");
3946 s_return(sc,car(y));
3952 case OP_GET_CLOSURE: /* get-closure-code */ /* a.k */
3953 sc->args = car(sc->args);
3954 if (sc->args == sc->NIL) {
3956 } else if (is_closure(sc->args)) {
3957 s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
3958 } else if (is_macro(sc->args)) {
3959 s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
3963 case OP_CLOSUREP: /* closure? */
3965 * Note, macro object is also a closure.
3966 * Therefore, (closure? <#MACRO>) ==> #t
3968 s_retbool(is_closure(car(sc->args)));
3969 case OP_MACROP: /* macro? */
3970 s_retbool(is_macro(car(sc->args)));
3972 sprintf(sc->strbuff, "%d: illegal operator", sc->op);
3973 Error_0(sc,sc->strbuff);
3975 return sc->T; /* NOTREACHED */
3979 /* gmcnutt: added to fix the script->C->script recursion problem */
3980 static pointer opexe_ghul(scheme *sc, enum scheme_opcodes op) {
3982 case OP_EXIT_REENTER:
3983 /* Returning sc->NIL will force Eval_Cycle to return without
3984 * consuming any more stack frames. We need to leave the stack
3985 * frames below this operation intact so that when C returns to
3986 * the script the script can continue processing. */
3991 return sc->T; /* NOTREACHED */
3995 typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes);
3997 typedef int (*test_predicate)(pointer);
3998 static int is_any(pointer p) { return 1;}
3999 static int is_num_integer(pointer p) {
4000 return is_number(p) && ((p)->_object._number.is_fixnum);
4002 static int is_nonneg(pointer p) {
4003 return is_num_integer(p) && ivalue(p)>=0;
4006 /* Correspond carefully with following defines! */
4013 {is_string, "string"},
4014 {is_symbol, "symbol"},
4018 {is_environment, "environment"},
4021 {is_character, "character"},
4022 {is_vector, "vector"},
4023 {is_number, "number"},
4024 {is_num_integer, "integer"},
4025 {is_nonneg, "non-negative integer"}
4029 #define TST_ANY "\001"
4030 #define TST_STRING "\002"
4031 #define TST_SYMBOL "\003"
4032 #define TST_PORT "\004"
4033 #define TST_INPORT "\005"
4034 #define TST_OUTPORT "\006"
4035 #define TST_ENVIRONMENT "\007"
4036 #define TST_PAIR "\010"
4037 #define TST_LIST "\011"
4038 #define TST_CHAR "\012"
4039 #define TST_VECTOR "\013"
4040 #define TST_NUMBER "\014"
4041 #define TST_INTEGER "\015"
4042 #define TST_NATURAL "\016"
4049 const char *arg_tests_encoding;
4052 #define INF_ARG 0xffff
4054 static op_code_info dispatch_table[]= {
4055 #define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
4056 #include "opdefines.h"
4060 static const char *procname(pointer x) {
4062 const char *name=dispatch_table[n].name;
4069 /* kernel of this interpreter */
4070 static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
4079 /* special debug hack */
4080 //assert((sc->oblist+1+(356/2))->_object._cons._cdr->_flag & T_IMMUTABLE);
4082 op_code_info *pcd=dispatch_table+sc->op;
4083 if (pcd->name!=0) { /* if built-in function, check arguments */
4086 int n=list_length(sc,sc->args);
4088 /* Check number of arguments */
4089 if(n<pcd->min_arity) {
4091 sprintf(msg,"%s: needs%s %d argument(s)",
4093 pcd->min_arity==pcd->max_arity?"":" at least",
4096 if(ok && n>pcd->max_arity) {
4098 sprintf(msg,"%s: needs%s %d argument(s)",
4100 pcd->min_arity==pcd->max_arity?"":" at most",
4104 if(pcd->arg_tests_encoding!=0) {
4107 const char *t=pcd->arg_tests_encoding;
4108 pointer arglist=sc->args;
4110 pointer arg=car(arglist);
4112 if(j==TST_INPORT[0]) {
4113 if(!is_inport(arg)) break;
4114 } else if(j==TST_OUTPORT[0]) {
4115 if(!is_outport(arg)) break;
4116 } else if(j==TST_LIST[0]) {
4117 if(arg!=sc->NIL && !is_pair(arg)) break;
4119 if(!tests[j].fct(arg)) break;
4122 if(t[1]!=0) {/* last test is replicated as necessary */
4125 arglist=cdr(arglist);
4130 sprintf(msg,"%s: argument %d must be: %s",
4138 if(_Error_1(sc,msg,0)==sc->NIL) {
4142 pcd=dispatch_table+sc->op;
4146 if (pcd->func(sc, (scheme_opcodes)sc->op) == sc->NIL) {
4151 fprintf(stderr,"No memory!\n");
4160 /* ========== Initialization of internal keywords ========== */
4162 static void assign_syntax(scheme *sc, const char *name) {
4165 x = oblist_add_by_name(sc, name);
4166 typeflag(x) |= T_SYNTAX;
4169 static void assign_proc(scheme *sc, enum scheme_opcodes op, const char *name) {
4172 x = mk_symbol(sc, name);
4174 new_slot_in_env(sc, x, y);
4177 static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
4180 y = get_cell(sc, sc->NIL, sc->NIL);
4181 typeflag(y) = (T_PROC | T_ATOM);
4182 ivalue_unchecked(y) = (long) op;
4187 /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
4188 static int syntaxnum(pointer p) {
4189 const char *s=strvalue(car(p));
4190 switch(strlength(car(p))) {
4192 if(s[0]=='i') return OP_IF0; /* if */
4193 else return OP_OR0; /* or */
4195 if(s[0]=='a') return OP_AND0; /* and */
4196 else return OP_LET0; /* let */
4199 case 'e': return OP_CASE0; /* case */
4200 case 'd': return OP_COND0; /* cond */
4201 case '*': return OP_LET0AST; /* let* */
4202 default: return OP_SET0; /* set! */
4206 case 'g': return OP_BEGIN; /* begin */
4207 case 'l': return OP_DELAY; /* delay */
4208 case 'c': return OP_MACRO0; /* macro */
4209 default: return OP_QUOTE; /* quote */
4213 case 'm': return OP_LAMBDA; /* lambda */
4214 case 'f': return OP_DEF0; /* define */
4215 default: return OP_LET0REC; /* letrec */
4218 return OP_C0STREAM; /* cons-stream */
4222 /* initialization of TinyScheme */
4224 INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
4225 return cons(sc,a,b);
4227 INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
4228 return immutable_cons(sc,a,b);
4231 static struct scheme_interface vtbl ={
4295 #if USE_CUSTOM_FINALIZE
4302 scheme *scheme_init_new() {
4303 scheme *sc=(scheme*)malloc(sizeof(scheme));
4304 if(!scheme_init(sc)) {
4312 scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
4313 scheme *sc=(scheme*)malloc(sizeof(scheme));
4314 if(!scheme_init_custom_alloc(sc,malloc,free)) {
4323 int scheme_init(scheme *sc) {
4324 return scheme_init_custom_alloc(sc,malloc,free);
4327 int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
4328 int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
4331 num_zero.is_fixnum=1;
4332 num_zero.value.ivalue=0;
4333 num_one.is_fixnum=1;
4334 num_one.value.ivalue=1;
4342 sc->last_cell_seg = -1;
4343 sc->sink = &sc->_sink;
4344 sc->NIL = &sc->_NIL;
4345 sc->T = &sc->_HASHT;
4346 sc->F = &sc->_HASHF;
4347 sc->EOF_OBJ=&sc->_EOF_OBJ;
4348 sc->free_cell = &sc->_NIL;
4352 sc->outport=sc->NIL;
4353 sc->save_inport=sc->NIL;
4354 sc->loadport=sc->NIL;
4356 sc->interactive_repl=0;
4358 if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
4363 dump_stack_initialize(sc);
4368 typeflag(sc->NIL) = (T_ATOM | MARK);
4369 car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
4372 typeflag(sc->T) = (T_ATOM | MARK);
4373 car(sc->T) = cdr(sc->T) = sc->T;
4376 typeflag(sc->F) = (T_ATOM | MARK);
4377 car(sc->F) = cdr(sc->F) = sc->F;
4379 sc->oblist = oblist_initial_value(sc);
4380 /* init global_env */
4381 new_frame_in_env(sc, sc->NIL);
4382 sc->global_env = sc->envir;
4384 x = mk_symbol(sc,"else");
4385 new_slot_in_env(sc, x, sc->T);
4387 assign_syntax(sc, "lambda");
4388 assign_syntax(sc, "quote");
4389 assign_syntax(sc, "define");
4390 assign_syntax(sc, "if");
4391 assign_syntax(sc, "begin");
4392 assign_syntax(sc, "set!");
4393 assign_syntax(sc, "let");
4394 assign_syntax(sc, "let*");
4395 assign_syntax(sc, "letrec");
4396 assign_syntax(sc, "cond");
4397 assign_syntax(sc, "delay");
4398 assign_syntax(sc, "and");
4399 assign_syntax(sc, "or");
4400 assign_syntax(sc, "cons-stream");
4401 assign_syntax(sc, "macro");
4402 assign_syntax(sc, "case");
4404 for(i=0; i<n; i++) {
4405 if(dispatch_table[i].name!=0) {
4406 assign_proc(sc, (scheme_opcodes)i, dispatch_table[i].name);
4410 /* initialization of global pointers to special symbols */
4411 sc->LAMBDA = mk_symbol(sc, "lambda");
4412 sc->QUOTE = mk_symbol(sc, "quote");
4413 sc->QQUOTE = mk_symbol(sc, "quasiquote");
4414 sc->UNQUOTE = mk_symbol(sc, "unquote");
4415 sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
4416 sc->FEED_TO = mk_symbol(sc, "=>");
4417 sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
4418 sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
4419 sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
4422 /* init protected list */
4423 list_init(&sc->protect);
4424 sc->ignore_protect = 0;
4427 return !sc->no_memory;
4430 void scheme_set_input_port_file(scheme *sc, FILE *fin) {
4431 sc->inport=port_from_file(sc,fin,port_input);
4434 void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
4435 sc->inport=port_from_string(sc,start,past_the_end,port_input);
4438 void scheme_set_output_port_file(scheme *sc, FILE *fout) {
4439 sc->outport=port_from_file(sc,fout,port_output);
4442 void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
4443 sc->outport=port_from_string(sc,start,past_the_end,port_output);
4446 void scheme_set_external_data(scheme *sc, void *p) {
4451 static void scheme_finalize_all(scheme *sc)
4456 for (i = sc->last_cell_seg; i >= 0; i--) {
4457 p = sc->cell_seg[i] + CELL_SEGSIZE;
4458 while (--p >= sc->cell_seg[i]) {
4462 finalize_cell(sc, p);
4466 fprintf(stderr, "scheme_finalize_all: %d finalized\n", j);
4470 void scheme_deinit(scheme *sc) {
4474 /* Check if the host program is still trying to protect some cells. */
4475 if (!list_empty(&sc->protect)) {
4476 #if USE_CUSTOM_FINALIZE
4477 /* Force all cells to be unprotected in order to break reference
4478 * cycles between protected cells and host program objects that need
4479 * to be dereferenced in the custom finalizer. If there are leaks in
4480 * the host program, we can't detect them here. */
4483 /* This probably indicates a memory leak in the host program. */
4484 fprintf(stderr, "warn: scheme protect list not empty!\n");
4491 sc->global_env=sc->NIL;
4492 dump_stack_free(sc);
4497 if(is_port(sc->inport)) {
4498 typeflag(sc->inport) = T_ATOM;
4501 sc->outport=sc->NIL;
4502 if(is_port(sc->save_inport)) {
4503 typeflag(sc->save_inport) = T_ATOM;
4505 sc->save_inport=sc->NIL;
4506 if(is_port(sc->loadport)) {
4507 typeflag(sc->loadport) = T_ATOM;
4509 sc->loadport=sc->NIL;
4511 gc(sc,sc->NIL,sc->NIL);
4517 for(i=0; i<=sc->last_cell_seg; i++) {
4518 sc->free(sc->alloc_seg[i]);
4523 void scheme_load_file(scheme *sc, FILE *fin) {
4524 dump_stack_reset(sc);
4525 sc->envir = sc->global_env;
4527 sc->load_stack[0].kind=port_input|port_file;
4528 sc->load_stack[0].rep.stdio.file=fin;
4529 sc->loadport=mk_port(sc,sc->load_stack);
4532 sc->interactive_repl=1;
4534 sc->inport=sc->loadport;
4535 Eval_Cycle(sc, OP_T0LVL);
4536 typeflag(sc->loadport)=T_ATOM;
4537 if(sc->retcode==0) {
4538 sc->retcode=sc->nesting!=0;
4541 #if USE_FILE_AND_LINE
4542 void scheme_load_named_file(scheme *sc, FILE *fin, const char *fname) {
4543 dump_stack_reset(sc);
4544 sc->envir = sc->global_env;
4546 sc->load_stack[0].kind=port_input|port_file;
4547 sc->load_stack[0].rep.stdio.file=fin;
4548 sc->load_stack[0].rep.stdio.name = strdup(fname);
4549 sc->load_stack[0].rep.stdio.line = 0;
4550 sc->loadport=mk_port(sc,sc->load_stack);
4553 sc->interactive_repl=1;
4555 sc->inport=sc->loadport;
4556 Eval_Cycle(sc, OP_T0LVL);
4557 typeflag(sc->loadport)=T_ATOM;
4558 if(sc->retcode==0) {
4559 sc->retcode=sc->nesting!=0;
4564 void scheme_load_string(scheme *sc, const char *cmd) {
4565 dump_stack_reset(sc);
4566 sc->envir = sc->global_env;
4568 sc->load_stack[0].kind=port_input|port_string;
4569 sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */
4570 sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd);
4571 sc->load_stack[0].rep.string.curr=(char*)cmd;
4572 sc->loadport=mk_port(sc,sc->load_stack);
4574 sc->interactive_repl=0;
4575 sc->inport=sc->loadport;
4576 Eval_Cycle(sc, OP_T0LVL);
4577 typeflag(sc->loadport)=T_ATOM;
4578 if(sc->retcode==0) {
4579 sc->retcode=sc->nesting!=0;
4583 void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
4586 x=find_slot_in_env(sc,envir,symbol,0);
4588 set_slot_in_env(sc, x, value);
4590 new_slot_spec_in_env(sc, envir, symbol, value);
4595 void scheme_apply0(scheme *sc, const char *procname) {
4596 pointer carx=mk_symbol(sc,procname);
4597 pointer cdrx=sc->NIL;
4599 dump_stack_reset(sc);
4600 sc->envir = sc->global_env;
4601 sc->code = cons(sc,carx,cdrx);
4602 sc->interactive_repl=0;
4604 Eval_Cycle(sc,OP_EVAL);
4607 //void scheme_call(scheme *sc, pointer func, pointer env, pointer args) {
4608 pointer scheme_call(scheme *sc, pointer func, pointer args) {
4611 /* We need to push a special operator on the stack to save all
4612 * stack frames below this one. */
4613 s_save(sc, OP_EXIT_REENTER, args, func);
4615 dump_stack_reset(sc);
4617 /* gjm: file_push() pre-increments the load stack index, so
4618 * reset it so that the first call to load will use index
4619 * 0. (This fixes a crash when the code calls the load
4624 dump_stack_reset(sc);
4626 sc->envir = sc->global_env;
4630 sc->interactive_repl =0;
4632 Eval_Cycle(sc, OP_APPLY);
4634 /* s_return puts the value in sc->value. I don't know how I got away with
4635 * using sc->code for so long... maybe it depends upon the context? I hope
4637 /* return sc->code; */
4644 #include "session.h"
4647 static void serialize(scheme *sc, pointer p, struct save *save, int flags)
4651 if (flags & SER_CAR) {
4652 save->write(save, "'()\n");
4654 } else if (p == sc->T) {
4655 save->write(save, "#t\n");
4656 } else if (p == sc->F) {
4657 save->write(save, "#f\n");
4658 } else if (is_number(p)) {
4659 if (is_integer(p)) {
4660 save->write(save, "%d\n", ivalue(p));
4661 } else if (is_real(p)) {
4662 save->write(save, "%f\n", rvalue(p));
4666 } else if (is_foreign(p)) {
4667 save->write(save, "'()\n");
4668 } else if (is_string(p)) {
4669 save->write(save, "\"%s\"\n", strvalue(p));
4670 } else if (is_vector(p)) {
4671 save->enter(save, "(vector\n");
4673 long vlength=ivalue(p);
4674 for (vindex=0;vindex<vlength;vindex++)
4676 serialize(sc, vector_elem(p,vindex), save, SER_CAR);
4678 save->exit(save, ")\n");
4686 if (flags & SER_CAR) {
4687 save->enter(save, "(list\n");
4689 serialize(sc, car(p), save, SER_CAR);
4690 serialize(sc, cdr(p), save, 0);
4691 if (flags & SER_CAR) {
4692 save->exit(save, ")\n");
4694 } else if (is_symbol(p)) {
4695 save->write(save, "'%s\n", symname(p));
4696 } else if (is_closure(p)) {
4697 fprintf(stderr, "can't serialize closures\n");
4703 void scheme_serialize(scheme *sc, pointer p, struct save *save)
4705 serialize(sc, p, save, SER_CAR);
4710 #define MAX_DUMP_LEN 256
4711 void celldump(scheme *sc, pointer pp)
4713 static const char *typestr[T_LAST_SYSTEM_TYPE+1] = {
4714 "---", "STR", "NUM", "SYM", "PRO",
4715 "PAI", "CLO", "CON", "FOR",
4716 "CHA", "POR", "VEC", "MAC",
4719 char strbuf[MAX_DUMP_LEN+1], *bptr;
4722 memset(strbuf, ' ', sizeof(strbuf));
4726 bptr += sprintf(bptr, "%p ", pp);
4729 if (0==typeflag(pp)) {
4730 bptr += sprintf(bptr, "F %p", cdr(pp));
4733 bptr += sprintf(bptr, "A ");
4736 for (i = 0; i < T_LAST_SYSTEM_TYPE && i != type(pp); i++)
4738 bptr += sprintf(bptr, typestr[i]);
4743 bptr += sprintf(bptr, "SYN|");
4744 if (is_immutable(pp))
4745 bptr += sprintf(bptr, "IMM|");
4747 bptr += sprintf(bptr, "ATM|");
4749 bptr += sprintf(bptr, "MRK|");
4755 bptr += sprintf(bptr, "%p %p",
4760 atom2str(sc, pp, 0, &str, &len);
4761 bptr += sprintf(bptr, "%s", str);
4765 #if USE_CUSTOM_FINALIZE
4766 if (is_custfin(pp)) {
4767 bptr += sprintf(bptr, " ~");
4773 if (!list_empty(&pp->plist)) {
4774 bptr += sprintf(bptr, " P%d", pp->pref);
4777 bptr += sprintf(bptr, "\n");
4778 strbuf[sizeof(strbuf)-1] = 0;
4780 /*putstr(sc, strbuf);*/
4781 fprintf(stderr,strbuf);
4786 static void memdump(scheme *sc)
4790 fprintf(stderr, ">>> MEMDUMP <<<\n");
4791 for (i=0; i <= sc->last_cell_seg; i++) {
4792 p = sc->cell_seg[i];
4793 for (j = 0; j < CELL_SEGSIZE; j++, p++) {
4800 static void memleakcheck(scheme *sc)
4802 int i, j, leaks = 0;
4804 fprintf(stderr, "Scheme leak check...\n");
4805 for (i=0; i <= sc->last_cell_seg; i++) {
4806 p = sc->cell_seg[i];
4807 for (j = 0; j < CELL_SEGSIZE; j++, p++) {
4814 fprintf(stderr, "%d leaked cells detected\n", leaks);
4816 #endif /* USE_CELLDUMP */
4819 void dump_protect(scheme *sc)
4822 list_for_each(&sc->protect, elem) {
4823 pointer pp = (pointer)elem;
4824 celldump(sc,pp); /* assumes USE_CELLDUMP */
4828 #endif /* USE_PROTECT */
4830 #if USE_CUSTOM_FINALIZE
4831 void scheme_set_custom_finalize(scheme *sc, void (*fin)(scheme *, pointer))
4833 sc->custom_finalize = fin;
4837 /* ========== Main ========== */
4843 extern MacTS_main(int argc, char **argv);
4845 int argc = ccommand(&argv);
4846 MacTS_main(argc,argv);
4849 int MacTS_main(int argc, char **argv) {
4851 int main(int argc, char **argv) {
4855 char *file_name=InitFile;
4862 if(argc==2 && strcmp(argv[1],"-?")==0) {
4863 printf("Usage: %s [-? | <file1> <file2> ... | -1 <file> <arg1> <arg2> ...]\n\tUse - as filename for stdin.\n",argv[0]);
4866 if(!scheme_init(&sc)) {
4867 fprintf(stderr,"Could not initialize!\n");
4870 scheme_set_input_port_file(&sc, stdin);
4871 scheme_set_output_port_file(&sc, stdout);
4873 scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext));
4876 if(access(file_name,0)!=0) {
4877 char *p=getenv("TINYSCHEMEINIT");
4883 if(strcmp(file_name,"-")==0) {
4885 } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
4886 pointer args=sc.NIL;
4887 isfile=file_name[1]=='1';
4889 if(strcmp(file_name,"-")==0) {
4892 fin=fopen(file_name,"r");
4894 for(;*argv;argv++) {
4895 pointer value=mk_string(&sc,*argv);
4896 args=cons(&sc,value,args);
4898 args=reverse_in_place(&sc,sc.NIL,args);
4899 scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
4902 fin=fopen(file_name,"r");
4904 if(isfile && fin==0) {
4905 fprintf(stderr,"Could not open file %s\n",file_name);
4908 scheme_load_file(&sc,fin);
4910 scheme_load_string(&sc,file_name);
4912 if(!isfile || fin!=stdin) {
4914 fprintf(stderr,"Errors encountered reading %s\n",file_name);
4922 } while(file_name!=0);
4924 scheme_load_file(&sc,stdin);
4934 int scm_len(scheme *sc, pointer list)
4938 while (scm_is_pair(sc, list)) {
4940 list = scm_cdr(sc, list);