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