ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.56
Committed: Tue Dec 1 03:44:32 2015 UTC (8 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.55: +6 -8 lines
Log Message:
more r7rs

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