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