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

File Contents

# User Rev Content
1 root 1.7 /*
2     * µscheme
3     *
4     * Copyright (C) 2015 Marc Alexander Lehmann <uscheme@schmorp.de>
5     * do as you want with this, attribution appreciated.
6     *
7     * Based opn tinyscheme-1.41 (original credits follow)
8 root 1.1 * Dimitrios Souflis (dsouflis@acm.org)
9     * Based on MiniScheme (original credits follow)
10     * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
11     * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
12     * (MINISCM) This version has been modified by R.C. Secrist.
13     * (MINISCM)
14     * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
15     * (MINISCM)
16     * (MINISCM) This is a revised and modified version by Akira KIDA.
17     * (MINISCM) current version is 0.85k4 (15 May 1994)
18     *
19     */
20    
21 root 1.43 #define EXPERIMENT 1
22    
23 root 1.52 #if 1
24 root 1.1 #define PAGE_SIZE 4096 /* does not work on sparc/alpha */
25     #include "malloc.c"
26 root 1.52 #endif
27 root 1.1
28     #define SCHEME_SOURCE
29     #include "scheme-private.h"
30     #ifndef WIN32
31     # include <unistd.h>
32     #endif
33     #if USE_MATH
34     # include <math.h>
35     #endif
36    
37 root 1.23 #include "ecb.h"
38    
39 root 1.1 #include <sys/types.h>
40     #include <sys/stat.h>
41     #include <fcntl.h>
42    
43 root 1.35 #if !USE_ERROR_CHECKING
44     # define NDEBUG
45     #endif
46    
47     #include <assert.h>
48     #include <stdlib.h>
49 root 1.2 #include <string.h>
50    
51 root 1.1 #include <limits.h>
52     #include <inttypes.h>
53     #include <float.h>
54     //#include <ctype.h>
55    
56 root 1.35 #if '1' != '0' + 1 \
57     || '2' != '0' + 2 || '3' != '0' + 3 || '4' != '0' + 4 || '5' != '0' + 5 \
58     || '6' != '0' + 6 || '7' != '0' + 7 || '8' != '0' + 8 || '9' != '0' + 9 \
59     || 'b' != 'a' + 1 || 'c' != 'a' + 2 || 'd' != 'a' + 3 || 'e' != 'a' + 4 \
60     || 'f' != 'a' + 5
61     # error "execution character set digits not consecutive"
62     #endif
63    
64 root 1.1 enum {
65     TOK_EOF,
66     TOK_LPAREN,
67     TOK_RPAREN,
68     TOK_DOT,
69     TOK_ATOM,
70 root 1.35 TOK_DOTATOM, /* atom name starting with '.' */
71     TOK_STRATOM, /* atom name enclosed in | */
72 root 1.1 TOK_QUOTE,
73     TOK_DQUOTE,
74     TOK_BQUOTE,
75     TOK_COMMA,
76     TOK_ATMARK,
77     TOK_SHARP,
78     TOK_SHARP_CONST,
79     TOK_VEC
80     };
81    
82     #define BACKQUOTE '`'
83 root 1.40 #define WHITESPACE " \t\r\n\v\f"
84     #define DELIMITERS "()\";" WHITESPACE
85 root 1.1
86 root 1.51 #define NIL POINTER (&SCHEME_V->xNIL)
87     #define S_T POINTER (&SCHEME_V->xT)
88     #define S_F POINTER (&SCHEME_V->xF)
89     #define S_SINK POINTER (&SCHEME_V->xsink)
90     #define S_EOF POINTER (&SCHEME_V->xEOF_OBJ)
91 root 1.1
92     #if !USE_MULTIPLICITY
93     static scheme sc;
94     #endif
95    
96     static void
97     xbase (char *s, long n, int base)
98     {
99     if (n < 0)
100     {
101     *s++ = '-';
102     n = -n;
103     }
104    
105     char *p = s;
106    
107     do {
108 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 root 1.58 case OP_EOF_OBJECT: /* eof-object */
4605     s_return (S_EOF);
4606    
4607 root 1.1 case OP_WRITE: /* write */
4608     case OP_DISPLAY: /* display */
4609     case OP_WRITE_CHAR: /* write-char */
4610     if (is_pair (cdr (SCHEME_V->args)))
4611     {
4612     if (cadr (SCHEME_V->args) != SCHEME_V->outport)
4613     {
4614     x = cons (SCHEME_V->outport, NIL);
4615     s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
4616     SCHEME_V->outport = cadr (SCHEME_V->args);
4617     }
4618     }
4619    
4620 root 1.16 SCHEME_V->args = a;
4621 root 1.1
4622     if (op == OP_WRITE)
4623     SCHEME_V->print_flag = 1;
4624     else
4625     SCHEME_V->print_flag = 0;
4626    
4627     s_goto (OP_P0LIST);
4628    
4629     case OP_NEWLINE: /* newline */
4630 root 1.16 if (is_pair (args))
4631 root 1.1 {
4632 root 1.16 if (a != SCHEME_V->outport)
4633 root 1.1 {
4634     x = cons (SCHEME_V->outport, NIL);
4635     s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
4636 root 1.16 SCHEME_V->outport = a;
4637 root 1.1 }
4638     }
4639    
4640     putstr (SCHEME_A_ "\n");
4641     s_return (S_T);
4642     #endif
4643    
4644     case OP_ERR0: /* error */
4645     SCHEME_V->retcode = -1;
4646    
4647 root 1.16 if (!is_string (a))
4648 root 1.1 {
4649 root 1.16 args = cons (mk_string (SCHEME_A_ " -- "), args);
4650     setimmutable (car (args));
4651 root 1.1 }
4652    
4653     putstr (SCHEME_A_ "Error: ");
4654 root 1.16 putstr (SCHEME_A_ strvalue (car (args)));
4655     SCHEME_V->args = cdr (args);
4656 root 1.1 s_goto (OP_ERR1);
4657    
4658     case OP_ERR1: /* error */
4659     putstr (SCHEME_A_ " ");
4660    
4661 root 1.16 if (args != NIL)
4662 root 1.1 {
4663 root 1.16 s_save (SCHEME_A_ OP_ERR1, cdr (args), NIL);
4664     SCHEME_V->args = a;
4665 root 1.1 SCHEME_V->print_flag = 1;
4666     s_goto (OP_P0LIST);
4667     }
4668     else
4669     {
4670     putstr (SCHEME_A_ "\n");
4671    
4672     if (SCHEME_V->interactive_repl)
4673 root 1.2 s_goto (OP_T0LVL);
4674 root 1.1 else
4675 root 1.20 return -1;
4676 root 1.1 }
4677    
4678     case OP_REVERSE: /* reverse */
4679 root 1.16 s_return (reverse (SCHEME_A_ a));
4680 root 1.1
4681     case OP_LIST_STAR: /* list* */
4682     s_return (list_star (SCHEME_A_ SCHEME_V->args));
4683    
4684     case OP_APPEND: /* append */
4685     x = NIL;
4686 root 1.16 y = args;
4687 root 1.1
4688     if (y == x)
4689     s_return (x);
4690    
4691     /* cdr() in the while condition is not a typo. If car() */
4692     /* is used (append '() 'a) will return the wrong result. */
4693     while (cdr (y) != NIL)
4694     {
4695     x = revappend (SCHEME_A_ x, car (y));
4696     y = cdr (y);
4697    
4698     if (x == S_F)
4699     Error_0 ("non-list argument to append");
4700     }
4701    
4702     s_return (reverse_in_place (SCHEME_A_ car (y), x));
4703    
4704     #if USE_PLIST
4705    
4706     case OP_PUT: /* put */
4707 root 1.16 if (!hasprop (a) || !hasprop (cadr (args)))
4708 root 1.2 Error_0 ("illegal use of put");
4709 root 1.1
4710 root 1.16 for (x = symprop (a), y = cadr (args); x != NIL; x = cdr (x))
4711 root 1.1 {
4712     if (caar (x) == y)
4713 root 1.2 break;
4714 root 1.1 }
4715    
4716     if (x != NIL)
4717 root 1.16 cdar (x) = caddr (args);
4718 root 1.1 else
4719 root 1.16 symprop (a) = cons (cons (y, caddr (args)), symprop (a));
4720 root 1.1
4721     s_return (S_T);
4722    
4723     case OP_GET: /* get */
4724 root 1.16 if (!hasprop (a) || !hasprop (cadr (args)))
4725 root 1.1 Error_0 ("illegal use of get");
4726    
4727 root 1.16 for (x = symprop (a), y = cadr (args); x != NIL; x = cdr (x))
4728 root 1.1 if (caar (x) == y)
4729     break;
4730    
4731     if (x != NIL)
4732     s_return (cdar (x));
4733     else
4734     s_return (NIL);
4735    
4736     #endif /* USE_PLIST */
4737    
4738     case OP_QUIT: /* quit */
4739 root 1.16 if (is_pair (args))
4740     SCHEME_V->retcode = ivalue (a);
4741 root 1.1
4742 root 1.20 return -1;
4743 root 1.1
4744     case OP_GC: /* gc */
4745     gc (SCHEME_A_ NIL, NIL);
4746     s_return (S_T);
4747    
4748     case OP_GCVERB: /* gc-verbose */
4749     {
4750     int was = SCHEME_V->gc_verbose;
4751    
4752 root 1.16 SCHEME_V->gc_verbose = (a != S_F);
4753 root 1.1 s_retbool (was);
4754     }
4755    
4756     case OP_NEWSEGMENT: /* new-segment */
4757 root 1.51 #if 0
4758 root 1.16 if (!is_pair (args) || !is_number (a))
4759 root 1.1 Error_0 ("new-segment: argument must be a number");
4760 root 1.51 #endif
4761     s_retbool (alloc_cellseg (SCHEME_A));
4762 root 1.1
4763     case OP_OBLIST: /* oblist */
4764     s_return (oblist_all_symbols (SCHEME_A));
4765    
4766     #if USE_PORTS
4767    
4768     case OP_CURR_INPORT: /* current-input-port */
4769     s_return (SCHEME_V->inport);
4770    
4771     case OP_CURR_OUTPORT: /* current-output-port */
4772     s_return (SCHEME_V->outport);
4773    
4774     case OP_OPEN_INFILE: /* open-input-file */
4775     case OP_OPEN_OUTFILE: /* open-output-file */
4776     case OP_OPEN_INOUTFILE: /* open-input-output-file */
4777     {
4778     int prop = 0;
4779     pointer p;
4780    
4781     switch (op)
4782     {
4783     case OP_OPEN_INFILE:
4784     prop = port_input;
4785     break;
4786    
4787     case OP_OPEN_OUTFILE:
4788     prop = port_output;
4789     break;
4790    
4791     case OP_OPEN_INOUTFILE:
4792     prop = port_input | port_output;
4793     break;
4794     }
4795    
4796 root 1.16 p = port_from_filename (SCHEME_A_ strvalue (a), prop);
4797 root 1.1
4798 root 1.23 s_return (p == NIL ? S_F : p);
4799 root 1.1 }
4800    
4801     # if USE_STRING_PORTS
4802    
4803     case OP_OPEN_INSTRING: /* open-input-string */
4804     case OP_OPEN_INOUTSTRING: /* open-input-output-string */
4805     {
4806     int prop = 0;
4807     pointer p;
4808    
4809     switch (op)
4810     {
4811     case OP_OPEN_INSTRING:
4812     prop = port_input;
4813     break;
4814    
4815     case OP_OPEN_INOUTSTRING:
4816     prop = port_input | port_output;
4817     break;
4818     }
4819    
4820 root 1.16 p = port_from_string (SCHEME_A_ strvalue (a),
4821     strvalue (a) + strlength (a), prop);
4822 root 1.1
4823 root 1.23 s_return (p == NIL ? S_F : p);
4824 root 1.1 }
4825    
4826     case OP_OPEN_OUTSTRING: /* open-output-string */
4827     {
4828     pointer p;
4829    
4830 root 1.16 if (a == NIL)
4831 root 1.23 p = port_from_scratch (SCHEME_A);
4832 root 1.1 else
4833 root 1.23 p = port_from_string (SCHEME_A_ strvalue (a),
4834     strvalue (a) + strlength (a), port_output);
4835 root 1.1
4836 root 1.23 s_return (p == NIL ? S_F : p);
4837 root 1.1 }
4838    
4839     case OP_GET_OUTSTRING: /* get-output-string */
4840     {
4841 root 1.51 port *p = port (a);
4842 root 1.1
4843 root 1.51 if (p->kind & port_string)
4844 root 1.1 {
4845     off_t size;
4846     char *str;
4847    
4848     size = p->rep.string.curr - p->rep.string.start + 1;
4849     str = malloc (size);
4850    
4851     if (str != NULL)
4852     {
4853     pointer s;
4854    
4855     memcpy (str, p->rep.string.start, size - 1);
4856     str[size - 1] = '\0';
4857     s = mk_string (SCHEME_A_ str);
4858     free (str);
4859     s_return (s);
4860     }
4861     }
4862    
4863     s_return (S_F);
4864     }
4865    
4866     # endif
4867    
4868     case OP_CLOSE_INPORT: /* close-input-port */
4869 root 1.16 port_close (SCHEME_A_ a, port_input);
4870 root 1.1 s_return (S_T);
4871    
4872     case OP_CLOSE_OUTPORT: /* close-output-port */
4873 root 1.16 port_close (SCHEME_A_ a, port_output);
4874 root 1.1 s_return (S_T);
4875     #endif
4876    
4877     case OP_INT_ENV: /* interaction-environment */
4878     s_return (SCHEME_V->global_env);
4879    
4880     case OP_CURR_ENV: /* current-environment */
4881     s_return (SCHEME_V->envir);
4882    
4883     }
4884    
4885 root 1.24 if (USE_ERROR_CHECKING) abort ();
4886 root 1.1 }
4887    
4888 root 1.20 static int
4889 root 1.1 opexe_5 (SCHEME_P_ enum scheme_opcodes op)
4890     {
4891 root 1.18 pointer args = SCHEME_V->args;
4892 root 1.1 pointer x;
4893    
4894     if (SCHEME_V->nesting != 0)
4895     {
4896     int n = SCHEME_V->nesting;
4897    
4898     SCHEME_V->nesting = 0;
4899     SCHEME_V->retcode = -1;
4900     Error_1 ("unmatched parentheses:", mk_integer (SCHEME_A_ n));
4901     }
4902    
4903     switch (op)
4904     {
4905     /* ========== reading part ========== */
4906     #if USE_PORTS
4907     case OP_READ:
4908 root 1.18 if (!is_pair (args))
4909 root 1.2 s_goto (OP_READ_INTERNAL);
4910 root 1.1
4911 root 1.18 if (!is_inport (car (args)))
4912     Error_1 ("read: not an input port:", car (args));
4913 root 1.1
4914 root 1.18 if (car (args) == SCHEME_V->inport)
4915 root 1.2 s_goto (OP_READ_INTERNAL);
4916 root 1.1
4917     x = SCHEME_V->inport;
4918 root 1.18 SCHEME_V->inport = car (args);
4919 root 1.1 x = cons (x, NIL);
4920     s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
4921     s_goto (OP_READ_INTERNAL);
4922    
4923     case OP_READ_CHAR: /* read-char */
4924     case OP_PEEK_CHAR: /* peek-char */
4925     {
4926     int c;
4927    
4928 root 1.18 if (is_pair (args))
4929 root 1.1 {
4930 root 1.18 if (car (args) != SCHEME_V->inport)
4931 root 1.1 {
4932     x = SCHEME_V->inport;
4933     x = cons (x, NIL);
4934     s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
4935 root 1.18 SCHEME_V->inport = car (args);
4936 root 1.1 }
4937     }
4938    
4939     c = inchar (SCHEME_A);
4940    
4941     if (c == EOF)
4942     s_return (S_EOF);
4943    
4944     if (SCHEME_V->op == OP_PEEK_CHAR)
4945     backchar (SCHEME_A_ c);
4946    
4947     s_return (mk_character (SCHEME_A_ c));
4948     }
4949    
4950     case OP_CHAR_READY: /* char-ready? */
4951     {
4952     pointer p = SCHEME_V->inport;
4953     int res;
4954    
4955 root 1.18 if (is_pair (args))
4956     p = car (args);
4957 root 1.1
4958 root 1.51 res = port (p)->kind & port_string;
4959 root 1.1
4960     s_retbool (res);
4961     }
4962    
4963     case OP_SET_INPORT: /* set-input-port */
4964 root 1.18 SCHEME_V->inport = car (args);
4965 root 1.1 s_return (SCHEME_V->value);
4966    
4967     case OP_SET_OUTPORT: /* set-output-port */
4968 root 1.18 SCHEME_V->outport = car (args);
4969 root 1.1 s_return (SCHEME_V->value);
4970     #endif
4971    
4972     case OP_RDSEXPR:
4973     switch (SCHEME_V->tok)
4974     {
4975     case TOK_EOF:
4976     s_return (S_EOF);
4977     /* NOTREACHED */
4978    
4979     case TOK_VEC:
4980     s_save (SCHEME_A_ OP_RDVEC, NIL, NIL);
4981 root 1.2 /* fall through */
4982 root 1.1
4983     case TOK_LPAREN:
4984     SCHEME_V->tok = token (SCHEME_A);
4985    
4986     if (SCHEME_V->tok == TOK_RPAREN)
4987     s_return (NIL);
4988     else if (SCHEME_V->tok == TOK_DOT)
4989     Error_0 ("syntax error: illegal dot expression");
4990     else
4991     {
4992     SCHEME_V->nesting_stack[SCHEME_V->file_i]++;
4993     s_save (SCHEME_A_ OP_RDLIST, NIL, NIL);
4994     s_goto (OP_RDSEXPR);
4995     }
4996    
4997     case TOK_QUOTE:
4998     s_save (SCHEME_A_ OP_RDQUOTE, NIL, NIL);
4999     SCHEME_V->tok = token (SCHEME_A);
5000     s_goto (OP_RDSEXPR);
5001    
5002     case TOK_BQUOTE:
5003     SCHEME_V->tok = token (SCHEME_A);
5004    
5005     if (SCHEME_V->tok == TOK_VEC)
5006     {
5007     s_save (SCHEME_A_ OP_RDQQUOTEVEC, NIL, NIL);
5008     SCHEME_V->tok = TOK_LPAREN;
5009     s_goto (OP_RDSEXPR);
5010     }
5011     else
5012 root 1.2 s_save (SCHEME_A_ OP_RDQQUOTE, NIL, NIL);
5013 root 1.1
5014     s_goto (OP_RDSEXPR);
5015    
5016     case TOK_COMMA:
5017     s_save (SCHEME_A_ OP_RDUNQUOTE, NIL, NIL);
5018     SCHEME_V->tok = token (SCHEME_A);
5019     s_goto (OP_RDSEXPR);
5020    
5021     case TOK_ATMARK:
5022     s_save (SCHEME_A_ OP_RDUQTSP, NIL, NIL);
5023     SCHEME_V->tok = token (SCHEME_A);
5024     s_goto (OP_RDSEXPR);
5025    
5026     case TOK_ATOM:
5027 root 1.35 s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ 0, DELIMITERS)));
5028    
5029     case TOK_DOTATOM:
5030     SCHEME_V->strbuff[0] = '.';
5031     s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ 1, DELIMITERS)));
5032 root 1.1
5033 root 1.36 case TOK_STRATOM:
5034     x = readstrexp (SCHEME_A_ '|');
5035     //TODO: haven't checked whether the garbage collector could interfere
5036     s_return (mk_atom (SCHEME_A_ strvalue (x)));
5037    
5038 root 1.1 case TOK_DQUOTE:
5039 root 1.35 x = readstrexp (SCHEME_A_ '"');
5040 root 1.1
5041     if (x == S_F)
5042     Error_0 ("Error reading string");
5043    
5044     setimmutable (x);
5045     s_return (x);
5046    
5047     case TOK_SHARP:
5048     {
5049     pointer f = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->SHARP_HOOK, 1);
5050    
5051     if (f == NIL)
5052     Error_0 ("undefined sharp expression");
5053     else
5054     {
5055     SCHEME_V->code = cons (slot_value_in_env (f), NIL);
5056     s_goto (OP_EVAL);
5057     }
5058     }
5059    
5060     case TOK_SHARP_CONST:
5061 root 1.35 if ((x = mk_sharp_const (SCHEME_A_ readstr_upto (SCHEME_A_ 0, DELIMITERS))) == NIL)
5062 root 1.1 Error_0 ("undefined sharp expression");
5063     else
5064     s_return (x);
5065    
5066     default:
5067     Error_0 ("syntax error: illegal token");
5068     }
5069    
5070     break;
5071    
5072     case OP_RDLIST:
5073 root 1.18 SCHEME_V->args = cons (SCHEME_V->value, args);
5074 root 1.2 SCHEME_V->tok = token (SCHEME_A);
5075 root 1.1
5076 root 1.2 switch (SCHEME_V->tok)
5077     {
5078     case TOK_EOF:
5079     s_return (S_EOF);
5080 root 1.1
5081 root 1.2 case TOK_RPAREN:
5082     {
5083     int c = inchar (SCHEME_A);
5084 root 1.1
5085 root 1.2 if (c != '\n')
5086     backchar (SCHEME_A_ c);
5087 root 1.1 #if SHOW_ERROR_LINE
5088 root 1.2 else if (SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
5089     SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line++;
5090     #endif
5091 root 1.1
5092 root 1.2 SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5093     s_return (reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args));
5094     }
5095    
5096     case TOK_DOT:
5097 root 1.1 s_save (SCHEME_A_ OP_RDDOT, SCHEME_V->args, NIL);
5098     SCHEME_V->tok = token (SCHEME_A);
5099     s_goto (OP_RDSEXPR);
5100 root 1.2
5101     default:
5102     s_save (SCHEME_A_ OP_RDLIST, SCHEME_V->args, NIL);
5103 root 1.1 s_goto (OP_RDSEXPR);
5104 root 1.2 }
5105 root 1.1
5106     case OP_RDDOT:
5107     if (token (SCHEME_A) != TOK_RPAREN)
5108     Error_0 ("syntax error: illegal dot expression");
5109 root 1.2
5110     SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5111 root 1.18 s_return (reverse_in_place (SCHEME_A_ SCHEME_V->value, args));
5112 root 1.1
5113     case OP_RDQUOTE:
5114     s_return (cons (SCHEME_V->QUOTE, cons (SCHEME_V->value, NIL)));
5115    
5116     case OP_RDQQUOTE:
5117     s_return (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)));
5118    
5119     case OP_RDQQUOTEVEC:
5120     s_return (cons (mk_symbol (SCHEME_A_ "apply"),
5121     cons (mk_symbol (SCHEME_A_ "vector"),
5122     cons (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)), NIL))));
5123    
5124     case OP_RDUNQUOTE:
5125     s_return (cons (SCHEME_V->UNQUOTE, cons (SCHEME_V->value, NIL)));
5126    
5127     case OP_RDUQTSP:
5128     s_return (cons (SCHEME_V->UNQUOTESP, cons (SCHEME_V->value, NIL)));
5129    
5130     case OP_RDVEC:
5131     /*SCHEME_V->code=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5132     s_goto(OP_EVAL); Cannot be quoted */
5133     /*x=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5134     s_return(x); Cannot be part of pairs */
5135     /*SCHEME_V->code=mk_proc(SCHEME_A_ OP_VECTOR);
5136     SCHEME_V->args=SCHEME_V->value;
5137     s_goto(OP_APPLY); */
5138     SCHEME_V->args = SCHEME_V->value;
5139     s_goto (OP_VECTOR);
5140    
5141     /* ========== printing part ========== */
5142     case OP_P0LIST:
5143 root 1.18 if (is_vector (args))
5144 root 1.1 {
5145     putstr (SCHEME_A_ "#(");
5146 root 1.18 SCHEME_V->args = cons (args, mk_integer (SCHEME_A_ 0));
5147 root 1.1 s_goto (OP_PVECFROM);
5148     }
5149 root 1.18 else if (is_environment (args))
5150 root 1.1 {
5151     putstr (SCHEME_A_ "#<ENVIRONMENT>");
5152     s_return (S_T);
5153     }
5154 root 1.18 else if (!is_pair (args))
5155 root 1.1 {
5156 root 1.18 printatom (SCHEME_A_ args, SCHEME_V->print_flag);
5157 root 1.1 s_return (S_T);
5158     }
5159     else
5160     {
5161 root 1.18 pointer a = car (args);
5162     pointer b = cdr (args);
5163     int ok_abbr = ok_abbrev (b);
5164     SCHEME_V->args = car (b);
5165    
5166     if (a == SCHEME_V->QUOTE && ok_abbr)
5167     putstr (SCHEME_A_ "'");
5168     else if (a == SCHEME_V->QQUOTE && ok_abbr)
5169     putstr (SCHEME_A_ "`");
5170     else if (a == SCHEME_V->UNQUOTE && ok_abbr)
5171     putstr (SCHEME_A_ ",");
5172     else if (a == SCHEME_V->UNQUOTESP && ok_abbr)
5173     putstr (SCHEME_A_ ",@");
5174     else
5175     {
5176     putstr (SCHEME_A_ "(");
5177     s_save (SCHEME_A_ OP_P1LIST, b, NIL);
5178     SCHEME_V->args = a;
5179     }
5180    
5181 root 1.1 s_goto (OP_P0LIST);
5182     }
5183    
5184     case OP_P1LIST:
5185 root 1.18 if (is_pair (args))
5186 root 1.1 {
5187 root 1.18 s_save (SCHEME_A_ OP_P1LIST, cdr (args), NIL);
5188 root 1.1 putstr (SCHEME_A_ " ");
5189 root 1.18 SCHEME_V->args = car (args);
5190 root 1.1 s_goto (OP_P0LIST);
5191     }
5192 root 1.18 else if (is_vector (args))
5193 root 1.1 {
5194     s_save (SCHEME_A_ OP_P1LIST, NIL, NIL);
5195     putstr (SCHEME_A_ " . ");
5196     s_goto (OP_P0LIST);
5197     }
5198     else
5199     {
5200 root 1.18 if (args != NIL)
5201 root 1.1 {
5202     putstr (SCHEME_A_ " . ");
5203 root 1.18 printatom (SCHEME_A_ args, SCHEME_V->print_flag);
5204 root 1.1 }
5205    
5206     putstr (SCHEME_A_ ")");
5207     s_return (S_T);
5208     }
5209    
5210     case OP_PVECFROM:
5211     {
5212 root 1.18 int i = ivalue_unchecked (cdr (args));
5213     pointer vec = car (args);
5214 root 1.7 int len = veclength (vec);
5215 root 1.1
5216     if (i == len)
5217     {
5218     putstr (SCHEME_A_ ")");
5219     s_return (S_T);
5220     }
5221     else
5222     {
5223 root 1.28 pointer elem = vector_get (vec, i);
5224 root 1.1
5225 root 1.18 ivalue_unchecked (cdr (args)) = i + 1;
5226     s_save (SCHEME_A_ OP_PVECFROM, args, NIL);
5227 root 1.1 SCHEME_V->args = elem;
5228    
5229     if (i > 0)
5230     putstr (SCHEME_A_ " ");
5231    
5232     s_goto (OP_P0LIST);
5233     }
5234     }
5235     }
5236    
5237 root 1.24 if (USE_ERROR_CHECKING) abort ();
5238 root 1.1 }
5239    
5240 root 1.20 static int
5241 root 1.1 opexe_6 (SCHEME_P_ enum scheme_opcodes op)
5242     {
5243 root 1.18 pointer args = SCHEME_V->args;
5244     pointer a = car (args);
5245 root 1.1 pointer x, y;
5246    
5247     switch (op)
5248     {
5249     case OP_LIST_LENGTH: /* length *//* a.k */
5250     {
5251 root 1.18 long v = list_length (SCHEME_A_ a);
5252 root 1.1
5253     if (v < 0)
5254 root 1.18 Error_1 ("length: not a list:", a);
5255 root 1.1
5256     s_return (mk_integer (SCHEME_A_ v));
5257     }
5258    
5259     case OP_ASSQ: /* assq *//* a.k */
5260 root 1.18 x = a;
5261 root 1.1
5262 root 1.18 for (y = cadr (args); is_pair (y); y = cdr (y))
5263 root 1.1 {
5264     if (!is_pair (car (y)))
5265     Error_0 ("unable to handle non pair element");
5266    
5267     if (x == caar (y))
5268     break;
5269     }
5270    
5271     if (is_pair (y))
5272     s_return (car (y));
5273     else
5274     s_return (S_F);
5275    
5276    
5277     case OP_GET_CLOSURE: /* get-closure-code *//* a.k */
5278 root 1.18 SCHEME_V->args = a;
5279 root 1.1
5280     if (SCHEME_V->args == NIL)
5281     s_return (S_F);
5282     else if (is_closure (SCHEME_V->args))
5283     s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5284     else if (is_macro (SCHEME_V->args))
5285     s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5286     else
5287     s_return (S_F);
5288    
5289     case OP_CLOSUREP: /* closure? */
5290     /*
5291     * Note, macro object is also a closure.
5292     * Therefore, (closure? <#MACRO>) ==> #t
5293 root 1.38 * (schmorp) well, obviously not, fix? TODO
5294 root 1.1 */
5295 root 1.18 s_retbool (is_closure (a));
5296 root 1.1
5297     case OP_MACROP: /* macro? */
5298 root 1.18 s_retbool (is_macro (a));
5299 root 1.1 }
5300    
5301 root 1.24 if (USE_ERROR_CHECKING) abort ();
5302 root 1.1 }
5303    
5304 root 1.20 /* dispatch functions (opexe_x) return new opcode, or 0 for same opcode, or -1 to stop */
5305     typedef int (*dispatch_func)(SCHEME_P_ enum scheme_opcodes);
5306 root 1.1
5307 root 1.19 typedef int (*test_predicate)(pointer);
5308 root 1.1 static int
5309 root 1.26 tst_any (pointer p)
5310 root 1.1 {
5311     return 1;
5312     }
5313    
5314     static int
5315 root 1.26 tst_inonneg (pointer p)
5316 root 1.1 {
5317 root 1.26 return is_integer (p) && ivalue_unchecked (p) >= 0;
5318 root 1.1 }
5319    
5320 root 1.19 static int
5321 root 1.26 tst_is_list (SCHEME_P_ pointer p)
5322 root 1.19 {
5323     return p == NIL || is_pair (p);
5324     }
5325    
5326 root 1.1 /* Correspond carefully with following defines! */
5327     static struct
5328     {
5329     test_predicate fct;
5330     const char *kind;
5331 root 1.26 } tests[] = {
5332     { tst_any , 0 },
5333     { is_string , "string" },
5334     { is_symbol , "symbol" },
5335     { is_port , "port" },
5336     { is_inport , "input port" },
5337     { is_outport , "output port" },
5338 root 1.19 { is_environment, "environment" },
5339 root 1.26 { is_pair , "pair" },
5340     { 0 , "pair or '()" },
5341     { is_character , "character" },
5342     { is_vector , "vector" },
5343     { is_number , "number" },
5344     { is_integer , "integer" },
5345     { tst_inonneg , "non-negative integer" }
5346 root 1.1 };
5347    
5348 root 1.20 #define TST_NONE 0 /* TST_NONE used for built-ins, 0 for internal ops */
5349 root 1.18 #define TST_ANY "\001"
5350     #define TST_STRING "\002"
5351     #define TST_SYMBOL "\003"
5352     #define TST_PORT "\004"
5353     #define TST_INPORT "\005"
5354     #define TST_OUTPORT "\006"
5355 root 1.1 #define TST_ENVIRONMENT "\007"
5356 root 1.18 #define TST_PAIR "\010"
5357     #define TST_LIST "\011"
5358     #define TST_CHAR "\012"
5359     #define TST_VECTOR "\013"
5360     #define TST_NUMBER "\014"
5361     #define TST_INTEGER "\015"
5362     #define TST_NATURAL "\016"
5363 root 1.1
5364 root 1.20 #define INF_ARG 0xff
5365     #define UNNAMED_OP ""
5366    
5367     static const char opnames[] =
5368     #define OP_DEF(func,name,minarity,maxarity,argtest,op) name "\x00"
5369     #include "opdefines.h"
5370     #undef OP_DEF
5371     ;
5372    
5373     static const char *
5374     opname (int idx)
5375     {
5376     const char *name = opnames;
5377    
5378     /* should do this at compile time, but would require external program, right? */
5379     while (idx--)
5380     name += strlen (name) + 1;
5381    
5382     return *name ? name : "ILLEGAL";
5383     }
5384    
5385     static const char *
5386     procname (pointer x)
5387     {
5388     return opname (procnum (x));
5389     }
5390    
5391 root 1.1 typedef struct
5392     {
5393 root 1.20 uint8_t func;
5394     /*dispatch_func func;*//*TODO: maybe optionally keep the pointer, for speed? */
5395     uint8_t builtin;
5396 root 1.26 #if USE_ERROR_CHECKING
5397 root 1.20 uint8_t min_arity;
5398     uint8_t max_arity;
5399 root 1.18 char arg_tests_encoding[3];
5400 root 1.26 #endif
5401 root 1.1 } op_code_info;
5402    
5403 root 1.20 static const op_code_info dispatch_table[] = {
5404 root 1.26 #if USE_ERROR_CHECKING
5405 root 1.20 #define OP_DEF(func,name,minarity,maxarity,argtest,op) { func, sizeof (name) > 1, minarity, maxarity, argtest },
5406 root 1.26 #else
5407     #define OP_DEF(func,name,minarity,maxarity,argtest,op) { func, sizeof (name) > 1 },
5408     #endif
5409 root 1.1 #include "opdefines.h"
5410 root 1.18 #undef OP_DEF
5411 root 1.1 {0}
5412     };
5413    
5414     /* kernel of this interpreter */
5415 root 1.23 static void ecb_hot
5416 root 1.1 Eval_Cycle (SCHEME_P_ enum scheme_opcodes op)
5417     {
5418     SCHEME_V->op = op;
5419    
5420     for (;;)
5421     {
5422 root 1.20 const op_code_info *pcd = dispatch_table + SCHEME_V->op;
5423 root 1.1
5424 root 1.4 #if USE_ERROR_CHECKING
5425 root 1.20 if (pcd->builtin) /* if built-in function, check arguments */
5426 root 1.1 {
5427     char msg[STRBUFFSIZE];
5428     int n = list_length (SCHEME_A_ SCHEME_V->args);
5429    
5430     /* Check number of arguments */
5431 root 1.10 if (ecb_expect_false (n < pcd->min_arity))
5432 root 1.1 {
5433     snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5434 root 1.20 opname (SCHEME_V->op), pcd->min_arity == pcd->max_arity ? "" : " at least", pcd->min_arity);
5435 root 1.21 xError_1 (SCHEME_A_ msg, 0);
5436     continue;
5437 root 1.1 }
5438 root 1.20 else if (ecb_expect_false (n > pcd->max_arity && pcd->max_arity != INF_ARG))
5439 root 1.1 {
5440     snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5441 root 1.20 opname (SCHEME_V->op), pcd->min_arity == pcd->max_arity ? "" : " at most", pcd->max_arity);
5442 root 1.21 xError_1 (SCHEME_A_ msg, 0);
5443     continue;
5444 root 1.1 }
5445 root 1.20 else
5446 root 1.1 {
5447 root 1.20 if (*pcd->arg_tests_encoding) /* literal 0 and TST_NONE treated the same */
5448 root 1.1 {
5449     int i = 0;
5450     int j;
5451     const char *t = pcd->arg_tests_encoding;
5452     pointer arglist = SCHEME_V->args;
5453    
5454     do
5455     {
5456     pointer arg = car (arglist);
5457    
5458 root 1.18 j = t[0];
5459 root 1.1
5460 root 1.26 /*TODO: tst_is_list has different prototype - fix if other tests acquire same prototype */
5461     if (j == TST_LIST[0])
5462     {
5463     if (!tst_is_list (SCHEME_A_ arg))
5464     break;
5465     }
5466     else
5467     {
5468     if (!tests[j - 1].fct (arg))
5469     break;
5470     }
5471 root 1.1
5472 root 1.28 if (t < pcd->arg_tests_encoding + sizeof (pcd->arg_tests_encoding) - 1 && t[1]) /* last test is replicated as necessary */
5473 root 1.2 t++;
5474 root 1.1
5475     arglist = cdr (arglist);
5476     i++;
5477     }
5478     while (i < n);
5479    
5480     if (i < n)
5481     {
5482 root 1.20 snprintf (msg, STRBUFFSIZE, "%s: argument %d must be: %s", opname (SCHEME_V->op), i + 1, tests[j].kind);
5483 root 1.21 xError_1 (SCHEME_A_ msg, 0);
5484     continue;
5485 root 1.1 }
5486     }
5487     }
5488     }
5489 root 1.4 #endif
5490 root 1.1
5491     ok_to_freely_gc (SCHEME_A);
5492    
5493 root 1.20 static const dispatch_func dispatch_funcs[] = {
5494     opexe_0,
5495     opexe_1,
5496     opexe_2,
5497     opexe_3,
5498     opexe_4,
5499     opexe_5,
5500     opexe_6,
5501     };
5502    
5503     if (ecb_expect_false (dispatch_funcs [pcd->func] (SCHEME_A_ SCHEME_V->op) != 0))
5504 root 1.1 return;
5505    
5506 root 1.5 if (SCHEME_V->no_memory && USE_ERROR_CHECKING)
5507 root 1.1 {
5508 root 1.53 putstr (SCHEME_A_ "No memory!\n");
5509 root 1.1 return;
5510     }
5511     }
5512     }
5513    
5514     /* ========== Initialization of internal keywords ========== */
5515    
5516     static void
5517 root 1.2 assign_syntax (SCHEME_P_ const char *name)
5518 root 1.1 {
5519     pointer x = oblist_add_by_name (SCHEME_A_ name);
5520     set_typeflag (x, typeflag (x) | T_SYNTAX);
5521     }
5522    
5523     static void
5524 root 1.2 assign_proc (SCHEME_P_ enum scheme_opcodes op, const char *name)
5525 root 1.1 {
5526     pointer x = mk_symbol (SCHEME_A_ name);
5527     pointer y = mk_proc (SCHEME_A_ op);
5528     new_slot_in_env (SCHEME_A_ x, y);
5529     }
5530    
5531     static pointer
5532     mk_proc (SCHEME_P_ enum scheme_opcodes op)
5533     {
5534     pointer y = get_cell (SCHEME_A_ NIL, NIL);
5535     set_typeflag (y, (T_PROC | T_ATOM));
5536 root 1.2 ivalue_unchecked (y) = op;
5537 root 1.1 return y;
5538     }
5539    
5540     /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
5541     static int
5542     syntaxnum (pointer p)
5543     {
5544 root 1.38 const char *s = strvalue (p);
5545 root 1.1
5546 root 1.38 switch (strlength (p))
5547 root 1.1 {
5548     case 2:
5549     if (s[0] == 'i')
5550     return OP_IF0; /* if */
5551     else
5552     return OP_OR0; /* or */
5553    
5554     case 3:
5555     if (s[0] == 'a')
5556     return OP_AND0; /* and */
5557     else
5558     return OP_LET0; /* let */
5559    
5560     case 4:
5561     switch (s[3])
5562     {
5563     case 'e':
5564     return OP_CASE0; /* case */
5565    
5566     case 'd':
5567     return OP_COND0; /* cond */
5568    
5569     case '*':
5570 root 1.10 return OP_LET0AST;/* let* */
5571 root 1.1
5572     default:
5573     return OP_SET0; /* set! */
5574     }
5575    
5576     case 5:
5577     switch (s[2])
5578     {
5579     case 'g':
5580     return OP_BEGIN; /* begin */
5581    
5582     case 'l':
5583     return OP_DELAY; /* delay */
5584    
5585     case 'c':
5586     return OP_MACRO0; /* macro */
5587    
5588     default:
5589     return OP_QUOTE; /* quote */
5590     }
5591    
5592     case 6:
5593     switch (s[2])
5594     {
5595     case 'm':
5596     return OP_LAMBDA; /* lambda */
5597    
5598     case 'f':
5599     return OP_DEF0; /* define */
5600    
5601     default:
5602 root 1.10 return OP_LET0REC;/* letrec */
5603 root 1.1 }
5604    
5605     default:
5606     return OP_C0STREAM; /* cons-stream */
5607     }
5608     }
5609    
5610     #if USE_MULTIPLICITY
5611 root 1.23 ecb_cold scheme *
5612 root 1.1 scheme_init_new ()
5613     {
5614     scheme *sc = malloc (sizeof (scheme));
5615    
5616     if (!scheme_init (SCHEME_A))
5617     {
5618     free (SCHEME_A);
5619     return 0;
5620     }
5621     else
5622     return sc;
5623     }
5624     #endif
5625    
5626 root 1.23 ecb_cold int
5627 root 1.1 scheme_init (SCHEME_P)
5628     {
5629     int i, n = sizeof (dispatch_table) / sizeof (dispatch_table[0]);
5630     pointer x;
5631    
5632 root 1.49 /* this memset is not strictly correct, as we assume (intcache)
5633     * that memset 0 will also set pointers to 0, but memset does
5634     * of course not guarantee that. screw such systems.
5635     */
5636     memset (SCHEME_V, 0, sizeof (*SCHEME_V));
5637 root 1.48
5638 root 1.1 num_set_fixnum (num_zero, 1);
5639     num_set_ivalue (num_zero, 0);
5640     num_set_fixnum (num_one, 1);
5641     num_set_ivalue (num_one, 1);
5642    
5643     #if USE_INTERFACE
5644     SCHEME_V->vptr = &vtbl;
5645     #endif
5646     SCHEME_V->gensym_cnt = 0;
5647     SCHEME_V->last_cell_seg = -1;
5648     SCHEME_V->free_cell = NIL;
5649     SCHEME_V->fcells = 0;
5650     SCHEME_V->no_memory = 0;
5651     SCHEME_V->inport = NIL;
5652     SCHEME_V->outport = NIL;
5653     SCHEME_V->save_inport = NIL;
5654     SCHEME_V->loadport = NIL;
5655     SCHEME_V->nesting = 0;
5656     SCHEME_V->interactive_repl = 0;
5657    
5658 root 1.51 if (!alloc_cellseg (SCHEME_A))
5659 root 1.1 {
5660     #if USE_ERROR_CHECKING
5661     SCHEME_V->no_memory = 1;
5662     return 0;
5663     #endif
5664     }
5665    
5666     SCHEME_V->gc_verbose = 0;
5667     dump_stack_initialize (SCHEME_A);
5668     SCHEME_V->code = NIL;
5669 root 1.2 SCHEME_V->args = NIL;
5670     SCHEME_V->envir = NIL;
5671 root 1.1 SCHEME_V->tracing = 0;
5672    
5673     /* init NIL */
5674 root 1.2 set_typeflag (NIL, T_ATOM | T_MARK);
5675 root 1.1 set_car (NIL, NIL);
5676     set_cdr (NIL, NIL);
5677     /* init T */
5678 root 1.2 set_typeflag (S_T, T_ATOM | T_MARK);
5679 root 1.1 set_car (S_T, S_T);
5680     set_cdr (S_T, S_T);
5681     /* init F */
5682 root 1.2 set_typeflag (S_F, T_ATOM | T_MARK);
5683 root 1.1 set_car (S_F, S_F);
5684     set_cdr (S_F, S_F);
5685 root 1.7 /* init EOF_OBJ */
5686     set_typeflag (S_EOF, T_ATOM | T_MARK);
5687     set_car (S_EOF, S_EOF);
5688     set_cdr (S_EOF, S_EOF);
5689 root 1.1 /* init sink */
5690 root 1.2 set_typeflag (S_SINK, T_PAIR | T_MARK);
5691 root 1.1 set_car (S_SINK, NIL);
5692 root 1.7
5693 root 1.1 /* init c_nest */
5694     SCHEME_V->c_nest = NIL;
5695    
5696     SCHEME_V->oblist = oblist_initial_value (SCHEME_A);
5697     /* init global_env */
5698     new_frame_in_env (SCHEME_A_ NIL);
5699     SCHEME_V->global_env = SCHEME_V->envir;
5700     /* init else */
5701     x = mk_symbol (SCHEME_A_ "else");
5702     new_slot_in_env (SCHEME_A_ x, S_T);
5703    
5704 root 1.2 {
5705     static const char *syntax_names[] = {
5706     "lambda", "quote", "define", "if", "begin", "set!",
5707     "let", "let*", "letrec", "cond", "delay", "and",
5708     "or", "cons-stream", "macro", "case"
5709     };
5710    
5711     for (i = 0; i < sizeof (syntax_names) / sizeof (*syntax_names); ++i)
5712     assign_syntax (SCHEME_A_ syntax_names[i]);
5713     }
5714 root 1.1
5715 root 1.20 // TODO: should iterate via strlen, to avoid n² complexity
5716 root 1.1 for (i = 0; i < n; i++)
5717 root 1.20 if (dispatch_table[i].builtin)
5718     assign_proc (SCHEME_A_ i, opname (i));
5719 root 1.1
5720     /* initialization of global pointers to special symbols */
5721 root 1.6 SCHEME_V->LAMBDA = mk_symbol (SCHEME_A_ "lambda");
5722     SCHEME_V->QUOTE = mk_symbol (SCHEME_A_ "quote");
5723     SCHEME_V->QQUOTE = mk_symbol (SCHEME_A_ "quasiquote");
5724     SCHEME_V->UNQUOTE = mk_symbol (SCHEME_A_ "unquote");
5725     SCHEME_V->UNQUOTESP = mk_symbol (SCHEME_A_ "unquote-splicing");
5726     SCHEME_V->FEED_TO = mk_symbol (SCHEME_A_ "=>");
5727     SCHEME_V->COLON_HOOK = mk_symbol (SCHEME_A_ "*colon-hook*");
5728     SCHEME_V->ERROR_HOOK = mk_symbol (SCHEME_A_ "*error-hook*");
5729     SCHEME_V->SHARP_HOOK = mk_symbol (SCHEME_A_ "*sharp-hook*");
5730 root 1.1 SCHEME_V->COMPILE_HOOK = mk_symbol (SCHEME_A_ "*compile-hook*");
5731    
5732     return !SCHEME_V->no_memory;
5733     }
5734    
5735     #if USE_PORTS
5736     void
5737     scheme_set_input_port_file (SCHEME_P_ int fin)
5738     {
5739     SCHEME_V->inport = port_from_file (SCHEME_A_ fin, port_input);
5740     }
5741    
5742     void
5743     scheme_set_input_port_string (SCHEME_P_ char *start, char *past_the_end)
5744     {
5745     SCHEME_V->inport = port_from_string (SCHEME_A_ start, past_the_end, port_input);
5746     }
5747    
5748     void
5749     scheme_set_output_port_file (SCHEME_P_ int fout)
5750     {
5751     SCHEME_V->outport = port_from_file (SCHEME_A_ fout, port_output);
5752     }
5753    
5754     void
5755     scheme_set_output_port_string (SCHEME_P_ char *start, char *past_the_end)
5756     {
5757     SCHEME_V->outport = port_from_string (SCHEME_A_ start, past_the_end, port_output);
5758     }
5759     #endif
5760    
5761     void
5762     scheme_set_external_data (SCHEME_P_ void *p)
5763     {
5764     SCHEME_V->ext_data = p;
5765     }
5766    
5767 root 1.23 ecb_cold void
5768 root 1.1 scheme_deinit (SCHEME_P)
5769     {
5770     int i;
5771    
5772     #if SHOW_ERROR_LINE
5773     char *fname;
5774     #endif
5775    
5776     SCHEME_V->oblist = NIL;
5777     SCHEME_V->global_env = NIL;
5778     dump_stack_free (SCHEME_A);
5779     SCHEME_V->envir = NIL;
5780     SCHEME_V->code = NIL;
5781     SCHEME_V->args = NIL;
5782     SCHEME_V->value = NIL;
5783    
5784     if (is_port (SCHEME_V->inport))
5785     set_typeflag (SCHEME_V->inport, T_ATOM);
5786    
5787     SCHEME_V->inport = NIL;
5788     SCHEME_V->outport = NIL;
5789    
5790     if (is_port (SCHEME_V->save_inport))
5791     set_typeflag (SCHEME_V->save_inport, T_ATOM);
5792    
5793     SCHEME_V->save_inport = NIL;
5794    
5795     if (is_port (SCHEME_V->loadport))
5796     set_typeflag (SCHEME_V->loadport, T_ATOM);
5797    
5798     SCHEME_V->loadport = NIL;
5799     SCHEME_V->gc_verbose = 0;
5800     gc (SCHEME_A_ NIL, NIL);
5801    
5802     for (i = 0; i <= SCHEME_V->last_cell_seg; i++)
5803     free (SCHEME_V->alloc_seg[i]);
5804    
5805     #if SHOW_ERROR_LINE
5806     for (i = 0; i <= SCHEME_V->file_i; i++)
5807     {
5808     if (SCHEME_V->load_stack[i].kind & port_file)
5809     {
5810     fname = SCHEME_V->load_stack[i].rep.stdio.filename;
5811    
5812     if (fname)
5813     free (fname);
5814     }
5815     }
5816     #endif
5817     }
5818    
5819     void
5820     scheme_load_file (SCHEME_P_ int fin)
5821     {
5822     scheme_load_named_file (SCHEME_A_ fin, 0);
5823     }
5824    
5825     void
5826     scheme_load_named_file (SCHEME_P_ int fin, const char *filename)
5827     {
5828     dump_stack_reset (SCHEME_A);
5829     SCHEME_V->envir = SCHEME_V->global_env;
5830     SCHEME_V->file_i = 0;
5831     SCHEME_V->load_stack[0].unget = -1;
5832     SCHEME_V->load_stack[0].kind = port_input | port_file;
5833     SCHEME_V->load_stack[0].rep.stdio.file = fin;
5834     #if USE_PORTS
5835     SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
5836     #endif
5837     SCHEME_V->retcode = 0;
5838    
5839     #if USE_PORTS
5840     if (fin == STDIN_FILENO)
5841     SCHEME_V->interactive_repl = 1;
5842     #endif
5843    
5844     #if USE_PORTS
5845     #if SHOW_ERROR_LINE
5846     SCHEME_V->load_stack[0].rep.stdio.curr_line = 0;
5847    
5848     if (fin != STDIN_FILENO && filename)
5849     SCHEME_V->load_stack[0].rep.stdio.filename = store_string (SCHEME_A_ strlen (filename), filename, 0);
5850     #endif
5851     #endif
5852    
5853     SCHEME_V->inport = SCHEME_V->loadport;
5854     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
5855     Eval_Cycle (SCHEME_A_ OP_T0LVL);
5856     set_typeflag (SCHEME_V->loadport, T_ATOM);
5857    
5858     if (SCHEME_V->retcode == 0)
5859     SCHEME_V->retcode = SCHEME_V->nesting != 0;
5860     }
5861    
5862     void
5863     scheme_load_string (SCHEME_P_ const char *cmd)
5864     {
5865     dump_stack_reset (SCHEME_A);
5866     SCHEME_V->envir = SCHEME_V->global_env;
5867     SCHEME_V->file_i = 0;
5868     SCHEME_V->load_stack[0].kind = port_input | port_string;
5869 root 1.17 SCHEME_V->load_stack[0].rep.string.start = (char *)cmd; /* This func respects const */
5870     SCHEME_V->load_stack[0].rep.string.past_the_end = (char *)cmd + strlen (cmd);
5871     SCHEME_V->load_stack[0].rep.string.curr = (char *)cmd;
5872 root 1.1 #if USE_PORTS
5873     SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
5874     #endif
5875     SCHEME_V->retcode = 0;
5876     SCHEME_V->interactive_repl = 0;
5877     SCHEME_V->inport = SCHEME_V->loadport;
5878     SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
5879     Eval_Cycle (SCHEME_A_ OP_T0LVL);
5880     set_typeflag (SCHEME_V->loadport, T_ATOM);
5881    
5882     if (SCHEME_V->retcode == 0)
5883     SCHEME_V->retcode = SCHEME_V->nesting != 0;
5884     }
5885    
5886     void
5887     scheme_define (SCHEME_P_ pointer envir, pointer symbol, pointer value)
5888     {
5889     pointer x;
5890    
5891     x = find_slot_in_env (SCHEME_A_ envir, symbol, 0);
5892    
5893     if (x != NIL)
5894 root 1.2 set_slot_in_env (SCHEME_A_ x, value);
5895 root 1.1 else
5896 root 1.2 new_slot_spec_in_env (SCHEME_A_ envir, symbol, value);
5897 root 1.1 }
5898    
5899     #if !STANDALONE
5900 root 1.2
5901 root 1.1 void
5902     scheme_register_foreign_func (scheme * sc, scheme_registerable * sr)
5903     {
5904     scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ sr->name), mk_foreign_func (SCHEME_A_ sr->f));
5905     }
5906    
5907     void
5908     scheme_register_foreign_func_list (scheme * sc, scheme_registerable * list, int count)
5909     {
5910     int i;
5911    
5912     for (i = 0; i < count; i++)
5913 root 1.2 scheme_register_foreign_func (SCHEME_A_ list + i);
5914 root 1.1 }
5915    
5916     pointer
5917     scheme_apply0 (SCHEME_P_ const char *procname)
5918     {
5919     return scheme_eval (SCHEME_A_ cons (mk_symbol (SCHEME_A_ procname), NIL));
5920     }
5921    
5922     void
5923     save_from_C_call (SCHEME_P)
5924     {
5925     pointer saved_data = cons (car (S_SINK),
5926     cons (SCHEME_V->envir,
5927     SCHEME_V->dump));
5928    
5929     /* Push */
5930     SCHEME_V->c_nest = cons (saved_data, SCHEME_V->c_nest);
5931     /* Truncate the dump stack so TS will return here when done, not
5932     directly resume pre-C-call operations. */
5933     dump_stack_reset (SCHEME_A);
5934     }
5935    
5936     void
5937     restore_from_C_call (SCHEME_P)
5938     {
5939     set_car (S_SINK, caar (SCHEME_V->c_nest));
5940     SCHEME_V->envir = cadar (SCHEME_V->c_nest);
5941     SCHEME_V->dump = cdr (cdar (SCHEME_V->c_nest));
5942     /* Pop */
5943     SCHEME_V->c_nest = cdr (SCHEME_V->c_nest);
5944     }
5945    
5946     /* "func" and "args" are assumed to be already eval'ed. */
5947     pointer
5948     scheme_call (SCHEME_P_ pointer func, pointer args)
5949     {
5950     int old_repl = SCHEME_V->interactive_repl;
5951    
5952     SCHEME_V->interactive_repl = 0;
5953     save_from_C_call (SCHEME_A);
5954     SCHEME_V->envir = SCHEME_V->global_env;
5955     SCHEME_V->args = args;
5956     SCHEME_V->code = func;
5957     SCHEME_V->retcode = 0;
5958     Eval_Cycle (SCHEME_A_ OP_APPLY);
5959     SCHEME_V->interactive_repl = old_repl;
5960     restore_from_C_call (SCHEME_A);
5961     return SCHEME_V->value;
5962     }
5963    
5964     pointer
5965     scheme_eval (SCHEME_P_ pointer obj)
5966     {
5967     int old_repl = SCHEME_V->interactive_repl;
5968    
5969     SCHEME_V->interactive_repl = 0;
5970     save_from_C_call (SCHEME_A);
5971     SCHEME_V->args = NIL;
5972     SCHEME_V->code = obj;
5973     SCHEME_V->retcode = 0;
5974     Eval_Cycle (SCHEME_A_ OP_EVAL);
5975     SCHEME_V->interactive_repl = old_repl;
5976     restore_from_C_call (SCHEME_A);
5977     return SCHEME_V->value;
5978     }
5979    
5980     #endif
5981    
5982     /* ========== Main ========== */
5983    
5984     #if STANDALONE
5985    
5986     int
5987     main (int argc, char **argv)
5988     {
5989     # if USE_MULTIPLICITY
5990     scheme ssc;
5991 root 1.2 scheme *const SCHEME_V = &ssc;
5992 root 1.1 # else
5993     # endif
5994     int fin;
5995     char *file_name = InitFile;
5996     int retcode;
5997     int isfile = 1;
5998 root 1.38 system ("ps v $PPID");//D
5999 root 1.1
6000     if (argc == 2 && strcmp (argv[1], "-?") == 0)
6001     {
6002 root 1.53 putstr (SCHEME_A_ "Usage: tinyscheme -?\n");
6003     putstr (SCHEME_A_ "or: tinyscheme [<file1> <file2> ...]\n");
6004     putstr (SCHEME_A_ "followed by\n");
6005     putstr (SCHEME_A_ " -1 <file> [<arg1> <arg2> ...]\n");
6006     putstr (SCHEME_A_ " -c <Scheme commands> [<arg1> <arg2> ...]\n");
6007     putstr (SCHEME_A_ "assuming that the executable is named tinyscheme.\n");
6008     putstr (SCHEME_A_ "Use - as filename for stdin.\n");
6009 root 1.1 return 1;
6010     }
6011    
6012     if (!scheme_init (SCHEME_A))
6013     {
6014 root 1.53 putstr (SCHEME_A_ "Could not initialize!\n");
6015 root 1.1 return 2;
6016     }
6017    
6018     # if USE_PORTS
6019     scheme_set_input_port_file (SCHEME_A_ STDIN_FILENO);
6020     scheme_set_output_port_file (SCHEME_A_ STDOUT_FILENO);
6021     # endif
6022    
6023     argv++;
6024    
6025     #if 0
6026     if (access (file_name, 0) != 0)
6027     {
6028     char *p = getenv ("TINYSCHEMEINIT");
6029    
6030     if (p != 0)
6031 root 1.2 file_name = p;
6032 root 1.1 }
6033     #endif
6034    
6035     do
6036     {
6037     #if USE_PORTS
6038     if (strcmp (file_name, "-") == 0)
6039     fin = STDIN_FILENO;
6040     else if (strcmp (file_name, "-1") == 0 || strcmp (file_name, "-c") == 0)
6041     {
6042     pointer args = NIL;
6043    
6044     isfile = file_name[1] == '1';
6045     file_name = *argv++;
6046    
6047     if (strcmp (file_name, "-") == 0)
6048     fin = STDIN_FILENO;
6049     else if (isfile)
6050     fin = open (file_name, O_RDONLY);
6051    
6052     for (; *argv; argv++)
6053     {
6054     pointer value = mk_string (SCHEME_A_ * argv);
6055    
6056     args = cons (value, args);
6057     }
6058    
6059     args = reverse_in_place (SCHEME_A_ NIL, args);
6060     scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ "*args*"), args);
6061    
6062     }
6063     else
6064     fin = open (file_name, O_RDONLY);
6065     #endif
6066    
6067     if (isfile && fin < 0)
6068     {
6069 root 1.53 putstr (SCHEME_A_ "Could not open file "); putstr (SCHEME_A_ file_name); putstr (SCHEME_A_ "\n");
6070 root 1.1 }
6071     else
6072     {
6073     if (isfile)
6074     scheme_load_named_file (SCHEME_A_ fin, file_name);
6075     else
6076     scheme_load_string (SCHEME_A_ file_name);
6077    
6078     #if USE_PORTS
6079     if (!isfile || fin != STDIN_FILENO)
6080     {
6081     if (SCHEME_V->retcode != 0)
6082     {
6083 root 1.53 putstr (SCHEME_A_ "Errors encountered reading "); putstr (SCHEME_A_ file_name); putstr (SCHEME_A_ "\n");
6084 root 1.1 }
6085    
6086     if (isfile)
6087     close (fin);
6088     }
6089     #endif
6090     }
6091    
6092     file_name = *argv++;
6093     }
6094     while (file_name != 0);
6095    
6096     if (argc == 1)
6097     scheme_load_named_file (SCHEME_A_ STDIN_FILENO, 0);
6098    
6099     retcode = SCHEME_V->retcode;
6100     scheme_deinit (SCHEME_A);
6101    
6102     return retcode;
6103     }
6104    
6105     #endif
6106    
6107     /*
6108     Local variables:
6109     c-file-style: "k&r"
6110     End:
6111     */