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