ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.48
Committed: Mon Nov 30 13:07:34 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.47: +32 -20 lines
Log Message:
intcache

File Contents

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