ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.37
Committed: Sun Nov 29 05:09:24 2015 UTC (8 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.36: +13 -0 lines
Log Message:
*** empty log message ***

File Contents

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