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