ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.42
Committed: Mon Nov 30 06:19:18 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.41: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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