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