ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.51
Committed: Tue Dec 1 01:54:27 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.50: +97 -102 lines
Log Message:
abstract pointer type

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