ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.60
Committed: Wed Dec 2 02:59:36 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.59: +187 -172 lines
Log Message:
hot cold

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