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