ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.7
Committed: Wed Nov 25 22:12:59 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.6: +55 -63 lines
Log Message:
*** empty log message ***

File Contents

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