ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.57
Committed: Tue Dec 1 04:57:49 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.56: +24 -22 lines
Log Message:
*** empty log message ***

File Contents

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