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