ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.56
Committed: Tue Dec 1 03:44:32 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.55: +6 -8 lines
Log Message:
more r7rs

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