ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.55
Committed: Tue Dec 1 03:03:11 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.54: +15 -17 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.7 /*
2     * µscheme
3     *
4     * Copyright (C) 2015 Marc Alexander Lehmann <uscheme@schmorp.de>
5     * do as you want with this, attribution appreciated.
6     *
7     * Based opn tinyscheme-1.41 (original credits follow)
8 root 1.1 * Dimitrios Souflis (dsouflis@acm.org)
9     * Based on MiniScheme (original credits follow)
10     * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
11     * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
12     * (MINISCM) This version has been modified by R.C. Secrist.
13     * (MINISCM)
14     * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
15     * (MINISCM)
16     * (MINISCM) This is a revised and modified version by Akira KIDA.
17     * (MINISCM) current version is 0.85k4 (15 May 1994)
18     *
19     */
20    
21 root 1.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.16 case OP_EXP: s_return (mk_real (SCHEME_A_ exp (rvalue (x))));
4017 root 1.55 case OP_LOG: s_return (mk_real (SCHEME_A_ log (rvalue (x))
4018     / (cadr (args) == NIL ? 1 : log (rvalue (cadr (args))))));
4019 root 1.16 case OP_SIN: s_return (mk_real (SCHEME_A_ sin (rvalue (x))));
4020     case OP_COS: s_return (mk_real (SCHEME_A_ cos (rvalue (x))));
4021     case OP_TAN: s_return (mk_real (SCHEME_A_ tan (rvalue (x))));
4022     case OP_ASIN: s_return (mk_real (SCHEME_A_ asin (rvalue (x))));
4023     case OP_ACOS: s_return (mk_real (SCHEME_A_ acos (rvalue (x))));
4024 root 1.1
4025     case OP_ATAN:
4026 root 1.55 s_return (mk_real (SCHEME_A_
4027     cdr (args) == NIL
4028     ? atan (rvalue (x))
4029     : atan2 (rvalue (x), rvalue (cadr (args)))));
4030 root 1.1
4031     case OP_SQRT:
4032     s_return (mk_real (SCHEME_A_ sqrt (rvalue (x))));
4033    
4034     case OP_EXPT:
4035     {
4036     RVALUE result;
4037     int real_result = 1;
4038 root 1.16 pointer y = cadr (args);
4039 root 1.1
4040 root 1.25 if (is_integer (x) && is_integer (y))
4041 root 1.1 real_result = 0;
4042    
4043     /* This 'if' is an R5RS compatibility fix. */
4044     /* NOTE: Remove this 'if' fix for R6RS. */
4045     if (rvalue (x) == 0 && rvalue (y) < 0)
4046 root 1.16 result = 0;
4047 root 1.1 else
4048 root 1.2 result = pow (rvalue (x), rvalue (y));
4049 root 1.1
4050     /* Before returning integer result make sure we can. */
4051     /* If the test fails, result is too big for integer. */
4052     if (!real_result)
4053     {
4054 root 1.16 long result_as_long = result;
4055 root 1.1
4056 root 1.26 if (result != result_as_long)
4057 root 1.1 real_result = 1;
4058     }
4059    
4060     if (real_result)
4061 root 1.2 s_return (mk_real (SCHEME_A_ result));
4062 root 1.1 else
4063 root 1.2 s_return (mk_integer (SCHEME_A_ result));
4064 root 1.1 }
4065    
4066 root 1.54 case OP_FLOOR: s_return (mk_real (SCHEME_A_ floor (rvalue (x))));
4067     case OP_CEILING: s_return (mk_real (SCHEME_A_ ceil (rvalue (x))));
4068     case OP_TRUNCATE: s_return (mk_real (SCHEME_A_ trunc (rvalue (x))));
4069     case OP_ROUND: s_return (mk_real (SCHEME_A_ nearbyint (rvalue (x))));
4070 root 1.1 #endif
4071    
4072     case OP_ADD: /* + */
4073     v = num_zero;
4074    
4075 root 1.16 for (x = args; x != NIL; x = cdr (x))
4076 root 1.23 v = num_op (NUM_ADD, v, nvalue (car (x)));
4077 root 1.1
4078     s_return (mk_number (SCHEME_A_ v));
4079    
4080     case OP_MUL: /* * */
4081     v = num_one;
4082    
4083 root 1.16 for (x = args; x != NIL; x = cdr (x))
4084 root 1.23 v = num_op (NUM_MUL, v, nvalue (car (x)));
4085 root 1.1
4086     s_return (mk_number (SCHEME_A_ v));
4087    
4088     case OP_SUB: /* - */
4089 root 1.16 if (cdr (args) == NIL)
4090 root 1.1 {
4091 root 1.16 x = args;
4092 root 1.1 v = num_zero;
4093     }
4094     else
4095     {
4096 root 1.16 x = cdr (args);
4097     v = nvalue (car (args));
4098 root 1.1 }
4099    
4100     for (; x != NIL; x = cdr (x))
4101 root 1.23 v = num_op (NUM_SUB, v, nvalue (car (x)));
4102 root 1.1
4103     s_return (mk_number (SCHEME_A_ v));
4104    
4105     case OP_DIV: /* / */
4106 root 1.16 if (cdr (args) == NIL)
4107 root 1.1 {
4108 root 1.16 x = args;
4109 root 1.1 v = num_one;
4110     }
4111     else
4112     {
4113 root 1.16 x = cdr (args);
4114     v = nvalue (car (args));
4115 root 1.1 }
4116    
4117     for (; x != NIL; x = cdr (x))
4118 root 1.23 if (!is_zero_rvalue (rvalue (car (x))))
4119     v = num_div (v, nvalue (car (x)));
4120     else
4121     Error_0 ("/: division by zero");
4122 root 1.1
4123     s_return (mk_number (SCHEME_A_ v));
4124    
4125     case OP_INTDIV: /* quotient */
4126 root 1.16 if (cdr (args) == NIL)
4127 root 1.1 {
4128 root 1.16 x = args;
4129 root 1.1 v = num_one;
4130     }
4131     else
4132     {
4133 root 1.16 x = cdr (args);
4134     v = nvalue (car (args));
4135 root 1.1 }
4136    
4137     for (; x != NIL; x = cdr (x))
4138     {
4139     if (ivalue (car (x)) != 0)
4140 root 1.23 v = num_op (NUM_INTDIV, v, nvalue (car (x)));
4141 root 1.1 else
4142     Error_0 ("quotient: division by zero");
4143     }
4144    
4145     s_return (mk_number (SCHEME_A_ v));
4146    
4147     case OP_REM: /* remainder */
4148 root 1.16 v = nvalue (x);
4149 root 1.1
4150 root 1.16 if (ivalue (cadr (args)) != 0)
4151     v = num_rem (v, nvalue (cadr (args)));
4152 root 1.1 else
4153     Error_0 ("remainder: division by zero");
4154    
4155     s_return (mk_number (SCHEME_A_ v));
4156    
4157     case OP_MOD: /* modulo */
4158 root 1.16 v = nvalue (x);
4159 root 1.1
4160 root 1.16 if (ivalue (cadr (args)) != 0)
4161     v = num_mod (v, nvalue (cadr (args)));
4162 root 1.1 else
4163     Error_0 ("modulo: division by zero");
4164    
4165     s_return (mk_number (SCHEME_A_ v));
4166    
4167 root 1.46 /* the compiler will optimize this mess... */
4168     case OP_CAR: op_car: s_return (car (x));
4169     case OP_CDR: op_cdr: s_return (cdr (x));
4170     case OP_CAAR: op_caar: x = car (x); goto op_car;
4171     case OP_CADR: op_cadr: x = cdr (x); goto op_car;
4172     case OP_CDAR: op_cdar: x = car (x); goto op_cdr;
4173     case OP_CDDR: op_cddr: x = cdr (x); goto op_cdr;
4174     case OP_CAAAR: op_caaar: x = car (x); goto op_caar;
4175     case OP_CAADR: op_caadr: x = cdr (x); goto op_caar;
4176     case OP_CADAR: op_cadar: x = car (x); goto op_cadr;
4177     case OP_CADDR: op_caddr: x = cdr (x); goto op_cadr;
4178     case OP_CDAAR: op_cdaar: x = car (x); goto op_cdar;
4179     case OP_CDADR: op_cdadr: x = cdr (x); goto op_cdar;
4180     case OP_CDDAR: op_cddar: x = car (x); goto op_cddr;
4181     case OP_CDDDR: op_cdddr: x = cdr (x); goto op_cddr;
4182     case OP_CAAAAR: x = car (x); goto op_caaar;
4183     case OP_CAAADR: x = cdr (x); goto op_caaar;
4184     case OP_CAADAR: x = car (x); goto op_caadr;
4185     case OP_CAADDR: x = cdr (x); goto op_caadr;
4186     case OP_CADAAR: x = car (x); goto op_cadar;
4187     case OP_CADADR: x = cdr (x); goto op_cadar;
4188     case OP_CADDAR: x = car (x); goto op_caddr;
4189     case OP_CADDDR: x = cdr (x); goto op_caddr;
4190     case OP_CDAAAR: x = car (x); goto op_cdaar;
4191     case OP_CDAADR: x = cdr (x); goto op_cdaar;
4192     case OP_CDADAR: x = car (x); goto op_cdadr;
4193     case OP_CDADDR: x = cdr (x); goto op_cdadr;
4194     case OP_CDDAAR: x = car (x); goto op_cddar;
4195     case OP_CDDADR: x = cdr (x); goto op_cddar;
4196     case OP_CDDDAR: x = car (x); goto op_cdddr;
4197     case OP_CDDDDR: x = cdr (x); goto op_cdddr;
4198 root 1.1
4199     case OP_CONS: /* cons */
4200 root 1.16 set_cdr (args, cadr (args));
4201     s_return (args);
4202 root 1.1
4203     case OP_SETCAR: /* set-car! */
4204 root 1.16 if (!is_immutable (x))
4205 root 1.1 {
4206 root 1.16 set_car (x, cadr (args));
4207     s_return (car (args));
4208 root 1.1 }
4209     else
4210     Error_0 ("set-car!: unable to alter immutable pair");
4211    
4212     case OP_SETCDR: /* set-cdr! */
4213 root 1.16 if (!is_immutable (x))
4214 root 1.1 {
4215 root 1.16 set_cdr (x, cadr (args));
4216     s_return (car (args));
4217 root 1.1 }
4218     else
4219     Error_0 ("set-cdr!: unable to alter immutable pair");
4220    
4221     case OP_CHAR2INT: /* char->integer */
4222 root 1.26 s_return (mk_integer (SCHEME_A_ ivalue_unchecked (x)));
4223 root 1.1
4224     case OP_INT2CHAR: /* integer->char */
4225 root 1.26 s_return (mk_character (SCHEME_A_ ivalue_unchecked (x)));
4226 root 1.1
4227     case OP_CHARUPCASE:
4228     {
4229 root 1.26 unsigned char c = ivalue_unchecked (x);
4230 root 1.1 c = toupper (c);
4231 root 1.2 s_return (mk_character (SCHEME_A_ c));
4232 root 1.1 }
4233    
4234     case OP_CHARDNCASE:
4235     {
4236 root 1.26 unsigned char c = ivalue_unchecked (x);
4237 root 1.1 c = tolower (c);
4238 root 1.2 s_return (mk_character (SCHEME_A_ c));
4239 root 1.1 }
4240    
4241     case OP_STR2SYM: /* string->symbol */
4242 root 1.16 s_return (mk_symbol (SCHEME_A_ strvalue (x)));
4243 root 1.1
4244     case OP_STR2ATOM: /* string->atom */
4245     {
4246 root 1.16 char *s = strvalue (x);
4247 root 1.1 long pf = 0;
4248    
4249 root 1.16 if (cdr (args) != NIL)
4250 root 1.1 {
4251 root 1.16 /* we know cadr(args) is a natural number */
4252 root 1.1 /* see if it is 2, 8, 10, or 16, or error */
4253 root 1.16 pf = ivalue_unchecked (cadr (args));
4254 root 1.1
4255     if (pf == 16 || pf == 10 || pf == 8 || pf == 2)
4256     {
4257     /* base is OK */
4258     }
4259     else
4260 root 1.2 pf = -1;
4261 root 1.1 }
4262    
4263     if (pf < 0)
4264 root 1.16 Error_1 ("string->atom: bad base:", cadr (args));
4265 root 1.1 else if (*s == '#') /* no use of base! */
4266 root 1.2 s_return (mk_sharp_const (SCHEME_A_ s + 1));
4267 root 1.1 else
4268     {
4269     if (pf == 0 || pf == 10)
4270 root 1.2 s_return (mk_atom (SCHEME_A_ s));
4271 root 1.1 else
4272     {
4273     char *ep;
4274     long iv = strtol (s, &ep, (int) pf);
4275    
4276     if (*ep == 0)
4277 root 1.2 s_return (mk_integer (SCHEME_A_ iv));
4278 root 1.1 else
4279 root 1.2 s_return (S_F);
4280 root 1.1 }
4281     }
4282     }
4283    
4284     case OP_SYM2STR: /* symbol->string */
4285 root 1.16 x = mk_string (SCHEME_A_ symname (x));
4286 root 1.1 setimmutable (x);
4287     s_return (x);
4288    
4289     case OP_ATOM2STR: /* atom->string */
4290     {
4291     long pf = 0;
4292    
4293 root 1.16 if (cdr (args) != NIL)
4294 root 1.1 {
4295 root 1.16 /* we know cadr(args) is a natural number */
4296 root 1.1 /* see if it is 2, 8, 10, or 16, or error */
4297 root 1.16 pf = ivalue_unchecked (cadr (args));
4298 root 1.1
4299     if (is_number (x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2))
4300     {
4301     /* base is OK */
4302     }
4303     else
4304 root 1.2 pf = -1;
4305 root 1.1 }
4306    
4307     if (pf < 0)
4308 root 1.16 Error_1 ("atom->string: bad base:", cadr (args));
4309 root 1.1 else if (is_number (x) || is_character (x) || is_string (x) || is_symbol (x))
4310     {
4311     char *p;
4312     int len;
4313    
4314 root 1.2 atom2str (SCHEME_A_ x, pf, &p, &len);
4315 root 1.1 s_return (mk_counted_string (SCHEME_A_ p, len));
4316     }
4317     else
4318 root 1.2 Error_1 ("atom->string: not an atom:", x);
4319 root 1.1 }
4320    
4321     case OP_MKSTRING: /* make-string */
4322     {
4323 root 1.26 int fill = cdr (args) != NIL ? charvalue (cadr (args)) : ' ';
4324     int len = ivalue_unchecked (x);
4325 root 1.1
4326 root 1.17 s_return (mk_empty_string (SCHEME_A_ len, fill));
4327 root 1.1 }
4328    
4329     case OP_STRLEN: /* string-length */
4330 root 1.16 s_return (mk_integer (SCHEME_A_ strlength (x)));
4331 root 1.1
4332     case OP_STRREF: /* string-ref */
4333     {
4334 root 1.26 char *str = strvalue (x);
4335     int index = ivalue_unchecked (cadr (args));
4336 root 1.1
4337 root 1.16 if (index >= strlength (x))
4338     Error_1 ("string-ref: out of bounds:", cadr (args));
4339 root 1.1
4340 root 1.17 s_return (mk_character (SCHEME_A_ ((unsigned char *)str)[index]));
4341 root 1.1 }
4342    
4343     case OP_STRSET: /* string-set! */
4344     {
4345 root 1.26 char *str = strvalue (x);
4346     int index = ivalue_unchecked (cadr (args));
4347 root 1.1 int c;
4348    
4349 root 1.16 if (is_immutable (x))
4350     Error_1 ("string-set!: unable to alter immutable string:", x);
4351 root 1.1
4352 root 1.16 if (index >= strlength (x))
4353     Error_1 ("string-set!: out of bounds:", cadr (args));
4354 root 1.1
4355 root 1.16 c = charvalue (caddr (args));
4356 root 1.1
4357 root 1.17 str[index] = c;
4358 root 1.16 s_return (car (args));
4359 root 1.1 }
4360    
4361     case OP_STRAPPEND: /* string-append */
4362     {
4363     /* in 1.29 string-append was in Scheme in init.scm but was too slow */
4364     int len = 0;
4365     pointer newstr;
4366     char *pos;
4367    
4368     /* compute needed length for new string */
4369 root 1.16 for (x = args; x != NIL; x = cdr (x))
4370 root 1.2 len += strlength (car (x));
4371 root 1.1
4372     newstr = mk_empty_string (SCHEME_A_ len, ' ');
4373    
4374     /* store the contents of the argument strings into the new string */
4375 root 1.16 for (pos = strvalue (newstr), x = args; x != NIL; pos += strlength (car (x)), x = cdr (x))
4376 root 1.2 memcpy (pos, strvalue (car (x)), strlength (car (x)));
4377 root 1.1
4378     s_return (newstr);
4379     }
4380    
4381     case OP_SUBSTR: /* substring */
4382     {
4383 root 1.26 char *str = strvalue (x);
4384     int index0 = ivalue_unchecked (cadr (args));
4385 root 1.1 int index1;
4386     int len;
4387    
4388 root 1.16 if (index0 > strlength (x))
4389     Error_1 ("substring: start out of bounds:", cadr (args));
4390 root 1.1
4391 root 1.16 if (cddr (args) != NIL)
4392 root 1.1 {
4393 root 1.26 index1 = ivalue_unchecked (caddr (args));
4394 root 1.1
4395 root 1.16 if (index1 > strlength (x) || index1 < index0)
4396     Error_1 ("substring: end out of bounds:", caddr (args));
4397 root 1.1 }
4398     else
4399 root 1.16 index1 = strlength (x);
4400 root 1.1
4401     len = index1 - index0;
4402     x = mk_empty_string (SCHEME_A_ len, ' ');
4403     memcpy (strvalue (x), str + index0, len);
4404     strvalue (x)[len] = 0;
4405    
4406     s_return (x);
4407     }
4408    
4409     case OP_VECTOR: /* vector */
4410     {
4411     int i;
4412     pointer vec;
4413 root 1.16 int len = list_length (SCHEME_A_ args);
4414 root 1.1
4415     if (len < 0)
4416 root 1.16 Error_1 ("vector: not a proper list:", args);
4417 root 1.1
4418     vec = mk_vector (SCHEME_A_ len);
4419    
4420     #if USE_ERROR_CHECKING
4421     if (SCHEME_V->no_memory)
4422     s_return (S_SINK);
4423     #endif
4424    
4425 root 1.16 for (x = args, i = 0; is_pair (x); x = cdr (x), i++)
4426 root 1.28 vector_set (vec, i, car (x));
4427 root 1.1
4428     s_return (vec);
4429     }
4430    
4431     case OP_MKVECTOR: /* make-vector */
4432     {
4433     pointer fill = NIL;
4434     pointer vec;
4435 root 1.26 int len = ivalue_unchecked (x);
4436 root 1.1
4437 root 1.16 if (cdr (args) != NIL)
4438     fill = cadr (args);
4439 root 1.1
4440     vec = mk_vector (SCHEME_A_ len);
4441    
4442     #if USE_ERROR_CHECKING
4443     if (SCHEME_V->no_memory)
4444     s_return (S_SINK);
4445     #endif
4446    
4447     if (fill != NIL)
4448 root 1.28 fill_vector (vec, 0, fill);
4449 root 1.1
4450     s_return (vec);
4451     }
4452    
4453     case OP_VECLEN: /* vector-length */
4454 root 1.16 s_return (mk_integer (SCHEME_A_ veclength (x)));
4455 root 1.1
4456 root 1.37 case OP_VECRESIZE:
4457     vector_resize (x, ivalue_unchecked (cadr (args)), caddr (args));
4458     s_return (x);
4459    
4460 root 1.1 case OP_VECREF: /* vector-ref */
4461     {
4462 root 1.26 int index = ivalue_unchecked (cadr (args));
4463 root 1.1
4464 root 1.16 if (index >= veclength (car (args)) && USE_ERROR_CHECKING)
4465     Error_1 ("vector-ref: out of bounds:", cadr (args));
4466 root 1.1
4467 root 1.28 s_return (vector_get (x, index));
4468 root 1.1 }
4469    
4470     case OP_VECSET: /* vector-set! */
4471     {
4472 root 1.26 int index = ivalue_unchecked (cadr (args));
4473 root 1.1
4474 root 1.16 if (is_immutable (x))
4475     Error_1 ("vector-set!: unable to alter immutable vector:", x);
4476 root 1.1
4477 root 1.16 if (index >= veclength (car (args)) && USE_ERROR_CHECKING)
4478     Error_1 ("vector-set!: out of bounds:", cadr (args));
4479 root 1.1
4480 root 1.28 vector_set (x, index, caddr (args));
4481 root 1.16 s_return (x);
4482 root 1.1 }
4483     }
4484    
4485 root 1.24 if (USE_ERROR_CHECKING) abort ();
4486 root 1.1 }
4487    
4488 root 1.20 static int
4489     opexe_2 (SCHEME_P_ enum scheme_opcodes op)
4490 root 1.1 {
4491 root 1.14 pointer x = SCHEME_V->args;
4492 root 1.1
4493 root 1.14 for (;;)
4494 root 1.1 {
4495 root 1.14 num v = nvalue (car (x));
4496     x = cdr (x);
4497 root 1.1
4498 root 1.14 if (x == NIL)
4499     break;
4500 root 1.1
4501 root 1.14 int r = num_cmp (v, nvalue (car (x)));
4502 root 1.1
4503 root 1.14 switch (op)
4504     {
4505     case OP_NUMEQ: r = r == 0; break;
4506     case OP_LESS: r = r < 0; break;
4507     case OP_GRE: r = r > 0; break;
4508     case OP_LEQ: r = r <= 0; break;
4509     case OP_GEQ: r = r >= 0; break;
4510     }
4511 root 1.1
4512 root 1.14 if (!r)
4513     s_return (S_F);
4514     }
4515 root 1.1
4516 root 1.14 s_return (S_T);
4517     }
4518 root 1.1
4519 root 1.20 static int
4520 root 1.14 opexe_3 (SCHEME_P_ enum scheme_opcodes op)
4521     {
4522 root 1.16 pointer args = SCHEME_V->args;
4523     pointer a = car (args);
4524     pointer d = cdr (args);
4525 root 1.14 int r;
4526 root 1.1
4527 root 1.14 switch (op)
4528     {
4529 root 1.43 case OP_NOT: /* not */ r = is_false (a) ; break;
4530     case OP_BOOLP: /* boolean? */ r = a == S_F || a == S_T ; break;
4531     case OP_EOFOBJP: /* eof-object? */ r = a == S_EOF ; break;
4532     case OP_NULLP: /* null? */ r = a == NIL ; break;
4533     case OP_SYMBOLP: /* symbol? */ r = is_symbol (a) ; break;
4534     case OP_GENSYMP: /* gensym? */ r = is_gensym (SCHEME_A_ a); break;
4535     case OP_NUMBERP: /* number? */ r = is_number (a) ; break;
4536     case OP_STRINGP: /* string? */ r = is_string (a) ; break;
4537     case OP_INTEGERP: /* integer? */ r = is_integer (a) ; break;
4538     case OP_REALP: /* real? */ r = is_number (a) ; break; /* all numbers are real */
4539     case OP_CHARP: /* char? */ r = is_character (a) ; break;
4540 root 1.14
4541 root 1.1 #if USE_CHAR_CLASSIFIERS
4542 root 1.26 case OP_CHARAP: /* char-alphabetic? */ r = Cisalpha (ivalue_unchecked (a)); break;
4543     case OP_CHARNP: /* char-numeric? */ r = Cisdigit (ivalue_unchecked (a)); break;
4544     case OP_CHARWP: /* char-whitespace? */ r = Cisspace (ivalue_unchecked (a)); break;
4545     case OP_CHARUP: /* char-upper-case? */ r = Cisupper (ivalue_unchecked (a)); break;
4546     case OP_CHARLP: /* char-lower-case? */ r = Cislower (ivalue_unchecked (a)); break;
4547 root 1.1 #endif
4548 root 1.14
4549 root 1.1 #if USE_PORTS
4550 root 1.15 case OP_PORTP: /* port? */ r = is_port (a) ; break;
4551     case OP_INPORTP: /* input-port? */ r = is_inport (a) ; break;
4552     case OP_OUTPORTP: /* output-port? */ r = is_outport (a); break;
4553 root 1.1 #endif
4554    
4555     case OP_PROCP: /* procedure? */
4556    
4557 root 1.14 /*--
4558     * continuation should be procedure by the example
4559     * (call-with-current-continuation procedure?) ==> #t
4560     * in R^3 report sec. 6.9
4561     */
4562     r = is_proc (a) || is_closure (a) || is_continuation (a) || is_foreign (a);
4563     break;
4564 root 1.1
4565 root 1.15 case OP_PAIRP: /* pair? */ r = is_pair (a) ; break;
4566     case OP_LISTP: /* list? */ r = list_length (SCHEME_A_ a) >= 0; break;
4567     case OP_ENVP: /* environment? */ r = is_environment (a) ; break;
4568     case OP_VECTORP: /* vector? */ r = is_vector (a) ; break;
4569 root 1.16 case OP_EQ: /* eq? */ r = a == cadr (args) ; break;
4570     case OP_EQV: /* eqv? */ r = eqv (a, cadr (args)) ; break;
4571 root 1.1 }
4572    
4573 root 1.14 s_retbool (r);
4574 root 1.1 }
4575    
4576 root 1.20 static int
4577 root 1.1 opexe_4 (SCHEME_P_ enum scheme_opcodes op)
4578     {
4579 root 1.16 pointer args = SCHEME_V->args;
4580     pointer a = car (args);
4581 root 1.1 pointer x, y;
4582    
4583     switch (op)
4584     {
4585     case OP_FORCE: /* force */
4586 root 1.16 SCHEME_V->code = a;
4587 root 1.1
4588     if (is_promise (SCHEME_V->code))
4589     {
4590     /* Should change type to closure here */
4591     s_save (SCHEME_A_ OP_SAVE_FORCED, NIL, SCHEME_V->code);
4592     SCHEME_V->args = NIL;
4593     s_goto (OP_APPLY);
4594     }
4595     else
4596 root 1.2 s_return (SCHEME_V->code);
4597 root 1.1
4598     case OP_SAVE_FORCED: /* Save forced value replacing promise */
4599 root 1.51 *CELL (SCHEME_V->code) = *CELL (SCHEME_V->value);
4600 root 1.1 s_return (SCHEME_V->value);
4601    
4602     #if USE_PORTS
4603    
4604     case OP_WRITE: /* write */
4605     case OP_DISPLAY: /* display */
4606     case OP_WRITE_CHAR: /* write-char */
4607     if (is_pair (cdr (SCHEME_V->args)))
4608     {
4609     if (cadr (SCHEME_V->args) != SCHEME_V->outport)
4610     {
4611     x = cons (SCHEME_V->outport, NIL);
4612     s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
4613     SCHEME_V->outport = cadr (SCHEME_V->args);
4614     }
4615     }
4616    
4617 root 1.16 SCHEME_V->args = a;
4618 root 1.1
4619     if (op == OP_WRITE)
4620     SCHEME_V->print_flag = 1;
4621     else
4622     SCHEME_V->print_flag = 0;
4623    
4624     s_goto (OP_P0LIST);
4625    
4626     case OP_NEWLINE: /* newline */
4627 root 1.16 if (is_pair (args))
4628 root 1.1 {
4629 root 1.16 if (a != SCHEME_V->outport)
4630 root 1.1 {
4631     x = cons (SCHEME_V->outport, NIL);
4632     s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
4633 root 1.16 SCHEME_V->outport = a;
4634 root 1.1 }
4635     }
4636    
4637     putstr (SCHEME_A_ "\n");
4638     s_return (S_T);
4639     #endif
4640    
4641     case OP_ERR0: /* error */
4642     SCHEME_V->retcode = -1;
4643    
4644 root 1.16 if (!is_string (a))
4645 root 1.1 {
4646 root 1.16 args = cons (mk_string (SCHEME_A_ " -- "), args);
4647     setimmutable (car (args));
4648 root 1.1 }
4649    
4650     putstr (SCHEME_A_ "Error: ");
4651 root 1.16 putstr (SCHEME_A_ strvalue (car (args)));
4652     SCHEME_V->args = cdr (args);
4653 root 1.1 s_goto (OP_ERR1);
4654    
4655     case OP_ERR1: /* error */
4656     putstr (SCHEME_A_ " ");
4657    
4658 root 1.16 if (args != NIL)
4659 root 1.1 {
4660 root 1.16 s_save (SCHEME_A_ OP_ERR1, cdr (args), NIL);
4661     SCHEME_V->args = a;
4662 root 1.1 SCHEME_V->print_flag = 1;
4663     s_goto (OP_P0LIST);
4664     }
4665     else
4666     {
4667     putstr (SCHEME_A_ "\n");
4668    
4669     if (SCHEME_V->interactive_repl)
4670 root 1.2 s_goto (OP_T0LVL);
4671 root 1.1 else
4672 root 1.20 return -1;
4673 root 1.1 }
4674    
4675     case OP_REVERSE: /* reverse */
4676 root 1.16 s_return (reverse (SCHEME_A_ a));
4677 root 1.1
4678     case OP_LIST_STAR: /* list* */
4679     s_return (list_star (SCHEME_A_ SCHEME_V->args));
4680    
4681     case OP_APPEND: /* append */
4682     x = NIL;
4683 root 1.16 y = args;
4684 root 1.1
4685     if (y == x)
4686     s_return (x);
4687    
4688     /* cdr() in the while condition is not a typo. If car() */
4689     /* is used (append '() 'a) will return the wrong result. */
4690     while (cdr (y) != NIL)
4691     {
4692     x = revappend (SCHEME_A_ x, car (y));
4693     y = cdr (y);
4694    
4695     if (x == S_F)
4696     Error_0 ("non-list argument to append");
4697     }
4698    
4699     s_return (reverse_in_place (SCHEME_A_ car (y), x));
4700    
4701     #if USE_PLIST
4702    
4703     case OP_PUT: /* put */
4704 root 1.16 if (!hasprop (a) || !hasprop (cadr (args)))
4705 root 1.2 Error_0 ("illegal use of put");
4706 root 1.1
4707 root 1.16 for (x = symprop (a), y = cadr (args); x != NIL; x = cdr (x))
4708 root 1.1 {
4709     if (caar (x) == y)
4710 root 1.2 break;
4711 root 1.1 }
4712    
4713     if (x != NIL)
4714 root 1.16 cdar (x) = caddr (args);
4715 root 1.1 else
4716 root 1.16 symprop (a) = cons (cons (y, caddr (args)), symprop (a));
4717 root 1.1
4718     s_return (S_T);
4719    
4720     case OP_GET: /* get */
4721 root 1.16 if (!hasprop (a) || !hasprop (cadr (args)))
4722 root 1.1 Error_0 ("illegal use of get");
4723    
4724 root 1.16 for (x = symprop (a), y = cadr (args); x != NIL; x = cdr (x))
4725 root 1.1 if (caar (x) == y)
4726     break;
4727    
4728     if (x != NIL)
4729     s_return (cdar (x));
4730     else
4731     s_return (NIL);
4732    
4733     #endif /* USE_PLIST */
4734    
4735     case OP_QUIT: /* quit */
4736 root 1.16 if (is_pair (args))
4737     SCHEME_V->retcode = ivalue (a);
4738 root 1.1
4739 root 1.20 return -1;
4740 root 1.1
4741     case OP_GC: /* gc */
4742     gc (SCHEME_A_ NIL, NIL);
4743     s_return (S_T);
4744    
4745     case OP_GCVERB: /* gc-verbose */
4746     {
4747     int was = SCHEME_V->gc_verbose;
4748    
4749 root 1.16 SCHEME_V->gc_verbose = (a != S_F);
4750 root 1.1 s_retbool (was);
4751     }
4752    
4753     case OP_NEWSEGMENT: /* new-segment */
4754 root 1.51 #if 0
4755 root 1.16 if (!is_pair (args) || !is_number (a))
4756 root 1.1 Error_0 ("new-segment: argument must be a number");
4757 root 1.51 #endif
4758     s_retbool (alloc_cellseg (SCHEME_A));
4759 root 1.1
4760     case OP_OBLIST: /* oblist */
4761     s_return (oblist_all_symbols (SCHEME_A));
4762    
4763     #if USE_PORTS
4764    
4765     case OP_CURR_INPORT: /* current-input-port */
4766     s_return (SCHEME_V->inport);
4767    
4768     case OP_CURR_OUTPORT: /* current-output-port */
4769     s_return (SCHEME_V->outport);
4770    
4771     case OP_OPEN_INFILE: /* open-input-file */
4772     case OP_OPEN_OUTFILE: /* open-output-file */
4773     case OP_OPEN_INOUTFILE: /* open-input-output-file */
4774     {
4775     int prop = 0;
4776     pointer p;
4777    
4778     switch (op)
4779     {
4780     case OP_OPEN_INFILE:
4781     prop = port_input;
4782     break;
4783    
4784     case OP_OPEN_OUTFILE:
4785     prop = port_output;
4786     break;
4787    
4788     case OP_OPEN_INOUTFILE:
4789     prop = port_input | port_output;
4790     break;
4791     }
4792    
4793 root 1.16 p = port_from_filename (SCHEME_A_ strvalue (a), prop);
4794 root 1.1
4795 root 1.23 s_return (p == NIL ? S_F : p);
4796 root 1.1 }
4797    
4798     # if USE_STRING_PORTS
4799    
4800     case OP_OPEN_INSTRING: /* open-input-string */
4801     case OP_OPEN_INOUTSTRING: /* open-input-output-string */
4802     {
4803     int prop = 0;
4804     pointer p;
4805    
4806     switch (op)
4807     {
4808     case OP_OPEN_INSTRING:
4809     prop = port_input;
4810     break;
4811    
4812     case OP_OPEN_INOUTSTRING:
4813     prop = port_input | port_output;
4814     break;
4815     }
4816    
4817 root 1.16 p = port_from_string (SCHEME_A_ strvalue (a),
4818     strvalue (a) + strlength (a), prop);
4819 root 1.1
4820 root 1.23 s_return (p == NIL ? S_F : p);
4821 root 1.1 }
4822    
4823     case OP_OPEN_OUTSTRING: /* open-output-string */
4824     {
4825     pointer p;
4826    
4827 root 1.16 if (a == NIL)
4828 root 1.23 p = port_from_scratch (SCHEME_A);
4829 root 1.1 else
4830 root 1.23 p = port_from_string (SCHEME_A_ strvalue (a),
4831     strvalue (a) + strlength (a), port_output);
4832 root 1.1
4833 root 1.23 s_return (p == NIL ? S_F : p);
4834 root 1.1 }
4835    
4836     case OP_GET_OUTSTRING: /* get-output-string */
4837     {
4838 root 1.51 port *p = port (a);
4839 root 1.1
4840 root 1.51 if (p->kind & port_string)
4841 root 1.1 {
4842     off_t size;
4843     char *str;
4844    
4845     size = p->rep.string.curr - p->rep.string.start + 1;
4846     str = malloc (size);
4847    
4848     if (str != NULL)
4849     {
4850     pointer s;
4851    
4852     memcpy (str, p->rep.string.start, size - 1);
4853     str[size - 1] = '\0';
4854     s = mk_string (SCHEME_A_ str);
4855     free (str);
4856     s_return (s);
4857     }
4858     }
4859    
4860     s_return (S_F);
4861     }
4862    
4863     # endif
4864    
4865     case OP_CLOSE_INPORT: /* close-input-port */
4866 root 1.16 port_close (SCHEME_A_ a, port_input);
4867 root 1.1 s_return (S_T);
4868    
4869     case OP_CLOSE_OUTPORT: /* close-output-port */
4870 root 1.16 port_close (SCHEME_A_ a, port_output);
4871 root 1.1 s_return (S_T);
4872     #endif
4873    
4874     case OP_INT_ENV: /* interaction-environment */
4875     s_return (SCHEME_V->global_env);
4876    
4877     case OP_CURR_ENV: /* current-environment */
4878     s_return (SCHEME_V->envir);
4879    
4880     }
4881    
4882 root 1.24 if (USE_ERROR_CHECKING) abort ();
4883 root 1.1 }
4884    
4885 root 1.20 static int
4886 root 1.1 opexe_5 (SCHEME_P_ enum scheme_opcodes op)
4887     {
4888 root 1.18 pointer args = SCHEME_V->args;
4889 root 1.1 pointer x;
4890    
4891     if (SCHEME_V->nesting != 0)
4892     {
4893     int n = SCHEME_V->nesting;
4894    
4895     SCHEME_V->nesting = 0;
4896     SCHEME_V->retcode = -1;
4897     Error_1 ("unmatched parentheses:", mk_integer (SCHEME_A_ n));
4898     }
4899    
4900     switch (op)
4901     {
4902     /* ========== reading part ========== */
4903     #if USE_PORTS
4904     case OP_READ:
4905 root 1.18 if (!is_pair (args))
4906 root 1.2 s_goto (OP_READ_INTERNAL);
4907 root 1.1
4908 root 1.18 if (!is_inport (car (args)))
4909     Error_1 ("read: not an input port:", car (args));
4910 root 1.1
4911 root 1.18 if (car (args) == SCHEME_V->inport)
4912 root 1.2 s_goto (OP_READ_INTERNAL);
4913 root 1.1
4914     x = SCHEME_V->inport;
4915 root 1.18 SCHEME_V->inport = car (args);
4916 root 1.1 x = cons (x, NIL);
4917     s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
4918     s_goto (OP_READ_INTERNAL);
4919    
4920     case OP_READ_CHAR: /* read-char */
4921     case OP_PEEK_CHAR: /* peek-char */
4922     {
4923     int c;
4924    
4925 root 1.18 if (is_pair (args))
4926 root 1.1 {
4927 root 1.18 if (car (args) != SCHEME_V->inport)
4928 root 1.1 {
4929     x = SCHEME_V->inport;
4930     x = cons (x, NIL);
4931     s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
4932 root 1.18 SCHEME_V->inport = car (args);
4933 root 1.1 }
4934     }
4935    
4936     c = inchar (SCHEME_A);
4937    
4938     if (c == EOF)
4939     s_return (S_EOF);
4940    
4941     if (SCHEME_V->op == OP_PEEK_CHAR)
4942     backchar (SCHEME_A_ c);
4943    
4944     s_return (mk_character (SCHEME_A_ c));
4945     }
4946    
4947     case OP_CHAR_READY: /* char-ready? */
4948     {
4949     pointer p = SCHEME_V->inport;
4950     int res;
4951    
4952 root 1.18 if (is_pair (args))
4953     p = car (args);
4954 root 1.1
4955 root 1.51 res = port (p)->kind & port_string;
4956 root 1.1
4957     s_retbool (res);
4958     }
4959    
4960     case OP_SET_INPORT: /* set-input-port */
4961 root 1.18 SCHEME_V->inport = car (args);
4962 root 1.1 s_return (SCHEME_V->value);
4963    
4964     case OP_SET_OUTPORT: /* set-output-port */
4965 root 1.18 SCHEME_V->outport = car (args);
4966 root 1.1 s_return (SCHEME_V->value);
4967     #endif
4968    
4969     case OP_RDSEXPR:
4970     switch (SCHEME_V->tok)
4971     {
4972     case TOK_EOF:
4973     s_return (S_EOF);
4974     /* NOTREACHED */
4975    
4976     case TOK_VEC:
4977     s_save (SCHEME_A_ OP_RDVEC, NIL, NIL);
4978 root 1.2 /* fall through */
4979 root 1.1
4980     case TOK_LPAREN:
4981     SCHEME_V->tok = token (SCHEME_A);
4982    
4983     if (SCHEME_V->tok == TOK_RPAREN)
4984     s_return (NIL);
4985     else if (SCHEME_V->tok == TOK_DOT)
4986     Error_0 ("syntax error: illegal dot expression");
4987     else
4988     {
4989     SCHEME_V->nesting_stack[SCHEME_V->file_i]++;
4990     s_save (SCHEME_A_ OP_RDLIST, NIL, NIL);
4991     s_goto (OP_RDSEXPR);
4992     }
4993    
4994     case TOK_QUOTE:
4995     s_save (SCHEME_A_ OP_RDQUOTE, NIL, NIL);
4996     SCHEME_V->tok = token (SCHEME_A);
4997     s_goto (OP_RDSEXPR);
4998    
4999     case TOK_BQUOTE:
5000     SCHEME_V->tok = token (SCHEME_A);
5001    
5002     if (SCHEME_V->tok == TOK_VEC)
5003     {
5004     s_save (SCHEME_A_ OP_RDQQUOTEVEC, NIL, NIL);
5005     SCHEME_V->tok = TOK_LPAREN;
5006     s_goto (OP_RDSEXPR);
5007     }
5008     else
5009 root 1.2 s_save (SCHEME_A_ OP_RDQQUOTE, NIL, NIL);
5010 root 1.1
5011     s_goto (OP_RDSEXPR);
5012    
5013     case TOK_COMMA:
5014     s_save (SCHEME_A_ OP_RDUNQUOTE, NIL, NIL);
5015     SCHEME_V->tok = token (SCHEME_A);
5016     s_goto (OP_RDSEXPR);
5017    
5018     case TOK_ATMARK:
5019     s_save (SCHEME_A_ OP_RDUQTSP, NIL, NIL);
5020     SCHEME_V->tok = token (SCHEME_A);
5021     s_goto (OP_RDSEXPR);
5022    
5023     case TOK_ATOM:
5024 root 1.35 s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ 0, DELIMITERS)));
5025    
5026     case TOK_DOTATOM:
5027     SCHEME_V->strbuff[0] = '.';
5028     s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ 1, DELIMITERS)));
5029 root 1.1
5030 root 1.36 case TOK_STRATOM:
5031     x = readstrexp (SCHEME_A_ '|');
5032     //TODO: haven't checked whether the garbage collector could interfere
5033     s_return (mk_atom (SCHEME_A_ strvalue (x)));
5034    
5035 root 1.1 case TOK_DQUOTE:
5036 root 1.35 x = readstrexp (SCHEME_A_ '"');
5037 root 1.1
5038     if (x == S_F)
5039     Error_0 ("Error reading string");
5040    
5041     setimmutable (x);
5042     s_return (x);
5043    
5044     case TOK_SHARP:
5045     {
5046     pointer f = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->SHARP_HOOK, 1);
5047    
5048     if (f == NIL)
5049     Error_0 ("undefined sharp expression");
5050     else
5051     {
5052     SCHEME_V->code = cons (slot_value_in_env (f), NIL);
5053     s_goto (OP_EVAL);
5054     }
5055     }
5056    
5057     case TOK_SHARP_CONST:
5058 root 1.35 if ((x = mk_sharp_const (SCHEME_A_ readstr_upto (SCHEME_A_ 0, DELIMITERS))) == NIL)
5059 root 1.1 Error_0 ("undefined sharp expression");
5060     else
5061     s_return (x);
5062    
5063     default:
5064     Error_0 ("syntax error: illegal token");
5065     }
5066    
5067     break;
5068    
5069     case OP_RDLIST:
5070 root 1.18 SCHEME_V->args = cons (SCHEME_V->value, args);
5071 root 1.2 SCHEME_V->tok = token (SCHEME_A);
5072 root 1.1
5073 root 1.2 switch (SCHEME_V->tok)
5074     {
5075     case TOK_EOF:
5076     s_return (S_EOF);
5077 root 1.1
5078 root 1.2 case TOK_RPAREN:
5079     {
5080     int c = inchar (SCHEME_A);
5081 root 1.1
5082 root 1.2 if (c != '\n')
5083     backchar (SCHEME_A_ c);
5084 root 1.1 #if SHOW_ERROR_LINE
5085 root 1.2 else if (SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
5086     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line++;
5087     #endif
5088 root 1.1
5089 root 1.2 SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5090     s_return (reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args));
5091     }
5092    
5093     case TOK_DOT:
5094 root 1.1 s_save (SCHEME_A_ OP_RDDOT, SCHEME_V->args, NIL);
5095     SCHEME_V->tok = token (SCHEME_A);
5096     s_goto (OP_RDSEXPR);
5097 root 1.2
5098     default:
5099     s_save (SCHEME_A_ OP_RDLIST, SCHEME_V->args, NIL);
5100 root 1.1 s_goto (OP_RDSEXPR);
5101 root 1.2 }
5102 root 1.1
5103     case OP_RDDOT:
5104     if (token (SCHEME_A) != TOK_RPAREN)
5105     Error_0 ("syntax error: illegal dot expression");
5106 root 1.2
5107     SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5108 root 1.18 s_return (reverse_in_place (SCHEME_A_ SCHEME_V->value, args));
5109 root 1.1
5110     case OP_RDQUOTE:
5111     s_return (cons (SCHEME_V->QUOTE, cons (SCHEME_V->value, NIL)));
5112    
5113     case OP_RDQQUOTE:
5114     s_return (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)));
5115    
5116     case OP_RDQQUOTEVEC:
5117     s_return (cons (mk_symbol (SCHEME_A_ "apply"),
5118     cons (mk_symbol (SCHEME_A_ "vector"),
5119     cons (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)), NIL))));
5120    
5121     case OP_RDUNQUOTE:
5122     s_return (cons (SCHEME_V->UNQUOTE, cons (SCHEME_V->value, NIL)));
5123    
5124     case OP_RDUQTSP:
5125     s_return (cons (SCHEME_V->UNQUOTESP, cons (SCHEME_V->value, NIL)));
5126    
5127     case OP_RDVEC:
5128     /*SCHEME_V->code=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5129     s_goto(OP_EVAL); Cannot be quoted */
5130     /*x=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5131     s_return(x); Cannot be part of pairs */
5132     /*SCHEME_V->code=mk_proc(SCHEME_A_ OP_VECTOR);
5133     SCHEME_V->args=SCHEME_V->value;
5134     s_goto(OP_APPLY); */
5135     SCHEME_V->args = SCHEME_V->value;
5136     s_goto (OP_VECTOR);
5137    
5138     /* ========== printing part ========== */
5139     case OP_P0LIST:
5140 root 1.18 if (is_vector (args))
5141 root 1.1 {
5142     putstr (SCHEME_A_ "#(");
5143 root 1.18 SCHEME_V->args = cons (args, mk_integer (SCHEME_A_ 0));
5144 root 1.1 s_goto (OP_PVECFROM);
5145     }
5146 root 1.18 else if (is_environment (args))
5147 root 1.1 {
5148     putstr (SCHEME_A_ "#<ENVIRONMENT>");
5149     s_return (S_T);
5150     }
5151 root 1.18 else if (!is_pair (args))
5152 root 1.1 {
5153 root 1.18 printatom (SCHEME_A_ args, SCHEME_V->print_flag);
5154 root 1.1 s_return (S_T);
5155     }
5156     else
5157     {
5158 root 1.18 pointer a = car (args);
5159     pointer b = cdr (args);
5160     int ok_abbr = ok_abbrev (b);
5161     SCHEME_V->args = car (b);
5162    
5163     if (a == SCHEME_V->QUOTE && ok_abbr)
5164     putstr (SCHEME_A_ "'");
5165     else if (a == SCHEME_V->QQUOTE && ok_abbr)
5166     putstr (SCHEME_A_ "`");
5167     else if (a == SCHEME_V->UNQUOTE && ok_abbr)
5168     putstr (SCHEME_A_ ",");
5169     else if (a == SCHEME_V->UNQUOTESP && ok_abbr)
5170     putstr (SCHEME_A_ ",@");
5171     else
5172     {
5173     putstr (SCHEME_A_ "(");
5174     s_save (SCHEME_A_ OP_P1LIST, b, NIL);
5175     SCHEME_V->args = a;
5176     }
5177    
5178 root 1.1 s_goto (OP_P0LIST);
5179     }
5180    
5181     case OP_P1LIST:
5182 root 1.18 if (is_pair (args))
5183 root 1.1 {
5184 root 1.18 s_save (SCHEME_A_ OP_P1LIST, cdr (args), NIL);
5185 root 1.1 putstr (SCHEME_A_ " ");
5186 root 1.18 SCHEME_V->args = car (args);
5187 root 1.1 s_goto (OP_P0LIST);
5188     }
5189 root 1.18 else if (is_vector (args))
5190 root 1.1 {
5191     s_save (SCHEME_A_ OP_P1LIST, NIL, NIL);
5192     putstr (SCHEME_A_ " . ");
5193     s_goto (OP_P0LIST);
5194     }
5195     else
5196     {
5197 root 1.18 if (args != NIL)
5198 root 1.1 {
5199     putstr (SCHEME_A_ " . ");
5200 root 1.18 printatom (SCHEME_A_ args, SCHEME_V->print_flag);
5201 root 1.1 }
5202    
5203     putstr (SCHEME_A_ ")");
5204     s_return (S_T);
5205     }
5206    
5207     case OP_PVECFROM:
5208     {
5209 root 1.18 int i = ivalue_unchecked (cdr (args));
5210     pointer vec = car (args);
5211 root 1.7 int len = veclength (vec);
5212 root 1.1
5213     if (i == len)
5214     {
5215     putstr (SCHEME_A_ ")");
5216     s_return (S_T);
5217     }
5218     else
5219     {
5220 root 1.28 pointer elem = vector_get (vec, i);
5221 root 1.1
5222 root 1.18 ivalue_unchecked (cdr (args)) = i + 1;
5223     s_save (SCHEME_A_ OP_PVECFROM, args, NIL);
5224 root 1.1 SCHEME_V->args = elem;
5225    
5226     if (i > 0)
5227     putstr (SCHEME_A_ " ");
5228    
5229     s_goto (OP_P0LIST);
5230     }
5231     }
5232     }
5233    
5234 root 1.24 if (USE_ERROR_CHECKING) abort ();
5235 root 1.1 }
5236    
5237 root 1.20 static int
5238 root 1.1 opexe_6 (SCHEME_P_ enum scheme_opcodes op)
5239     {
5240 root 1.18 pointer args = SCHEME_V->args;
5241     pointer a = car (args);
5242 root 1.1 pointer x, y;
5243    
5244     switch (op)
5245     {
5246     case OP_LIST_LENGTH: /* length *//* a.k */
5247     {
5248 root 1.18 long v = list_length (SCHEME_A_ a);
5249 root 1.1
5250     if (v < 0)
5251 root 1.18 Error_1 ("length: not a list:", a);
5252 root 1.1
5253     s_return (mk_integer (SCHEME_A_ v));
5254     }
5255    
5256     case OP_ASSQ: /* assq *//* a.k */
5257 root 1.18 x = a;
5258 root 1.1
5259 root 1.18 for (y = cadr (args); is_pair (y); y = cdr (y))
5260 root 1.1 {
5261     if (!is_pair (car (y)))
5262     Error_0 ("unable to handle non pair element");
5263    
5264     if (x == caar (y))
5265     break;
5266     }
5267    
5268     if (is_pair (y))
5269     s_return (car (y));
5270     else
5271     s_return (S_F);
5272    
5273    
5274     case OP_GET_CLOSURE: /* get-closure-code *//* a.k */
5275 root 1.18 SCHEME_V->args = a;
5276 root 1.1
5277     if (SCHEME_V->args == NIL)
5278     s_return (S_F);
5279     else if (is_closure (SCHEME_V->args))
5280     s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5281     else if (is_macro (SCHEME_V->args))
5282     s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5283     else
5284     s_return (S_F);
5285    
5286     case OP_CLOSUREP: /* closure? */
5287     /*
5288     * Note, macro object is also a closure.
5289     * Therefore, (closure? <#MACRO>) ==> #t
5290 root 1.38 * (schmorp) well, obviously not, fix? TODO
5291 root 1.1 */
5292 root 1.18 s_retbool (is_closure (a));
5293 root 1.1
5294     case OP_MACROP: /* macro? */
5295 root 1.18 s_retbool (is_macro (a));
5296 root 1.1 }
5297    
5298 root 1.24 if (USE_ERROR_CHECKING) abort ();
5299 root 1.1 }
5300    
5301 root 1.20 /* dispatch functions (opexe_x) return new opcode, or 0 for same opcode, or -1 to stop */
5302     typedef int (*dispatch_func)(SCHEME_P_ enum scheme_opcodes);
5303 root 1.1
5304 root 1.19 typedef int (*test_predicate)(pointer);
5305 root 1.1 static int
5306 root 1.26 tst_any (pointer p)
5307 root 1.1 {
5308     return 1;
5309     }
5310    
5311     static int
5312 root 1.26 tst_inonneg (pointer p)
5313 root 1.1 {
5314 root 1.26 return is_integer (p) && ivalue_unchecked (p) >= 0;
5315 root 1.1 }
5316    
5317 root 1.19 static int
5318 root 1.26 tst_is_list (SCHEME_P_ pointer p)
5319 root 1.19 {
5320     return p == NIL || is_pair (p);
5321     }
5322    
5323 root 1.1 /* Correspond carefully with following defines! */
5324     static struct
5325     {
5326     test_predicate fct;
5327     const char *kind;
5328 root 1.26 } tests[] = {
5329     { tst_any , 0 },
5330     { is_string , "string" },
5331     { is_symbol , "symbol" },
5332     { is_port , "port" },
5333     { is_inport , "input port" },
5334     { is_outport , "output port" },
5335 root 1.19 { is_environment, "environment" },
5336 root 1.26 { is_pair , "pair" },
5337     { 0 , "pair or '()" },
5338     { is_character , "character" },
5339     { is_vector , "vector" },
5340     { is_number , "number" },
5341     { is_integer , "integer" },
5342     { tst_inonneg , "non-negative integer" }
5343 root 1.1 };
5344    
5345 root 1.20 #define TST_NONE 0 /* TST_NONE used for built-ins, 0 for internal ops */
5346 root 1.18 #define TST_ANY "\001"
5347     #define TST_STRING "\002"
5348     #define TST_SYMBOL "\003"
5349     #define TST_PORT "\004"
5350     #define TST_INPORT "\005"
5351     #define TST_OUTPORT "\006"
5352 root 1.1 #define TST_ENVIRONMENT "\007"
5353 root 1.18 #define TST_PAIR "\010"
5354     #define TST_LIST "\011"
5355     #define TST_CHAR "\012"
5356     #define TST_VECTOR "\013"
5357     #define TST_NUMBER "\014"
5358     #define TST_INTEGER "\015"
5359     #define TST_NATURAL "\016"
5360 root 1.1
5361 root 1.20 #define INF_ARG 0xff
5362     #define UNNAMED_OP ""
5363    
5364     static const char opnames[] =
5365     #define OP_DEF(func,name,minarity,maxarity,argtest,op) name "\x00"
5366     #include "opdefines.h"
5367     #undef OP_DEF
5368     ;
5369    
5370     static const char *
5371     opname (int idx)
5372     {
5373     const char *name = opnames;
5374    
5375     /* should do this at compile time, but would require external program, right? */
5376     while (idx--)
5377     name += strlen (name) + 1;
5378    
5379     return *name ? name : "ILLEGAL";
5380     }
5381    
5382     static const char *
5383     procname (pointer x)
5384     {
5385     return opname (procnum (x));
5386     }
5387    
5388 root 1.1 typedef struct
5389     {
5390 root 1.20 uint8_t func;
5391     /*dispatch_func func;*//*TODO: maybe optionally keep the pointer, for speed? */
5392     uint8_t builtin;
5393 root 1.26 #if USE_ERROR_CHECKING
5394 root 1.20 uint8_t min_arity;
5395     uint8_t max_arity;
5396 root 1.18 char arg_tests_encoding[3];
5397 root 1.26 #endif
5398 root 1.1 } op_code_info;
5399    
5400 root 1.20 static const op_code_info dispatch_table[] = {
5401 root 1.26 #if USE_ERROR_CHECKING
5402 root 1.20 #define OP_DEF(func,name,minarity,maxarity,argtest,op) { func, sizeof (name) > 1, minarity, maxarity, argtest },
5403 root 1.26 #else
5404     #define OP_DEF(func,name,minarity,maxarity,argtest,op) { func, sizeof (name) > 1 },
5405     #endif
5406 root 1.1 #include "opdefines.h"
5407 root 1.18 #undef OP_DEF
5408 root 1.1 {0}
5409     };
5410    
5411     /* kernel of this interpreter */
5412 root 1.23 static void ecb_hot
5413 root 1.1 Eval_Cycle (SCHEME_P_ enum scheme_opcodes op)
5414     {
5415     SCHEME_V->op = op;
5416    
5417     for (;;)
5418     {
5419 root 1.20 const op_code_info *pcd = dispatch_table + SCHEME_V->op;
5420 root 1.1
5421 root 1.4 #if USE_ERROR_CHECKING
5422 root 1.20 if (pcd->builtin) /* if built-in function, check arguments */
5423 root 1.1 {
5424     char msg[STRBUFFSIZE];
5425     int n = list_length (SCHEME_A_ SCHEME_V->args);
5426    
5427     /* Check number of arguments */
5428 root 1.10 if (ecb_expect_false (n < pcd->min_arity))
5429 root 1.1 {
5430     snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5431 root 1.20 opname (SCHEME_V->op), pcd->min_arity == pcd->max_arity ? "" : " at least", pcd->min_arity);
5432 root 1.21 xError_1 (SCHEME_A_ msg, 0);
5433     continue;
5434 root 1.1 }
5435 root 1.20 else if (ecb_expect_false (n > pcd->max_arity && pcd->max_arity != INF_ARG))
5436 root 1.1 {
5437     snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5438 root 1.20 opname (SCHEME_V->op), pcd->min_arity == pcd->max_arity ? "" : " at most", pcd->max_arity);
5439 root 1.21 xError_1 (SCHEME_A_ msg, 0);
5440     continue;
5441 root 1.1 }
5442 root 1.20 else
5443 root 1.1 {
5444 root 1.20 if (*pcd->arg_tests_encoding) /* literal 0 and TST_NONE treated the same */
5445 root 1.1 {
5446     int i = 0;
5447     int j;
5448     const char *t = pcd->arg_tests_encoding;
5449     pointer arglist = SCHEME_V->args;
5450    
5451     do
5452     {
5453     pointer arg = car (arglist);
5454    
5455 root 1.18 j = t[0];
5456 root 1.1
5457 root 1.26 /*TODO: tst_is_list has different prototype - fix if other tests acquire same prototype */
5458     if (j == TST_LIST[0])
5459     {
5460     if (!tst_is_list (SCHEME_A_ arg))
5461     break;
5462     }
5463     else
5464     {
5465     if (!tests[j - 1].fct (arg))
5466     break;
5467     }
5468 root 1.1
5469 root 1.28 if (t < pcd->arg_tests_encoding + sizeof (pcd->arg_tests_encoding) - 1 && t[1]) /* last test is replicated as necessary */
5470 root 1.2 t++;
5471 root 1.1
5472     arglist = cdr (arglist);
5473     i++;
5474     }
5475     while (i < n);
5476    
5477     if (i < n)
5478     {
5479 root 1.20 snprintf (msg, STRBUFFSIZE, "%s: argument %d must be: %s", opname (SCHEME_V->op), i + 1, tests[j].kind);
5480 root 1.21 xError_1 (SCHEME_A_ msg, 0);
5481     continue;
5482 root 1.1 }
5483     }
5484     }
5485     }
5486 root 1.4 #endif
5487 root 1.1
5488     ok_to_freely_gc (SCHEME_A);
5489    
5490 root 1.20 static const dispatch_func dispatch_funcs[] = {
5491     opexe_0,
5492     opexe_1,
5493     opexe_2,
5494     opexe_3,
5495     opexe_4,
5496     opexe_5,
5497     opexe_6,
5498     };
5499    
5500     if (ecb_expect_false (dispatch_funcs [pcd->func] (SCHEME_A_ SCHEME_V->op) != 0))
5501 root 1.1 return;
5502    
5503 root 1.5 if (SCHEME_V->no_memory && USE_ERROR_CHECKING)
5504 root 1.1 {
5505 root 1.53 putstr (SCHEME_A_ "No memory!\n");
5506 root 1.1 return;
5507     }
5508     }
5509     }
5510    
5511     /* ========== Initialization of internal keywords ========== */
5512    
5513     static void
5514 root 1.2 assign_syntax (SCHEME_P_ const char *name)
5515 root 1.1 {
5516     pointer x = oblist_add_by_name (SCHEME_A_ name);
5517     set_typeflag (x, typeflag (x) | T_SYNTAX);
5518     }
5519    
5520     static void
5521 root 1.2 assign_proc (SCHEME_P_ enum scheme_opcodes op, const char *name)
5522 root 1.1 {
5523     pointer x = mk_symbol (SCHEME_A_ name);
5524     pointer y = mk_proc (SCHEME_A_ op);
5525     new_slot_in_env (SCHEME_A_ x, y);
5526     }
5527    
5528     static pointer
5529     mk_proc (SCHEME_P_ enum scheme_opcodes op)
5530     {
5531     pointer y = get_cell (SCHEME_A_ NIL, NIL);
5532     set_typeflag (y, (T_PROC | T_ATOM));
5533 root 1.2 ivalue_unchecked (y) = op;
5534 root 1.1 return y;
5535     }
5536    
5537     /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
5538     static int
5539     syntaxnum (pointer p)
5540     {
5541 root 1.38 const char *s = strvalue (p);
5542 root 1.1
5543 root 1.38 switch (strlength (p))
5544 root 1.1 {
5545     case 2:
5546     if (s[0] == 'i')
5547     return OP_IF0; /* if */
5548     else
5549     return OP_OR0; /* or */
5550    
5551     case 3:
5552     if (s[0] == 'a')
5553     return OP_AND0; /* and */
5554     else
5555     return OP_LET0; /* let */
5556    
5557     case 4:
5558     switch (s[3])
5559     {
5560     case 'e':
5561     return OP_CASE0; /* case */
5562    
5563     case 'd':
5564     return OP_COND0; /* cond */
5565    
5566     case '*':
5567 root 1.10 return OP_LET0AST;/* let* */
5568 root 1.1
5569     default:
5570     return OP_SET0; /* set! */
5571     }
5572    
5573     case 5:
5574     switch (s[2])
5575     {
5576     case 'g':
5577     return OP_BEGIN; /* begin */
5578    
5579     case 'l':
5580     return OP_DELAY; /* delay */
5581    
5582     case 'c':
5583     return OP_MACRO0; /* macro */
5584    
5585     default:
5586     return OP_QUOTE; /* quote */
5587     }
5588    
5589     case 6:
5590     switch (s[2])
5591     {
5592     case 'm':
5593     return OP_LAMBDA; /* lambda */
5594    
5595     case 'f':
5596     return OP_DEF0; /* define */
5597    
5598     default:
5599 root 1.10 return OP_LET0REC;/* letrec */
5600 root 1.1 }
5601    
5602     default:
5603     return OP_C0STREAM; /* cons-stream */
5604     }
5605     }
5606    
5607     #if USE_MULTIPLICITY
5608 root 1.23 ecb_cold scheme *
5609 root 1.1 scheme_init_new ()
5610     {
5611     scheme *sc = malloc (sizeof (scheme));
5612    
5613     if (!scheme_init (SCHEME_A))
5614     {
5615     free (SCHEME_A);
5616     return 0;
5617     }
5618     else
5619     return sc;
5620     }
5621     #endif
5622    
5623 root 1.23 ecb_cold int
5624 root 1.1 scheme_init (SCHEME_P)
5625     {
5626     int i, n = sizeof (dispatch_table) / sizeof (dispatch_table[0]);
5627     pointer x;
5628    
5629 root 1.49 /* this memset is not strictly correct, as we assume (intcache)
5630     * that memset 0 will also set pointers to 0, but memset does
5631     * of course not guarantee that. screw such systems.
5632     */
5633     memset (SCHEME_V, 0, sizeof (*SCHEME_V));
5634 root 1.48
5635 root 1.1 num_set_fixnum (num_zero, 1);
5636     num_set_ivalue (num_zero, 0);
5637     num_set_fixnum (num_one, 1);
5638     num_set_ivalue (num_one, 1);
5639    
5640     #if USE_INTERFACE
5641     SCHEME_V->vptr = &vtbl;
5642     #endif
5643     SCHEME_V->gensym_cnt = 0;
5644     SCHEME_V->last_cell_seg = -1;
5645     SCHEME_V->free_cell = NIL;
5646     SCHEME_V->fcells = 0;
5647     SCHEME_V->no_memory = 0;
5648     SCHEME_V->inport = NIL;
5649     SCHEME_V->outport = NIL;
5650     SCHEME_V->save_inport = NIL;
5651     SCHEME_V->loadport = NIL;
5652     SCHEME_V->nesting = 0;
5653     SCHEME_V->interactive_repl = 0;
5654    
5655 root 1.51 if (!alloc_cellseg (SCHEME_A))
5656 root 1.1 {
5657     #if USE_ERROR_CHECKING
5658     SCHEME_V->no_memory = 1;
5659     return 0;
5660     #endif
5661     }
5662    
5663     SCHEME_V->gc_verbose = 0;
5664     dump_stack_initialize (SCHEME_A);
5665     SCHEME_V->code = NIL;
5666 root 1.2 SCHEME_V->args = NIL;
5667     SCHEME_V->envir = NIL;
5668 root 1.1 SCHEME_V->tracing = 0;
5669    
5670     /* init NIL */
5671 root 1.2 set_typeflag (NIL, T_ATOM | T_MARK);
5672 root 1.1 set_car (NIL, NIL);
5673     set_cdr (NIL, NIL);
5674     /* init T */
5675 root 1.2 set_typeflag (S_T, T_ATOM | T_MARK);
5676 root 1.1 set_car (S_T, S_T);
5677     set_cdr (S_T, S_T);
5678     /* init F */
5679 root 1.2 set_typeflag (S_F, T_ATOM | T_MARK);
5680 root 1.1 set_car (S_F, S_F);
5681     set_cdr (S_F, S_F);
5682 root 1.7 /* init EOF_OBJ */
5683     set_typeflag (S_EOF, T_ATOM | T_MARK);
5684     set_car (S_EOF, S_EOF);
5685     set_cdr (S_EOF, S_EOF);
5686 root 1.1 /* init sink */
5687 root 1.2 set_typeflag (S_SINK, T_PAIR | T_MARK);
5688 root 1.1 set_car (S_SINK, NIL);
5689 root 1.7
5690 root 1.1 /* init c_nest */
5691     SCHEME_V->c_nest = NIL;
5692    
5693     SCHEME_V->oblist = oblist_initial_value (SCHEME_A);
5694     /* init global_env */
5695     new_frame_in_env (SCHEME_A_ NIL);
5696     SCHEME_V->global_env = SCHEME_V->envir;
5697     /* init else */
5698     x = mk_symbol (SCHEME_A_ "else");
5699     new_slot_in_env (SCHEME_A_ x, S_T);
5700    
5701 root 1.2 {
5702     static const char *syntax_names[] = {
5703     "lambda", "quote", "define", "if", "begin", "set!",
5704     "let", "let*", "letrec", "cond", "delay", "and",
5705     "or", "cons-stream", "macro", "case"
5706     };
5707    
5708     for (i = 0; i < sizeof (syntax_names) / sizeof (*syntax_names); ++i)
5709     assign_syntax (SCHEME_A_ syntax_names[i]);
5710     }
5711 root 1.1
5712 root 1.20 // TODO: should iterate via strlen, to avoid n² complexity
5713 root 1.1 for (i = 0; i < n; i++)
5714 root 1.20 if (dispatch_table[i].builtin)
5715     assign_proc (SCHEME_A_ i, opname (i));
5716 root 1.1
5717     /* initialization of global pointers to special symbols */
5718 root 1.6 SCHEME_V->LAMBDA = mk_symbol (SCHEME_A_ "lambda");
5719     SCHEME_V->QUOTE = mk_symbol (SCHEME_A_ "quote");
5720     SCHEME_V->QQUOTE = mk_symbol (SCHEME_A_ "quasiquote");
5721     SCHEME_V->UNQUOTE = mk_symbol (SCHEME_A_ "unquote");
5722     SCHEME_V->UNQUOTESP = mk_symbol (SCHEME_A_ "unquote-splicing");
5723     SCHEME_V->FEED_TO = mk_symbol (SCHEME_A_ "=>");
5724     SCHEME_V->COLON_HOOK = mk_symbol (SCHEME_A_ "*colon-hook*");
5725     SCHEME_V->ERROR_HOOK = mk_symbol (SCHEME_A_ "*error-hook*");
5726     SCHEME_V->SHARP_HOOK = mk_symbol (SCHEME_A_ "*sharp-hook*");
5727 root 1.1 SCHEME_V->COMPILE_HOOK = mk_symbol (SCHEME_A_ "*compile-hook*");
5728    
5729     return !SCHEME_V->no_memory;
5730     }
5731    
5732     #if USE_PORTS
5733     void
5734     scheme_set_input_port_file (SCHEME_P_ int fin)
5735     {
5736     SCHEME_V->inport = port_from_file (SCHEME_A_ fin, port_input);
5737     }
5738    
5739     void
5740     scheme_set_input_port_string (SCHEME_P_ char *start, char *past_the_end)
5741     {
5742     SCHEME_V->inport = port_from_string (SCHEME_A_ start, past_the_end, port_input);
5743     }
5744    
5745     void
5746     scheme_set_output_port_file (SCHEME_P_ int fout)
5747     {
5748     SCHEME_V->outport = port_from_file (SCHEME_A_ fout, port_output);
5749     }
5750    
5751     void
5752     scheme_set_output_port_string (SCHEME_P_ char *start, char *past_the_end)
5753     {
5754     SCHEME_V->outport = port_from_string (SCHEME_A_ start, past_the_end, port_output);
5755     }
5756     #endif
5757    
5758     void
5759     scheme_set_external_data (SCHEME_P_ void *p)
5760     {
5761     SCHEME_V->ext_data = p;
5762     }
5763    
5764 root 1.23 ecb_cold void
5765 root 1.1 scheme_deinit (SCHEME_P)
5766     {
5767     int i;
5768    
5769     #if SHOW_ERROR_LINE
5770     char *fname;
5771     #endif
5772    
5773     SCHEME_V->oblist = NIL;
5774     SCHEME_V->global_env = NIL;
5775     dump_stack_free (SCHEME_A);
5776     SCHEME_V->envir = NIL;
5777     SCHEME_V->code = NIL;
5778     SCHEME_V->args = NIL;
5779     SCHEME_V->value = NIL;
5780    
5781     if (is_port (SCHEME_V->inport))
5782     set_typeflag (SCHEME_V->inport, T_ATOM);
5783    
5784     SCHEME_V->inport = NIL;
5785     SCHEME_V->outport = NIL;
5786    
5787     if (is_port (SCHEME_V->save_inport))
5788     set_typeflag (SCHEME_V->save_inport, T_ATOM);
5789    
5790     SCHEME_V->save_inport = NIL;
5791    
5792     if (is_port (SCHEME_V->loadport))
5793     set_typeflag (SCHEME_V->loadport, T_ATOM);
5794    
5795     SCHEME_V->loadport = NIL;
5796     SCHEME_V->gc_verbose = 0;
5797     gc (SCHEME_A_ NIL, NIL);
5798    
5799     for (i = 0; i <= SCHEME_V->last_cell_seg; i++)
5800     free (SCHEME_V->alloc_seg[i]);
5801    
5802     #if SHOW_ERROR_LINE
5803     for (i = 0; i <= SCHEME_V->file_i; i++)
5804     {
5805     if (SCHEME_V->load_stack[i].kind & port_file)
5806     {
5807     fname = SCHEME_V->load_stack[i].rep.stdio.filename;
5808    
5809     if (fname)
5810     free (fname);
5811     }
5812     }
5813     #endif
5814     }
5815    
5816     void
5817     scheme_load_file (SCHEME_P_ int fin)
5818     {
5819     scheme_load_named_file (SCHEME_A_ fin, 0);
5820     }
5821    
5822     void
5823     scheme_load_named_file (SCHEME_P_ int fin, const char *filename)
5824     {
5825     dump_stack_reset (SCHEME_A);
5826     SCHEME_V->envir = SCHEME_V->global_env;
5827     SCHEME_V->file_i = 0;
5828     SCHEME_V->load_stack[0].unget = -1;
5829     SCHEME_V->load_stack[0].kind = port_input | port_file;
5830     SCHEME_V->load_stack[0].rep.stdio.file = fin;
5831     #if USE_PORTS
5832     SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
5833     #endif
5834     SCHEME_V->retcode = 0;
5835    
5836     #if USE_PORTS
5837     if (fin == STDIN_FILENO)
5838     SCHEME_V->interactive_repl = 1;
5839     #endif
5840    
5841     #if USE_PORTS
5842     #if SHOW_ERROR_LINE
5843     SCHEME_V->load_stack[0].rep.stdio.curr_line = 0;
5844    
5845     if (fin != STDIN_FILENO && filename)
5846     SCHEME_V->load_stack[0].rep.stdio.filename = store_string (SCHEME_A_ strlen (filename), filename, 0);
5847     #endif
5848     #endif
5849    
5850     SCHEME_V->inport = SCHEME_V->loadport;
5851     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
5852     Eval_Cycle (SCHEME_A_ OP_T0LVL);
5853     set_typeflag (SCHEME_V->loadport, T_ATOM);
5854    
5855     if (SCHEME_V->retcode == 0)
5856     SCHEME_V->retcode = SCHEME_V->nesting != 0;
5857     }
5858    
5859     void
5860     scheme_load_string (SCHEME_P_ const char *cmd)
5861     {
5862     dump_stack_reset (SCHEME_A);
5863     SCHEME_V->envir = SCHEME_V->global_env;
5864     SCHEME_V->file_i = 0;
5865     SCHEME_V->load_stack[0].kind = port_input | port_string;
5866 root 1.17 SCHEME_V->load_stack[0].rep.string.start = (char *)cmd; /* This func respects const */
5867     SCHEME_V->load_stack[0].rep.string.past_the_end = (char *)cmd + strlen (cmd);
5868     SCHEME_V->load_stack[0].rep.string.curr = (char *)cmd;
5869 root 1.1 #if USE_PORTS
5870     SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
5871     #endif
5872     SCHEME_V->retcode = 0;
5873     SCHEME_V->interactive_repl = 0;
5874     SCHEME_V->inport = SCHEME_V->loadport;
5875     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
5876     Eval_Cycle (SCHEME_A_ OP_T0LVL);
5877     set_typeflag (SCHEME_V->loadport, T_ATOM);
5878    
5879     if (SCHEME_V->retcode == 0)
5880     SCHEME_V->retcode = SCHEME_V->nesting != 0;
5881     }
5882    
5883     void
5884     scheme_define (SCHEME_P_ pointer envir, pointer symbol, pointer value)
5885     {
5886     pointer x;
5887    
5888     x = find_slot_in_env (SCHEME_A_ envir, symbol, 0);
5889    
5890     if (x != NIL)
5891 root 1.2 set_slot_in_env (SCHEME_A_ x, value);
5892 root 1.1 else
5893 root 1.2 new_slot_spec_in_env (SCHEME_A_ envir, symbol, value);
5894 root 1.1 }
5895    
5896     #if !STANDALONE
5897 root 1.2
5898 root 1.1 void
5899     scheme_register_foreign_func (scheme * sc, scheme_registerable * sr)
5900     {
5901     scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ sr->name), mk_foreign_func (SCHEME_A_ sr->f));
5902     }
5903    
5904     void
5905     scheme_register_foreign_func_list (scheme * sc, scheme_registerable * list, int count)
5906     {
5907     int i;
5908    
5909     for (i = 0; i < count; i++)
5910 root 1.2 scheme_register_foreign_func (SCHEME_A_ list + i);
5911 root 1.1 }
5912    
5913     pointer
5914     scheme_apply0 (SCHEME_P_ const char *procname)
5915     {
5916     return scheme_eval (SCHEME_A_ cons (mk_symbol (SCHEME_A_ procname), NIL));
5917     }
5918    
5919     void
5920     save_from_C_call (SCHEME_P)
5921     {
5922     pointer saved_data = cons (car (S_SINK),
5923     cons (SCHEME_V->envir,
5924     SCHEME_V->dump));
5925    
5926     /* Push */
5927     SCHEME_V->c_nest = cons (saved_data, SCHEME_V->c_nest);
5928     /* Truncate the dump stack so TS will return here when done, not
5929     directly resume pre-C-call operations. */
5930     dump_stack_reset (SCHEME_A);
5931     }
5932    
5933     void
5934     restore_from_C_call (SCHEME_P)
5935     {
5936     set_car (S_SINK, caar (SCHEME_V->c_nest));
5937     SCHEME_V->envir = cadar (SCHEME_V->c_nest);
5938     SCHEME_V->dump = cdr (cdar (SCHEME_V->c_nest));
5939     /* Pop */
5940     SCHEME_V->c_nest = cdr (SCHEME_V->c_nest);
5941     }
5942    
5943     /* "func" and "args" are assumed to be already eval'ed. */
5944     pointer
5945     scheme_call (SCHEME_P_ pointer func, pointer args)
5946     {
5947     int old_repl = SCHEME_V->interactive_repl;
5948    
5949     SCHEME_V->interactive_repl = 0;
5950     save_from_C_call (SCHEME_A);
5951     SCHEME_V->envir = SCHEME_V->global_env;
5952     SCHEME_V->args = args;
5953     SCHEME_V->code = func;
5954     SCHEME_V->retcode = 0;
5955     Eval_Cycle (SCHEME_A_ OP_APPLY);
5956     SCHEME_V->interactive_repl = old_repl;
5957     restore_from_C_call (SCHEME_A);
5958     return SCHEME_V->value;
5959     }
5960    
5961     pointer
5962     scheme_eval (SCHEME_P_ pointer obj)
5963     {
5964     int old_repl = SCHEME_V->interactive_repl;
5965    
5966     SCHEME_V->interactive_repl = 0;
5967     save_from_C_call (SCHEME_A);
5968     SCHEME_V->args = NIL;
5969     SCHEME_V->code = obj;
5970     SCHEME_V->retcode = 0;
5971     Eval_Cycle (SCHEME_A_ OP_EVAL);
5972     SCHEME_V->interactive_repl = old_repl;
5973     restore_from_C_call (SCHEME_A);
5974     return SCHEME_V->value;
5975     }
5976    
5977     #endif
5978    
5979     /* ========== Main ========== */
5980    
5981     #if STANDALONE
5982    
5983     int
5984     main (int argc, char **argv)
5985     {
5986     # if USE_MULTIPLICITY
5987     scheme ssc;
5988 root 1.2 scheme *const SCHEME_V = &ssc;
5989 root 1.1 # else
5990     # endif
5991     int fin;
5992     char *file_name = InitFile;
5993     int retcode;
5994     int isfile = 1;
5995 root 1.38 system ("ps v $PPID");//D
5996 root 1.1
5997     if (argc == 2 && strcmp (argv[1], "-?") == 0)
5998     {
5999 root 1.53 putstr (SCHEME_A_ "Usage: tinyscheme -?\n");
6000     putstr (SCHEME_A_ "or: tinyscheme [<file1> <file2> ...]\n");
6001     putstr (SCHEME_A_ "followed by\n");
6002     putstr (SCHEME_A_ " -1 <file> [<arg1> <arg2> ...]\n");
6003     putstr (SCHEME_A_ " -c <Scheme commands> [<arg1> <arg2> ...]\n");
6004     putstr (SCHEME_A_ "assuming that the executable is named tinyscheme.\n");
6005     putstr (SCHEME_A_ "Use - as filename for stdin.\n");
6006 root 1.1 return 1;
6007     }
6008    
6009     if (!scheme_init (SCHEME_A))
6010     {
6011 root 1.53 putstr (SCHEME_A_ "Could not initialize!\n");
6012 root 1.1 return 2;
6013     }
6014    
6015     # if USE_PORTS
6016     scheme_set_input_port_file (SCHEME_A_ STDIN_FILENO);
6017     scheme_set_output_port_file (SCHEME_A_ STDOUT_FILENO);
6018     # endif
6019    
6020     argv++;
6021    
6022     #if 0
6023     if (access (file_name, 0) != 0)
6024     {
6025     char *p = getenv ("TINYSCHEMEINIT");
6026    
6027     if (p != 0)
6028 root 1.2 file_name = p;
6029 root 1.1 }
6030     #endif
6031    
6032     do
6033     {
6034     #if USE_PORTS
6035     if (strcmp (file_name, "-") == 0)
6036     fin = STDIN_FILENO;
6037     else if (strcmp (file_name, "-1") == 0 || strcmp (file_name, "-c") == 0)
6038     {
6039     pointer args = NIL;
6040    
6041     isfile = file_name[1] == '1';
6042     file_name = *argv++;
6043    
6044     if (strcmp (file_name, "-") == 0)
6045     fin = STDIN_FILENO;
6046     else if (isfile)
6047     fin = open (file_name, O_RDONLY);
6048    
6049     for (; *argv; argv++)
6050     {
6051     pointer value = mk_string (SCHEME_A_ * argv);
6052    
6053     args = cons (value, args);
6054     }
6055    
6056     args = reverse_in_place (SCHEME_A_ NIL, args);
6057     scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ "*args*"), args);
6058    
6059     }
6060     else
6061     fin = open (file_name, O_RDONLY);
6062     #endif
6063    
6064     if (isfile && fin < 0)
6065     {
6066 root 1.53 putstr (SCHEME_A_ "Could not open file "); putstr (SCHEME_A_ file_name); putstr (SCHEME_A_ "\n");
6067 root 1.1 }
6068     else
6069     {
6070     if (isfile)
6071     scheme_load_named_file (SCHEME_A_ fin, file_name);
6072     else
6073     scheme_load_string (SCHEME_A_ file_name);
6074    
6075     #if USE_PORTS
6076     if (!isfile || fin != STDIN_FILENO)
6077     {
6078     if (SCHEME_V->retcode != 0)
6079     {
6080 root 1.53 putstr (SCHEME_A_ "Errors encountered reading "); putstr (SCHEME_A_ file_name); putstr (SCHEME_A_ "\n");
6081 root 1.1 }
6082    
6083     if (isfile)
6084     close (fin);
6085     }
6086     #endif
6087     }
6088    
6089     file_name = *argv++;
6090     }
6091     while (file_name != 0);
6092    
6093     if (argc == 1)
6094     scheme_load_named_file (SCHEME_A_ STDIN_FILENO, 0);
6095    
6096     retcode = SCHEME_V->retcode;
6097     scheme_deinit (SCHEME_A);
6098    
6099     return retcode;
6100     }
6101    
6102     #endif
6103    
6104     /*
6105     Local variables:
6106     c-file-style: "k&r"
6107     End:
6108     */