ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.1
Committed: Wed Nov 25 05:02:56 2015 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1
2     /* T I N Y S C H E M E 1 . 4 1
3     * Dimitrios Souflis (dsouflis@acm.org)
4     * Based on MiniScheme (original credits follow)
5     * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
6     * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
7     * (MINISCM) This version has been modified by R.C. Secrist.
8     * (MINISCM)
9     * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
10     * (MINISCM)
11     * (MINISCM) This is a revised and modified version by Akira KIDA.
12     * (MINISCM) current version is 0.85k4 (15 May 1994)
13     *
14     */
15    
16     #define PAGE_SIZE 4096 /* does not work on sparc/alpha */
17     #include "malloc.c"
18    
19     #define SCHEME_SOURCE
20     #include "scheme-private.h"
21     #ifndef WIN32
22     # include <unistd.h>
23     #endif
24     #if USE_MATH
25     # include <math.h>
26     #endif
27    
28     #include <sys/types.h>
29     #include <sys/stat.h>
30     #include <fcntl.h>
31    
32     #include <limits.h>
33     #include <inttypes.h>
34     #include <float.h>
35     //#include <ctype.h>
36    
37     enum {
38     TOK_EOF,
39     TOK_LPAREN,
40     TOK_RPAREN,
41     TOK_DOT,
42     TOK_ATOM,
43     TOK_QUOTE,
44     TOK_DQUOTE,
45     TOK_BQUOTE,
46     TOK_COMMA,
47     TOK_ATMARK,
48     TOK_SHARP,
49     TOK_SHARP_CONST,
50     TOK_VEC
51     };
52    
53     #define BACKQUOTE '`'
54     #define DELIMITERS "()\";\f\t\v\n\r "
55    
56     #define NIL (&SCHEME_V->xNIL) //TODO: make this 0?
57     #define S_T (&SCHEME_V->xT)
58     #define S_F (&SCHEME_V->xF)
59     #define S_SINK (&SCHEME_V->xsink)
60     #define S_EOF (&SCHEME_V->xEOF_OBJ)
61    
62     /*
63     * Basic memory allocation units
64     */
65    
66     #define banner "TinyScheme 1.41-s"
67    
68     #include <string.h>
69     #include <stdlib.h>
70    
71     #if !USE_MULTIPLICITY
72     static scheme sc;
73     #endif
74    
75     static void
76     xbase (char *s, long n, int base)
77     {
78     if (n < 0)
79     {
80     *s++ = '-';
81     n = -n;
82     }
83    
84     char *p = s;
85    
86     do {
87     *p++ = '0' + n % base;
88     n /= base;
89     } while (n);
90    
91     *p-- = 0;
92    
93     while (p > s)
94     {
95     char x = *s; *s = *p; *p = x;
96     --p; ++s;
97     }
98     }
99    
100     static void
101     xnum (char *s, long n)
102     {
103     xbase (s, n, 10);
104     }
105    
106     static void
107     xwrstr (const char *s)
108     {
109     write (1, s, strlen (s));
110     }
111    
112     static void
113     xwrnum (long n)
114     {
115     char buf[64];
116    
117     xnum (buf, n);
118     xwrstr (buf);
119     }
120    
121     static char
122     xtoupper (char c)
123     {
124     if (c >= 'a' && c <= 'z')
125     c -= 'a' - 'A';
126    
127     return c;
128     }
129    
130     static char
131     xtolower (char c)
132     {
133     if (c >= 'A' && c <= 'Z')
134     c += 'a' - 'A';
135    
136     return c;
137     }
138    
139     #if USE_STRLWR
140     static const char *
141     strlwr (char *s)
142     {
143     const char *p = s;
144    
145     while (*s)
146     {
147     *s = tolower (*s);
148     s++;
149     }
150    
151     return p;
152     }
153     #endif
154    
155     #define stricmp(a,b) strcmp (a, b)
156     #define strlwr(s) (s)
157     #define toupper(c) xtoupper(c)
158     #define tolower(c) xtolower(c)
159    
160     #ifndef prompt
161     # define prompt "ts> "
162     #endif
163    
164     #ifndef InitFile
165     # define InitFile "init.scm"
166     #endif
167    
168     #ifndef FIRST_CELLSEGS
169     # define FIRST_CELLSEGS 3
170     #endif
171    
172     enum scheme_types
173     {
174     T_NULL,
175     T_STRING,
176     T_NUMBER,
177     T_SYMBOL,
178     T_PROC,
179     T_PAIR,
180     T_CLOSURE,
181     T_CONTINUATION,
182     T_FOREIGN,
183     T_CHARACTER,
184     T_PORT,
185     T_VECTOR,
186     T_MACRO,
187     T_PROMISE,
188     T_ENVIRONMENT,
189     T_NUM_SYSTEM_TYPES
190     };
191    
192     #define T_MASKTYPE 31 /* 0000000000011111 */
193     #define T_SYNTAX 4096 /* 0001000000000000 */
194     #define T_IMMUTABLE 8192 /* 0010000000000000 */
195     #define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
196     #define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
197     #define MARK 32768 /* 1000000000000000 */
198     #define UNMARK 32767 /* 0111111111111111 */
199    
200    
201     static num num_add (num a, num b);
202     static num num_mul (num a, num b);
203     static num num_div (num a, num b);
204     static num num_intdiv (num a, num b);
205     static num num_sub (num a, num b);
206     static num num_rem (num a, num b);
207     static num num_mod (num a, num b);
208     static int num_eq (num a, num b);
209     static int num_gt (num a, num b);
210     static int num_ge (num a, num b);
211     static int num_lt (num a, num b);
212     static int num_le (num a, num b);
213    
214     #if USE_MATH
215     static double round_per_R5RS (double x);
216     #endif
217     static int is_zero_rvalue (RVALUE x);
218    
219     static INLINE int
220     num_is_integer (pointer p)
221     {
222     return num_is_fixnum (p->object.number);
223     }
224    
225     static num num_zero;
226     static num num_one;
227    
228     /* macros for cell operations */
229     #define typeflag(p) ((p)->flag + 0)
230     #define set_typeflag(p,v) ((p)->flag = (v))
231     #define type(p) (typeflag (p) & T_MASKTYPE)
232    
233     INTERFACE INLINE int
234     is_string (pointer p)
235     {
236     return type (p) == T_STRING;
237     }
238    
239     #define strvalue(p) ((p)->object.string.svalue)
240     #define strlength(p) ((p)->object.string.length)
241    
242     INTERFACE int is_list (SCHEME_P_ pointer p);
243     INTERFACE INLINE int
244     is_vector (pointer p)
245     {
246     return type (p) == T_VECTOR;
247     }
248    
249     INTERFACE void fill_vector (pointer vec, pointer obj);
250     INTERFACE pointer vector_elem (pointer vec, int ielem);
251     INTERFACE void set_vector_elem (pointer vec, int ielem, pointer a);
252    
253     INTERFACE INLINE int
254     is_number (pointer p)
255     {
256     return type (p) == T_NUMBER;
257     }
258    
259     INTERFACE INLINE int
260     is_integer (pointer p)
261     {
262     if (!is_number (p))
263     return 0;
264    
265     if (num_is_integer (p) || ivalue (p) == rvalue (p))
266     return 1;
267    
268     return 0;
269     }
270    
271     INTERFACE INLINE int
272     is_real (pointer p)
273     {
274     return is_number (p) && !num_is_fixnum (p->object.number);
275     }
276    
277     INTERFACE INLINE int
278     is_character (pointer p)
279     {
280     return type (p) == T_CHARACTER;
281     }
282    
283     INTERFACE INLINE char *
284     string_value (pointer p)
285     {
286     return strvalue (p);
287     }
288    
289     INLINE num
290     nvalue (pointer p)
291     {
292     return (p)->object.number;
293     }
294    
295     INTERFACE long
296     ivalue (pointer p)
297     {
298     return num_is_integer (p) ? num_ivalue ((p)->object.number) : (long) num_rvalue ((p)->object.number);
299     }
300    
301     INTERFACE RVALUE
302     rvalue (pointer p)
303     {
304     return num_is_integer (p) ? (RVALUE) num_ivalue ((p)->object.number) : num_rvalue ((p)->object.number);
305     }
306    
307     #define ivalue_unchecked(p) ((p)->object.number.value.ivalue)
308     #if USE_FLOAT
309     # define rvalue_unchecked(p) ((p)->object.number.value.rvalue)
310     # define set_num_integer(p) (p)->object.number.is_fixnum=1;
311     # define set_num_real(p) (p)->object.number.is_fixnum=0;
312     #else
313     # define rvalue_unchecked(p) ((p)->object.number.value.ivalue)
314     # define set_num_integer(p) 0
315     # define set_num_real(p) 0
316     #endif
317     INTERFACE long
318     charvalue (pointer p)
319     {
320     return ivalue_unchecked (p);
321     }
322    
323     INTERFACE INLINE int
324     is_port (pointer p)
325     {
326     return type (p) == T_PORT;
327     }
328    
329     INTERFACE INLINE int
330     is_inport (pointer p)
331     {
332     return is_port (p) && p->object.port->kind & port_input;
333     }
334    
335     INTERFACE INLINE int
336     is_outport (pointer p)
337     {
338     return is_port (p) && p->object.port->kind & port_output;
339     }
340    
341     INTERFACE INLINE int
342     is_pair (pointer p)
343     {
344     return type (p) == T_PAIR;
345     }
346    
347     #define car(p) ((p)->object.cons.car + 0)
348     #define cdr(p) ((p)->object.cons.cdr) /* find_consecutive_cells uses &cdr */
349    
350     #define caar(p) car (car (p))
351     #define cadr(p) car (cdr (p))
352     #define cdar(p) cdr (car (p))
353     #define cddr(p) cdr (cdr (p))
354    
355     #define cadar(p) car (cdr (car (p)))
356     #define caddr(p) car (cdr (cdr (p)))
357     #define cdaar(p) cdr (car (car (p)))
358    
359     INTERFACE void
360     set_car (pointer p, pointer q)
361     {
362     p->object.cons.car = q;
363     }
364    
365     INTERFACE void
366     set_cdr (pointer p, pointer q)
367     {
368     p->object.cons.cdr = q;
369     }
370    
371     INTERFACE pointer
372     pair_car (pointer p)
373     {
374     return car (p);
375     }
376    
377     INTERFACE pointer
378     pair_cdr (pointer p)
379     {
380     return cdr (p);
381     }
382    
383     INTERFACE INLINE int
384     is_symbol (pointer p)
385     {
386     return type (p) == T_SYMBOL;
387     }
388    
389     INTERFACE INLINE char *
390     symname (pointer p)
391     {
392     return strvalue (car (p));
393     }
394    
395     #if USE_PLIST
396     SCHEME_EXPORT INLINE int
397     hasprop (pointer p)
398     {
399     return typeflag (p) & T_SYMBOL;
400     }
401    
402     # define symprop(p) cdr(p)
403     #endif
404    
405     INTERFACE INLINE int
406     is_syntax (pointer p)
407     {
408     return typeflag (p) & T_SYNTAX;
409     }
410    
411     INTERFACE INLINE int
412     is_proc (pointer p)
413     {
414     return type (p) == T_PROC;
415     }
416    
417     INTERFACE INLINE int
418     is_foreign (pointer p)
419     {
420     return type (p) == T_FOREIGN;
421     }
422    
423     INTERFACE INLINE char *
424     syntaxname (pointer p)
425     {
426     return strvalue (car (p));
427     }
428    
429     #define procnum(p) ivalue(p)
430     static const char *procname (pointer x);
431    
432     INTERFACE INLINE int
433     is_closure (pointer p)
434     {
435     return type (p) == T_CLOSURE;
436     }
437    
438     INTERFACE INLINE int
439     is_macro (pointer p)
440     {
441     return type (p) == T_MACRO;
442     }
443    
444     INTERFACE INLINE pointer
445     closure_code (pointer p)
446     {
447     return car (p);
448     }
449    
450     INTERFACE INLINE pointer
451     closure_env (pointer p)
452     {
453     return cdr (p);
454     }
455    
456     INTERFACE INLINE int
457     is_continuation (pointer p)
458     {
459     return type (p) == T_CONTINUATION;
460     }
461    
462     #define cont_dump(p) cdr (p)
463     #define set_cont_dump(p,v) set_cdr ((p), (v))
464    
465     /* To do: promise should be forced ONCE only */
466     INTERFACE INLINE int
467     is_promise (pointer p)
468     {
469     return type (p) == T_PROMISE;
470     }
471    
472     INTERFACE INLINE int
473     is_environment (pointer p)
474     {
475     return type (p) == T_ENVIRONMENT;
476     }
477    
478     #define setenvironment(p) set_typeflag ((p), T_ENVIRONMENT)
479    
480     #define is_atom(p) (typeflag (p) & T_ATOM)
481     #define setatom(p) set_typeflag ((p), typeflag (p) | T_ATOM)
482     #define clratom(p) set_typeflag ((p), typeflag (p) & CLRATOM)
483    
484     #define is_mark(p) (typeflag (p) & MARK)
485     #define setmark(p) set_typeflag ((p), typeflag (p) | MARK)
486     #define clrmark(p) set_typeflag ((p), typeflag (p) & UNMARK)
487    
488     INTERFACE INLINE int
489     is_immutable (pointer p)
490     {
491     return typeflag (p) & T_IMMUTABLE;
492     }
493    
494     INTERFACE INLINE void
495     setimmutable (pointer p)
496     {
497     set_typeflag (p, T_IMMUTABLE);
498     }
499    
500     #if USE_CHAR_CLASSIFIERS
501     static INLINE int
502     Cisalpha (int c)
503     {
504     return isascii (c) && isalpha (c);
505     }
506    
507     static INLINE int
508     Cisdigit (int c)
509     {
510     return isascii (c) && isdigit (c);
511     }
512    
513     static INLINE int
514     Cisspace (int c)
515     {
516     return isascii (c) && isspace (c);
517     }
518    
519     static INLINE int
520     Cisupper (int c)
521     {
522     return isascii (c) && isupper (c);
523     }
524    
525     static INLINE int
526     Cislower (int c)
527     {
528     return isascii (c) && islower (c);
529     }
530     #endif
531    
532     #if USE_ASCII_NAMES
533     static const char *charnames[32] = {
534     "nul",
535     "soh",
536     "stx",
537     "etx",
538     "eot",
539     "enq",
540     "ack",
541     "bel",
542     "bs",
543     "ht",
544     "lf",
545     "vt",
546     "ff",
547     "cr",
548     "so",
549     "si",
550     "dle",
551     "dc1",
552     "dc2",
553     "dc3",
554     "dc4",
555     "nak",
556     "syn",
557     "etb",
558     "can",
559     "em",
560     "sub",
561     "esc",
562     "fs",
563     "gs",
564     "rs",
565     "us"
566     };
567    
568     static int
569     is_ascii_name (const char *name, int *pc)
570     {
571     int i;
572    
573     for (i = 0; i < 32; i++)
574     {
575     if (stricmp (name, charnames[i]) == 0)
576     {
577     *pc = i;
578     return 1;
579     }
580     }
581    
582     if (stricmp (name, "del") == 0)
583     {
584     *pc = 127;
585     return 1;
586     }
587    
588     return 0;
589     }
590    
591     #endif
592    
593     static int file_push (SCHEME_P_ const char *fname);
594     static void file_pop (SCHEME_P);
595     static int file_interactive (SCHEME_P);
596     static INLINE int is_one_of (char *s, int c);
597     static int alloc_cellseg (SCHEME_P_ int n);
598     static long binary_decode (const char *s);
599     static INLINE pointer get_cell (SCHEME_P_ pointer a, pointer b);
600     static pointer xget_cell (SCHEME_P_ pointer a, pointer b);
601     static pointer reserve_cells (SCHEME_P_ int n);
602     static pointer get_consecutive_cells (SCHEME_P_ int n);
603     static pointer find_consecutive_cells (SCHEME_P_ int n);
604     static void finalize_cell (SCHEME_P_ pointer a);
605     static int count_consecutive_cells (pointer x, int needed);
606     static pointer find_slot_in_env (SCHEME_P_ pointer env, pointer sym, int all);
607     static pointer mk_number (SCHEME_P_ num n);
608     static char *store_string (SCHEME_P_ int len, const char *str, char fill);
609     static pointer mk_vector (SCHEME_P_ int len);
610     static pointer mk_atom (SCHEME_P_ char *q);
611     static pointer mk_sharp_const (SCHEME_P_ char *name);
612    
613     #if USE_PORTS
614     static pointer mk_port (SCHEME_P_ port *p);
615     static pointer port_from_filename (SCHEME_P_ const char *fn, int prop);
616     static pointer port_from_file (SCHEME_P_ int, int prop);
617     static pointer port_from_string (SCHEME_P_ char *start, char *past_the_end, int prop);
618     static port *port_rep_from_filename (SCHEME_P_ const char *fn, int prop);
619     static port *port_rep_from_file (SCHEME_P_ int, int prop);
620     static port *port_rep_from_string (SCHEME_P_ char *start, char *past_the_end, int prop);
621     static void port_close (SCHEME_P_ pointer p, int flag);
622     #endif
623     static void mark (pointer a);
624     static void gc (SCHEME_P_ pointer a, pointer b);
625     static int basic_inchar (port *pt);
626     static int inchar (SCHEME_P);
627     static void backchar (SCHEME_P_ int c);
628     static char *readstr_upto (SCHEME_P_ char *delim);
629     static pointer readstrexp (SCHEME_P);
630     static INLINE int skipspace (SCHEME_P);
631     static int token (SCHEME_P);
632     static void printslashstring (SCHEME_P_ char *s, int len);
633     static void atom2str (SCHEME_P_ pointer l, int f, char **pp, int *plen);
634     static void printatom (SCHEME_P_ pointer l, int f);
635     static pointer mk_proc (SCHEME_P_ enum scheme_opcodes op);
636     static pointer mk_closure (SCHEME_P_ pointer c, pointer e);
637     static pointer mk_continuation (SCHEME_P_ pointer d);
638     static pointer reverse (SCHEME_P_ pointer a);
639     static pointer reverse_in_place (SCHEME_P_ pointer term, pointer list);
640     static pointer revappend (SCHEME_P_ pointer a, pointer b);
641     static pointer ss_get_cont (SCHEME_P);
642     static void ss_set_cont (SCHEME_P_ pointer cont);
643     static void dump_stack_mark (SCHEME_P);
644     static pointer opexe_0 (SCHEME_P_ enum scheme_opcodes op);
645     static pointer opexe_2 (SCHEME_P_ enum scheme_opcodes op);
646     static pointer opexe_3 (SCHEME_P_ enum scheme_opcodes op);
647     static pointer opexe_4 (SCHEME_P_ enum scheme_opcodes op);
648     static pointer opexe_5 (SCHEME_P_ enum scheme_opcodes op);
649     static pointer opexe_6 (SCHEME_P_ enum scheme_opcodes op);
650     static void Eval_Cycle (SCHEME_P_ enum scheme_opcodes op);
651     static void assign_syntax (SCHEME_P_ char *name);
652     static int syntaxnum (pointer p);
653     static void assign_proc (SCHEME_P_ enum scheme_opcodes, char *name);
654    
655     static num
656     num_add (num a, num b)
657     {
658     num ret;
659    
660     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b));
661    
662     if (num_is_fixnum (ret))
663     num_set_ivalue (ret, a.value.ivalue + b.value.ivalue);
664     else
665     num_set_rvalue (ret, num_rvalue (a) + num_rvalue (b));
666    
667     return ret;
668     }
669    
670     static num
671     num_mul (num a, num b)
672     {
673     num ret;
674    
675     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b));
676    
677     if (num_is_fixnum (ret))
678     num_set_ivalue (ret, a.value.ivalue * b.value.ivalue);
679     else
680     num_set_rvalue (ret, num_rvalue (a) * num_rvalue (b));
681    
682     return ret;
683     }
684    
685     static num
686     num_div (num a, num b)
687     {
688     num ret;
689    
690     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b) && a.value.ivalue % b.value.ivalue == 0);
691    
692     if (num_is_fixnum (ret))
693     num_set_ivalue (ret, a.value.ivalue / b.value.ivalue);
694     else
695     num_set_rvalue (ret, num_rvalue (a) / num_rvalue (b));
696    
697     return ret;
698     }
699    
700     static num
701     num_intdiv (num a, num b)
702     {
703     num ret;
704    
705     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b));
706    
707     if (num_is_fixnum (ret))
708     num_set_ivalue (ret, a.value.ivalue / b.value.ivalue);
709     else
710     num_set_rvalue (ret, num_rvalue (a) / num_rvalue (b));
711    
712     return ret;
713     }
714    
715     static num
716     num_sub (num a, num b)
717     {
718     num ret;
719    
720     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b));
721    
722     if (num_is_fixnum (ret))
723     num_set_ivalue (ret, a.value.ivalue - b.value.ivalue);
724     else
725     num_set_rvalue (ret, num_rvalue (a) - num_rvalue (b));
726    
727     return ret;
728     }
729    
730     static num
731     num_rem (num a, num b)
732     {
733     num ret;
734     long e1, e2, res;
735    
736     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b));
737     e1 = num_ivalue (a);
738     e2 = num_ivalue (b);
739     res = e1 % e2;
740    
741     /* remainder should have same sign as second operand */
742     if (res > 0)
743     {
744     if (e1 < 0)
745     res -= labs (e2);
746     }
747     else if (res < 0)
748     {
749     if (e1 > 0)
750     res += labs (e2);
751     }
752    
753     num_set_ivalue (ret, res);
754     return ret;
755     }
756    
757     static num
758     num_mod (num a, num b)
759     {
760     num ret;
761     long e1, e2, res;
762    
763     num_set_fixnum (ret, num_is_fixnum (a) && num_is_fixnum (b));
764     e1 = num_ivalue (a);
765     e2 = num_ivalue (b);
766     res = e1 % e2;
767    
768     /* modulo should have same sign as second operand */
769     if (res * e2 < 0)
770     res += e2;
771    
772     num_set_ivalue (ret, res);
773     return ret;
774     }
775    
776     static int
777     num_eq (num a, num b)
778     {
779     int ret;
780     int is_fixnum = num_is_fixnum (a) && num_is_fixnum (b);
781    
782     if (is_fixnum)
783     ret = a.value.ivalue == b.value.ivalue;
784     else
785     ret = num_rvalue (a) == num_rvalue (b);
786    
787     return ret;
788     }
789    
790    
791     static int
792     num_gt (num a, num b)
793     {
794     int ret;
795     int is_fixnum = num_is_fixnum (a) && num_is_fixnum (b);
796    
797     if (is_fixnum)
798     ret = a.value.ivalue > b.value.ivalue;
799     else
800     ret = num_rvalue (a) > num_rvalue (b);
801    
802     return ret;
803     }
804    
805     static int
806     num_ge (num a, num b)
807     {
808     return !num_lt (a, b);
809     }
810    
811     static int
812     num_lt (num a, num b)
813     {
814     int ret;
815     int is_fixnum = num_is_fixnum (a) && num_is_fixnum (b);
816    
817     if (is_fixnum)
818     ret = a.value.ivalue < b.value.ivalue;
819     else
820     ret = num_rvalue (a) < num_rvalue (b);
821    
822     return ret;
823     }
824    
825     static int
826     num_le (num a, num b)
827     {
828     return !num_gt (a, b);
829     }
830    
831     #if USE_MATH
832    
833     /* Round to nearest. Round to even if midway */
834     static double
835     round_per_R5RS (double x)
836     {
837     double fl = floor (x);
838     double ce = ceil (x);
839     double dfl = x - fl;
840     double dce = ce - x;
841    
842     if (dfl > dce)
843     return ce;
844     else if (dfl < dce)
845     return fl;
846     else
847     {
848     if (fmod (fl, 2.0) == 0.0) /* I imagine this holds */
849     return fl;
850     else
851     return ce;
852     }
853     }
854     #endif
855    
856     static int
857     is_zero_rvalue (RVALUE x)
858     {
859     #if USE_FLOAT
860     return x < DBL_MIN && x > -DBL_MIN; /* why the hate of denormals? this should be == 0. */
861     #else
862     return x == 0;
863     #endif
864     }
865    
866     static long
867     binary_decode (const char *s)
868     {
869     long x = 0;
870    
871     while (*s != 0 && (*s == '1' || *s == '0'))
872     {
873     x <<= 1;
874     x += *s - '0';
875     s++;
876     }
877    
878     return x;
879     }
880    
881     /* allocate new cell segment */
882     static int
883     alloc_cellseg (SCHEME_P_ int n)
884     {
885     pointer newp;
886     pointer last;
887     pointer p;
888     char *cp;
889     long i;
890     int k;
891    
892     static int segsize = CELL_SEGSIZE >> 1;
893     segsize <<= 1;
894    
895     for (k = 0; k < n; k++)
896     {
897     if (SCHEME_V->last_cell_seg >= CELL_NSEGMENT - 1)
898     return k;
899    
900     cp = malloc (segsize * sizeof (struct cell));
901    
902     if (!cp && USE_ERROR_CHECKING)
903     return k;
904    
905     i = ++SCHEME_V->last_cell_seg;
906     SCHEME_V->alloc_seg[i] = cp;
907    
908     /* insert new segment in address order */
909     newp = (pointer)cp;
910     SCHEME_V->cell_seg[i] = newp;
911     SCHEME_V->cell_segsize[i] = segsize;
912    
913     //TODO: insert, not swap
914     while (i > 0 && SCHEME_V->cell_seg[i - 1] > SCHEME_V->cell_seg[i])
915     {
916     p = SCHEME_V->cell_seg[i];
917     SCHEME_V->cell_seg[i] = SCHEME_V->cell_seg[i - 1];
918     SCHEME_V->cell_seg[i - 1] = p;
919    
920     k = SCHEME_V->cell_segsize[i];
921     SCHEME_V->cell_segsize[i] = SCHEME_V->cell_segsize[i - 1];
922     SCHEME_V->cell_segsize[i - 1] = k;
923    
924     --i;
925     }
926    
927     SCHEME_V->fcells += segsize;
928     last = newp + segsize - 1;
929    
930     for (p = newp; p <= last; p++)
931     {
932     set_typeflag (p, 0);
933     set_cdr (p, p + 1);
934     set_car (p, NIL);
935     }
936    
937     /* insert new cells in address order on free list */
938     if (SCHEME_V->free_cell == NIL || p < SCHEME_V->free_cell)
939     {
940     set_cdr (last, SCHEME_V->free_cell);
941     SCHEME_V->free_cell = newp;
942     }
943     else
944     {
945     p = SCHEME_V->free_cell;
946    
947     while (cdr (p) != NIL && newp > cdr (p))
948     p = cdr (p);
949    
950     set_cdr (last, cdr (p));
951     set_cdr (p, newp);
952     }
953     }
954    
955     return n;
956     }
957    
958     /* get new cell. parameter a, b is marked by gc. */
959     static INLINE pointer
960     get_cell_x (SCHEME_P_ pointer a, pointer b)
961     {
962     if (SCHEME_V->free_cell == NIL)
963     {
964     if (SCHEME_V->no_memory && USE_ERROR_CHECKING)
965     return S_SINK;
966    
967     if (SCHEME_V->free_cell == NIL)
968     {
969     const int min_to_be_recovered = SCHEME_V->last_cell_seg < 128 ? 128 * 8 : SCHEME_V->last_cell_seg * 8;
970    
971     gc (SCHEME_A_ a, b);
972    
973     if (SCHEME_V->fcells < min_to_be_recovered || SCHEME_V->free_cell == NIL)
974     {
975     /* if only a few recovered, get more to avoid fruitless gc's */
976     if (!alloc_cellseg (SCHEME_A_ 1) && SCHEME_V->free_cell == NIL)
977     {
978     #if USE_ERROR_CHECKING
979     SCHEME_V->no_memory = 1;
980     return S_SINK;
981     #endif
982     }
983     }
984     }
985     }
986    
987     {
988     pointer x = SCHEME_V->free_cell;
989    
990     SCHEME_V->free_cell = cdr (x);
991     --SCHEME_V->fcells;
992     return x;
993     }
994     }
995    
996     /* make sure that there is a given number of cells free */
997     static pointer
998     reserve_cells (SCHEME_P_ int n)
999     {
1000     if (SCHEME_V->no_memory && USE_ERROR_CHECKING)
1001     return NIL;
1002    
1003     /* Are there enough cells available? */
1004     if (SCHEME_V->fcells < n)
1005     {
1006     /* If not, try gc'ing some */
1007     gc (SCHEME_A_ NIL, NIL);
1008    
1009     if (SCHEME_V->fcells < n)
1010     {
1011     /* If there still aren't, try getting more heap */
1012     if (!alloc_cellseg (SCHEME_A_ 1) && USE_ERROR_CHECKING)
1013     {
1014     SCHEME_V->no_memory = 1;
1015     return NIL;
1016     }
1017     }
1018    
1019     if (SCHEME_V->fcells < n && USE_ERROR_CHECKING)
1020     {
1021     /* If all fail, report failure */
1022     SCHEME_V->no_memory = 1;
1023     return NIL;
1024     }
1025     }
1026    
1027     return S_T;
1028     }
1029    
1030     static pointer
1031     get_consecutive_cells (SCHEME_P_ int n)
1032     {
1033     pointer x;
1034    
1035     if (SCHEME_V->no_memory && USE_ERROR_CHECKING)
1036     return S_SINK;
1037    
1038     /* Are there any cells available? */
1039     x = find_consecutive_cells (SCHEME_A_ n);
1040    
1041     if (x != NIL)
1042     return x;
1043    
1044     /* If not, try gc'ing some */
1045     gc (SCHEME_A_ NIL, NIL);
1046    
1047     for (;;)
1048     {
1049     x = find_consecutive_cells (SCHEME_A_ n);
1050    
1051     if (x != NIL)
1052     return x;
1053    
1054     /* If there still aren't, try getting more heap */
1055     if (!alloc_cellseg (SCHEME_A_ 1))
1056     {
1057     #if USE_ERROR_CHECKING
1058     SCHEME_V->no_memory = 1;
1059     return S_SINK;
1060     #endif
1061     }
1062     }
1063     }
1064    
1065     static int
1066     count_consecutive_cells (pointer x, int needed)
1067     {
1068     int n = 1;
1069    
1070     while (cdr (x) == x + 1)
1071     {
1072     x = cdr (x);
1073     n++;
1074    
1075     if (n > needed)
1076     return n;
1077     }
1078    
1079     return n;
1080     }
1081    
1082     static pointer
1083     find_consecutive_cells (SCHEME_P_ int n)
1084     {
1085     pointer *pp;
1086     int cnt;
1087    
1088     pp = &SCHEME_V->free_cell;
1089    
1090     while (*pp != NIL)
1091     {
1092     cnt = count_consecutive_cells (*pp, n);
1093    
1094     if (cnt >= n)
1095     {
1096     pointer x = *pp;
1097    
1098     *pp = cdr (*pp + n - 1);
1099     SCHEME_V->fcells -= n;
1100     return x;
1101     }
1102    
1103     pp = &cdr (*pp + cnt - 1);
1104     }
1105    
1106     return NIL;
1107     }
1108    
1109     /* To retain recent allocs before interpreter knows about them -
1110     Tehom */
1111    
1112     static void
1113     push_recent_alloc (SCHEME_P_ pointer recent, pointer extra)
1114     {
1115     pointer holder = get_cell_x (SCHEME_A_ recent, extra);
1116    
1117     set_typeflag (holder, T_PAIR | T_IMMUTABLE);
1118     set_car (holder, recent);
1119     set_cdr (holder, car (S_SINK));
1120     set_car (S_SINK, holder);
1121     }
1122    
1123     static pointer
1124     get_cell (SCHEME_P_ pointer a, pointer b)
1125     {
1126     pointer cell = get_cell_x (SCHEME_A_ a, b);
1127    
1128     /* For right now, include "a" and "b" in "cell" so that gc doesn't
1129     think they are garbage. */
1130     /* Tentatively record it as a pair so gc understands it. */
1131     set_typeflag (cell, T_PAIR);
1132     set_car (cell, a);
1133     set_cdr (cell, b);
1134     push_recent_alloc (SCHEME_A_ cell, NIL);
1135    
1136     return cell;
1137     }
1138    
1139     static pointer
1140     get_vector_object (SCHEME_P_ int len, pointer init)
1141     {
1142     pointer cells = get_consecutive_cells (SCHEME_A_ len / 2 + len % 2 + 1);
1143    
1144     #if USE_ERROR_CHECKING
1145     if (SCHEME_V->no_memory)
1146     return S_SINK;
1147     #endif
1148    
1149     /* Record it as a vector so that gc understands it. */
1150     set_typeflag (cells, T_VECTOR | T_ATOM);
1151     ivalue_unchecked (cells) = len;
1152     set_num_integer (cells);
1153     fill_vector (cells, init);
1154     push_recent_alloc (SCHEME_A_ cells, NIL);
1155    
1156     return cells;
1157     }
1158    
1159     static INLINE void
1160     ok_to_freely_gc (SCHEME_P)
1161     {
1162     set_car (S_SINK, NIL);
1163     }
1164    
1165     #if defined TSGRIND
1166     static void
1167     check_cell_alloced (pointer p, int expect_alloced)
1168     {
1169     /* Can't use putstr(SCHEME_A_ str) because callers have no access to
1170     sc. */
1171     if (typeflag (p) & !expect_alloced)
1172     xwrstr ("Cell is already allocated!\n");
1173    
1174     if (!(typeflag (p)) & expect_alloced)
1175     xwrstr ("Cell is not allocated!\n");
1176     }
1177    
1178     static void
1179     check_range_alloced (pointer p, int n, int expect_alloced)
1180     {
1181     int i;
1182    
1183     for (i = 0; i < n; i++)
1184     check_cell_alloced (p + i, expect_alloced);
1185     }
1186     #endif
1187    
1188     /* Medium level cell allocation */
1189    
1190     /* get new cons cell */
1191     pointer
1192     xcons (SCHEME_P_ pointer a, pointer b, int immutable)
1193     {
1194     pointer x = get_cell (SCHEME_A_ a, b);
1195    
1196     set_typeflag (x, T_PAIR);
1197    
1198     if (immutable)
1199     setimmutable (x);
1200    
1201     set_car (x, a);
1202     set_cdr (x, b);
1203     return x;
1204     }
1205    
1206     /* ========== oblist implementation ========== */
1207    
1208     #ifndef USE_OBJECT_LIST
1209    
1210     static int hash_fn (const char *key, int table_size);
1211    
1212     static pointer
1213     oblist_initial_value (SCHEME_P)
1214     {
1215     return mk_vector (SCHEME_A_ 461); /* probably should be bigger */
1216     }
1217    
1218     /* returns the new symbol */
1219     static pointer
1220     oblist_add_by_name (SCHEME_P_ const char *name)
1221     {
1222     pointer x;
1223     int location;
1224    
1225     x = immutable_cons (mk_string (SCHEME_A_ name), NIL);
1226     set_typeflag (x, T_SYMBOL);
1227     setimmutable (car (x));
1228    
1229     location = hash_fn (name, ivalue_unchecked (SCHEME_V->oblist));
1230     set_vector_elem (SCHEME_V->oblist, location, immutable_cons (x, vector_elem (SCHEME_V->oblist, location)));
1231     return x;
1232     }
1233    
1234     static INLINE pointer
1235     oblist_find_by_name (SCHEME_P_ const char *name)
1236     {
1237     int location;
1238     pointer x;
1239     char *s;
1240    
1241     location = hash_fn (name, ivalue_unchecked (SCHEME_V->oblist));
1242    
1243     for (x = vector_elem (SCHEME_V->oblist, location); x != NIL; x = cdr (x))
1244     {
1245     s = symname (car (x));
1246    
1247     /* case-insensitive, per R5RS section 2 */
1248     if (stricmp (name, s) == 0)
1249     return car (x);
1250     }
1251    
1252     return NIL;
1253     }
1254    
1255     static pointer
1256     oblist_all_symbols (SCHEME_P)
1257     {
1258     int i;
1259     pointer x;
1260     pointer ob_list = NIL;
1261    
1262     for (i = 0; i < ivalue_unchecked (SCHEME_V->oblist); i++)
1263     for (x = vector_elem (SCHEME_V->oblist, i); x != NIL; x = cdr (x))
1264     ob_list = cons (x, ob_list);
1265    
1266     return ob_list;
1267     }
1268    
1269     #else
1270    
1271     static pointer
1272     oblist_initial_value (SCHEME_P)
1273     {
1274     return NIL;
1275     }
1276    
1277     static INLINE pointer
1278     oblist_find_by_name (SCHEME_P_ const char *name)
1279     {
1280     pointer x;
1281     char *s;
1282    
1283     for (x = SCHEME_V->oblist; x != NIL; x = cdr (x))
1284     {
1285     s = symname (car (x));
1286    
1287     /* case-insensitive, per R5RS section 2 */
1288     if (stricmp (name, s) == 0)
1289     return car (x);
1290     }
1291    
1292     return NIL;
1293     }
1294    
1295     /* returns the new symbol */
1296     static pointer
1297     oblist_add_by_name (SCHEME_P_ const char *name)
1298     {
1299     pointer x;
1300    
1301     x = immutable_cons (mk_string (SCHEME_A_ name), NIL);
1302     set_typeflag (x, T_SYMBOL);
1303     setimmutable (car (x));
1304     SCHEME_V->oblist = immutable_cons (x, SCHEME_V->oblist);
1305     return x;
1306     }
1307    
1308     static pointer
1309     oblist_all_symbols (SCHEME_P)
1310     {
1311     return SCHEME_V->oblist;
1312     }
1313    
1314     #endif
1315    
1316     #if USE_PORTS
1317     static pointer
1318     mk_port (SCHEME_P_ port *p)
1319     {
1320     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1321    
1322     set_typeflag (x, T_PORT | T_ATOM);
1323     x->object.port = p;
1324    
1325     return x;
1326     }
1327     #endif
1328    
1329     pointer
1330     mk_foreign_func (SCHEME_P_ foreign_func f)
1331     {
1332     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1333    
1334     set_typeflag (x, (T_FOREIGN | T_ATOM));
1335     x->object.ff = f;
1336    
1337     return x;
1338     }
1339    
1340     INTERFACE pointer
1341     mk_character (SCHEME_P_ int c)
1342     {
1343     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1344    
1345     set_typeflag (x, (T_CHARACTER | T_ATOM));
1346     ivalue_unchecked (x) = c;
1347     set_num_integer (x);
1348     return x;
1349     }
1350    
1351     /* get number atom (integer) */
1352     INTERFACE pointer
1353     mk_integer (SCHEME_P_ long num)
1354     {
1355     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1356    
1357     set_typeflag (x, (T_NUMBER | T_ATOM));
1358     ivalue_unchecked (x) = num;
1359     set_num_integer (x);
1360     return x;
1361     }
1362    
1363     INTERFACE pointer
1364     mk_real (SCHEME_P_ RVALUE n)
1365     {
1366     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1367    
1368     set_typeflag (x, (T_NUMBER | T_ATOM));
1369     rvalue_unchecked (x) = n;
1370     set_num_real (x);
1371     return x;
1372     }
1373    
1374     static pointer
1375     mk_number (SCHEME_P_ num n)
1376     {
1377     if (num_is_fixnum (n))
1378     {
1379     return mk_integer (SCHEME_A_ num_ivalue (n));
1380     }
1381     else
1382     {
1383     return mk_real (SCHEME_A_ num_rvalue (n));
1384     }
1385     }
1386    
1387     /* allocate name to string area */
1388     static char *
1389     store_string (SCHEME_P_ int len_str, const char *str, char fill)
1390     {
1391     char *q;
1392    
1393     q = (char *)malloc (len_str + 1);
1394    
1395     if (q == 0)
1396     {
1397     #if USE_ERROR_CHECKING
1398     SCHEME_V->no_memory = 1;
1399     return SCHEME_V->strbuff;
1400     #endif
1401     }
1402    
1403     if (str)
1404     {
1405     int l = strlen (str);
1406    
1407     if (l > len_str)
1408     l = len_str;
1409    
1410     memcpy (q, str, l + 1);
1411     q[l + 1] = 0;
1412     }
1413     else
1414     {
1415     memset (q, fill, len_str);
1416     q[len_str] = 0;
1417     }
1418    
1419     return q;
1420     }
1421    
1422     /* get new string */
1423     INTERFACE pointer
1424     mk_string (SCHEME_P_ const char *str)
1425     {
1426     return mk_counted_string (SCHEME_A_ str, strlen (str));
1427     }
1428    
1429     INTERFACE pointer
1430     mk_counted_string (SCHEME_P_ const char *str, int len)
1431     {
1432     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1433    
1434     set_typeflag (x, T_STRING | T_ATOM);
1435     strvalue (x) = store_string (SCHEME_A_ len, str, 0);
1436     strlength (x) = len;
1437     return x;
1438     }
1439    
1440     INTERFACE pointer
1441     mk_empty_string (SCHEME_P_ int len, char fill)
1442     {
1443     pointer x = get_cell (SCHEME_A_ NIL, NIL);
1444    
1445     set_typeflag (x, T_STRING | T_ATOM);
1446     strvalue (x) = store_string (SCHEME_A_ len, 0, fill);
1447     strlength (x) = len;
1448     return x;
1449     }
1450    
1451     INTERFACE pointer
1452     mk_vector (SCHEME_P_ int len)
1453     {
1454     return get_vector_object (SCHEME_A_ len, NIL);
1455     }
1456    
1457     INTERFACE void
1458     fill_vector (pointer vec, pointer obj)
1459     {
1460     int i;
1461     int num = ivalue (vec) / 2 + ivalue (vec) % 2;
1462    
1463     for (i = 0; i < num; i++)
1464     {
1465     set_typeflag (vec + 1 + i, T_PAIR);
1466     setimmutable (vec + 1 + i);
1467     set_car (vec + 1 + i, obj);
1468     set_cdr (vec + 1 + i, obj);
1469     }
1470     }
1471    
1472     INTERFACE pointer
1473     vector_elem (pointer vec, int ielem)
1474     {
1475     int n = ielem / 2;
1476    
1477     if (ielem % 2 == 0)
1478     return car (vec + 1 + n);
1479     else
1480     return cdr (vec + 1 + n);
1481     }
1482    
1483     INTERFACE void
1484     set_vector_elem (pointer vec, int ielem, pointer a)
1485     {
1486     int n = ielem / 2;
1487    
1488     if (ielem % 2 == 0)
1489     set_car (vec + 1 + n, a);
1490     else
1491     set_cdr (vec + 1 + n, a);
1492     }
1493    
1494     /* get new symbol */
1495     INTERFACE pointer
1496     mk_symbol (SCHEME_P_ const char *name)
1497     {
1498     pointer x;
1499    
1500     /* first check oblist */
1501     x = oblist_find_by_name (SCHEME_A_ name);
1502    
1503     if (x != NIL)
1504     return x;
1505     else
1506     {
1507     x = oblist_add_by_name (SCHEME_A_ name);
1508     return x;
1509     }
1510     }
1511    
1512     INTERFACE pointer
1513     gensym (SCHEME_P)
1514     {
1515     pointer x;
1516     char name[40];
1517    
1518     for (; SCHEME_V->gensym_cnt < LONG_MAX; SCHEME_V->gensym_cnt++)
1519     {
1520     strcpy (name, "gensym-");
1521     xnum (name + 7, SCHEME_V->gensym_cnt);
1522    
1523     /* first check oblist */
1524     x = oblist_find_by_name (SCHEME_A_ name);
1525    
1526     if (x != NIL)
1527     continue;
1528     else
1529     {
1530     x = oblist_add_by_name (SCHEME_A_ name);
1531     return x;
1532     }
1533     }
1534    
1535     return NIL;
1536     }
1537    
1538     /* make symbol or number atom from string */
1539     static pointer
1540     mk_atom (SCHEME_P_ char *q)
1541     {
1542     char c, *p;
1543     int has_dec_point = 0;
1544     int has_fp_exp = 0;
1545    
1546     #if USE_COLON_HOOK
1547    
1548     if ((p = strstr (q, "::")) != 0)
1549     {
1550     *p = 0;
1551     return cons (SCHEME_V->COLON_HOOK,
1552     cons (cons (SCHEME_V->QUOTE,
1553     cons (mk_atom (SCHEME_A_ p + 2), NIL)), cons (mk_symbol (SCHEME_A_ strlwr (q)), NIL)));
1554     }
1555    
1556     #endif
1557    
1558     p = q;
1559     c = *p++;
1560    
1561     if ((c == '+') || (c == '-'))
1562     {
1563     c = *p++;
1564    
1565     if (c == '.')
1566     {
1567     has_dec_point = 1;
1568     c = *p++;
1569     }
1570    
1571     if (!isdigit (c))
1572     {
1573     return mk_symbol (SCHEME_A_ strlwr (q));
1574     }
1575     }
1576     else if (c == '.')
1577     {
1578     has_dec_point = 1;
1579     c = *p++;
1580    
1581     if (!isdigit (c))
1582     {
1583     return mk_symbol (SCHEME_A_ strlwr (q));
1584     }
1585     }
1586     else if (!isdigit (c))
1587     {
1588     return mk_symbol (SCHEME_A_ strlwr (q));
1589     }
1590    
1591     for (; (c = *p) != 0; ++p)
1592     {
1593     if (!isdigit (c))
1594     {
1595     if (c == '.')
1596     {
1597     if (!has_dec_point)
1598     {
1599     has_dec_point = 1;
1600     continue;
1601     }
1602     }
1603     else if ((c == 'e') || (c == 'E'))
1604     {
1605     if (!has_fp_exp)
1606     {
1607     has_dec_point = 1; /* decimal point illegal
1608     from now on */
1609     p++;
1610    
1611     if ((*p == '-') || (*p == '+') || isdigit (*p))
1612     {
1613     continue;
1614     }
1615     }
1616     }
1617    
1618     return mk_symbol (SCHEME_A_ strlwr (q));
1619     }
1620     }
1621    
1622     #if USE_FLOAT
1623     if (has_dec_point)
1624     return mk_real (SCHEME_A_ atof (q));
1625     #endif
1626    
1627     return mk_integer (SCHEME_A_ strtol (q, 0, 10));
1628     }
1629    
1630     /* make constant */
1631     static pointer
1632     mk_sharp_const (SCHEME_P_ char *name)
1633     {
1634     long x;
1635     char tmp[STRBUFFSIZE];
1636    
1637     if (!strcmp (name, "t"))
1638     return S_T;
1639     else if (!strcmp (name, "f"))
1640     return S_F;
1641     else if (*name == 'o') /* #o (octal) */
1642     {
1643     x = strtol (name + 1, 0, 8);
1644     return mk_integer (SCHEME_A_ x);
1645     }
1646     else if (*name == 'd') /* #d (decimal) */
1647     {
1648     x = strtol (name + 1, 0, 10);
1649     return mk_integer (SCHEME_A_ x);
1650     }
1651     else if (*name == 'x') /* #x (hex) */
1652     {
1653     x = strtol (name + 1, 0, 16);
1654     return mk_integer (SCHEME_A_ x);
1655     }
1656     else if (*name == 'b') /* #b (binary) */
1657     {
1658     x = binary_decode (name + 1);
1659     return mk_integer (SCHEME_A_ x);
1660     }
1661     else if (*name == '\\') /* #\w (character) */
1662     {
1663     int c = 0;
1664    
1665     if (stricmp (name + 1, "space") == 0)
1666     c = ' ';
1667     else if (stricmp (name + 1, "newline") == 0)
1668     c = '\n';
1669     else if (stricmp (name + 1, "return") == 0)
1670     c = '\r';
1671     else if (stricmp (name + 1, "tab") == 0)
1672     c = '\t';
1673     else if (name[1] == 'x' && name[2] != 0)
1674     {
1675     int c1 = strtol (name + 2, 0, 16);
1676    
1677     if (c1 <= UCHAR_MAX)
1678     c = c1;
1679     else
1680     return NIL;
1681    
1682     #if USE_ASCII_NAMES
1683     }
1684     else if (is_ascii_name (name + 1, &c))
1685     {
1686     /* nothing */
1687     #endif
1688     }
1689     else if (name[2] == 0)
1690     c = name[1];
1691     else
1692     return NIL;
1693    
1694     return mk_character (SCHEME_A_ c);
1695     }
1696     else
1697     return NIL;
1698     }
1699    
1700     /* ========== garbage collector ========== */
1701    
1702     /*--
1703     * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
1704     * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
1705     * for marking.
1706     */
1707     static void
1708     mark (pointer a)
1709     {
1710     pointer t, q, p;
1711    
1712     t = (pointer) 0;
1713     p = a;
1714     E2:
1715     setmark (p);
1716     printf ("mark %p %x\n", p, p->flag);//D
1717    
1718     if (is_vector (p))
1719     {
1720     int i;
1721     int num = ivalue_unchecked (p) / 2 + ivalue_unchecked (p) % 2;
1722    
1723     for (i = 0; i < num; i++)
1724     {
1725     /* Vector cells will be treated like ordinary cells */
1726     mark (p + 1 + i);
1727     }
1728     }
1729    
1730     if (is_atom (p))
1731     goto E6;
1732    
1733     /* E4: down car */
1734     q = car (p);
1735    
1736     if (q && !is_mark (q))
1737     {
1738     setatom (p); /* a note that we have moved car */
1739     set_car (p, t);
1740     t = p;
1741     p = q;
1742     goto E2;
1743     }
1744    
1745     E5:
1746     q = cdr (p); /* down cdr */
1747     printf ("mark+ %p\n", q, q->flag);//D
1748    
1749     if (q && !is_mark (q))
1750     {
1751     set_cdr (p, t);
1752     t = p;
1753     p = q;
1754     goto E2;
1755     }
1756    
1757     E6: /* up. Undo the link switching from steps E4 and E5. */
1758    
1759     if (!t)
1760     return;
1761    
1762     q = t;
1763    
1764     if (is_atom (q))
1765     {
1766     clratom (q);
1767     t = car (q);
1768     set_car (q, p);
1769     p = q;
1770     goto E5;
1771     }
1772     else
1773     {
1774     t = cdr (q);
1775     set_cdr (q, p);
1776     p = q;
1777     goto E6;
1778     }
1779     }
1780    
1781     /* garbage collection. parameter a, b is marked. */
1782     static void
1783     gc (SCHEME_P_ pointer a, pointer b)
1784     {
1785     pointer p;
1786     int i;
1787    
1788     if (SCHEME_V->gc_verbose)
1789     putstr (SCHEME_A_ "gc...");
1790    
1791     /* mark system globals */
1792     mark (SCHEME_V->oblist);
1793     mark (SCHEME_V->global_env);
1794    
1795     /* mark current registers */
1796     mark (SCHEME_V->args);
1797     mark (SCHEME_V->envir);
1798     mark (SCHEME_V->code);
1799     dump_stack_mark (SCHEME_A);
1800     mark (SCHEME_V->value);
1801     mark (SCHEME_V->inport);
1802     mark (SCHEME_V->save_inport);
1803     mark (SCHEME_V->outport);
1804     mark (SCHEME_V->loadport);
1805    
1806     /* Mark recent objects the interpreter doesn't know about yet. */
1807     mark (car (S_SINK));
1808     /* Mark any older stuff above nested C calls */
1809     mark (SCHEME_V->c_nest);
1810    
1811     /* mark variables a, b */
1812     mark (a);
1813     mark (b);
1814    
1815     /* garbage collect */
1816     clrmark (NIL);
1817     SCHEME_V->fcells = 0;
1818     SCHEME_V->free_cell = NIL;
1819    
1820     /* free-list is kept sorted by address so as to maintain consecutive
1821     ranges, if possible, for use with vectors. Here we scan the cells
1822     (which are also kept sorted by address) downwards to build the
1823     free-list in sorted order.
1824     */
1825     for (i = SCHEME_V->last_cell_seg; i >= 0; i--)
1826     {
1827     p = SCHEME_V->cell_seg[i] + SCHEME_V->cell_segsize [i];
1828    
1829     while (--p >= SCHEME_V->cell_seg[i])
1830     {
1831     if (is_mark (p))
1832     clrmark (p);
1833     else
1834     {
1835     /* reclaim cell */
1836     if (typeflag (p) != 0)
1837     {
1838     finalize_cell (SCHEME_A_ p);
1839     set_typeflag (p, 0);
1840     set_car (p, NIL);
1841     }
1842    
1843     ++SCHEME_V->fcells;
1844     set_cdr (p, SCHEME_V->free_cell);
1845     SCHEME_V->free_cell = p;
1846     }
1847     }
1848     }
1849    
1850     if (SCHEME_V->gc_verbose)
1851     xwrstr ("done: "); xwrnum (SCHEME_V->fcells); xwrstr (" cells were recovered.\n");
1852     }
1853    
1854     static void
1855     finalize_cell (SCHEME_P_ pointer a)
1856     {
1857     if (is_string (a))
1858     free (strvalue (a));
1859     #if USE_PORTS
1860     else if (is_port (a))
1861     {
1862     if (a->object.port->kind & port_file && a->object.port->rep.stdio.closeit)
1863     port_close (SCHEME_A_ a, port_input | port_output);
1864    
1865     free (a->object.port);
1866     }
1867     #endif
1868     }
1869    
1870     /* ========== Routines for Reading ========== */
1871    
1872     static int
1873     file_push (SCHEME_P_ const char *fname)
1874     {
1875     #if USE_PORTS
1876     int fin;
1877    
1878     if (SCHEME_V->file_i == MAXFIL - 1)
1879     return 0;
1880    
1881     fin = open (fname, O_RDONLY);
1882    
1883     if (fin >= 0)
1884     {
1885     SCHEME_V->file_i++;
1886     SCHEME_V->load_stack[SCHEME_V->file_i].unget = -1;
1887     SCHEME_V->load_stack[SCHEME_V->file_i].kind = port_file | port_input;
1888     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.file = fin;
1889     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.closeit = 1;
1890     SCHEME_V->nesting_stack[SCHEME_V->file_i] = 0;
1891     SCHEME_V->loadport->object.port = SCHEME_V->load_stack + SCHEME_V->file_i;
1892    
1893     #if SHOW_ERROR_LINE
1894     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line = 0;
1895    
1896     if (fname)
1897     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.filename = store_string (SCHEME_A_ strlen (fname), fname, 0);
1898     #endif
1899     }
1900    
1901     return fin >= 0;
1902    
1903     #else
1904     return 1;
1905     #endif
1906     }
1907    
1908     static void
1909     file_pop (SCHEME_P)
1910     {
1911     if (SCHEME_V->file_i != 0)
1912     {
1913     SCHEME_V->nesting = SCHEME_V->nesting_stack[SCHEME_V->file_i];
1914     #if USE_PORTS
1915     port_close (SCHEME_A_ SCHEME_V->loadport, port_input);
1916     #endif
1917     SCHEME_V->file_i--;
1918     SCHEME_V->loadport->object.port = SCHEME_V->load_stack + SCHEME_V->file_i;
1919     }
1920     }
1921    
1922     static int
1923     file_interactive (SCHEME_P)
1924     {
1925     #if USE_PORTS
1926     return SCHEME_V->file_i == 0
1927     && SCHEME_V->load_stack[0].rep.stdio.file == STDIN_FILENO
1928     && (SCHEME_V->inport->object.port->kind & port_file);
1929     #else
1930     return 0;
1931     #endif
1932     }
1933    
1934     #if USE_PORTS
1935     static port *
1936     port_rep_from_filename (SCHEME_P_ const char *fn, int prop)
1937     {
1938     int fd;
1939     int flags;
1940     char *rw;
1941     port *pt;
1942    
1943     if (prop == (port_input | port_output))
1944     flags = O_RDWR | O_APPEND | O_CREAT;
1945     else if (prop == port_output)
1946     flags = O_WRONLY | O_TRUNC | O_CREAT;
1947     else
1948     flags = O_RDONLY;
1949    
1950     fd = open (fn, flags, 0666);
1951    
1952     if (fd < 0)
1953     return 0;
1954    
1955     pt = port_rep_from_file (SCHEME_A_ fd, prop);
1956     pt->rep.stdio.closeit = 1;
1957    
1958     # if SHOW_ERROR_LINE
1959     if (fn)
1960     pt->rep.stdio.filename = store_string (SCHEME_A_ strlen (fn), fn, 0);
1961    
1962     pt->rep.stdio.curr_line = 0;
1963     # endif
1964    
1965     return pt;
1966     }
1967    
1968     static pointer
1969     port_from_filename (SCHEME_P_ const char *fn, int prop)
1970     {
1971     port *pt = port_rep_from_filename (SCHEME_A_ fn, prop);
1972    
1973     if (!pt && USE_ERROR_CHECKING)
1974     return NIL;
1975    
1976     return mk_port (SCHEME_A_ pt);
1977     }
1978    
1979     static port *
1980     port_rep_from_file (SCHEME_P_ int f, int prop)
1981     {
1982     port *pt = malloc (sizeof *pt);
1983    
1984     if (!pt && USE_ERROR_CHECKING)
1985     return NULL;
1986    
1987     pt->unget = -1;
1988     pt->kind = port_file | prop;
1989     pt->rep.stdio.file = f;
1990     pt->rep.stdio.closeit = 0;
1991     return pt;
1992     }
1993    
1994     static pointer
1995     port_from_file (SCHEME_P_ int f, int prop)
1996     {
1997     port *pt = port_rep_from_file (SCHEME_A_ f, prop);
1998    
1999     if (!pt && USE_ERROR_CHECKING)
2000     return NIL;
2001    
2002     return mk_port (SCHEME_A_ pt);
2003     }
2004    
2005     static port *
2006     port_rep_from_string (SCHEME_P_ char *start, char *past_the_end, int prop)
2007     {
2008     port *pt = malloc (sizeof (port));
2009    
2010     if (!pt && USE_ERROR_CHECKING)
2011     return 0;
2012    
2013     pt->unget = -1;
2014     pt->kind = port_string | prop;
2015     pt->rep.string.start = start;
2016     pt->rep.string.curr = start;
2017     pt->rep.string.past_the_end = past_the_end;
2018     return pt;
2019     }
2020    
2021     static pointer
2022     port_from_string (SCHEME_P_ char *start, char *past_the_end, int prop)
2023     {
2024     port *pt = port_rep_from_string (SCHEME_A_ start, past_the_end, prop);
2025    
2026     if (!pt && USE_ERROR_CHECKING)
2027     return NIL;
2028    
2029     return mk_port (SCHEME_A_ pt);
2030     }
2031    
2032     # define BLOCK_SIZE 256
2033    
2034     static port *
2035     port_rep_from_scratch (SCHEME_P)
2036     {
2037     char *start;
2038     port *pt = malloc (sizeof (port));
2039    
2040     if (!pt && USE_ERROR_CHECKING)
2041     return 0;
2042    
2043     start = malloc (BLOCK_SIZE);
2044    
2045     if (start == 0)
2046     return 0;
2047    
2048     memset (start, ' ', BLOCK_SIZE - 1);
2049     start[BLOCK_SIZE - 1] = '\0';
2050     pt->unget = -1;
2051     pt->kind = port_string | port_output | port_srfi6;
2052     pt->rep.string.start = start;
2053     pt->rep.string.curr = start;
2054     pt->rep.string.past_the_end = start + BLOCK_SIZE - 1;
2055     return pt;
2056     }
2057    
2058     static pointer
2059     port_from_scratch (SCHEME_P)
2060     {
2061     port *pt = port_rep_from_scratch (SCHEME_A);
2062    
2063     if (!pt && USE_ERROR_CHECKING)
2064     return NIL;
2065    
2066     return mk_port (SCHEME_A_ pt);
2067     }
2068    
2069     static void
2070     port_close (SCHEME_P_ pointer p, int flag)
2071     {
2072     port *pt = p->object.port;
2073    
2074     pt->kind &= ~flag;
2075    
2076     if ((pt->kind & (port_input | port_output)) == 0)
2077     {
2078     if (pt->kind & port_file)
2079     {
2080    
2081     # if SHOW_ERROR_LINE
2082     /* Cleanup is here so (close-*-port) functions could work too */
2083     pt->rep.stdio.curr_line = 0;
2084    
2085     if (pt->rep.stdio.filename)
2086     free (pt->rep.stdio.filename);
2087    
2088     # endif
2089    
2090     close (pt->rep.stdio.file);
2091     }
2092    
2093     pt->kind = port_free;
2094     }
2095     }
2096     #endif
2097    
2098     /* get new character from input file */
2099     static int
2100     inchar (SCHEME_P)
2101     {
2102     int c;
2103     port *pt;
2104    
2105     pt = SCHEME_V->inport->object.port;
2106    
2107     if (pt->kind & port_saw_EOF)
2108     return EOF;
2109    
2110     c = basic_inchar (pt);
2111    
2112     if (c == EOF && SCHEME_V->inport == SCHEME_V->loadport)
2113     {
2114     /* Instead, set port_saw_EOF */
2115     pt->kind |= port_saw_EOF;
2116    
2117     /* file_pop(SCHEME_A); */
2118     return EOF;
2119     /* NOTREACHED */
2120     }
2121    
2122     return c;
2123     }
2124    
2125     static int ungot = -1;
2126    
2127     static int
2128     basic_inchar (port *pt)
2129     {
2130     #if USE_PORTS
2131     if (pt->unget != -1)
2132     {
2133     int r = pt->unget;
2134     pt->unget = -1;
2135     return r;
2136     }
2137    
2138     if (pt->kind & port_file)
2139     {
2140     char c;
2141    
2142     if (!read (pt->rep.stdio.file, &c, 1))
2143     return EOF;
2144    
2145     return c;
2146     }
2147     else
2148     {
2149     if (*pt->rep.string.curr == 0 || pt->rep.string.curr == pt->rep.string.past_the_end)
2150     return EOF;
2151     else
2152     return *pt->rep.string.curr++;
2153     }
2154     #else
2155     if (ungot == -1)
2156     {
2157     char c;
2158     if (!read (0, &c, 1))
2159     return EOF;
2160    
2161     ungot = c;
2162     }
2163    
2164     {
2165     int r = ungot;
2166     ungot = -1;
2167     return r;
2168     }
2169     #endif
2170     }
2171    
2172     /* back character to input buffer */
2173     static void
2174     backchar (SCHEME_P_ int c)
2175     {
2176     #if USE_PORTS
2177     port *pt;
2178    
2179     if (c == EOF)
2180     return;
2181    
2182     pt = SCHEME_V->inport->object.port;
2183     pt->unget = c;
2184     #else
2185     if (c == EOF)
2186     return;
2187    
2188     ungot = c;
2189     #endif
2190     }
2191    
2192     #if USE_PORTS
2193     static int
2194     realloc_port_string (SCHEME_P_ port *p)
2195     {
2196     char *start = p->rep.string.start;
2197     size_t new_size = p->rep.string.past_the_end - start + 1 + BLOCK_SIZE;
2198     char *str = malloc (new_size);
2199    
2200     if (str)
2201     {
2202     memset (str, ' ', new_size - 1);
2203     str[new_size - 1] = '\0';
2204     strcpy (str, start);
2205     p->rep.string.start = str;
2206     p->rep.string.past_the_end = str + new_size - 1;
2207     p->rep.string.curr -= start - str;
2208     free (start);
2209     return 1;
2210     }
2211     else
2212     return 0;
2213     }
2214     #endif
2215    
2216     INTERFACE void
2217     putstr (SCHEME_P_ const char *s)
2218     {
2219     #if USE_PORTS
2220     port *pt = SCHEME_V->outport->object.port;
2221    
2222     if (pt->kind & port_file)
2223     write (pt->rep.stdio.file, s, strlen (s));
2224     else
2225     for (; *s; s++)
2226     if (pt->rep.string.curr != pt->rep.string.past_the_end)
2227     *pt->rep.string.curr++ = *s;
2228     else if (pt->kind & port_srfi6 && realloc_port_string (SCHEME_A_ pt))
2229     *pt->rep.string.curr++ = *s;
2230    
2231     #else
2232     xwrstr (s);
2233     #endif
2234     }
2235    
2236     static void
2237     putchars (SCHEME_P_ const char *s, int len)
2238     {
2239     #if USE_PORTS
2240     port *pt = SCHEME_V->outport->object.port;
2241    
2242     if (pt->kind & port_file)
2243     write (pt->rep.stdio.file, s, len);
2244     else
2245     {
2246     for (; len; len--)
2247     {
2248     if (pt->rep.string.curr != pt->rep.string.past_the_end)
2249     *pt->rep.string.curr++ = *s++;
2250     else if (pt->kind & port_srfi6 && realloc_port_string (SCHEME_A_ pt))
2251     *pt->rep.string.curr++ = *s++;
2252     }
2253     }
2254    
2255     #else
2256     write (1, s, len);
2257     #endif
2258     }
2259    
2260     INTERFACE void
2261     putcharacter (SCHEME_P_ int c)
2262     {
2263     #if USE_PORTS
2264     port *pt = SCHEME_V->outport->object.port;
2265    
2266     if (pt->kind & port_file)
2267     {
2268     char cc = c;
2269     write (pt->rep.stdio.file, &cc, 1);
2270     }
2271     else
2272     {
2273     if (pt->rep.string.curr != pt->rep.string.past_the_end)
2274     *pt->rep.string.curr++ = c;
2275     else if (pt->kind & port_srfi6 && realloc_port_string (SCHEME_A_ pt))
2276     *pt->rep.string.curr++ = c;
2277     }
2278    
2279     #else
2280     char cc = c;
2281     write (1, &c, 1);
2282     #endif
2283     }
2284    
2285     /* read characters up to delimiter, but cater to character constants */
2286     static char *
2287     readstr_upto (SCHEME_P_ char *delim)
2288     {
2289     char *p = SCHEME_V->strbuff;
2290    
2291     while ((p - SCHEME_V->strbuff < sizeof (SCHEME_V->strbuff)) && !is_one_of (delim, (*p++ = inchar (SCHEME_A))));
2292    
2293     if (p == SCHEME_V->strbuff + 2 && p[-2] == '\\')
2294     {
2295     *p = 0;
2296     }
2297     else
2298     {
2299     backchar (SCHEME_A_ p[-1]);
2300     *--p = '\0';
2301     }
2302    
2303     return SCHEME_V->strbuff;
2304     }
2305    
2306     /* read string expression "xxx...xxx" */
2307     static pointer
2308     readstrexp (SCHEME_P)
2309     {
2310     char *p = SCHEME_V->strbuff;
2311     int c;
2312     int c1 = 0;
2313     enum
2314     { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2 } state = st_ok;
2315    
2316     for (;;)
2317     {
2318     c = inchar (SCHEME_A);
2319    
2320     if (c == EOF || p - SCHEME_V->strbuff > sizeof (SCHEME_V->strbuff) - 1)
2321     {
2322     return S_F;
2323     }
2324    
2325     switch (state)
2326     {
2327     case st_ok:
2328     switch (c)
2329     {
2330     case '\\':
2331     state = st_bsl;
2332     break;
2333    
2334     case '"':
2335     *p = 0;
2336     return mk_counted_string (SCHEME_A_ SCHEME_V->strbuff, p - SCHEME_V->strbuff);
2337    
2338     default:
2339     *p++ = c;
2340     break;
2341     }
2342    
2343     break;
2344    
2345     case st_bsl:
2346     switch (c)
2347     {
2348     case '0':
2349     case '1':
2350     case '2':
2351     case '3':
2352     case '4':
2353     case '5':
2354     case '6':
2355     case '7':
2356     state = st_oct1;
2357     c1 = c - '0';
2358     break;
2359    
2360     case 'x':
2361     case 'X':
2362     state = st_x1;
2363     c1 = 0;
2364     break;
2365    
2366     case 'n':
2367     *p++ = '\n';
2368     state = st_ok;
2369     break;
2370    
2371     case 't':
2372     *p++ = '\t';
2373     state = st_ok;
2374     break;
2375    
2376     case 'r':
2377     *p++ = '\r';
2378     state = st_ok;
2379     break;
2380    
2381     case '"':
2382     *p++ = '"';
2383     state = st_ok;
2384     break;
2385    
2386     default:
2387     *p++ = c;
2388     state = st_ok;
2389     break;
2390     }
2391    
2392     break;
2393    
2394     case st_x1:
2395     case st_x2:
2396     c = toupper (c);
2397    
2398     if (c >= '0' && c <= 'F')
2399     {
2400     if (c <= '9')
2401     {
2402     c1 = (c1 << 4) + c - '0';
2403     }
2404     else
2405     {
2406     c1 = (c1 << 4) + c - 'A' + 10;
2407     }
2408    
2409     if (state == st_x1)
2410     {
2411     state = st_x2;
2412     }
2413     else
2414     {
2415     *p++ = c1;
2416     state = st_ok;
2417     }
2418     }
2419     else
2420     {
2421     return S_F;
2422     }
2423    
2424     break;
2425    
2426     case st_oct1:
2427     case st_oct2:
2428     if (c < '0' || c > '7')
2429     {
2430     *p++ = c1;
2431     backchar (SCHEME_A_ c);
2432     state = st_ok;
2433     }
2434     else
2435     {
2436     if (state == st_oct2 && c1 >= 32)
2437     return S_F;
2438    
2439     c1 = (c1 << 3) + (c - '0');
2440    
2441     if (state == st_oct1)
2442     state = st_oct2;
2443     else
2444     {
2445     *p++ = c1;
2446     state = st_ok;
2447     }
2448     }
2449    
2450     break;
2451    
2452     }
2453     }
2454     }
2455    
2456     /* check c is in chars */
2457     static INLINE int
2458     is_one_of (char *s, int c)
2459     {
2460     if (c == EOF)
2461     return 1;
2462    
2463     while (*s)
2464     if (*s++ == c)
2465     return 1;
2466    
2467     return 0;
2468     }
2469    
2470     /* skip white characters */
2471     static INLINE int
2472     skipspace (SCHEME_P)
2473     {
2474     int c, curr_line = 0;
2475    
2476     do
2477     {
2478     c = inchar (SCHEME_A);
2479     #if SHOW_ERROR_LINE
2480     if (c == '\n')
2481     curr_line++;
2482    
2483     #endif
2484     }
2485     while (c == ' ' || c == '\n' || c == '\r' || c == '\t');
2486    
2487     /* record it */
2488     #if SHOW_ERROR_LINE
2489     if (SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
2490     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line += curr_line;
2491     #endif
2492    
2493     if (c != EOF)
2494     {
2495     backchar (SCHEME_A_ c);
2496     return 1;
2497     }
2498     else
2499     return EOF;
2500     }
2501    
2502     /* get token */
2503     static int
2504     token (SCHEME_P)
2505     {
2506     int c = skipspace (SCHEME_A);
2507    
2508     if (c == EOF)
2509     return TOK_EOF;
2510    
2511     switch ((c = inchar (SCHEME_A)))
2512     {
2513     case EOF:
2514     return TOK_EOF;
2515    
2516     case '(':
2517     return TOK_LPAREN;
2518    
2519     case ')':
2520     return TOK_RPAREN;
2521    
2522     case '.':
2523     c = inchar (SCHEME_A);
2524    
2525     if (is_one_of (" \n\t", c))
2526     return TOK_DOT;
2527     else
2528     {
2529     backchar (SCHEME_A_ c);
2530     backchar (SCHEME_A_ '.');
2531     return TOK_ATOM;
2532     }
2533    
2534     case '\'':
2535     return TOK_QUOTE;
2536    
2537     case ';':
2538     while ((c = inchar (SCHEME_A)) != '\n' && c != EOF)
2539     ;
2540    
2541     #if SHOW_ERROR_LINE
2542    
2543     if (c == '\n' && SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
2544     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line++;
2545    
2546     #endif
2547    
2548     if (c == EOF)
2549     return TOK_EOF;
2550     else
2551     return token (SCHEME_A);
2552    
2553     case '"':
2554     return TOK_DQUOTE;
2555    
2556     case BACKQUOTE:
2557     return TOK_BQUOTE;
2558    
2559     case ',':
2560     if ((c = inchar (SCHEME_A)) == '@')
2561     return TOK_ATMARK;
2562     else
2563     {
2564     backchar (SCHEME_A_ c);
2565     return TOK_COMMA;
2566     }
2567    
2568     case '#':
2569     c = inchar (SCHEME_A);
2570    
2571     if (c == '(')
2572     return TOK_VEC;
2573     else if (c == '!')
2574     {
2575     while ((c = inchar (SCHEME_A)) != '\n' && c != EOF)
2576     ;
2577    
2578     #if SHOW_ERROR_LINE
2579    
2580     if (c == '\n' && SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
2581     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line++;
2582    
2583     #endif
2584    
2585     if (c == EOF)
2586     return TOK_EOF;
2587     else
2588     return token (SCHEME_A);
2589     }
2590     else
2591     {
2592     backchar (SCHEME_A_ c);
2593    
2594     if (is_one_of (" tfodxb\\", c))
2595     return TOK_SHARP_CONST;
2596     else
2597     return TOK_SHARP;
2598     }
2599    
2600     default:
2601     backchar (SCHEME_A_ c);
2602     return TOK_ATOM;
2603     }
2604     }
2605    
2606     /* ========== Routines for Printing ========== */
2607     #define ok_abbrev(x) (is_pair(x) && cdr(x) == NIL)
2608    
2609     static void
2610     printslashstring (SCHEME_P_ char *p, int len)
2611     {
2612     int i;
2613     unsigned char *s = (unsigned char *) p;
2614    
2615     putcharacter (SCHEME_A_ '"');
2616    
2617     for (i = 0; i < len; i++)
2618     {
2619     if (*s == 0xff || *s == '"' || *s < ' ' || *s == '\\')
2620     {
2621     putcharacter (SCHEME_A_ '\\');
2622    
2623     switch (*s)
2624     {
2625     case '"':
2626     putcharacter (SCHEME_A_ '"');
2627     break;
2628    
2629     case '\n':
2630     putcharacter (SCHEME_A_ 'n');
2631     break;
2632    
2633     case '\t':
2634     putcharacter (SCHEME_A_ 't');
2635     break;
2636    
2637     case '\r':
2638     putcharacter (SCHEME_A_ 'r');
2639     break;
2640    
2641     case '\\':
2642     putcharacter (SCHEME_A_ '\\');
2643     break;
2644    
2645     default:
2646     {
2647     int d = *s / 16;
2648    
2649     putcharacter (SCHEME_A_ 'x');
2650    
2651     if (d < 10)
2652     {
2653     putcharacter (SCHEME_A_ d + '0');
2654     }
2655     else
2656     {
2657     putcharacter (SCHEME_A_ d - 10 + 'A');
2658     }
2659    
2660     d = *s % 16;
2661    
2662     if (d < 10)
2663     {
2664     putcharacter (SCHEME_A_ d + '0');
2665     }
2666     else
2667     {
2668     putcharacter (SCHEME_A_ d - 10 + 'A');
2669     }
2670     }
2671     }
2672     }
2673     else
2674     {
2675     putcharacter (SCHEME_A_ * s);
2676     }
2677    
2678     s++;
2679     }
2680    
2681     putcharacter (SCHEME_A_ '"');
2682     }
2683    
2684    
2685     /* print atoms */
2686     static void
2687     printatom (SCHEME_P_ pointer l, int f)
2688     {
2689     char *p;
2690     int len;
2691    
2692     atom2str (SCHEME_A_ l, f, &p, &len);
2693     putchars (SCHEME_A_ p, len);
2694     }
2695    
2696    
2697     /* Uses internal buffer unless string pointer is already available */
2698     static void
2699     atom2str (SCHEME_P_ pointer l, int f, char **pp, int *plen)
2700     {
2701     char *p;
2702    
2703     if (l == NIL)
2704     p = "()";
2705     else if (l == S_T)
2706     p = "#t";
2707     else if (l == S_F)
2708     p = "#f";
2709     else if (l == S_EOF)
2710     p = "#<EOF>";
2711     else if (is_port (l))
2712     p = "#<PORT>";
2713     else if (is_number (l))
2714     {
2715     p = SCHEME_V->strbuff;
2716    
2717     if (f <= 1 || f == 10) /* f is the base for numbers if > 1 */
2718     {
2719     if (num_is_integer (l))
2720     xnum (p, ivalue_unchecked (l));
2721     #if USE_FLOAT
2722     else
2723     {
2724     snprintf (p, STRBUFFSIZE, "%.10g", rvalue_unchecked (l));
2725     /* r5rs says there must be a '.' (unless 'e'?) */
2726     f = strcspn (p, ".e");
2727    
2728     if (p[f] == 0)
2729     {
2730     p[f] = '.'; /* not found, so add '.0' at the end */
2731     p[f + 1] = '0';
2732     p[f + 2] = 0;
2733     }
2734     }
2735     #endif
2736     }
2737     else
2738     {
2739     long v = ivalue (l);
2740    
2741     if (f == 16)
2742     xbase (p, v, 16);
2743     else if (f == 8)
2744     xbase (p, v, 8);
2745     else if (f == 2)
2746     {
2747     unsigned long b = (v < 0) ? -v : v;
2748    
2749     p = &p[STRBUFFSIZE - 1];
2750     *p = 0;
2751    
2752     do
2753     {
2754     *--p = (b & 1) ? '1' : '0';
2755     b >>= 1;
2756     }
2757     while (b != 0);
2758    
2759     if (v < 0)
2760     *--p = '-';
2761     }
2762     }
2763     }
2764     else if (is_string (l))
2765     {
2766     if (!f)
2767     p = strvalue (l);
2768     else /* Hack, uses the fact that printing is needed */
2769     {
2770     *pp = SCHEME_V->strbuff;
2771     *plen = 0;
2772     printslashstring (SCHEME_A_ strvalue (l), strlength (l));
2773     return;
2774     }
2775     }
2776     else if (is_character (l))
2777     {
2778     int c = charvalue (l);
2779    
2780     p = SCHEME_V->strbuff;
2781    
2782     if (!f)
2783     {
2784     p[0] = c;
2785     p[1] = 0;
2786     }
2787     else
2788     {
2789     switch (c)
2790     {
2791     case ' ':
2792     p ="#\\space";
2793     break;
2794    
2795     case '\n':
2796     p ="#\\newline";
2797     break;
2798    
2799     case '\r':
2800     p ="#\\return";
2801     break;
2802    
2803     case '\t':
2804     p ="#\\tab";
2805     break;
2806    
2807     default:
2808     #if USE_ASCII_NAMES
2809     if (c == 127)
2810     {
2811     strcpy (p, "#\\del");
2812     break;
2813     }
2814     else if (c < 32)
2815     {
2816     strcpy (p, "#\\");
2817     strcpy (p + 2, charnames[c]);
2818     break;
2819     }
2820    
2821     #else
2822    
2823     if (c < 32)
2824     {
2825     strcpy (p, "#\\x");
2826     xbase (p + 3, c, 16);
2827     break;
2828     }
2829    
2830     #endif
2831     strcpy (p, "#\\%");
2832     p[2] = c;
2833     break;
2834     }
2835     }
2836     }
2837     else if (is_symbol (l))
2838     p = symname (l);
2839     else if (is_proc (l))
2840     {
2841     #if USE_PRINTF
2842     p = SCHEME_V->strbuff;
2843     snprintf (p, STRBUFFSIZE, "#<%s PROCEDURE %ld>", procname (l), procnum (l));
2844     #else
2845     p = "#<PROCEDURE>";
2846     #endif
2847     }
2848     else if (is_macro (l))
2849     p = "#<MACRO>";
2850     else if (is_closure (l))
2851     p = "#<CLOSURE>";
2852     else if (is_promise (l))
2853     p = "#<PROMISE>";
2854     else if (is_foreign (l))
2855     {
2856     #if USE_PRINTF
2857     p = SCHEME_V->strbuff;
2858     snprintf (p, STRBUFFSIZE, "#<FOREIGN PROCEDURE %ld>", procnum (l));
2859     #else
2860     p = "#<FOREIGN PROCEDURE>";
2861     #endif
2862     }
2863     else if (is_continuation (l))
2864     p = "#<CONTINUATION>";
2865     else
2866     p = "#<ERROR>";
2867    
2868     *pp = p;
2869     *plen = strlen (p);
2870     }
2871    
2872     /* ========== Routines for Evaluation Cycle ========== */
2873    
2874     /* make closure. c is code. e is environment */
2875     static pointer
2876     mk_closure (SCHEME_P_ pointer c, pointer e)
2877     {
2878     pointer x = get_cell (SCHEME_A_ c, e);
2879    
2880     set_typeflag (x, T_CLOSURE);
2881     set_car (x, c);
2882     set_cdr (x, e);
2883     return x;
2884     }
2885    
2886     /* make continuation. */
2887     static pointer
2888     mk_continuation (SCHEME_P_ pointer d)
2889     {
2890     pointer x = get_cell (SCHEME_A_ NIL, d);
2891    
2892     set_typeflag (x, T_CONTINUATION);
2893     set_cont_dump (x, d);
2894     return x;
2895     }
2896    
2897     static pointer
2898     list_star (SCHEME_P_ pointer d)
2899     {
2900     pointer p, q;
2901    
2902     if (cdr (d) == NIL)
2903     {
2904     return car (d);
2905     }
2906    
2907     p = cons (car (d), cdr (d));
2908     q = p;
2909    
2910     while (cdr (cdr (p)) != NIL)
2911     {
2912     d = cons (car (p), cdr (p));
2913    
2914     if (cdr (cdr (p)) != NIL)
2915     {
2916     p = cdr (d);
2917     }
2918     }
2919    
2920     set_cdr (p, car (cdr (p)));
2921     return q;
2922     }
2923    
2924     /* reverse list -- produce new list */
2925     static pointer
2926     reverse (SCHEME_P_ pointer a)
2927     {
2928     /* a must be checked by gc */
2929     pointer p = NIL;
2930    
2931     for (; is_pair (a); a = cdr (a))
2932     p = cons (car (a), p);
2933    
2934     return p;
2935     }
2936    
2937     /* reverse list --- in-place */
2938     static pointer
2939     reverse_in_place (SCHEME_P_ pointer term, pointer list)
2940     {
2941     pointer p = list, result = term, q;
2942    
2943     while (p != NIL)
2944     {
2945     q = cdr (p);
2946     set_cdr (p, result);
2947     result = p;
2948     p = q;
2949     }
2950    
2951     return result;
2952     }
2953    
2954     /* append list -- produce new list (in reverse order) */
2955     static pointer
2956     revappend (SCHEME_P_ pointer a, pointer b)
2957     {
2958     pointer result = a;
2959     pointer p = b;
2960    
2961     while (is_pair (p))
2962     {
2963     result = cons (car (p), result);
2964     p = cdr (p);
2965     }
2966    
2967     if (p == NIL)
2968     return result;
2969    
2970     return S_F; /* signal an error */
2971     }
2972    
2973     /* equivalence of atoms */
2974     int
2975     eqv (pointer a, pointer b)
2976     {
2977     if (is_string (a))
2978     {
2979     if (is_string (b))
2980     return strvalue (a) == strvalue (b);
2981     else
2982     return 0;
2983     }
2984     else if (is_number (a))
2985     {
2986     if (is_number (b))
2987     if (num_is_integer (a) == num_is_integer (b))
2988     return num_eq (nvalue (a), nvalue (b));
2989    
2990     return 0;
2991     }
2992     else if (is_character (a))
2993     {
2994     if (is_character (b))
2995     return charvalue (a) == charvalue (b);
2996     else
2997     return 0;
2998     }
2999     else if (is_port (a))
3000     {
3001     if (is_port (b))
3002     return a == b;
3003     else
3004     return 0;
3005     }
3006     else if (is_proc (a))
3007     {
3008     if (is_proc (b))
3009     return procnum (a) == procnum (b);
3010     else
3011     return 0;
3012     }
3013     else
3014     return a == b;
3015     }
3016    
3017     /* true or false value macro */
3018    
3019     /* () is #t in R5RS */
3020     #define is_true(p) ((p) != S_F)
3021     #define is_false(p) ((p) == S_F)
3022    
3023     /* ========== Environment implementation ========== */
3024    
3025     #if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
3026    
3027     static int
3028     hash_fn (const char *key, int table_size)
3029     {
3030     unsigned int hashed = 0;
3031     const char *c;
3032     int bits_per_int = sizeof (unsigned int) * 8;
3033    
3034     for (c = key; *c; c++)
3035     {
3036     /* letters have about 5 bits in them */
3037     hashed = (hashed << 5) | (hashed >> (bits_per_int - 5));
3038     hashed ^= *c;
3039     }
3040    
3041     return hashed % table_size;
3042     }
3043     #endif
3044    
3045     #ifndef USE_ALIST_ENV
3046    
3047     /*
3048     * In this implementation, each frame of the environment may be
3049     * a hash table: a vector of alists hashed by variable name.
3050     * In practice, we use a vector only for the initial frame;
3051     * subsequent frames are too small and transient for the lookup
3052     * speed to out-weigh the cost of making a new vector.
3053     */
3054    
3055     static void
3056     new_frame_in_env (SCHEME_P_ pointer old_env)
3057     {
3058     pointer new_frame;
3059    
3060     /* The interaction-environment has about 300 variables in it. */
3061     if (old_env == NIL)
3062     new_frame = mk_vector (SCHEME_A_ 461);
3063     else
3064     new_frame = NIL;
3065    
3066     SCHEME_V->envir = immutable_cons (new_frame, old_env);
3067     setenvironment (SCHEME_V->envir);
3068     }
3069    
3070     static INLINE void
3071     new_slot_spec_in_env (SCHEME_P_ pointer env, pointer variable, pointer value)
3072     {
3073     pointer slot = immutable_cons (variable, value);
3074    
3075     if (is_vector (car (env)))
3076     {
3077     int location = hash_fn (symname (variable), ivalue_unchecked (car (env)));
3078    
3079     set_vector_elem (car (env), location, immutable_cons (slot, vector_elem (car (env), location)));
3080     }
3081     else
3082     set_car (env, immutable_cons (slot, car (env)));
3083     }
3084    
3085     static pointer
3086     find_slot_in_env (SCHEME_P_ pointer env, pointer hdl, int all)
3087     {
3088     pointer x, y;
3089     int location;
3090    
3091     for (x = env; x != NIL; x = cdr (x))
3092     {
3093     if (is_vector (car (x)))
3094     {
3095     location = hash_fn (symname (hdl), ivalue_unchecked (car (x)));
3096     y = vector_elem (car (x), location);
3097     }
3098     else
3099     y = car (x);
3100    
3101     for (; y != NIL; y = cdr (y))
3102     if (caar (y) == hdl)
3103     break;
3104    
3105     if (y != NIL)
3106     break;
3107    
3108     if (!all)
3109     return NIL;
3110     }
3111    
3112     if (x != NIL)
3113     return car (y);
3114    
3115     return NIL;
3116     }
3117    
3118     #else /* USE_ALIST_ENV */
3119    
3120     static INLINE void
3121     new_frame_in_env (SCHEME_P_ pointer old_env)
3122     {
3123     SCHEME_V->envir = immutable_cons (NIL, old_env);
3124     setenvironment (SCHEME_V->envir);
3125     }
3126    
3127     static INLINE void
3128     new_slot_spec_in_env (SCHEME_P_ pointer env, pointer variable, pointer value)
3129     {
3130     set_car (env, immutable_cons (immutable_cons (variable, value), car (env)));
3131     }
3132    
3133     static pointer
3134     find_slot_in_env (SCHEME_P_ pointer env, pointer hdl, int all)
3135     {
3136     pointer x, y;
3137    
3138     for (x = env; x != NIL; x = cdr (x))
3139     {
3140     for (y = car (x); y != NIL; y = cdr (y))
3141     if (caar (y) == hdl)
3142     break;
3143    
3144     if (y != NIL)
3145     break;
3146    
3147     if (!all)
3148     return NIL;
3149     }
3150    
3151     if (x != NIL)
3152     return car (y);
3153    
3154     return NIL;
3155     }
3156    
3157     #endif /* USE_ALIST_ENV else */
3158    
3159     static INLINE void
3160     new_slot_in_env (SCHEME_P_ pointer variable, pointer value)
3161     {
3162     new_slot_spec_in_env (SCHEME_A_ SCHEME_V->envir, variable, value);
3163     }
3164    
3165     static INLINE void
3166     set_slot_in_env (SCHEME_P_ pointer slot, pointer value)
3167     {
3168     set_cdr (slot, value);
3169     }
3170    
3171     static INLINE pointer
3172     slot_value_in_env (pointer slot)
3173     {
3174     return cdr (slot);
3175     }
3176    
3177     /* ========== Evaluation Cycle ========== */
3178    
3179     static pointer
3180     xError_1 (SCHEME_P_ const char *s, pointer a)
3181     {
3182     #if USE_ERROR_HOOK
3183     pointer x;
3184     pointer hdl = SCHEME_V->ERROR_HOOK;
3185     #endif
3186    
3187     #if USE_PRINTF
3188     #if SHOW_ERROR_LINE
3189     char sbuf[STRBUFFSIZE];
3190    
3191     /* make sure error is not in REPL */
3192     if ((SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file) && SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.file != STDIN_FILENO)
3193     {
3194     int ln = SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line;
3195     const char *fname = SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.filename;
3196    
3197     /* should never happen */
3198     if (!fname)
3199     fname = "<unknown>";
3200    
3201     /* we started from 0 */
3202     ln++;
3203     snprintf (sbuf, STRBUFFSIZE, "(%s : %i) %s", fname, ln, s);
3204    
3205     s = sbuf;
3206     }
3207     #endif
3208     #endif
3209    
3210     #if USE_ERROR_HOOK
3211     x = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, hdl, 1);
3212    
3213     if (x != NIL)
3214     {
3215     if (a)
3216     SCHEME_V->code = cons (cons (SCHEME_V->QUOTE, cons (a, NIL)), NIL);
3217     else
3218     SCHEME_V->code = NIL;
3219    
3220     SCHEME_V->code = cons (mk_string (SCHEME_A_ s), SCHEME_V->code);
3221     setimmutable (car (SCHEME_V->code));
3222     SCHEME_V->code = cons (slot_value_in_env (x), SCHEME_V->code);
3223     SCHEME_V->op = OP_EVAL;
3224    
3225     return S_T;
3226     }
3227     #endif
3228    
3229     if (a)
3230     SCHEME_V->args = cons (a, NIL);
3231     else
3232     SCHEME_V->args = NIL;
3233    
3234     SCHEME_V->args = cons (mk_string (SCHEME_A_ s), SCHEME_V->args);
3235     setimmutable (car (SCHEME_V->args));
3236     SCHEME_V->op = (int)OP_ERR0;
3237     return S_T;
3238     }
3239    
3240     #define Error_1(s, a) return xError_1(SCHEME_A_ USE_ERROR_CHECKING ? s : "", a)
3241     #define Error_0(s) Error_1 (s, 0)
3242    
3243     /* Too small to turn into function */
3244     #define BEGIN do {
3245     #define END } while (0)
3246     #define s_goto(a) BEGIN \
3247     SCHEME_V->op = (int)(a); \
3248     return S_T; END
3249    
3250     #define s_return(a) return xs_return(SCHEME_A_ a)
3251    
3252     #ifndef USE_SCHEME_STACK
3253    
3254     /* this structure holds all the interpreter's registers */
3255     struct dump_stack_frame
3256     {
3257     enum scheme_opcodes op;
3258     pointer args;
3259     pointer envir;
3260     pointer code;
3261     };
3262    
3263     # define STACK_GROWTH 3
3264    
3265     static void
3266     s_save (SCHEME_P_ enum scheme_opcodes op, pointer args, pointer code)
3267     {
3268     int nframes = (uintptr_t)SCHEME_V->dump;
3269     struct dump_stack_frame *next_frame;
3270    
3271     /* enough room for the next frame? */
3272     if (nframes >= SCHEME_V->dump_size)
3273     {
3274     SCHEME_V->dump_size += STACK_GROWTH;
3275     SCHEME_V->dump_base = realloc (SCHEME_V->dump_base, sizeof (struct dump_stack_frame) * SCHEME_V->dump_size);
3276     }
3277    
3278     next_frame = SCHEME_V->dump_base + nframes;
3279     next_frame->op = op;
3280     next_frame->args = args;
3281     next_frame->envir = SCHEME_V->envir;
3282     next_frame->code = code;
3283     SCHEME_V->dump = (pointer)(uintptr_t)(nframes + 1);
3284     }
3285    
3286     static pointer
3287     xs_return (SCHEME_P_ pointer a)
3288     {
3289     int nframes = (uintptr_t)SCHEME_V->dump;
3290     struct dump_stack_frame *frame;
3291    
3292     SCHEME_V->value = a;
3293    
3294     if (nframes <= 0)
3295     return NIL;
3296    
3297     nframes--;
3298     frame = SCHEME_V->dump_base + nframes;
3299     SCHEME_V->op = frame->op;
3300     SCHEME_V->args = frame->args;
3301     SCHEME_V->envir = frame->envir;
3302     SCHEME_V->code = frame->code;
3303     SCHEME_V->dump = (pointer)(uintptr_t)nframes;
3304    
3305     return S_T;
3306     }
3307    
3308     static INLINE void
3309     dump_stack_reset (SCHEME_P)
3310     {
3311     /* in this implementation, SCHEME_V->dump is the number of frames on the stack */
3312     SCHEME_V->dump = (pointer)0;
3313     }
3314    
3315     static INLINE void
3316     dump_stack_initialize (SCHEME_P)
3317     {
3318     SCHEME_V->dump_size = 0;
3319     SCHEME_V->dump_base = NULL;
3320     dump_stack_reset (SCHEME_A);
3321     }
3322    
3323     static void
3324     dump_stack_free (SCHEME_P)
3325     {
3326     free (SCHEME_V->dump_base);
3327     SCHEME_V->dump_base = NULL;
3328     SCHEME_V->dump = (pointer)0;
3329     SCHEME_V->dump_size = 0;
3330     }
3331    
3332     static void
3333     dump_stack_mark (SCHEME_P)
3334     {
3335     int nframes = (uintptr_t)SCHEME_V->dump;
3336     int i;
3337    
3338     for (i = 0; i < nframes; i++)
3339     {
3340     struct dump_stack_frame *frame = SCHEME_V->dump_base + i;
3341    
3342     mark (frame->args);
3343     mark (frame->envir);
3344     mark (frame->code);
3345     }
3346     }
3347    
3348     static pointer
3349     ss_get_cont (SCHEME_P)
3350     {
3351     int nframes = (uintptr_t)SCHEME_V->dump;
3352     int i;
3353    
3354     pointer cont = NIL;
3355    
3356     for (i = nframes; i--; )
3357     {
3358     struct dump_stack_frame *frame = SCHEME_V->dump_base + i;
3359    
3360     cont = cons (mk_integer (SCHEME_A_ frame->op),
3361     cons (frame->args,
3362     cons (frame->envir,
3363     cons (frame->code,
3364     cont))));
3365     }
3366    
3367     return cont;
3368     }
3369    
3370     static void
3371     ss_set_cont (SCHEME_P_ pointer cont)
3372     {
3373     int i = 0;
3374     struct dump_stack_frame *frame = SCHEME_V->dump_base;
3375    
3376     while (cont != NIL)
3377     {
3378     frame->op = ivalue (car (cont)); cont = cdr (cont);
3379     frame->args = car (cont) ; cont = cdr (cont);
3380     frame->envir = car (cont) ; cont = cdr (cont);
3381     frame->code = car (cont) ; cont = cdr (cont);
3382    
3383     ++frame;
3384     ++i;
3385     }
3386    
3387     SCHEME_V->dump = (pointer)(uintptr_t)i;
3388     }
3389    
3390     #else
3391    
3392     static INLINE void
3393     dump_stack_reset (SCHEME_P)
3394     {
3395     SCHEME_V->dump = NIL;
3396     }
3397    
3398     static INLINE void
3399     dump_stack_initialize (SCHEME_P)
3400     {
3401     dump_stack_reset (SCHEME_A);
3402     }
3403    
3404     static void
3405     dump_stack_free (SCHEME_P)
3406     {
3407     SCHEME_V->dump = NIL;
3408     }
3409    
3410     static pointer
3411     xs_return (SCHEME_P_ pointer a)
3412     {
3413     pointer dump = SCHEME_V->dump;
3414    
3415     SCHEME_V->value = a;
3416    
3417     if (dump == NIL)
3418     return NIL;
3419    
3420     SCHEME_V->op = ivalue (car (dump));
3421     SCHEME_V->args = car (dump) ; dump = cdr (dump);
3422     SCHEME_V->envir = car (dump) ; dump = cdr (dump);
3423     SCHEME_V->code = car (dump) ; dump = cdr (dump);
3424    
3425     SCHEME_V->dump = dump;
3426    
3427     return S_T;
3428     }
3429    
3430     static void
3431     s_save (SCHEME_P_ enum scheme_opcodes op, pointer args, pointer code)
3432     {
3433     SCHEME_V->dump = cons (mk_integer (SCHEME_A_ op),
3434     cons (args,
3435     cons (SCHEME_V->envir,
3436     cons (code,
3437     SCHEME_V->dump))));
3438     }
3439    
3440     static void
3441     dump_stack_mark (SCHEME_P)
3442     {
3443     mark (SCHEME_V->dump);
3444     }
3445    
3446     static pointer
3447     ss_get_cont (SCHEME_P)
3448     {
3449     return SCHEME_V->dump;
3450     }
3451    
3452     static void
3453     ss_set_cont (SCHEME_P_ pointer cont)
3454     {
3455     SCHEME_V->dump = cont;
3456     }
3457    
3458     #endif
3459    
3460     #define s_retbool(tf) s_return ((tf) ? S_T : S_F)
3461    
3462     static pointer
3463     opexe_0 (SCHEME_P_ enum scheme_opcodes op)
3464     {
3465     pointer x, y;
3466    
3467     switch (op)
3468     {
3469     case OP_LOAD: /* load */
3470     if (file_interactive (SCHEME_A))
3471     {
3472     xwrstr ("Loading "); xwrstr (strvalue (car (SCHEME_V->args))); xwrstr ("\n");
3473     //D fprintf (SCHEME_V->outport->object.port->rep.stdio.file, "Loading %s\n", strvalue (car (SCHEME_V->args)));
3474     }
3475    
3476     if (!file_push (SCHEME_A_ strvalue (car (SCHEME_V->args))))
3477     Error_1 ("unable to open", car (SCHEME_V->args));
3478     else
3479     {
3480     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
3481     s_goto (OP_T0LVL);
3482     }
3483    
3484     case OP_T0LVL: /* top level */
3485    
3486     /* If we reached the end of file, this loop is done. */
3487     if (SCHEME_V->loadport->object.port->kind & port_saw_EOF)
3488     {
3489     if (SCHEME_V->file_i == 0)
3490     {
3491     SCHEME_V->args = NIL;
3492     s_goto (OP_QUIT);
3493     }
3494     else
3495     {
3496     file_pop (SCHEME_A);
3497     s_return (SCHEME_V->value);
3498     }
3499    
3500     /* NOTREACHED */
3501     }
3502    
3503     /* If interactive, be nice to user. */
3504     if (file_interactive (SCHEME_A))
3505     {
3506     SCHEME_V->envir = SCHEME_V->global_env;
3507     dump_stack_reset (SCHEME_A);
3508     putstr (SCHEME_A_ "\n");
3509     putstr (SCHEME_A_ prompt);
3510     }
3511    
3512     /* Set up another iteration of REPL */
3513     SCHEME_V->nesting = 0;
3514     SCHEME_V->save_inport = SCHEME_V->inport;
3515     SCHEME_V->inport = SCHEME_V->loadport;
3516     s_save (SCHEME_A_ OP_T0LVL, NIL, NIL);
3517     s_save (SCHEME_A_ OP_VALUEPRINT, NIL, NIL);
3518     s_save (SCHEME_A_ OP_T1LVL, NIL, NIL);
3519     s_goto (OP_READ_INTERNAL);
3520    
3521     case OP_T1LVL: /* top level */
3522     SCHEME_V->code = SCHEME_V->value;
3523     SCHEME_V->inport = SCHEME_V->save_inport;
3524     s_goto (OP_EVAL);
3525    
3526     case OP_READ_INTERNAL: /* internal read */
3527     SCHEME_V->tok = token (SCHEME_A);
3528    
3529     if (SCHEME_V->tok == TOK_EOF)
3530     {
3531     s_return (S_EOF);
3532     }
3533    
3534     s_goto (OP_RDSEXPR);
3535    
3536     case OP_GENSYM:
3537     s_return (gensym (SCHEME_A));
3538    
3539     case OP_VALUEPRINT: /* print evaluation result */
3540    
3541     /* OP_VALUEPRINT is always pushed, because when changing from
3542     non-interactive to interactive mode, it needs to be
3543     already on the stack */
3544     #if USE_TRACING
3545     if (SCHEME_V->tracing)
3546     {
3547     putstr (SCHEME_A_ "\nGives: ");
3548     }
3549     #endif
3550    
3551     if (file_interactive (SCHEME_A))
3552     {
3553     SCHEME_V->print_flag = 1;
3554     SCHEME_V->args = SCHEME_V->value;
3555     s_goto (OP_P0LIST);
3556     }
3557     else
3558     {
3559     s_return (SCHEME_V->value);
3560     }
3561    
3562     case OP_EVAL: /* main part of evaluation */
3563     #if USE_TRACING
3564     if (SCHEME_V->tracing)
3565     {
3566     /*s_save(SCHEME_A_ OP_VALUEPRINT,NIL,NIL); */
3567     s_save (SCHEME_A_ OP_REAL_EVAL, SCHEME_V->args, SCHEME_V->code);
3568     SCHEME_V->args = SCHEME_V->code;
3569     putstr (SCHEME_A_ "\nEval: ");
3570     s_goto (OP_P0LIST);
3571     }
3572    
3573     /* fall through */
3574     case OP_REAL_EVAL:
3575     #endif
3576     if (is_symbol (SCHEME_V->code)) /* symbol */
3577     {
3578     x = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->code, 1);
3579    
3580     if (x != NIL)
3581     s_return (slot_value_in_env (x));
3582     else
3583     Error_1 ("eval: unbound variable:", SCHEME_V->code);
3584     }
3585     else if (is_pair (SCHEME_V->code))
3586     {
3587     if (is_syntax (x = car (SCHEME_V->code))) /* SYNTAX */
3588     {
3589     SCHEME_V->code = cdr (SCHEME_V->code);
3590     s_goto (syntaxnum (x));
3591     }
3592     else /* first, eval top element and eval arguments */
3593     {
3594     s_save (SCHEME_A_ OP_E0ARGS, NIL, SCHEME_V->code);
3595     /* If no macros => s_save(SCHEME_A_ OP_E1ARGS, NIL, cdr(SCHEME_V->code)); */
3596     SCHEME_V->code = car (SCHEME_V->code);
3597     s_goto (OP_EVAL);
3598     }
3599     }
3600     else
3601     s_return (SCHEME_V->code);
3602    
3603     case OP_E0ARGS: /* eval arguments */
3604     if (is_macro (SCHEME_V->value)) /* macro expansion */
3605     {
3606     s_save (SCHEME_A_ OP_DOMACRO, NIL, NIL);
3607     SCHEME_V->args = cons (SCHEME_V->code, NIL);
3608     SCHEME_V->code = SCHEME_V->value;
3609     s_goto (OP_APPLY);
3610     }
3611     else
3612     {
3613     SCHEME_V->code = cdr (SCHEME_V->code);
3614     s_goto (OP_E1ARGS);
3615     }
3616    
3617     case OP_E1ARGS: /* eval arguments */
3618     SCHEME_V->args = cons (SCHEME_V->value, SCHEME_V->args);
3619    
3620     if (is_pair (SCHEME_V->code)) /* continue */
3621     {
3622     s_save (SCHEME_A_ OP_E1ARGS, SCHEME_V->args, cdr (SCHEME_V->code));
3623     SCHEME_V->code = car (SCHEME_V->code);
3624     SCHEME_V->args = NIL;
3625     s_goto (OP_EVAL);
3626     }
3627     else /* end */
3628     {
3629     SCHEME_V->args = reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args);
3630     SCHEME_V->code = car (SCHEME_V->args);
3631     SCHEME_V->args = cdr (SCHEME_V->args);
3632     s_goto (OP_APPLY);
3633     }
3634    
3635     #if USE_TRACING
3636    
3637     case OP_TRACING:
3638     {
3639     int tr = SCHEME_V->tracing;
3640    
3641     SCHEME_V->tracing = ivalue (car (SCHEME_V->args));
3642     s_return (mk_integer (SCHEME_A_ tr));
3643     }
3644    
3645     #endif
3646    
3647     case OP_APPLY: /* apply 'code' to 'args' */
3648     #if USE_TRACING
3649     if (SCHEME_V->tracing)
3650     {
3651     s_save (SCHEME_A_ OP_REAL_APPLY, SCHEME_V->args, SCHEME_V->code);
3652     SCHEME_V->print_flag = 1;
3653     /* SCHEME_V->args=cons(SCHEME_V->code,SCHEME_V->args); */
3654     putstr (SCHEME_A_ "\nApply to: ");
3655     s_goto (OP_P0LIST);
3656     }
3657    
3658     /* fall through */
3659     case OP_REAL_APPLY:
3660     #endif
3661     if (is_proc (SCHEME_V->code))
3662     {
3663     s_goto (procnum (SCHEME_V->code)); /* PROCEDURE */
3664     }
3665     else if (is_foreign (SCHEME_V->code))
3666     {
3667     /* Keep nested calls from GC'ing the arglist */
3668     push_recent_alloc (SCHEME_A_ SCHEME_V->args, NIL);
3669     x = SCHEME_V->code->object.ff (SCHEME_A_ SCHEME_V->args);
3670    
3671     s_return (x);
3672     }
3673     else if (is_closure (SCHEME_V->code) || is_macro (SCHEME_V->code) || is_promise (SCHEME_V->code)) /* CLOSURE */
3674     {
3675     /* Should not accept promise */
3676     /* make environment */
3677     new_frame_in_env (SCHEME_A_ closure_env (SCHEME_V->code));
3678    
3679     for (x = car (closure_code (SCHEME_V->code)), y = SCHEME_V->args; is_pair (x); x = cdr (x), y = cdr (y))
3680     {
3681     if (y == NIL)
3682     {
3683     Error_0 ("not enough arguments");
3684     }
3685     else
3686     {
3687     new_slot_in_env (SCHEME_A_ car (x), car (y));
3688     }
3689     }
3690    
3691     if (x == NIL)
3692     {
3693    
3694     /*--
3695     * if (y != NIL) {
3696     * Error_0("too many arguments");
3697     * }
3698     */
3699     }
3700     else if (is_symbol (x))
3701     new_slot_in_env (SCHEME_A_ x, y);
3702     else
3703     {
3704     Error_1 ("syntax error in closure: not a symbol:", x);
3705     }
3706    
3707     SCHEME_V->code = cdr (closure_code (SCHEME_V->code));
3708     SCHEME_V->args = NIL;
3709     s_goto (OP_BEGIN);
3710     }
3711     else if (is_continuation (SCHEME_V->code)) /* CONTINUATION */
3712     {
3713     ss_set_cont (SCHEME_A_ cont_dump (SCHEME_V->code));
3714     s_return (SCHEME_V->args != NIL ? car (SCHEME_V->args) : NIL);
3715     }
3716     else
3717     Error_0 ("illegal function");
3718    
3719     case OP_DOMACRO: /* do macro */
3720     SCHEME_V->code = SCHEME_V->value;
3721     s_goto (OP_EVAL);
3722    
3723     #if 1
3724    
3725     case OP_LAMBDA: /* lambda */
3726     /* If the hook is defined, apply it to SCHEME_V->code, otherwise
3727     set SCHEME_V->value fall thru */
3728     {
3729     pointer f = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->COMPILE_HOOK, 1);
3730    
3731     if (f != NIL)
3732     {
3733     s_save (SCHEME_A_ OP_LAMBDA1, SCHEME_V->args, SCHEME_V->code);
3734     SCHEME_V->args = cons (SCHEME_V->code, NIL);
3735     SCHEME_V->code = slot_value_in_env (f);
3736     s_goto (OP_APPLY);
3737     }
3738    
3739     SCHEME_V->value = SCHEME_V->code;
3740     /* Fallthru */
3741     }
3742    
3743     case OP_LAMBDA1:
3744     s_return (mk_closure (SCHEME_A_ SCHEME_V->value, SCHEME_V->envir));
3745    
3746     #else
3747    
3748     case OP_LAMBDA: /* lambda */
3749     s_return (mk_closure (SCHEME_A_ SCHEME_V->code, SCHEME_V->envir));
3750    
3751     #endif
3752    
3753     case OP_MKCLOSURE: /* make-closure */
3754     x = car (SCHEME_V->args);
3755    
3756     if (car (x) == SCHEME_V->LAMBDA)
3757     x = cdr (x);
3758    
3759     if (cdr (SCHEME_V->args) == NIL)
3760     y = SCHEME_V->envir;
3761     else
3762     y = cadr (SCHEME_V->args);
3763    
3764     s_return (mk_closure (SCHEME_A_ x, y));
3765    
3766     case OP_QUOTE: /* quote */
3767     s_return (car (SCHEME_V->code));
3768    
3769     case OP_DEF0: /* define */
3770     if (is_immutable (car (SCHEME_V->code)))
3771     Error_1 ("define: unable to alter immutable", car (SCHEME_V->code));
3772    
3773     if (is_pair (car (SCHEME_V->code)))
3774     {
3775     x = caar (SCHEME_V->code);
3776     SCHEME_V->code = cons (SCHEME_V->LAMBDA, cons (cdar (SCHEME_V->code), cdr (SCHEME_V->code)));
3777     }
3778     else
3779     {
3780     x = car (SCHEME_V->code);
3781     SCHEME_V->code = cadr (SCHEME_V->code);
3782     }
3783    
3784     if (!is_symbol (x))
3785     {
3786     Error_0 ("variable is not a symbol");
3787     }
3788    
3789     s_save (SCHEME_A_ OP_DEF1, NIL, x);
3790     s_goto (OP_EVAL);
3791    
3792     case OP_DEF1: /* define */
3793     x = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->code, 0);
3794    
3795     if (x != NIL)
3796     {
3797     set_slot_in_env (SCHEME_A_ x, SCHEME_V->value);
3798     }
3799     else
3800     {
3801     new_slot_in_env (SCHEME_A_ SCHEME_V->code, SCHEME_V->value);
3802     }
3803    
3804     s_return (SCHEME_V->code);
3805    
3806    
3807     case OP_DEFP: /* defined? */
3808     x = SCHEME_V->envir;
3809    
3810     if (cdr (SCHEME_V->args) != NIL)
3811     {
3812     x = cadr (SCHEME_V->args);
3813     }
3814    
3815     s_retbool (find_slot_in_env (SCHEME_A_ x, car (SCHEME_V->args), 1) != NIL);
3816    
3817     case OP_SET0: /* set! */
3818     if (is_immutable (car (SCHEME_V->code)))
3819     Error_1 ("set!: unable to alter immutable variable", car (SCHEME_V->code));
3820    
3821     s_save (SCHEME_A_ OP_SET1, NIL, car (SCHEME_V->code));
3822     SCHEME_V->code = cadr (SCHEME_V->code);
3823     s_goto (OP_EVAL);
3824    
3825     case OP_SET1: /* set! */
3826     y = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->code, 1);
3827    
3828     if (y != NIL)
3829     {
3830     set_slot_in_env (SCHEME_A_ y, SCHEME_V->value);
3831     s_return (SCHEME_V->value);
3832     }
3833     else
3834     {
3835     Error_1 ("set!: unbound variable:", SCHEME_V->code);
3836     }
3837    
3838    
3839     case OP_BEGIN: /* begin */
3840     if (!is_pair (SCHEME_V->code))
3841     {
3842     s_return (SCHEME_V->code);
3843     }
3844    
3845     if (cdr (SCHEME_V->code) != NIL)
3846     {
3847     s_save (SCHEME_A_ OP_BEGIN, NIL, cdr (SCHEME_V->code));
3848     }
3849    
3850     SCHEME_V->code = car (SCHEME_V->code);
3851     s_goto (OP_EVAL);
3852    
3853     case OP_IF0: /* if */
3854     s_save (SCHEME_A_ OP_IF1, NIL, cdr (SCHEME_V->code));
3855     SCHEME_V->code = car (SCHEME_V->code);
3856     s_goto (OP_EVAL);
3857    
3858     case OP_IF1: /* if */
3859     if (is_true (SCHEME_V->value))
3860     SCHEME_V->code = car (SCHEME_V->code);
3861     else
3862     SCHEME_V->code = cadr (SCHEME_V->code); /* (if #f 1) ==> () because
3863    
3864     * car(NIL) = NIL */
3865     s_goto (OP_EVAL);
3866    
3867     case OP_LET0: /* let */
3868     SCHEME_V->args = NIL;
3869     SCHEME_V->value = SCHEME_V->code;
3870     SCHEME_V->code = is_symbol (car (SCHEME_V->code)) ? cadr (SCHEME_V->code) : car (SCHEME_V->code);
3871     s_goto (OP_LET1);
3872    
3873     case OP_LET1: /* let (calculate parameters) */
3874     SCHEME_V->args = cons (SCHEME_V->value, SCHEME_V->args);
3875    
3876     if (is_pair (SCHEME_V->code)) /* continue */
3877     {
3878     if (!is_pair (car (SCHEME_V->code)) || !is_pair (cdar (SCHEME_V->code)))
3879     {
3880     Error_1 ("Bad syntax of binding spec in let :", car (SCHEME_V->code));
3881     }
3882    
3883     s_save (SCHEME_A_ OP_LET1, SCHEME_V->args, cdr (SCHEME_V->code));
3884     SCHEME_V->code = cadar (SCHEME_V->code);
3885     SCHEME_V->args = NIL;
3886     s_goto (OP_EVAL);
3887     }
3888     else /* end */
3889     {
3890     SCHEME_V->args = reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args);
3891     SCHEME_V->code = car (SCHEME_V->args);
3892     SCHEME_V->args = cdr (SCHEME_V->args);
3893     s_goto (OP_LET2);
3894     }
3895    
3896     case OP_LET2: /* let */
3897     new_frame_in_env (SCHEME_A_ SCHEME_V->envir);
3898    
3899     for (x = is_symbol (car (SCHEME_V->code)) ? cadr (SCHEME_V->code) : car (SCHEME_V->code), y = SCHEME_V->args;
3900     y != NIL; x = cdr (x), y = cdr (y))
3901     {
3902     new_slot_in_env (SCHEME_A_ caar (x), car (y));
3903     }
3904    
3905     if (is_symbol (car (SCHEME_V->code))) /* named let */
3906     {
3907     for (x = cadr (SCHEME_V->code), SCHEME_V->args = NIL; x != NIL; x = cdr (x))
3908     {
3909     if (!is_pair (x))
3910     Error_1 ("Bad syntax of binding in let :", x);
3911    
3912     if (!is_list (SCHEME_A_ car (x)))
3913     Error_1 ("Bad syntax of binding in let :", car (x));
3914    
3915     SCHEME_V->args = cons (caar (x), SCHEME_V->args);
3916     }
3917    
3918     x =
3919     mk_closure (SCHEME_A_ cons (reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args), cddr (SCHEME_V->code)),
3920     SCHEME_V->envir);
3921     new_slot_in_env (SCHEME_A_ car (SCHEME_V->code), x);
3922     SCHEME_V->code = cddr (SCHEME_V->code);
3923     SCHEME_V->args = NIL;
3924     }
3925     else
3926     {
3927     SCHEME_V->code = cdr (SCHEME_V->code);
3928     SCHEME_V->args = NIL;
3929     }
3930    
3931     s_goto (OP_BEGIN);
3932    
3933     case OP_LET0AST: /* let* */
3934     if (car (SCHEME_V->code) == NIL)
3935     {
3936     new_frame_in_env (SCHEME_A_ SCHEME_V->envir);
3937     SCHEME_V->code = cdr (SCHEME_V->code);
3938     s_goto (OP_BEGIN);
3939     }
3940    
3941     if (!is_pair (car (SCHEME_V->code)) || !is_pair (caar (SCHEME_V->code)) || !is_pair (cdaar (SCHEME_V->code)))
3942     Error_1 ("Bad syntax of binding spec in let* :", car (SCHEME_V->code));
3943    
3944     s_save (SCHEME_A_ OP_LET1AST, cdr (SCHEME_V->code), car (SCHEME_V->code));
3945     SCHEME_V->code = car (cdaar (SCHEME_V->code));
3946     s_goto (OP_EVAL);
3947    
3948     case OP_LET1AST: /* let* (make new frame) */
3949     new_frame_in_env (SCHEME_A_ SCHEME_V->envir);
3950     s_goto (OP_LET2AST);
3951    
3952     case OP_LET2AST: /* let* (calculate parameters) */
3953     new_slot_in_env (SCHEME_A_ caar (SCHEME_V->code), SCHEME_V->value);
3954     SCHEME_V->code = cdr (SCHEME_V->code);
3955    
3956     if (is_pair (SCHEME_V->code)) /* continue */
3957     {
3958     s_save (SCHEME_A_ OP_LET2AST, SCHEME_V->args, SCHEME_V->code);
3959     SCHEME_V->code = cadar (SCHEME_V->code);
3960     SCHEME_V->args = NIL;
3961     s_goto (OP_EVAL);
3962     }
3963     else /* end */
3964     {
3965     SCHEME_V->code = SCHEME_V->args;
3966     SCHEME_V->args = NIL;
3967     s_goto (OP_BEGIN);
3968     }
3969    
3970     case OP_LET0REC: /* letrec */
3971     new_frame_in_env (SCHEME_A_ SCHEME_V->envir);
3972     SCHEME_V->args = NIL;
3973     SCHEME_V->value = SCHEME_V->code;
3974     SCHEME_V->code = car (SCHEME_V->code);
3975     s_goto (OP_LET1REC);
3976    
3977     case OP_LET1REC: /* letrec (calculate parameters) */
3978     SCHEME_V->args = cons (SCHEME_V->value, SCHEME_V->args);
3979    
3980     if (is_pair (SCHEME_V->code)) /* continue */
3981     {
3982     if (!is_pair (car (SCHEME_V->code)) || !is_pair (cdar (SCHEME_V->code)))
3983     {
3984     Error_1 ("Bad syntax of binding spec in letrec :", car (SCHEME_V->code));
3985     }
3986    
3987     s_save (SCHEME_A_ OP_LET1REC, SCHEME_V->args, cdr (SCHEME_V->code));
3988     SCHEME_V->code = cadar (SCHEME_V->code);
3989     SCHEME_V->args = NIL;
3990     s_goto (OP_EVAL);
3991     }
3992     else /* end */
3993     {
3994     SCHEME_V->args = reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args);
3995     SCHEME_V->code = car (SCHEME_V->args);
3996     SCHEME_V->args = cdr (SCHEME_V->args);
3997     s_goto (OP_LET2REC);
3998     }
3999    
4000     case OP_LET2REC: /* letrec */
4001     for (x = car (SCHEME_V->code), y = SCHEME_V->args; y != NIL; x = cdr (x), y = cdr (y))
4002     {
4003     new_slot_in_env (SCHEME_A_ caar (x), car (y));
4004     }
4005    
4006     SCHEME_V->code = cdr (SCHEME_V->code);
4007     SCHEME_V->args = NIL;
4008     s_goto (OP_BEGIN);
4009    
4010     case OP_COND0: /* cond */
4011     if (!is_pair (SCHEME_V->code))
4012     {
4013     Error_0 ("syntax error in cond");
4014     }
4015    
4016     s_save (SCHEME_A_ OP_COND1, NIL, SCHEME_V->code);
4017     SCHEME_V->code = caar (SCHEME_V->code);
4018     s_goto (OP_EVAL);
4019    
4020     case OP_COND1: /* cond */
4021     if (is_true (SCHEME_V->value))
4022     {
4023     if ((SCHEME_V->code = cdar (SCHEME_V->code)) == NIL)
4024     {
4025     s_return (SCHEME_V->value);
4026     }
4027    
4028     if (car (SCHEME_V->code) == SCHEME_V->FEED_TO)
4029     {
4030     if (!is_pair (cdr (SCHEME_V->code)))
4031     {
4032     Error_0 ("syntax error in cond");
4033     }
4034    
4035     x = cons (SCHEME_V->QUOTE, cons (SCHEME_V->value, NIL));
4036     SCHEME_V->code = cons (cadr (SCHEME_V->code), cons (x, NIL));
4037     s_goto (OP_EVAL);
4038     }
4039    
4040     s_goto (OP_BEGIN);
4041     }
4042     else
4043     {
4044     if ((SCHEME_V->code = cdr (SCHEME_V->code)) == NIL)
4045     {
4046     s_return (NIL);
4047     }
4048     else
4049     {
4050     s_save (SCHEME_A_ OP_COND1, NIL, SCHEME_V->code);
4051     SCHEME_V->code = caar (SCHEME_V->code);
4052     s_goto (OP_EVAL);
4053     }
4054     }
4055    
4056     case OP_DELAY: /* delay */
4057     x = mk_closure (SCHEME_A_ cons (NIL, SCHEME_V->code), SCHEME_V->envir);
4058     set_typeflag (x, T_PROMISE);
4059     s_return (x);
4060    
4061     case OP_AND0: /* and */
4062     if (SCHEME_V->code == NIL)
4063     {
4064     s_return (S_T);
4065     }
4066    
4067     s_save (SCHEME_A_ OP_AND1, NIL, cdr (SCHEME_V->code));
4068     SCHEME_V->code = car (SCHEME_V->code);
4069     s_goto (OP_EVAL);
4070    
4071     case OP_AND1: /* and */
4072     if (is_false (SCHEME_V->value))
4073     {
4074     s_return (SCHEME_V->value);
4075     }
4076     else if (SCHEME_V->code == NIL)
4077     {
4078     s_return (SCHEME_V->value);
4079     }
4080     else
4081     {
4082     s_save (SCHEME_A_ OP_AND1, NIL, cdr (SCHEME_V->code));
4083     SCHEME_V->code = car (SCHEME_V->code);
4084     s_goto (OP_EVAL);
4085     }
4086    
4087     case OP_OR0: /* or */
4088     if (SCHEME_V->code == NIL)
4089     {
4090     s_return (S_F);
4091     }
4092    
4093     s_save (SCHEME_A_ OP_OR1, NIL, cdr (SCHEME_V->code));
4094     SCHEME_V->code = car (SCHEME_V->code);
4095     s_goto (OP_EVAL);
4096    
4097     case OP_OR1: /* or */
4098     if (is_true (SCHEME_V->value))
4099     {
4100     s_return (SCHEME_V->value);
4101     }
4102     else if (SCHEME_V->code == NIL)
4103     {
4104     s_return (SCHEME_V->value);
4105     }
4106     else
4107     {
4108     s_save (SCHEME_A_ OP_OR1, NIL, cdr (SCHEME_V->code));
4109     SCHEME_V->code = car (SCHEME_V->code);
4110     s_goto (OP_EVAL);
4111     }
4112    
4113     case OP_C0STREAM: /* cons-stream */
4114     s_save (SCHEME_A_ OP_C1STREAM, NIL, cdr (SCHEME_V->code));
4115     SCHEME_V->code = car (SCHEME_V->code);
4116     s_goto (OP_EVAL);
4117    
4118     case OP_C1STREAM: /* cons-stream */
4119     SCHEME_V->args = SCHEME_V->value; /* save SCHEME_V->value to register SCHEME_V->args for gc */
4120     x = mk_closure (SCHEME_A_ cons (NIL, SCHEME_V->code), SCHEME_V->envir);
4121     set_typeflag (x, T_PROMISE);
4122     s_return (cons (SCHEME_V->args, x));
4123    
4124     case OP_MACRO0: /* macro */
4125     if (is_pair (car (SCHEME_V->code)))
4126     {
4127     x = caar (SCHEME_V->code);
4128     SCHEME_V->code = cons (SCHEME_V->LAMBDA, cons (cdar (SCHEME_V->code), cdr (SCHEME_V->code)));
4129     }
4130     else
4131     {
4132     x = car (SCHEME_V->code);
4133     SCHEME_V->code = cadr (SCHEME_V->code);
4134     }
4135    
4136     if (!is_symbol (x))
4137     {
4138     Error_0 ("variable is not a symbol");
4139     }
4140    
4141     s_save (SCHEME_A_ OP_MACRO1, NIL, x);
4142     s_goto (OP_EVAL);
4143    
4144     case OP_MACRO1: /* macro */
4145     set_typeflag (SCHEME_V->value, T_MACRO);
4146     x = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->code, 0);
4147    
4148     if (x != NIL)
4149     {
4150     set_slot_in_env (SCHEME_A_ x, SCHEME_V->value);
4151     }
4152     else
4153     {
4154     new_slot_in_env (SCHEME_A_ SCHEME_V->code, SCHEME_V->value);
4155     }
4156    
4157     s_return (SCHEME_V->code);
4158    
4159     case OP_CASE0: /* case */
4160     s_save (SCHEME_A_ OP_CASE1, NIL, cdr (SCHEME_V->code));
4161     SCHEME_V->code = car (SCHEME_V->code);
4162     s_goto (OP_EVAL);
4163    
4164     case OP_CASE1: /* case */
4165     for (x = SCHEME_V->code; x != NIL; x = cdr (x))
4166     {
4167     if (!is_pair (y = caar (x)))
4168     {
4169     break;
4170     }
4171    
4172     for (; y != NIL; y = cdr (y))
4173     {
4174     if (eqv (car (y), SCHEME_V->value))
4175     {
4176     break;
4177     }
4178     }
4179    
4180     if (y != NIL)
4181     {
4182     break;
4183     }
4184     }
4185    
4186     if (x != NIL)
4187     {
4188     if (is_pair (caar (x)))
4189     {
4190     SCHEME_V->code = cdar (x);
4191     s_goto (OP_BEGIN);
4192     }
4193     else /* else */
4194     {
4195     s_save (SCHEME_A_ OP_CASE2, NIL, cdar (x));
4196     SCHEME_V->code = caar (x);
4197     s_goto (OP_EVAL);
4198     }
4199     }
4200     else
4201     {
4202     s_return (NIL);
4203     }
4204    
4205     case OP_CASE2: /* case */
4206     if (is_true (SCHEME_V->value))
4207     {
4208     s_goto (OP_BEGIN);
4209     }
4210     else
4211     {
4212     s_return (NIL);
4213     }
4214    
4215     case OP_PAPPLY: /* apply */
4216     SCHEME_V->code = car (SCHEME_V->args);
4217     SCHEME_V->args = list_star (SCHEME_A_ cdr (SCHEME_V->args));
4218     /*SCHEME_V->args = cadr(SCHEME_V->args); */
4219     s_goto (OP_APPLY);
4220    
4221     case OP_PEVAL: /* eval */
4222     if (cdr (SCHEME_V->args) != NIL)
4223     {
4224     SCHEME_V->envir = cadr (SCHEME_V->args);
4225     }
4226    
4227     SCHEME_V->code = car (SCHEME_V->args);
4228     s_goto (OP_EVAL);
4229    
4230     case OP_CONTINUATION: /* call-with-current-continuation */
4231     SCHEME_V->code = car (SCHEME_V->args);
4232     SCHEME_V->args = cons (mk_continuation (SCHEME_A_ ss_get_cont (SCHEME_V)), NIL);
4233     s_goto (OP_APPLY);
4234     }
4235    
4236     return S_T;
4237     }
4238    
4239     static pointer
4240     opexe_2 (SCHEME_P_ enum scheme_opcodes op)
4241     {
4242     pointer x;
4243     num v;
4244    
4245     #if USE_MATH
4246     RVALUE dd;
4247     #endif
4248    
4249     switch (op)
4250     {
4251     #if USE_MATH
4252    
4253     case OP_INEX2EX: /* inexact->exact */
4254     x = car (SCHEME_V->args);
4255    
4256     if (num_is_integer (x))
4257     {
4258     s_return (x);
4259     }
4260     else if (modf (rvalue_unchecked (x), &dd) == 0.0)
4261     {
4262     s_return (mk_integer (SCHEME_A_ ivalue (x)));
4263     }
4264     else
4265     {
4266     Error_1 ("inexact->exact: not integral:", x);
4267     }
4268    
4269     case OP_EXP:
4270     x = car (SCHEME_V->args);
4271     s_return (mk_real (SCHEME_A_ exp (rvalue (x))));
4272    
4273     case OP_LOG:
4274     x = car (SCHEME_V->args);
4275     s_return (mk_real (SCHEME_A_ log (rvalue (x))));
4276    
4277     case OP_SIN:
4278     x = car (SCHEME_V->args);
4279     s_return (mk_real (SCHEME_A_ sin (rvalue (x))));
4280    
4281     case OP_COS:
4282     x = car (SCHEME_V->args);
4283     s_return (mk_real (SCHEME_A_ cos (rvalue (x))));
4284    
4285     case OP_TAN:
4286     x = car (SCHEME_V->args);
4287     s_return (mk_real (SCHEME_A_ tan (rvalue (x))));
4288    
4289     case OP_ASIN:
4290     x = car (SCHEME_V->args);
4291     s_return (mk_real (SCHEME_A_ asin (rvalue (x))));
4292    
4293     case OP_ACOS:
4294     x = car (SCHEME_V->args);
4295     s_return (mk_real (SCHEME_A_ acos (rvalue (x))));
4296    
4297     case OP_ATAN:
4298     x = car (SCHEME_V->args);
4299    
4300     if (cdr (SCHEME_V->args) == NIL)
4301     {
4302     s_return (mk_real (SCHEME_A_ atan (rvalue (x))));
4303     }
4304     else
4305     {
4306     pointer y = cadr (SCHEME_V->args);
4307    
4308     s_return (mk_real (SCHEME_A_ atan2 (rvalue (x), rvalue (y))));
4309     }
4310    
4311     case OP_SQRT:
4312     x = car (SCHEME_V->args);
4313     s_return (mk_real (SCHEME_A_ sqrt (rvalue (x))));
4314    
4315     case OP_EXPT:
4316     {
4317     RVALUE result;
4318     int real_result = 1;
4319     pointer y = cadr (SCHEME_V->args);
4320    
4321     x = car (SCHEME_V->args);
4322    
4323     if (num_is_integer (x) && num_is_integer (y))
4324     real_result = 0;
4325    
4326     /* This 'if' is an R5RS compatibility fix. */
4327     /* NOTE: Remove this 'if' fix for R6RS. */
4328     if (rvalue (x) == 0 && rvalue (y) < 0)
4329     {
4330     result = 0.0;
4331     }
4332     else
4333     {
4334     result = pow (rvalue (x), rvalue (y));
4335     }
4336    
4337     /* Before returning integer result make sure we can. */
4338     /* If the test fails, result is too big for integer. */
4339     if (!real_result)
4340     {
4341     long result_as_long = (long) result;
4342    
4343     if (result != (RVALUE) result_as_long)
4344     real_result = 1;
4345     }
4346    
4347     if (real_result)
4348     {
4349     s_return (mk_real (SCHEME_A_ result));
4350     }
4351     else
4352     {
4353     s_return (mk_integer (SCHEME_A_ result));
4354     }
4355     }
4356    
4357     case OP_FLOOR:
4358     x = car (SCHEME_V->args);
4359     s_return (mk_real (SCHEME_A_ floor (rvalue (x))));
4360    
4361     case OP_CEILING:
4362     x = car (SCHEME_V->args);
4363     s_return (mk_real (SCHEME_A_ ceil (rvalue (x))));
4364    
4365     case OP_TRUNCATE:
4366     {
4367     RVALUE rvalue_of_x;
4368    
4369     x = car (SCHEME_V->args);
4370     rvalue_of_x = rvalue (x);
4371    
4372     if (rvalue_of_x > 0)
4373     {
4374     s_return (mk_real (SCHEME_A_ floor (rvalue_of_x)));
4375     }
4376     else
4377     {
4378     s_return (mk_real (SCHEME_A_ ceil (rvalue_of_x)));
4379     }
4380     }
4381    
4382     case OP_ROUND:
4383     x = car (SCHEME_V->args);
4384    
4385     if (num_is_integer (x))
4386     s_return (x);
4387    
4388     s_return (mk_real (SCHEME_A_ round_per_R5RS (rvalue (x))));
4389     #endif
4390    
4391     case OP_ADD: /* + */
4392     v = num_zero;
4393    
4394     for (x = SCHEME_V->args; x != NIL; x = cdr (x))
4395     v = num_add (v, nvalue (car (x)));
4396    
4397     s_return (mk_number (SCHEME_A_ v));
4398    
4399     case OP_MUL: /* * */
4400     v = num_one;
4401    
4402     for (x = SCHEME_V->args; x != NIL; x = cdr (x))
4403     v = num_mul (v, nvalue (car (x)));
4404    
4405     s_return (mk_number (SCHEME_A_ v));
4406    
4407     case OP_SUB: /* - */
4408     if (cdr (SCHEME_V->args) == NIL)
4409     {
4410     x = SCHEME_V->args;
4411     v = num_zero;
4412     }
4413     else
4414     {
4415     x = cdr (SCHEME_V->args);
4416     v = nvalue (car (SCHEME_V->args));
4417     }
4418    
4419     for (; x != NIL; x = cdr (x))
4420     v = num_sub (v, nvalue (car (x)));
4421    
4422     s_return (mk_number (SCHEME_A_ v));
4423    
4424     case OP_DIV: /* / */
4425     if (cdr (SCHEME_V->args) == NIL)
4426     {
4427     x = SCHEME_V->args;
4428     v = num_one;
4429     }
4430     else
4431     {
4432     x = cdr (SCHEME_V->args);
4433     v = nvalue (car (SCHEME_V->args));
4434     }
4435    
4436     for (; x != NIL; x = cdr (x))
4437     {
4438     if (!is_zero_rvalue (rvalue (car (x))))
4439     v = num_div (v, nvalue (car (x)));
4440     else
4441     Error_0 ("/: division by zero");
4442     }
4443    
4444     s_return (mk_number (SCHEME_A_ v));
4445    
4446     case OP_INTDIV: /* quotient */
4447     if (cdr (SCHEME_V->args) == NIL)
4448     {
4449     x = SCHEME_V->args;
4450     v = num_one;
4451     }
4452     else
4453     {
4454     x = cdr (SCHEME_V->args);
4455     v = nvalue (car (SCHEME_V->args));
4456     }
4457    
4458     for (; x != NIL; x = cdr (x))
4459     {
4460     if (ivalue (car (x)) != 0)
4461     v = num_intdiv (v, nvalue (car (x)));
4462     else
4463     Error_0 ("quotient: division by zero");
4464     }
4465    
4466     s_return (mk_number (SCHEME_A_ v));
4467    
4468     case OP_REM: /* remainder */
4469     v = nvalue (car (SCHEME_V->args));
4470    
4471     if (ivalue (cadr (SCHEME_V->args)) != 0)
4472     v = num_rem (v, nvalue (cadr (SCHEME_V->args)));
4473     else
4474     Error_0 ("remainder: division by zero");
4475    
4476     s_return (mk_number (SCHEME_A_ v));
4477    
4478     case OP_MOD: /* modulo */
4479     v = nvalue (car (SCHEME_V->args));
4480    
4481     if (ivalue (cadr (SCHEME_V->args)) != 0)
4482     v = num_mod (v, nvalue (cadr (SCHEME_V->args)));
4483     else
4484     Error_0 ("modulo: division by zero");
4485    
4486     s_return (mk_number (SCHEME_A_ v));
4487    
4488     case OP_CAR: /* car */
4489     s_return (caar (SCHEME_V->args));
4490    
4491     case OP_CDR: /* cdr */
4492     s_return (cdar (SCHEME_V->args));
4493    
4494     case OP_CONS: /* cons */
4495     set_cdr (SCHEME_V->args, cadr (SCHEME_V->args));
4496     s_return (SCHEME_V->args);
4497    
4498     case OP_SETCAR: /* set-car! */
4499     if (!is_immutable (car (SCHEME_V->args)))
4500     {
4501     set_car (car (SCHEME_V->args), cadr (SCHEME_V->args));
4502     s_return (car (SCHEME_V->args));
4503     }
4504     else
4505     Error_0 ("set-car!: unable to alter immutable pair");
4506    
4507     case OP_SETCDR: /* set-cdr! */
4508     if (!is_immutable (car (SCHEME_V->args)))
4509     {
4510     set_cdr (car (SCHEME_V->args), cadr (SCHEME_V->args));
4511     s_return (car (SCHEME_V->args));
4512     }
4513     else
4514     Error_0 ("set-cdr!: unable to alter immutable pair");
4515    
4516     case OP_CHAR2INT: /* char->integer */
4517     {
4518     char c;
4519    
4520     c = (char) ivalue (car (SCHEME_V->args));
4521     s_return (mk_integer (SCHEME_A_ (unsigned char) c));
4522     }
4523    
4524     case OP_INT2CHAR: /* integer->char */
4525     {
4526     unsigned char c;
4527    
4528     c = (unsigned char) ivalue (car (SCHEME_V->args));
4529     s_return (mk_character (SCHEME_A_ (char) c));
4530     }
4531    
4532     case OP_CHARUPCASE:
4533     {
4534     unsigned char c;
4535    
4536     c = (unsigned char) ivalue (car (SCHEME_V->args));
4537     c = toupper (c);
4538     s_return (mk_character (SCHEME_A_ (char) c));
4539     }
4540    
4541     case OP_CHARDNCASE:
4542     {
4543     unsigned char c;
4544    
4545     c = (unsigned char) ivalue (car (SCHEME_V->args));
4546     c = tolower (c);
4547     s_return (mk_character (SCHEME_A_ (char) c));
4548     }
4549    
4550     case OP_STR2SYM: /* string->symbol */
4551     s_return (mk_symbol (SCHEME_A_ strvalue (car (SCHEME_V->args))));
4552    
4553     case OP_STR2ATOM: /* string->atom */
4554     {
4555     char *s = strvalue (car (SCHEME_V->args));
4556     long pf = 0;
4557    
4558     if (cdr (SCHEME_V->args) != NIL)
4559     {
4560     /* we know cadr(SCHEME_V->args) is a natural number */
4561     /* see if it is 2, 8, 10, or 16, or error */
4562     pf = ivalue_unchecked (cadr (SCHEME_V->args));
4563    
4564     if (pf == 16 || pf == 10 || pf == 8 || pf == 2)
4565     {
4566     /* base is OK */
4567     }
4568     else
4569     {
4570     pf = -1;
4571     }
4572     }
4573    
4574     if (pf < 0)
4575     {
4576     Error_1 ("string->atom: bad base:", cadr (SCHEME_V->args));
4577     }
4578     else if (*s == '#') /* no use of base! */
4579     {
4580     s_return (mk_sharp_const (SCHEME_A_ s + 1));
4581     }
4582     else
4583     {
4584     if (pf == 0 || pf == 10)
4585     {
4586     s_return (mk_atom (SCHEME_A_ s));
4587     }
4588     else
4589     {
4590     char *ep;
4591     long iv = strtol (s, &ep, (int) pf);
4592    
4593     if (*ep == 0)
4594     {
4595     s_return (mk_integer (SCHEME_A_ iv));
4596     }
4597     else
4598     {
4599     s_return (S_F);
4600     }
4601     }
4602     }
4603     }
4604    
4605     case OP_SYM2STR: /* symbol->string */
4606     x = mk_string (SCHEME_A_ symname (car (SCHEME_V->args)));
4607     setimmutable (x);
4608     s_return (x);
4609    
4610     case OP_ATOM2STR: /* atom->string */
4611     {
4612     long pf = 0;
4613    
4614     x = car (SCHEME_V->args);
4615    
4616     if (cdr (SCHEME_V->args) != NIL)
4617     {
4618     /* we know cadr(SCHEME_V->args) is a natural number */
4619     /* see if it is 2, 8, 10, or 16, or error */
4620     pf = ivalue_unchecked (cadr (SCHEME_V->args));
4621    
4622     if (is_number (x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2))
4623     {
4624     /* base is OK */
4625     }
4626     else
4627     {
4628     pf = -1;
4629     }
4630     }
4631    
4632     if (pf < 0)
4633     {
4634     Error_1 ("atom->string: bad base:", cadr (SCHEME_V->args));
4635     }
4636     else if (is_number (x) || is_character (x) || is_string (x) || is_symbol (x))
4637     {
4638     char *p;
4639     int len;
4640    
4641     atom2str (SCHEME_A_ x, (int) pf, &p, &len);
4642     s_return (mk_counted_string (SCHEME_A_ p, len));
4643     }
4644     else
4645     {
4646     Error_1 ("atom->string: not an atom:", x);
4647     }
4648     }
4649    
4650     case OP_MKSTRING: /* make-string */
4651     {
4652     int fill = ' ';
4653     int len;
4654    
4655     len = ivalue (car (SCHEME_V->args));
4656    
4657     if (cdr (SCHEME_V->args) != NIL)
4658     {
4659     fill = charvalue (cadr (SCHEME_V->args));
4660     }
4661    
4662     s_return (mk_empty_string (SCHEME_A_ len, (char) fill));
4663     }
4664    
4665     case OP_STRLEN: /* string-length */
4666     s_return (mk_integer (SCHEME_A_ strlength (car (SCHEME_V->args))));
4667    
4668     case OP_STRREF: /* string-ref */
4669     {
4670     char *str;
4671     int index;
4672    
4673     str = strvalue (car (SCHEME_V->args));
4674    
4675     index = ivalue (cadr (SCHEME_V->args));
4676    
4677     if (index >= strlength (car (SCHEME_V->args)))
4678     {
4679     Error_1 ("string-ref: out of bounds:", cadr (SCHEME_V->args));
4680     }
4681    
4682     s_return (mk_character (SCHEME_A_ ((unsigned char *) str)[index]));
4683     }
4684    
4685     case OP_STRSET: /* string-set! */
4686     {
4687     char *str;
4688     int index;
4689     int c;
4690    
4691     if (is_immutable (car (SCHEME_V->args)))
4692     {
4693     Error_1 ("string-set!: unable to alter immutable string:", car (SCHEME_V->args));
4694     }
4695    
4696     str = strvalue (car (SCHEME_V->args));
4697    
4698     index = ivalue (cadr (SCHEME_V->args));
4699    
4700     if (index >= strlength (car (SCHEME_V->args)))
4701     {
4702     Error_1 ("string-set!: out of bounds:", cadr (SCHEME_V->args));
4703     }
4704    
4705     c = charvalue (caddr (SCHEME_V->args));
4706    
4707     str[index] = (char) c;
4708     s_return (car (SCHEME_V->args));
4709     }
4710    
4711     case OP_STRAPPEND: /* string-append */
4712     {
4713     /* in 1.29 string-append was in Scheme in init.scm but was too slow */
4714     int len = 0;
4715     pointer newstr;
4716     char *pos;
4717    
4718     /* compute needed length for new string */
4719     for (x = SCHEME_V->args; x != NIL; x = cdr (x))
4720     {
4721     len += strlength (car (x));
4722     }
4723    
4724     newstr = mk_empty_string (SCHEME_A_ len, ' ');
4725    
4726     /* store the contents of the argument strings into the new string */
4727     for (pos = strvalue (newstr), x = SCHEME_V->args; x != NIL; pos += strlength (car (x)), x = cdr (x))
4728     {
4729     memcpy (pos, strvalue (car (x)), strlength (car (x)));
4730     }
4731    
4732     s_return (newstr);
4733     }
4734    
4735     case OP_SUBSTR: /* substring */
4736     {
4737     char *str;
4738     int index0;
4739     int index1;
4740     int len;
4741    
4742     str = strvalue (car (SCHEME_V->args));
4743    
4744     index0 = ivalue (cadr (SCHEME_V->args));
4745    
4746     if (index0 > strlength (car (SCHEME_V->args)))
4747     {
4748     Error_1 ("substring: start out of bounds:", cadr (SCHEME_V->args));
4749     }
4750    
4751     if (cddr (SCHEME_V->args) != NIL)
4752     {
4753     index1 = ivalue (caddr (SCHEME_V->args));
4754    
4755     if (index1 > strlength (car (SCHEME_V->args)) || index1 < index0)
4756     {
4757     Error_1 ("substring: end out of bounds:", caddr (SCHEME_V->args));
4758     }
4759     }
4760     else
4761     {
4762     index1 = strlength (car (SCHEME_V->args));
4763     }
4764    
4765     len = index1 - index0;
4766     x = mk_empty_string (SCHEME_A_ len, ' ');
4767     memcpy (strvalue (x), str + index0, len);
4768     strvalue (x)[len] = 0;
4769    
4770     s_return (x);
4771     }
4772    
4773     case OP_VECTOR: /* vector */
4774     {
4775     int i;
4776     pointer vec;
4777     int len = list_length (SCHEME_A_ SCHEME_V->args);
4778    
4779     if (len < 0)
4780     {
4781     Error_1 ("vector: not a proper list:", SCHEME_V->args);
4782     }
4783    
4784     vec = mk_vector (SCHEME_A_ len);
4785    
4786     #if USE_ERROR_CHECKING
4787     if (SCHEME_V->no_memory)
4788     s_return (S_SINK);
4789     #endif
4790    
4791     for (x = SCHEME_V->args, i = 0; is_pair (x); x = cdr (x), i++)
4792     set_vector_elem (vec, i, car (x));
4793    
4794     s_return (vec);
4795     }
4796    
4797     case OP_MKVECTOR: /* make-vector */
4798     {
4799     pointer fill = NIL;
4800     int len;
4801     pointer vec;
4802    
4803     len = ivalue (car (SCHEME_V->args));
4804    
4805     if (cdr (SCHEME_V->args) != NIL)
4806     fill = cadr (SCHEME_V->args);
4807    
4808     vec = mk_vector (SCHEME_A_ len);
4809    
4810     #if USE_ERROR_CHECKING
4811     if (SCHEME_V->no_memory)
4812     s_return (S_SINK);
4813     #endif
4814    
4815     if (fill != NIL)
4816     fill_vector (vec, fill);
4817    
4818     s_return (vec);
4819     }
4820    
4821     case OP_VECLEN: /* vector-length */
4822     s_return (mk_integer (SCHEME_A_ ivalue (car (SCHEME_V->args))));
4823    
4824     case OP_VECREF: /* vector-ref */
4825     {
4826     int index;
4827    
4828     index = ivalue (cadr (SCHEME_V->args));
4829    
4830     if (index >= ivalue (car (SCHEME_V->args)))
4831     {
4832     Error_1 ("vector-ref: out of bounds:", cadr (SCHEME_V->args));
4833     }
4834    
4835     s_return (vector_elem (car (SCHEME_V->args), index));
4836     }
4837    
4838     case OP_VECSET: /* vector-set! */
4839     {
4840     int index;
4841    
4842     if (is_immutable (car (SCHEME_V->args)))
4843     {
4844     Error_1 ("vector-set!: unable to alter immutable vector:", car (SCHEME_V->args));
4845     }
4846    
4847     index = ivalue (cadr (SCHEME_V->args));
4848    
4849     if (index >= ivalue (car (SCHEME_V->args)))
4850     {
4851     Error_1 ("vector-set!: out of bounds:", cadr (SCHEME_V->args));
4852     }
4853    
4854     set_vector_elem (car (SCHEME_V->args), index, caddr (SCHEME_V->args));
4855     s_return (car (SCHEME_V->args));
4856     }
4857     }
4858    
4859     return S_T;
4860     }
4861    
4862     INTERFACE int
4863     is_list (SCHEME_P_ pointer a)
4864     {
4865     return list_length (SCHEME_A_ a) >= 0;
4866     }
4867    
4868     /* Result is:
4869     proper list: length
4870     circular list: -1
4871     not even a pair: -2
4872     dotted list: -2 minus length before dot
4873     */
4874     INTERFACE int
4875     list_length (SCHEME_P_ pointer a)
4876     {
4877     int i = 0;
4878     pointer slow, fast;
4879    
4880     slow = fast = a;
4881    
4882     while (1)
4883     {
4884     if (fast == NIL)
4885     return i;
4886    
4887     if (!is_pair (fast))
4888     return -2 - i;
4889    
4890     fast = cdr (fast);
4891     ++i;
4892    
4893     if (fast == NIL)
4894     return i;
4895    
4896     if (!is_pair (fast))
4897     return -2 - i;
4898    
4899     ++i;
4900     fast = cdr (fast);
4901    
4902     /* Safe because we would have already returned if `fast'
4903     encountered a non-pair. */
4904     slow = cdr (slow);
4905    
4906     if (fast == slow)
4907     {
4908     /* the fast pointer has looped back around and caught up
4909     with the slow pointer, hence the structure is circular,
4910     not of finite length, and therefore not a list */
4911     return -1;
4912     }
4913     }
4914     }
4915    
4916     static pointer
4917     opexe_3 (SCHEME_P_ enum scheme_opcodes op)
4918     {
4919     pointer x;
4920     num v;
4921     int (*comp_func) (num, num);
4922    
4923     switch (op)
4924     {
4925     case OP_NOT: /* not */
4926     s_retbool (is_false (car (SCHEME_V->args)));
4927    
4928     case OP_BOOLP: /* boolean? */
4929     s_retbool (car (SCHEME_V->args) == S_F || car (SCHEME_V->args) == S_T);
4930    
4931     case OP_EOFOBJP: /* boolean? */
4932     s_retbool (car (SCHEME_V->args) == S_EOF);
4933    
4934     case OP_NULLP: /* null? */
4935     s_retbool (car (SCHEME_V->args) == NIL);
4936    
4937     case OP_NUMEQ: /* = */
4938     case OP_LESS: /* < */
4939     case OP_GRE: /* > */
4940     case OP_LEQ: /* <= */
4941     case OP_GEQ: /* >= */
4942     switch (op)
4943     {
4944     case OP_NUMEQ:
4945     comp_func = num_eq;
4946     break;
4947    
4948     case OP_LESS:
4949     comp_func = num_lt;
4950     break;
4951    
4952     case OP_GRE:
4953     comp_func = num_gt;
4954     break;
4955    
4956     case OP_LEQ:
4957     comp_func = num_le;
4958     break;
4959    
4960     case OP_GEQ:
4961     comp_func = num_ge;
4962     break;
4963     }
4964    
4965     x = SCHEME_V->args;
4966     v = nvalue (car (x));
4967     x = cdr (x);
4968    
4969     for (; x != NIL; x = cdr (x))
4970     {
4971     if (!comp_func (v, nvalue (car (x))))
4972     {
4973     s_retbool (0);
4974     }
4975    
4976     v = nvalue (car (x));
4977     }
4978    
4979     s_retbool (1);
4980    
4981     case OP_SYMBOLP: /* symbol? */
4982     s_retbool (is_symbol (car (SCHEME_V->args)));
4983    
4984     case OP_NUMBERP: /* number? */
4985     s_retbool (is_number (car (SCHEME_V->args)));
4986    
4987     case OP_STRINGP: /* string? */
4988     s_retbool (is_string (car (SCHEME_V->args)));
4989    
4990     case OP_INTEGERP: /* integer? */
4991     s_retbool (is_integer (car (SCHEME_V->args)));
4992    
4993     case OP_REALP: /* real? */
4994     s_retbool (is_number (car (SCHEME_V->args))); /* All numbers are real */
4995    
4996     case OP_CHARP: /* char? */
4997     s_retbool (is_character (car (SCHEME_V->args)));
4998     #if USE_CHAR_CLASSIFIERS
4999    
5000     case OP_CHARAP: /* char-alphabetic? */
5001     s_retbool (Cisalpha (ivalue (car (SCHEME_V->args))));
5002    
5003     case OP_CHARNP: /* char-numeric? */
5004     s_retbool (Cisdigit (ivalue (car (SCHEME_V->args))));
5005    
5006     case OP_CHARWP: /* char-whitespace? */
5007     s_retbool (Cisspace (ivalue (car (SCHEME_V->args))));
5008    
5009     case OP_CHARUP: /* char-upper-case? */
5010     s_retbool (Cisupper (ivalue (car (SCHEME_V->args))));
5011    
5012     case OP_CHARLP: /* char-lower-case? */
5013     s_retbool (Cislower (ivalue (car (SCHEME_V->args))));
5014     #endif
5015     #if USE_PORTS
5016    
5017     case OP_PORTP: /* port? */
5018     s_retbool (is_port (car (SCHEME_V->args)));
5019    
5020     case OP_INPORTP: /* input-port? */
5021     s_retbool (is_inport (car (SCHEME_V->args)));
5022    
5023     case OP_OUTPORTP: /* output-port? */
5024     s_retbool (is_outport (car (SCHEME_V->args)));
5025     #endif
5026    
5027     case OP_PROCP: /* procedure? */
5028    
5029     /*--
5030     * continuation should be procedure by the example
5031     * (call-with-current-continuation procedure?) ==> #t
5032     * in R^3 report sec. 6.9
5033     */
5034     s_retbool (is_proc (car (SCHEME_V->args)) || is_closure (car (SCHEME_V->args))
5035     || is_continuation (car (SCHEME_V->args)) || is_foreign (car (SCHEME_V->args)));
5036    
5037     case OP_PAIRP: /* pair? */
5038     s_retbool (is_pair (car (SCHEME_V->args)));
5039    
5040     case OP_LISTP: /* list? */
5041     s_retbool (list_length (SCHEME_A_ car (SCHEME_V->args)) >= 0);
5042    
5043     case OP_ENVP: /* environment? */
5044     s_retbool (is_environment (car (SCHEME_V->args)));
5045    
5046     case OP_VECTORP: /* vector? */
5047     s_retbool (is_vector (car (SCHEME_V->args)));
5048    
5049     case OP_EQ: /* eq? */
5050     s_retbool (car (SCHEME_V->args) == cadr (SCHEME_V->args));
5051    
5052     case OP_EQV: /* eqv? */
5053     s_retbool (eqv (car (SCHEME_V->args), cadr (SCHEME_V->args)));
5054     }
5055    
5056     return S_T;
5057     }
5058    
5059     static pointer
5060     opexe_4 (SCHEME_P_ enum scheme_opcodes op)
5061     {
5062     pointer x, y;
5063    
5064     switch (op)
5065     {
5066     case OP_FORCE: /* force */
5067     SCHEME_V->code = car (SCHEME_V->args);
5068    
5069     if (is_promise (SCHEME_V->code))
5070     {
5071     /* Should change type to closure here */
5072     s_save (SCHEME_A_ OP_SAVE_FORCED, NIL, SCHEME_V->code);
5073     SCHEME_V->args = NIL;
5074     s_goto (OP_APPLY);
5075     }
5076     else
5077     {
5078     s_return (SCHEME_V->code);
5079     }
5080    
5081     case OP_SAVE_FORCED: /* Save forced value replacing promise */
5082     memcpy (SCHEME_V->code, SCHEME_V->value, sizeof (struct cell));
5083     s_return (SCHEME_V->value);
5084    
5085     #if USE_PORTS
5086    
5087     case OP_WRITE: /* write */
5088     case OP_DISPLAY: /* display */
5089     case OP_WRITE_CHAR: /* write-char */
5090     if (is_pair (cdr (SCHEME_V->args)))
5091     {
5092     if (cadr (SCHEME_V->args) != SCHEME_V->outport)
5093     {
5094     x = cons (SCHEME_V->outport, NIL);
5095     s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
5096     SCHEME_V->outport = cadr (SCHEME_V->args);
5097     }
5098     }
5099    
5100     SCHEME_V->args = car (SCHEME_V->args);
5101    
5102     if (op == OP_WRITE)
5103     SCHEME_V->print_flag = 1;
5104     else
5105     SCHEME_V->print_flag = 0;
5106    
5107     s_goto (OP_P0LIST);
5108    
5109     case OP_NEWLINE: /* newline */
5110     if (is_pair (SCHEME_V->args))
5111     {
5112     if (car (SCHEME_V->args) != SCHEME_V->outport)
5113     {
5114     x = cons (SCHEME_V->outport, NIL);
5115     s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
5116     SCHEME_V->outport = car (SCHEME_V->args);
5117     }
5118     }
5119    
5120     putstr (SCHEME_A_ "\n");
5121     s_return (S_T);
5122     #endif
5123    
5124     case OP_ERR0: /* error */
5125     SCHEME_V->retcode = -1;
5126    
5127     if (!is_string (car (SCHEME_V->args)))
5128     {
5129     SCHEME_V->args = cons (mk_string (SCHEME_A_ " -- "), SCHEME_V->args);
5130     setimmutable (car (SCHEME_V->args));
5131     }
5132    
5133     putstr (SCHEME_A_ "Error: ");
5134     putstr (SCHEME_A_ strvalue (car (SCHEME_V->args)));
5135     SCHEME_V->args = cdr (SCHEME_V->args);
5136     s_goto (OP_ERR1);
5137    
5138     case OP_ERR1: /* error */
5139     putstr (SCHEME_A_ " ");
5140    
5141     if (SCHEME_V->args != NIL)
5142     {
5143     s_save (SCHEME_A_ OP_ERR1, cdr (SCHEME_V->args), NIL);
5144     SCHEME_V->args = car (SCHEME_V->args);
5145     SCHEME_V->print_flag = 1;
5146     s_goto (OP_P0LIST);
5147     }
5148     else
5149     {
5150     putstr (SCHEME_A_ "\n");
5151    
5152     if (SCHEME_V->interactive_repl)
5153     {
5154     s_goto (OP_T0LVL);
5155     }
5156     else
5157     {
5158     return NIL;
5159     }
5160     }
5161    
5162     case OP_REVERSE: /* reverse */
5163     s_return (reverse (SCHEME_A_ car (SCHEME_V->args)));
5164    
5165     case OP_LIST_STAR: /* list* */
5166     s_return (list_star (SCHEME_A_ SCHEME_V->args));
5167    
5168     case OP_APPEND: /* append */
5169     x = NIL;
5170     y = SCHEME_V->args;
5171    
5172     if (y == x)
5173     s_return (x);
5174    
5175     /* cdr() in the while condition is not a typo. If car() */
5176     /* is used (append '() 'a) will return the wrong result. */
5177     while (cdr (y) != NIL)
5178     {
5179     x = revappend (SCHEME_A_ x, car (y));
5180     y = cdr (y);
5181    
5182     if (x == S_F)
5183     Error_0 ("non-list argument to append");
5184     }
5185    
5186     s_return (reverse_in_place (SCHEME_A_ car (y), x));
5187    
5188     #if USE_PLIST
5189    
5190     case OP_PUT: /* put */
5191     if (!hasprop (car (SCHEME_V->args)) || !hasprop (cadr (SCHEME_V->args)))
5192     {
5193     Error_0 ("illegal use of put");
5194     }
5195    
5196     for (x = symprop (car (SCHEME_V->args)), y = cadr (SCHEME_V->args); x != NIL; x = cdr (x))
5197     {
5198     if (caar (x) == y)
5199     {
5200     break;
5201     }
5202     }
5203    
5204     if (x != NIL)
5205     cdar (x) = caddr (SCHEME_V->args);
5206     else
5207     symprop (car (SCHEME_V->args)) = cons (cons (y, caddr (SCHEME_V->args)), symprop (car (SCHEME_V->args)));
5208    
5209     s_return (S_T);
5210    
5211     case OP_GET: /* get */
5212     if (!hasprop (car (SCHEME_V->args)) || !hasprop (cadr (SCHEME_V->args)))
5213     Error_0 ("illegal use of get");
5214    
5215     for (x = symprop (car (SCHEME_V->args)), y = cadr (SCHEME_V->args); x != NIL; x = cdr (x))
5216     if (caar (x) == y)
5217     break;
5218    
5219     if (x != NIL)
5220     s_return (cdar (x));
5221     else
5222     s_return (NIL);
5223    
5224     #endif /* USE_PLIST */
5225    
5226     case OP_QUIT: /* quit */
5227     if (is_pair (SCHEME_V->args))
5228     SCHEME_V->retcode = ivalue (car (SCHEME_V->args));
5229    
5230     return NIL;
5231    
5232     case OP_GC: /* gc */
5233     gc (SCHEME_A_ NIL, NIL);
5234     s_return (S_T);
5235    
5236     case OP_GCVERB: /* gc-verbose */
5237     {
5238     int was = SCHEME_V->gc_verbose;
5239    
5240     SCHEME_V->gc_verbose = (car (SCHEME_V->args) != S_F);
5241     s_retbool (was);
5242     }
5243    
5244     case OP_NEWSEGMENT: /* new-segment */
5245     if (!is_pair (SCHEME_V->args) || !is_number (car (SCHEME_V->args)))
5246     Error_0 ("new-segment: argument must be a number");
5247    
5248     alloc_cellseg (SCHEME_A_ (int)ivalue (car (SCHEME_V->args)));
5249    
5250     s_return (S_T);
5251    
5252     case OP_OBLIST: /* oblist */
5253     s_return (oblist_all_symbols (SCHEME_A));
5254    
5255     #if USE_PORTS
5256    
5257     case OP_CURR_INPORT: /* current-input-port */
5258     s_return (SCHEME_V->inport);
5259    
5260     case OP_CURR_OUTPORT: /* current-output-port */
5261     s_return (SCHEME_V->outport);
5262    
5263     case OP_OPEN_INFILE: /* open-input-file */
5264     case OP_OPEN_OUTFILE: /* open-output-file */
5265     case OP_OPEN_INOUTFILE: /* open-input-output-file */
5266     {
5267     int prop = 0;
5268     pointer p;
5269    
5270     switch (op)
5271     {
5272     case OP_OPEN_INFILE:
5273     prop = port_input;
5274     break;
5275    
5276     case OP_OPEN_OUTFILE:
5277     prop = port_output;
5278     break;
5279    
5280     case OP_OPEN_INOUTFILE:
5281     prop = port_input | port_output;
5282     break;
5283     }
5284    
5285     p = port_from_filename (SCHEME_A_ strvalue (car (SCHEME_V->args)), prop);
5286    
5287     if (p == NIL)
5288     {
5289     s_return (S_F);
5290     }
5291    
5292     s_return (p);
5293     }
5294    
5295     # if USE_STRING_PORTS
5296    
5297     case OP_OPEN_INSTRING: /* open-input-string */
5298     case OP_OPEN_INOUTSTRING: /* open-input-output-string */
5299     {
5300     int prop = 0;
5301     pointer p;
5302    
5303     switch (op)
5304     {
5305     case OP_OPEN_INSTRING:
5306     prop = port_input;
5307     break;
5308    
5309     case OP_OPEN_INOUTSTRING:
5310     prop = port_input | port_output;
5311     break;
5312     }
5313    
5314     p = port_from_string (SCHEME_A_ strvalue (car (SCHEME_V->args)),
5315     strvalue (car (SCHEME_V->args)) + strlength (car (SCHEME_V->args)), prop);
5316    
5317     if (p == NIL)
5318     {
5319     s_return (S_F);
5320     }
5321    
5322     s_return (p);
5323     }
5324    
5325     case OP_OPEN_OUTSTRING: /* open-output-string */
5326     {
5327     pointer p;
5328    
5329     if (car (SCHEME_V->args) == NIL)
5330     {
5331     p = port_from_scratch (SCHEME_A);
5332    
5333     if (p == NIL)
5334     {
5335     s_return (S_F);
5336     }
5337     }
5338     else
5339     {
5340     p = port_from_string (SCHEME_A_ strvalue (car (SCHEME_V->args)),
5341     strvalue (car (SCHEME_V->args)) + strlength (car (SCHEME_V->args)), port_output);
5342    
5343     if (p == NIL)
5344     {
5345     s_return (S_F);
5346     }
5347     }
5348    
5349     s_return (p);
5350     }
5351    
5352     case OP_GET_OUTSTRING: /* get-output-string */
5353     {
5354     port *p;
5355    
5356     if ((p = car (SCHEME_V->args)->object.port)->kind & port_string)
5357     {
5358     off_t size;
5359     char *str;
5360    
5361     size = p->rep.string.curr - p->rep.string.start + 1;
5362     str = malloc (size);
5363    
5364     if (str != NULL)
5365     {
5366     pointer s;
5367    
5368     memcpy (str, p->rep.string.start, size - 1);
5369     str[size - 1] = '\0';
5370     s = mk_string (SCHEME_A_ str);
5371     free (str);
5372     s_return (s);
5373     }
5374     }
5375    
5376     s_return (S_F);
5377     }
5378    
5379     # endif
5380    
5381     case OP_CLOSE_INPORT: /* close-input-port */
5382     port_close (SCHEME_A_ car (SCHEME_V->args), port_input);
5383     s_return (S_T);
5384    
5385     case OP_CLOSE_OUTPORT: /* close-output-port */
5386     port_close (SCHEME_A_ car (SCHEME_V->args), port_output);
5387     s_return (S_T);
5388     #endif
5389    
5390     case OP_INT_ENV: /* interaction-environment */
5391     s_return (SCHEME_V->global_env);
5392    
5393     case OP_CURR_ENV: /* current-environment */
5394     s_return (SCHEME_V->envir);
5395    
5396     }
5397    
5398     return S_T;
5399     }
5400    
5401     static pointer
5402     opexe_5 (SCHEME_P_ enum scheme_opcodes op)
5403     {
5404     pointer x;
5405    
5406     if (SCHEME_V->nesting != 0)
5407     {
5408     int n = SCHEME_V->nesting;
5409    
5410     SCHEME_V->nesting = 0;
5411     SCHEME_V->retcode = -1;
5412     Error_1 ("unmatched parentheses:", mk_integer (SCHEME_A_ n));
5413     }
5414    
5415     switch (op)
5416     {
5417     /* ========== reading part ========== */
5418     #if USE_PORTS
5419     case OP_READ:
5420     if (!is_pair (SCHEME_V->args))
5421     {
5422     s_goto (OP_READ_INTERNAL);
5423     }
5424    
5425     if (!is_inport (car (SCHEME_V->args)))
5426     {
5427     Error_1 ("read: not an input port:", car (SCHEME_V->args));
5428     }
5429    
5430     if (car (SCHEME_V->args) == SCHEME_V->inport)
5431     {
5432     s_goto (OP_READ_INTERNAL);
5433     }
5434    
5435     x = SCHEME_V->inport;
5436     SCHEME_V->inport = car (SCHEME_V->args);
5437     x = cons (x, NIL);
5438     s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
5439     s_goto (OP_READ_INTERNAL);
5440    
5441     case OP_READ_CHAR: /* read-char */
5442     case OP_PEEK_CHAR: /* peek-char */
5443     {
5444     int c;
5445    
5446     if (is_pair (SCHEME_V->args))
5447     {
5448     if (car (SCHEME_V->args) != SCHEME_V->inport)
5449     {
5450     x = SCHEME_V->inport;
5451     x = cons (x, NIL);
5452     s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
5453     SCHEME_V->inport = car (SCHEME_V->args);
5454     }
5455     }
5456    
5457     c = inchar (SCHEME_A);
5458    
5459     if (c == EOF)
5460     s_return (S_EOF);
5461    
5462     if (SCHEME_V->op == OP_PEEK_CHAR)
5463     backchar (SCHEME_A_ c);
5464    
5465     s_return (mk_character (SCHEME_A_ c));
5466     }
5467    
5468     case OP_CHAR_READY: /* char-ready? */
5469     {
5470     pointer p = SCHEME_V->inport;
5471     int res;
5472    
5473     if (is_pair (SCHEME_V->args))
5474     {
5475     p = car (SCHEME_V->args);
5476     }
5477    
5478     res = p->object.port->kind & port_string;
5479    
5480     s_retbool (res);
5481     }
5482    
5483     case OP_SET_INPORT: /* set-input-port */
5484     SCHEME_V->inport = car (SCHEME_V->args);
5485     s_return (SCHEME_V->value);
5486    
5487     case OP_SET_OUTPORT: /* set-output-port */
5488     SCHEME_V->outport = car (SCHEME_V->args);
5489     s_return (SCHEME_V->value);
5490     #endif
5491    
5492     case OP_RDSEXPR:
5493     switch (SCHEME_V->tok)
5494     {
5495     case TOK_EOF:
5496     s_return (S_EOF);
5497     /* NOTREACHED */
5498    
5499     case TOK_VEC:
5500     s_save (SCHEME_A_ OP_RDVEC, NIL, NIL);
5501    
5502     /* fall through */
5503     case TOK_LPAREN:
5504     SCHEME_V->tok = token (SCHEME_A);
5505    
5506     if (SCHEME_V->tok == TOK_RPAREN)
5507     s_return (NIL);
5508     else if (SCHEME_V->tok == TOK_DOT)
5509     Error_0 ("syntax error: illegal dot expression");
5510     else
5511     {
5512     SCHEME_V->nesting_stack[SCHEME_V->file_i]++;
5513     s_save (SCHEME_A_ OP_RDLIST, NIL, NIL);
5514     s_goto (OP_RDSEXPR);
5515     }
5516    
5517     case TOK_QUOTE:
5518     s_save (SCHEME_A_ OP_RDQUOTE, NIL, NIL);
5519     SCHEME_V->tok = token (SCHEME_A);
5520     s_goto (OP_RDSEXPR);
5521    
5522     case TOK_BQUOTE:
5523     SCHEME_V->tok = token (SCHEME_A);
5524    
5525     if (SCHEME_V->tok == TOK_VEC)
5526     {
5527     s_save (SCHEME_A_ OP_RDQQUOTEVEC, NIL, NIL);
5528     SCHEME_V->tok = TOK_LPAREN;
5529     s_goto (OP_RDSEXPR);
5530     }
5531     else
5532     {
5533     s_save (SCHEME_A_ OP_RDQQUOTE, NIL, NIL);
5534     }
5535    
5536     s_goto (OP_RDSEXPR);
5537    
5538     case TOK_COMMA:
5539     s_save (SCHEME_A_ OP_RDUNQUOTE, NIL, NIL);
5540     SCHEME_V->tok = token (SCHEME_A);
5541     s_goto (OP_RDSEXPR);
5542    
5543     case TOK_ATMARK:
5544     s_save (SCHEME_A_ OP_RDUQTSP, NIL, NIL);
5545     SCHEME_V->tok = token (SCHEME_A);
5546     s_goto (OP_RDSEXPR);
5547    
5548     case TOK_ATOM:
5549     s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ DELIMITERS)));
5550    
5551     case TOK_DQUOTE:
5552     x = readstrexp (SCHEME_A);
5553    
5554     if (x == S_F)
5555     Error_0 ("Error reading string");
5556    
5557     setimmutable (x);
5558     s_return (x);
5559    
5560     case TOK_SHARP:
5561     {
5562     pointer f = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->SHARP_HOOK, 1);
5563    
5564     if (f == NIL)
5565     Error_0 ("undefined sharp expression");
5566     else
5567     {
5568     SCHEME_V->code = cons (slot_value_in_env (f), NIL);
5569     s_goto (OP_EVAL);
5570     }
5571     }
5572    
5573     case TOK_SHARP_CONST:
5574     if ((x = mk_sharp_const (SCHEME_A_ readstr_upto (SCHEME_A_ DELIMITERS))) == NIL)
5575     Error_0 ("undefined sharp expression");
5576     else
5577     s_return (x);
5578    
5579     default:
5580     Error_0 ("syntax error: illegal token");
5581     }
5582    
5583     break;
5584    
5585     case OP_RDLIST:
5586     {
5587     SCHEME_V->args = cons (SCHEME_V->value, SCHEME_V->args);
5588     SCHEME_V->tok = token (SCHEME_A);
5589    
5590     if (SCHEME_V->tok == TOK_EOF)
5591     s_return (S_EOF);
5592     else if (SCHEME_V->tok == TOK_RPAREN)
5593     {
5594     int c = inchar (SCHEME_A);
5595    
5596     if (c != '\n')
5597     backchar (SCHEME_A_ c);
5598    
5599     #if SHOW_ERROR_LINE
5600     else if (SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
5601     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line++;
5602    
5603     #endif
5604     SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5605     s_return (reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args));
5606     }
5607     else if (SCHEME_V->tok == TOK_DOT)
5608     {
5609     s_save (SCHEME_A_ OP_RDDOT, SCHEME_V->args, NIL);
5610     SCHEME_V->tok = token (SCHEME_A);
5611     s_goto (OP_RDSEXPR);
5612     }
5613     else
5614     {
5615     s_save (SCHEME_A_ OP_RDLIST, SCHEME_V->args, NIL);;
5616     s_goto (OP_RDSEXPR);
5617     }
5618     }
5619    
5620     case OP_RDDOT:
5621     if (token (SCHEME_A) != TOK_RPAREN)
5622     Error_0 ("syntax error: illegal dot expression");
5623     else
5624     {
5625     SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5626     s_return (reverse_in_place (SCHEME_A_ SCHEME_V->value, SCHEME_V->args));
5627     }
5628    
5629     case OP_RDQUOTE:
5630     s_return (cons (SCHEME_V->QUOTE, cons (SCHEME_V->value, NIL)));
5631    
5632     case OP_RDQQUOTE:
5633     s_return (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)));
5634    
5635     case OP_RDQQUOTEVEC:
5636     s_return (cons (mk_symbol (SCHEME_A_ "apply"),
5637     cons (mk_symbol (SCHEME_A_ "vector"),
5638     cons (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)), NIL))));
5639    
5640     case OP_RDUNQUOTE:
5641     s_return (cons (SCHEME_V->UNQUOTE, cons (SCHEME_V->value, NIL)));
5642    
5643     case OP_RDUQTSP:
5644     s_return (cons (SCHEME_V->UNQUOTESP, cons (SCHEME_V->value, NIL)));
5645    
5646     case OP_RDVEC:
5647     /*SCHEME_V->code=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5648     s_goto(OP_EVAL); Cannot be quoted */
5649     /*x=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5650     s_return(x); Cannot be part of pairs */
5651     /*SCHEME_V->code=mk_proc(SCHEME_A_ OP_VECTOR);
5652     SCHEME_V->args=SCHEME_V->value;
5653     s_goto(OP_APPLY); */
5654     SCHEME_V->args = SCHEME_V->value;
5655     s_goto (OP_VECTOR);
5656    
5657     /* ========== printing part ========== */
5658     case OP_P0LIST:
5659     if (is_vector (SCHEME_V->args))
5660     {
5661     putstr (SCHEME_A_ "#(");
5662     SCHEME_V->args = cons (SCHEME_V->args, mk_integer (SCHEME_A_ 0));
5663     s_goto (OP_PVECFROM);
5664     }
5665     else if (is_environment (SCHEME_V->args))
5666     {
5667     putstr (SCHEME_A_ "#<ENVIRONMENT>");
5668     s_return (S_T);
5669     }
5670     else if (!is_pair (SCHEME_V->args))
5671     {
5672     printatom (SCHEME_A_ SCHEME_V->args, SCHEME_V->print_flag);
5673     s_return (S_T);
5674     }
5675     else if (car (SCHEME_V->args) == SCHEME_V->QUOTE && ok_abbrev (cdr (SCHEME_V->args)))
5676     {
5677     putstr (SCHEME_A_ "'");
5678     SCHEME_V->args = cadr (SCHEME_V->args);
5679     s_goto (OP_P0LIST);
5680     }
5681     else if (car (SCHEME_V->args) == SCHEME_V->QQUOTE && ok_abbrev (cdr (SCHEME_V->args)))
5682     {
5683     putstr (SCHEME_A_ "`");
5684     SCHEME_V->args = cadr (SCHEME_V->args);
5685     s_goto (OP_P0LIST);
5686     }
5687     else if (car (SCHEME_V->args) == SCHEME_V->UNQUOTE && ok_abbrev (cdr (SCHEME_V->args)))
5688     {
5689     putstr (SCHEME_A_ ",");
5690     SCHEME_V->args = cadr (SCHEME_V->args);
5691     s_goto (OP_P0LIST);
5692     }
5693     else if (car (SCHEME_V->args) == SCHEME_V->UNQUOTESP && ok_abbrev (cdr (SCHEME_V->args)))
5694     {
5695     putstr (SCHEME_A_ ",@");
5696     SCHEME_V->args = cadr (SCHEME_V->args);
5697     s_goto (OP_P0LIST);
5698     }
5699     else
5700     {
5701     putstr (SCHEME_A_ "(");
5702     s_save (SCHEME_A_ OP_P1LIST, cdr (SCHEME_V->args), NIL);
5703     SCHEME_V->args = car (SCHEME_V->args);
5704     s_goto (OP_P0LIST);
5705     }
5706    
5707     case OP_P1LIST:
5708     if (is_pair (SCHEME_V->args))
5709     {
5710     s_save (SCHEME_A_ OP_P1LIST, cdr (SCHEME_V->args), NIL);
5711     putstr (SCHEME_A_ " ");
5712     SCHEME_V->args = car (SCHEME_V->args);
5713     s_goto (OP_P0LIST);
5714     }
5715     else if (is_vector (SCHEME_V->args))
5716     {
5717     s_save (SCHEME_A_ OP_P1LIST, NIL, NIL);
5718     putstr (SCHEME_A_ " . ");
5719     s_goto (OP_P0LIST);
5720     }
5721     else
5722     {
5723     if (SCHEME_V->args != NIL)
5724     {
5725     putstr (SCHEME_A_ " . ");
5726     printatom (SCHEME_A_ SCHEME_V->args, SCHEME_V->print_flag);
5727     }
5728    
5729     putstr (SCHEME_A_ ")");
5730     s_return (S_T);
5731     }
5732    
5733     case OP_PVECFROM:
5734     {
5735     int i = ivalue_unchecked (cdr (SCHEME_V->args));
5736     pointer vec = car (SCHEME_V->args);
5737     int len = ivalue_unchecked (vec);
5738    
5739     if (i == len)
5740     {
5741     putstr (SCHEME_A_ ")");
5742     s_return (S_T);
5743     }
5744     else
5745     {
5746     pointer elem = vector_elem (vec, i);
5747    
5748     ivalue_unchecked (cdr (SCHEME_V->args)) = i + 1;
5749     s_save (SCHEME_A_ OP_PVECFROM, SCHEME_V->args, NIL);
5750     SCHEME_V->args = elem;
5751    
5752     if (i > 0)
5753     putstr (SCHEME_A_ " ");
5754    
5755     s_goto (OP_P0LIST);
5756     }
5757     }
5758     }
5759    
5760     return S_T;
5761     }
5762    
5763     static pointer
5764     opexe_6 (SCHEME_P_ enum scheme_opcodes op)
5765     {
5766     pointer x, y;
5767    
5768     switch (op)
5769     {
5770     case OP_LIST_LENGTH: /* length *//* a.k */
5771     {
5772     long v = list_length (SCHEME_A_ car (SCHEME_V->args));
5773    
5774     if (v < 0)
5775     Error_1 ("length: not a list:", car (SCHEME_V->args));
5776    
5777     s_return (mk_integer (SCHEME_A_ v));
5778     }
5779    
5780     case OP_ASSQ: /* assq *//* a.k */
5781     x = car (SCHEME_V->args);
5782    
5783     for (y = cadr (SCHEME_V->args); is_pair (y); y = cdr (y))
5784     {
5785     if (!is_pair (car (y)))
5786     Error_0 ("unable to handle non pair element");
5787    
5788     if (x == caar (y))
5789     break;
5790     }
5791    
5792     if (is_pair (y))
5793     s_return (car (y));
5794     else
5795     s_return (S_F);
5796    
5797    
5798     case OP_GET_CLOSURE: /* get-closure-code *//* a.k */
5799     SCHEME_V->args = car (SCHEME_V->args);
5800    
5801     if (SCHEME_V->args == NIL)
5802     s_return (S_F);
5803     else if (is_closure (SCHEME_V->args))
5804     s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5805     else if (is_macro (SCHEME_V->args))
5806     s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5807     else
5808     s_return (S_F);
5809    
5810     case OP_CLOSUREP: /* closure? */
5811     /*
5812     * Note, macro object is also a closure.
5813     * Therefore, (closure? <#MACRO>) ==> #t
5814     */
5815     s_retbool (is_closure (car (SCHEME_V->args)));
5816    
5817     case OP_MACROP: /* macro? */
5818     s_retbool (is_macro (car (SCHEME_V->args)));
5819     }
5820    
5821     return S_T; /* NOTREACHED */
5822     }
5823    
5824     typedef pointer (*dispatch_func) (SCHEME_P_ enum scheme_opcodes);
5825    
5826     typedef int (*test_predicate) (pointer);
5827     static int
5828     is_any (pointer p)
5829     {
5830     return 1;
5831     }
5832    
5833     static int
5834     is_nonneg (pointer p)
5835     {
5836     return ivalue (p) >= 0 && is_integer (p);
5837     }
5838    
5839     /* Correspond carefully with following defines! */
5840     static struct
5841     {
5842     test_predicate fct;
5843     const char *kind;
5844     } tests[] =
5845     {
5846     { 0, 0}, /* unused */
5847     { is_any, 0},
5848     { is_string, "string" },
5849     { is_symbol, "symbol" },
5850     { is_port, "port" },
5851     { is_inport, "input port" },
5852     { is_outport, "output port" },
5853     { is_environment, "environment" },
5854     { is_pair, "pair" },
5855     { 0, "pair or '()" },
5856     { is_character, "character" },
5857     { is_vector, "vector" },
5858     { is_number, "number" },
5859     { is_integer, "integer" },
5860     { is_nonneg, "non-negative integer" }
5861     };
5862    
5863     #define TST_NONE 0
5864     #define TST_ANY "\001"
5865     #define TST_STRING "\002"
5866     #define TST_SYMBOL "\003"
5867     #define TST_PORT "\004"
5868     #define TST_INPORT "\005"
5869     #define TST_OUTPORT "\006"
5870     #define TST_ENVIRONMENT "\007"
5871     #define TST_PAIR "\010"
5872     #define TST_LIST "\011"
5873     #define TST_CHAR "\012"
5874     #define TST_VECTOR "\013"
5875     #define TST_NUMBER "\014"
5876     #define TST_INTEGER "\015"
5877     #define TST_NATURAL "\016"
5878    
5879     typedef struct
5880     {
5881     dispatch_func func;
5882     char *name;
5883     int min_arity;
5884     int max_arity;
5885     char *arg_tests_encoding;
5886     } op_code_info;
5887    
5888     #define INF_ARG 0xffff
5889    
5890     static op_code_info dispatch_table[] = {
5891     #define OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
5892     #include "opdefines.h"
5893     {0}
5894     };
5895    
5896     static const char *
5897     procname (pointer x)
5898     {
5899     int n = procnum (x);
5900     const char *name = dispatch_table[n].name;
5901    
5902     if (name == 0)
5903     {
5904     name = "ILLEGAL!";
5905     }
5906    
5907     return name;
5908     }
5909    
5910     /* kernel of this interpreter */
5911     static void
5912     Eval_Cycle (SCHEME_P_ enum scheme_opcodes op)
5913     {
5914     SCHEME_V->op = op;
5915    
5916     for (;;)
5917     {
5918     op_code_info *pcd = dispatch_table + SCHEME_V->op;
5919    
5920     if (pcd->name != 0) /* if built-in function, check arguments */
5921     {
5922     char msg[STRBUFFSIZE];
5923     int ok = 1;
5924     int n = list_length (SCHEME_A_ SCHEME_V->args);
5925    
5926     #if USE_ERROR_CHECKING
5927     /* Check number of arguments */
5928     if (n < pcd->min_arity)
5929     {
5930     ok = 0;
5931     snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5932     pcd->name, pcd->min_arity == pcd->max_arity ? "" : " at least", pcd->min_arity);
5933     }
5934    
5935     if (ok && n > pcd->max_arity)
5936     {
5937     ok = 0;
5938     snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5939     pcd->name, pcd->min_arity == pcd->max_arity ? "" : " at most", pcd->max_arity);
5940     }
5941     #endif
5942    
5943     if (ok)
5944     {
5945     if (pcd->arg_tests_encoding != 0)
5946     {
5947     int i = 0;
5948     int j;
5949     const char *t = pcd->arg_tests_encoding;
5950     pointer arglist = SCHEME_V->args;
5951    
5952     do
5953     {
5954     pointer arg = car (arglist);
5955    
5956     j = (int) t[0];
5957    
5958     if (j == TST_LIST[0])
5959     {
5960     if (arg != NIL && !is_pair (arg))
5961     break;
5962     }
5963     else
5964     {
5965     if (!tests[j].fct (arg))
5966     break;
5967     }
5968    
5969     if (t[1] != 0) /* last test is replicated as necessary */
5970     {
5971     t++;
5972     }
5973    
5974     arglist = cdr (arglist);
5975     i++;
5976     }
5977     while (i < n);
5978    
5979     #if USE_ERROR_CHECKING
5980     if (i < n)
5981     {
5982     ok = 0;
5983     snprintf (msg, STRBUFFSIZE, "%s: argument %d must be: %s", pcd->name, i + 1, tests[j].kind);
5984     }
5985     #endif
5986     }
5987     }
5988    
5989     if (!ok)
5990     {
5991     if (xError_1 (SCHEME_A_ msg, 0) == NIL)
5992     return;
5993    
5994     pcd = dispatch_table + SCHEME_V->op;
5995     }
5996     }
5997    
5998     ok_to_freely_gc (SCHEME_A);
5999    
6000     if (pcd->func (SCHEME_A_ (enum scheme_opcodes) SCHEME_V->op) == NIL)
6001     return;
6002    
6003     #if USE_ERROR_CHECKING
6004     if (SCHEME_V->no_memory)
6005     {
6006     xwrstr ("No memory!\n");
6007     return;
6008     }
6009     #endif
6010     }
6011     }
6012    
6013     /* ========== Initialization of internal keywords ========== */
6014    
6015     static void
6016     assign_syntax (SCHEME_P_ char *name)
6017     {
6018     pointer x = oblist_add_by_name (SCHEME_A_ name);
6019     set_typeflag (x, typeflag (x) | T_SYNTAX);
6020     }
6021    
6022     static void
6023     assign_proc (SCHEME_P_ enum scheme_opcodes op, char *name)
6024     {
6025     pointer x = mk_symbol (SCHEME_A_ name);
6026     pointer y = mk_proc (SCHEME_A_ op);
6027     new_slot_in_env (SCHEME_A_ x, y);
6028     }
6029    
6030     static pointer
6031     mk_proc (SCHEME_P_ enum scheme_opcodes op)
6032     {
6033     pointer y = get_cell (SCHEME_A_ NIL, NIL);
6034     set_typeflag (y, (T_PROC | T_ATOM));
6035     ivalue_unchecked (y) = (long) op;
6036     set_num_integer (y);
6037     return y;
6038     }
6039    
6040     /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
6041     static int
6042     syntaxnum (pointer p)
6043     {
6044     const char *s = strvalue (car (p));
6045    
6046     switch (strlength (car (p)))
6047     {
6048     case 2:
6049     if (s[0] == 'i')
6050     return OP_IF0; /* if */
6051     else
6052     return OP_OR0; /* or */
6053    
6054     case 3:
6055     if (s[0] == 'a')
6056     return OP_AND0; /* and */
6057     else
6058     return OP_LET0; /* let */
6059    
6060     case 4:
6061     switch (s[3])
6062     {
6063     case 'e':
6064     return OP_CASE0; /* case */
6065    
6066     case 'd':
6067     return OP_COND0; /* cond */
6068    
6069     case '*':
6070     return OP_LET0AST; /* let* */
6071    
6072     default:
6073     return OP_SET0; /* set! */
6074     }
6075    
6076     case 5:
6077     switch (s[2])
6078     {
6079     case 'g':
6080     return OP_BEGIN; /* begin */
6081    
6082     case 'l':
6083     return OP_DELAY; /* delay */
6084    
6085     case 'c':
6086     return OP_MACRO0; /* macro */
6087    
6088     default:
6089     return OP_QUOTE; /* quote */
6090     }
6091    
6092     case 6:
6093     switch (s[2])
6094     {
6095     case 'm':
6096     return OP_LAMBDA; /* lambda */
6097    
6098     case 'f':
6099     return OP_DEF0; /* define */
6100    
6101     default:
6102     return OP_LET0REC; /* letrec */
6103     }
6104    
6105     default:
6106     return OP_C0STREAM; /* cons-stream */
6107     }
6108     }
6109    
6110     #if USE_MULTIPLICITY
6111     scheme *
6112     scheme_init_new ()
6113     {
6114     scheme *sc = malloc (sizeof (scheme));
6115    
6116     if (!scheme_init (SCHEME_A))
6117     {
6118     free (SCHEME_A);
6119     return 0;
6120     }
6121     else
6122     return sc;
6123     }
6124     #endif
6125    
6126     int
6127     scheme_init (SCHEME_P)
6128     {
6129     int i, n = sizeof (dispatch_table) / sizeof (dispatch_table[0]);
6130     pointer x;
6131    
6132     num_set_fixnum (num_zero, 1);
6133     num_set_ivalue (num_zero, 0);
6134     num_set_fixnum (num_one, 1);
6135     num_set_ivalue (num_one, 1);
6136    
6137     #if USE_INTERFACE
6138     SCHEME_V->vptr = &vtbl;
6139     #endif
6140     SCHEME_V->gensym_cnt = 0;
6141     SCHEME_V->last_cell_seg = -1;
6142     SCHEME_V->free_cell = NIL;
6143     SCHEME_V->fcells = 0;
6144     SCHEME_V->no_memory = 0;
6145     SCHEME_V->inport = NIL;
6146     SCHEME_V->outport = NIL;
6147     SCHEME_V->save_inport = NIL;
6148     SCHEME_V->loadport = NIL;
6149     SCHEME_V->nesting = 0;
6150     SCHEME_V->interactive_repl = 0;
6151    
6152     if (alloc_cellseg (SCHEME_A_ FIRST_CELLSEGS) != FIRST_CELLSEGS)
6153     {
6154     #if USE_ERROR_CHECKING
6155     SCHEME_V->no_memory = 1;
6156     return 0;
6157     #endif
6158     }
6159    
6160     SCHEME_V->gc_verbose = 0;
6161     dump_stack_initialize (SCHEME_A);
6162     SCHEME_V->code = NIL;
6163     SCHEME_V->tracing = 0;
6164    
6165     /* init NIL */
6166     set_typeflag (NIL, T_ATOM | MARK);
6167     set_car (NIL, NIL);
6168     set_cdr (NIL, NIL);
6169     /* init T */
6170     set_typeflag (S_T, T_ATOM | MARK);
6171     set_car (S_T, S_T);
6172     set_cdr (S_T, S_T);
6173     /* init F */
6174     set_typeflag (S_F, T_ATOM | MARK);
6175     set_car (S_F, S_F);
6176     set_cdr (S_F, S_F);
6177     /* init sink */
6178     set_typeflag (S_SINK, T_PAIR | MARK);
6179     set_car (S_SINK, NIL);
6180     /* init c_nest */
6181     SCHEME_V->c_nest = NIL;
6182    
6183     SCHEME_V->oblist = oblist_initial_value (SCHEME_A);
6184     /* init global_env */
6185     new_frame_in_env (SCHEME_A_ NIL);
6186     SCHEME_V->global_env = SCHEME_V->envir;
6187     /* init else */
6188     x = mk_symbol (SCHEME_A_ "else");
6189     new_slot_in_env (SCHEME_A_ x, S_T);
6190    
6191     assign_syntax (SCHEME_A_ "lambda");
6192     assign_syntax (SCHEME_A_ "quote");
6193     assign_syntax (SCHEME_A_ "define");
6194     assign_syntax (SCHEME_A_ "if");
6195     assign_syntax (SCHEME_A_ "begin");
6196     assign_syntax (SCHEME_A_ "set!");
6197     assign_syntax (SCHEME_A_ "let");
6198     assign_syntax (SCHEME_A_ "let*");
6199     assign_syntax (SCHEME_A_ "letrec");
6200     assign_syntax (SCHEME_A_ "cond");
6201     assign_syntax (SCHEME_A_ "delay");
6202     assign_syntax (SCHEME_A_ "and");
6203     assign_syntax (SCHEME_A_ "or");
6204     assign_syntax (SCHEME_A_ "cons-stream");
6205     assign_syntax (SCHEME_A_ "macro");
6206     assign_syntax (SCHEME_A_ "case");
6207    
6208     for (i = 0; i < n; i++)
6209     {
6210     if (dispatch_table[i].name != 0)
6211     {
6212     assign_proc (SCHEME_A_ (enum scheme_opcodes) i, dispatch_table[i].name);
6213     }
6214     }
6215    
6216     /* initialization of global pointers to special symbols */
6217     SCHEME_V->LAMBDA = mk_symbol (SCHEME_A_ "lambda");
6218     SCHEME_V->QUOTE = mk_symbol (SCHEME_A_ "quote");
6219     SCHEME_V->QQUOTE = mk_symbol (SCHEME_A_ "quasiquote");
6220     SCHEME_V->UNQUOTE = mk_symbol (SCHEME_A_ "unquote");
6221     SCHEME_V->UNQUOTESP = mk_symbol (SCHEME_A_ "unquote-splicing");
6222     SCHEME_V->FEED_TO = mk_symbol (SCHEME_A_ "=>");
6223     SCHEME_V->COLON_HOOK = mk_symbol (SCHEME_A_ "*colon-hook*");
6224     SCHEME_V->ERROR_HOOK = mk_symbol (SCHEME_A_ "*error-hook*");
6225     SCHEME_V->SHARP_HOOK = mk_symbol (SCHEME_A_ "*sharp-hook*");
6226     SCHEME_V->COMPILE_HOOK = mk_symbol (SCHEME_A_ "*compile-hook*");
6227    
6228     return !SCHEME_V->no_memory;
6229     }
6230    
6231     #if USE_PORTS
6232     void
6233     scheme_set_input_port_file (SCHEME_P_ int fin)
6234     {
6235     SCHEME_V->inport = port_from_file (SCHEME_A_ fin, port_input);
6236     }
6237    
6238     void
6239     scheme_set_input_port_string (SCHEME_P_ char *start, char *past_the_end)
6240     {
6241     SCHEME_V->inport = port_from_string (SCHEME_A_ start, past_the_end, port_input);
6242     }
6243    
6244     void
6245     scheme_set_output_port_file (SCHEME_P_ int fout)
6246     {
6247     SCHEME_V->outport = port_from_file (SCHEME_A_ fout, port_output);
6248     }
6249    
6250     void
6251     scheme_set_output_port_string (SCHEME_P_ char *start, char *past_the_end)
6252     {
6253     SCHEME_V->outport = port_from_string (SCHEME_A_ start, past_the_end, port_output);
6254     }
6255     #endif
6256    
6257     void
6258     scheme_set_external_data (SCHEME_P_ void *p)
6259     {
6260     SCHEME_V->ext_data = p;
6261     }
6262    
6263     void
6264     scheme_deinit (SCHEME_P)
6265     {
6266     int i;
6267    
6268     #if SHOW_ERROR_LINE
6269     char *fname;
6270     #endif
6271    
6272     SCHEME_V->oblist = NIL;
6273     SCHEME_V->global_env = NIL;
6274     dump_stack_free (SCHEME_A);
6275     SCHEME_V->envir = NIL;
6276     SCHEME_V->code = NIL;
6277     SCHEME_V->args = NIL;
6278     SCHEME_V->value = NIL;
6279    
6280     if (is_port (SCHEME_V->inport))
6281     set_typeflag (SCHEME_V->inport, T_ATOM);
6282    
6283     SCHEME_V->inport = NIL;
6284     SCHEME_V->outport = NIL;
6285    
6286     if (is_port (SCHEME_V->save_inport))
6287     set_typeflag (SCHEME_V->save_inport, T_ATOM);
6288    
6289     SCHEME_V->save_inport = NIL;
6290    
6291     if (is_port (SCHEME_V->loadport))
6292     set_typeflag (SCHEME_V->loadport, T_ATOM);
6293    
6294     SCHEME_V->loadport = NIL;
6295     SCHEME_V->gc_verbose = 0;
6296     gc (SCHEME_A_ NIL, NIL);
6297    
6298     for (i = 0; i <= SCHEME_V->last_cell_seg; i++)
6299     free (SCHEME_V->alloc_seg[i]);
6300    
6301     #if SHOW_ERROR_LINE
6302     for (i = 0; i <= SCHEME_V->file_i; i++)
6303     {
6304     if (SCHEME_V->load_stack[i].kind & port_file)
6305     {
6306     fname = SCHEME_V->load_stack[i].rep.stdio.filename;
6307    
6308     if (fname)
6309     free (fname);
6310     }
6311     }
6312     #endif
6313     }
6314    
6315     void
6316     scheme_load_file (SCHEME_P_ int fin)
6317     {
6318     scheme_load_named_file (SCHEME_A_ fin, 0);
6319     }
6320    
6321     void
6322     scheme_load_named_file (SCHEME_P_ int fin, const char *filename)
6323     {
6324     dump_stack_reset (SCHEME_A);
6325     SCHEME_V->envir = SCHEME_V->global_env;
6326     SCHEME_V->file_i = 0;
6327     SCHEME_V->load_stack[0].unget = -1;
6328     SCHEME_V->load_stack[0].kind = port_input | port_file;
6329     SCHEME_V->load_stack[0].rep.stdio.file = fin;
6330     #if USE_PORTS
6331     SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
6332     #endif
6333     SCHEME_V->retcode = 0;
6334    
6335     #if USE_PORTS
6336     if (fin == STDIN_FILENO)
6337     SCHEME_V->interactive_repl = 1;
6338     #endif
6339    
6340     #if USE_PORTS
6341     #if SHOW_ERROR_LINE
6342     SCHEME_V->load_stack[0].rep.stdio.curr_line = 0;
6343    
6344     if (fin != STDIN_FILENO && filename)
6345     SCHEME_V->load_stack[0].rep.stdio.filename = store_string (SCHEME_A_ strlen (filename), filename, 0);
6346     #endif
6347     #endif
6348    
6349     SCHEME_V->inport = SCHEME_V->loadport;
6350     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
6351     Eval_Cycle (SCHEME_A_ OP_T0LVL);
6352     set_typeflag (SCHEME_V->loadport, T_ATOM);
6353    
6354     if (SCHEME_V->retcode == 0)
6355     SCHEME_V->retcode = SCHEME_V->nesting != 0;
6356     }
6357    
6358     void
6359     scheme_load_string (SCHEME_P_ const char *cmd)
6360     {
6361     dump_stack_reset (SCHEME_A);
6362     SCHEME_V->envir = SCHEME_V->global_env;
6363     SCHEME_V->file_i = 0;
6364     SCHEME_V->load_stack[0].kind = port_input | port_string;
6365     SCHEME_V->load_stack[0].rep.string.start = (char *) cmd; /* This func respects const */
6366     SCHEME_V->load_stack[0].rep.string.past_the_end = (char *) cmd + strlen (cmd);
6367     SCHEME_V->load_stack[0].rep.string.curr = (char *) cmd;
6368     #if USE_PORTS
6369     SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
6370     #endif
6371     SCHEME_V->retcode = 0;
6372     SCHEME_V->interactive_repl = 0;
6373     SCHEME_V->inport = SCHEME_V->loadport;
6374     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
6375     Eval_Cycle (SCHEME_A_ OP_T0LVL);
6376     set_typeflag (SCHEME_V->loadport, T_ATOM);
6377    
6378     if (SCHEME_V->retcode == 0)
6379     SCHEME_V->retcode = SCHEME_V->nesting != 0;
6380     }
6381    
6382     void
6383     scheme_define (SCHEME_P_ pointer envir, pointer symbol, pointer value)
6384     {
6385     pointer x;
6386    
6387     x = find_slot_in_env (SCHEME_A_ envir, symbol, 0);
6388    
6389     if (x != NIL)
6390     {
6391     set_slot_in_env (SCHEME_A_ x, value);
6392     }
6393     else
6394     {
6395     new_slot_spec_in_env (SCHEME_A_ envir, symbol, value);
6396     }
6397     }
6398    
6399     #if !STANDALONE
6400     void
6401     scheme_register_foreign_func (scheme * sc, scheme_registerable * sr)
6402     {
6403     scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ sr->name), mk_foreign_func (SCHEME_A_ sr->f));
6404     }
6405    
6406     void
6407     scheme_register_foreign_func_list (scheme * sc, scheme_registerable * list, int count)
6408     {
6409     int i;
6410    
6411     for (i = 0; i < count; i++)
6412     {
6413     scheme_register_foreign_func (SCHEME_A_ list + i);
6414     }
6415     }
6416    
6417     pointer
6418     scheme_apply0 (SCHEME_P_ const char *procname)
6419     {
6420     return scheme_eval (SCHEME_A_ cons (mk_symbol (SCHEME_A_ procname), NIL));
6421     }
6422    
6423     void
6424     save_from_C_call (SCHEME_P)
6425     {
6426     pointer saved_data = cons (car (S_SINK),
6427     cons (SCHEME_V->envir,
6428     SCHEME_V->dump));
6429    
6430     /* Push */
6431     SCHEME_V->c_nest = cons (saved_data, SCHEME_V->c_nest);
6432     /* Truncate the dump stack so TS will return here when done, not
6433     directly resume pre-C-call operations. */
6434     dump_stack_reset (SCHEME_A);
6435     }
6436    
6437     void
6438     restore_from_C_call (SCHEME_P)
6439     {
6440     set_car (S_SINK, caar (SCHEME_V->c_nest));
6441     SCHEME_V->envir = cadar (SCHEME_V->c_nest);
6442     SCHEME_V->dump = cdr (cdar (SCHEME_V->c_nest));
6443     /* Pop */
6444     SCHEME_V->c_nest = cdr (SCHEME_V->c_nest);
6445     }
6446    
6447     /* "func" and "args" are assumed to be already eval'ed. */
6448     pointer
6449     scheme_call (SCHEME_P_ pointer func, pointer args)
6450     {
6451     int old_repl = SCHEME_V->interactive_repl;
6452    
6453     SCHEME_V->interactive_repl = 0;
6454     save_from_C_call (SCHEME_A);
6455     SCHEME_V->envir = SCHEME_V->global_env;
6456     SCHEME_V->args = args;
6457     SCHEME_V->code = func;
6458     SCHEME_V->retcode = 0;
6459     Eval_Cycle (SCHEME_A_ OP_APPLY);
6460     SCHEME_V->interactive_repl = old_repl;
6461     restore_from_C_call (SCHEME_A);
6462     return SCHEME_V->value;
6463     }
6464    
6465     pointer
6466     scheme_eval (SCHEME_P_ pointer obj)
6467     {
6468     int old_repl = SCHEME_V->interactive_repl;
6469    
6470     SCHEME_V->interactive_repl = 0;
6471     save_from_C_call (SCHEME_A);
6472     SCHEME_V->args = NIL;
6473     SCHEME_V->code = obj;
6474     SCHEME_V->retcode = 0;
6475     Eval_Cycle (SCHEME_A_ OP_EVAL);
6476     SCHEME_V->interactive_repl = old_repl;
6477     restore_from_C_call (SCHEME_A);
6478     return SCHEME_V->value;
6479     }
6480    
6481    
6482     #endif
6483    
6484     /* ========== Main ========== */
6485    
6486     #if STANDALONE
6487    
6488     # if defined(__APPLE__) && !defined (OSX)
6489     int
6490     main ()
6491     {
6492     extern MacTS_main (int argc, char **argv);
6493     char **argv;
6494     int argc = ccommand (&argv);
6495    
6496     MacTS_main (argc, argv);
6497     return 0;
6498     }
6499    
6500     int
6501     MacTS_main (int argc, char **argv)
6502     {
6503     # else
6504     int
6505     main (int argc, char **argv)
6506     {
6507     # endif
6508     # if USE_MULTIPLICITY
6509     scheme ssc;
6510     scheme *const sc = &ssc;
6511     # else
6512     # endif
6513     int fin;
6514     char *file_name = InitFile;
6515     int retcode;
6516     int isfile = 1;
6517    
6518     if (argc == 1)
6519     xwrstr (banner);
6520    
6521     if (argc == 2 && strcmp (argv[1], "-?") == 0)
6522     {
6523     xwrstr ("Usage: tinyscheme -?\n");
6524     xwrstr ("or: tinyscheme [<file1> <file2> ...]\n");
6525     xwrstr ("followed by\n");
6526     xwrstr (" -1 <file> [<arg1> <arg2> ...]\n");
6527     xwrstr (" -c <Scheme commands> [<arg1> <arg2> ...]\n");
6528     xwrstr ("assuming that the executable is named tinyscheme.\n");
6529     xwrstr ("Use - as filename for stdin.\n");
6530     return 1;
6531     }
6532    
6533     if (!scheme_init (SCHEME_A))
6534     {
6535     xwrstr ("Could not initialize!\n");
6536     return 2;
6537     }
6538    
6539     # if USE_PORTS
6540     scheme_set_input_port_file (SCHEME_A_ STDIN_FILENO);
6541     scheme_set_output_port_file (SCHEME_A_ STDOUT_FILENO);
6542     # endif
6543    
6544     argv++;
6545    
6546     #if 0
6547     if (access (file_name, 0) != 0)
6548     {
6549     char *p = getenv ("TINYSCHEMEINIT");
6550    
6551     if (p != 0)
6552     {
6553     file_name = p;
6554     }
6555     }
6556     #endif
6557    
6558     do
6559     {
6560     #if USE_PORTS
6561     if (strcmp (file_name, "-") == 0)
6562     fin = STDIN_FILENO;
6563     else if (strcmp (file_name, "-1") == 0 || strcmp (file_name, "-c") == 0)
6564     {
6565     pointer args = NIL;
6566    
6567     isfile = file_name[1] == '1';
6568     file_name = *argv++;
6569    
6570     if (strcmp (file_name, "-") == 0)
6571     fin = STDIN_FILENO;
6572     else if (isfile)
6573     fin = open (file_name, O_RDONLY);
6574    
6575     for (; *argv; argv++)
6576     {
6577     pointer value = mk_string (SCHEME_A_ * argv);
6578    
6579     args = cons (value, args);
6580     }
6581    
6582     args = reverse_in_place (SCHEME_A_ NIL, args);
6583     scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ "*args*"), args);
6584    
6585     }
6586     else
6587     fin = open (file_name, O_RDONLY);
6588     #endif
6589    
6590     if (isfile && fin < 0)
6591     {
6592     xwrstr ("Could not open file "); xwrstr (file_name); xwrstr ("\n");
6593     }
6594     else
6595     {
6596     if (isfile)
6597     scheme_load_named_file (SCHEME_A_ fin, file_name);
6598     else
6599     scheme_load_string (SCHEME_A_ file_name);
6600    
6601     #if USE_PORTS
6602     if (!isfile || fin != STDIN_FILENO)
6603     {
6604     if (SCHEME_V->retcode != 0)
6605     {
6606     xwrstr ("Errors encountered reading "); xwrstr (file_name); xwrstr ("\n");
6607     }
6608    
6609     if (isfile)
6610     close (fin);
6611     }
6612     #endif
6613     }
6614    
6615     file_name = *argv++;
6616     }
6617     while (file_name != 0);
6618    
6619     if (argc == 1)
6620     scheme_load_named_file (SCHEME_A_ STDIN_FILENO, 0);
6621    
6622     retcode = SCHEME_V->retcode;
6623     scheme_deinit (SCHEME_A);
6624    
6625     return retcode;
6626     }
6627    
6628     #endif
6629    
6630     /*
6631     Local variables:
6632     c-file-style: "k&r"
6633     End:
6634     */