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