ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.9
Committed: Wed Nov 25 22:39:19 2015 UTC (8 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.8: +5 -11 lines
Log Message:
*** empty log message ***

File Contents

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