ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.61
Committed: Wed Dec 2 07:43:46 2015 UTC (8 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.60: +264 -166 lines
Log Message:
*** empty log message ***

File Contents

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