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