ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/microscheme/scheme.c
Revision: 1.54
Committed: Tue Dec 1 02:42:35 2015 UTC (8 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.53: +4 -42 lines
Log Message:
*** empty log message ***

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 {
4005 if (is_integer (x))
4006 s_return (x);
4007
4008 RVALUE r = rvalue_unchecked (x);
4009
4010 if (r == (RVALUE)(IVALUE)r)
4011 s_return (mk_integer (SCHEME_A_ rvalue_unchecked (x)));
4012 else
4013 Error_1 ("inexact->exact: not integral:", x);
4014 }
4015
4016 case OP_EXP: s_return (mk_real (SCHEME_A_ exp (rvalue (x))));
4017 case OP_LOG: s_return (mk_real (SCHEME_A_ log (rvalue (x))));
4018 case OP_SIN: s_return (mk_real (SCHEME_A_ sin (rvalue (x))));
4019 case OP_COS: s_return (mk_real (SCHEME_A_ cos (rvalue (x))));
4020 case OP_TAN: s_return (mk_real (SCHEME_A_ tan (rvalue (x))));
4021 case OP_ASIN: s_return (mk_real (SCHEME_A_ asin (rvalue (x))));
4022 case OP_ACOS: s_return (mk_real (SCHEME_A_ acos (rvalue (x))));
4023
4024 case OP_ATAN:
4025 if (cdr (args) == NIL)
4026 s_return (mk_real (SCHEME_A_ atan (rvalue (x))));
4027 else
4028 {
4029 pointer y = cadr (args);
4030 s_return (mk_real (SCHEME_A_ atan2 (rvalue (x), rvalue (y))));
4031 }
4032
4033 case OP_SQRT:
4034 s_return (mk_real (SCHEME_A_ sqrt (rvalue (x))));
4035
4036 case OP_EXPT:
4037 {
4038 RVALUE result;
4039 int real_result = 1;
4040 pointer y = cadr (args);
4041
4042 if (is_integer (x) && is_integer (y))
4043 real_result = 0;
4044
4045 /* This 'if' is an R5RS compatibility fix. */
4046 /* NOTE: Remove this 'if' fix for R6RS. */
4047 if (rvalue (x) == 0 && rvalue (y) < 0)
4048 result = 0;
4049 else
4050 result = pow (rvalue (x), rvalue (y));
4051
4052 /* Before returning integer result make sure we can. */
4053 /* If the test fails, result is too big for integer. */
4054 if (!real_result)
4055 {
4056 long result_as_long = result;
4057
4058 if (result != result_as_long)
4059 real_result = 1;
4060 }
4061
4062 if (real_result)
4063 s_return (mk_real (SCHEME_A_ result));
4064 else
4065 s_return (mk_integer (SCHEME_A_ result));
4066 }
4067
4068 case OP_FLOOR: s_return (mk_real (SCHEME_A_ floor (rvalue (x))));
4069 case OP_CEILING: s_return (mk_real (SCHEME_A_ ceil (rvalue (x))));
4070 case OP_TRUNCATE: s_return (mk_real (SCHEME_A_ trunc (rvalue (x))));
4071 case OP_ROUND: s_return (mk_real (SCHEME_A_ nearbyint (rvalue (x))));
4072 #endif
4073
4074 case OP_ADD: /* + */
4075 v = num_zero;
4076
4077 for (x = args; x != NIL; x = cdr (x))
4078 v = num_op (NUM_ADD, v, nvalue (car (x)));
4079
4080 s_return (mk_number (SCHEME_A_ v));
4081
4082 case OP_MUL: /* * */
4083 v = num_one;
4084
4085 for (x = args; x != NIL; x = cdr (x))
4086 v = num_op (NUM_MUL, v, nvalue (car (x)));
4087
4088 s_return (mk_number (SCHEME_A_ v));
4089
4090 case OP_SUB: /* - */
4091 if (cdr (args) == NIL)
4092 {
4093 x = args;
4094 v = num_zero;
4095 }
4096 else
4097 {
4098 x = cdr (args);
4099 v = nvalue (car (args));
4100 }
4101
4102 for (; x != NIL; x = cdr (x))
4103 v = num_op (NUM_SUB, v, nvalue (car (x)));
4104
4105 s_return (mk_number (SCHEME_A_ v));
4106
4107 case OP_DIV: /* / */
4108 if (cdr (args) == NIL)
4109 {
4110 x = args;
4111 v = num_one;
4112 }
4113 else
4114 {
4115 x = cdr (args);
4116 v = nvalue (car (args));
4117 }
4118
4119 for (; x != NIL; x = cdr (x))
4120 if (!is_zero_rvalue (rvalue (car (x))))
4121 v = num_div (v, nvalue (car (x)));
4122 else
4123 Error_0 ("/: division by zero");
4124
4125 s_return (mk_number (SCHEME_A_ v));
4126
4127 case OP_INTDIV: /* quotient */
4128 if (cdr (args) == NIL)
4129 {
4130 x = args;
4131 v = num_one;
4132 }
4133 else
4134 {
4135 x = cdr (args);
4136 v = nvalue (car (args));
4137 }
4138
4139 for (; x != NIL; x = cdr (x))
4140 {
4141 if (ivalue (car (x)) != 0)
4142 v = num_op (NUM_INTDIV, v, nvalue (car (x)));
4143 else
4144 Error_0 ("quotient: division by zero");
4145 }
4146
4147 s_return (mk_number (SCHEME_A_ v));
4148
4149 case OP_REM: /* remainder */
4150 v = nvalue (x);
4151
4152 if (ivalue (cadr (args)) != 0)
4153 v = num_rem (v, nvalue (cadr (args)));
4154 else
4155 Error_0 ("remainder: division by zero");
4156
4157 s_return (mk_number (SCHEME_A_ v));
4158
4159 case OP_MOD: /* modulo */
4160 v = nvalue (x);
4161
4162 if (ivalue (cadr (args)) != 0)
4163 v = num_mod (v, nvalue (cadr (args)));
4164 else
4165 Error_0 ("modulo: division by zero");
4166
4167 s_return (mk_number (SCHEME_A_ v));
4168
4169 /* the compiler will optimize this mess... */
4170 case OP_CAR: op_car: s_return (car (x));
4171 case OP_CDR: op_cdr: s_return (cdr (x));
4172 case OP_CAAR: op_caar: x = car (x); goto op_car;
4173 case OP_CADR: op_cadr: x = cdr (x); goto op_car;
4174 case OP_CDAR: op_cdar: x = car (x); goto op_cdr;
4175 case OP_CDDR: op_cddr: x = cdr (x); goto op_cdr;
4176 case OP_CAAAR: op_caaar: x = car (x); goto op_caar;
4177 case OP_CAADR: op_caadr: x = cdr (x); goto op_caar;
4178 case OP_CADAR: op_cadar: x = car (x); goto op_cadr;
4179 case OP_CADDR: op_caddr: x = cdr (x); goto op_cadr;
4180 case OP_CDAAR: op_cdaar: x = car (x); goto op_cdar;
4181 case OP_CDADR: op_cdadr: x = cdr (x); goto op_cdar;
4182 case OP_CDDAR: op_cddar: x = car (x); goto op_cddr;
4183 case OP_CDDDR: op_cdddr: x = cdr (x); goto op_cddr;
4184 case OP_CAAAAR: x = car (x); goto op_caaar;
4185 case OP_CAAADR: x = cdr (x); goto op_caaar;
4186 case OP_CAADAR: x = car (x); goto op_caadr;
4187 case OP_CAADDR: x = cdr (x); goto op_caadr;
4188 case OP_CADAAR: x = car (x); goto op_cadar;
4189 case OP_CADADR: x = cdr (x); goto op_cadar;
4190 case OP_CADDAR: x = car (x); goto op_caddr;
4191 case OP_CADDDR: x = cdr (x); goto op_caddr;
4192 case OP_CDAAAR: x = car (x); goto op_cdaar;
4193 case OP_CDAADR: x = cdr (x); goto op_cdaar;
4194 case OP_CDADAR: x = car (x); goto op_cdadr;
4195 case OP_CDADDR: x = cdr (x); goto op_cdadr;
4196 case OP_CDDAAR: x = car (x); goto op_cddar;
4197 case OP_CDDADR: x = cdr (x); goto op_cddar;
4198 case OP_CDDDAR: x = car (x); goto op_cdddr;
4199 case OP_CDDDDR: x = cdr (x); goto op_cdddr;
4200
4201 case OP_CONS: /* cons */
4202 set_cdr (args, cadr (args));
4203 s_return (args);
4204
4205 case OP_SETCAR: /* set-car! */
4206 if (!is_immutable (x))
4207 {
4208 set_car (x, cadr (args));
4209 s_return (car (args));
4210 }
4211 else
4212 Error_0 ("set-car!: unable to alter immutable pair");
4213
4214 case OP_SETCDR: /* set-cdr! */
4215 if (!is_immutable (x))
4216 {
4217 set_cdr (x, cadr (args));
4218 s_return (car (args));
4219 }
4220 else
4221 Error_0 ("set-cdr!: unable to alter immutable pair");
4222
4223 case OP_CHAR2INT: /* char->integer */
4224 s_return (mk_integer (SCHEME_A_ ivalue_unchecked (x)));
4225
4226 case OP_INT2CHAR: /* integer->char */
4227 s_return (mk_character (SCHEME_A_ ivalue_unchecked (x)));
4228
4229 case OP_CHARUPCASE:
4230 {
4231 unsigned char c = ivalue_unchecked (x);
4232 c = toupper (c);
4233 s_return (mk_character (SCHEME_A_ c));
4234 }
4235
4236 case OP_CHARDNCASE:
4237 {
4238 unsigned char c = ivalue_unchecked (x);
4239 c = tolower (c);
4240 s_return (mk_character (SCHEME_A_ c));
4241 }
4242
4243 case OP_STR2SYM: /* string->symbol */
4244 s_return (mk_symbol (SCHEME_A_ strvalue (x)));
4245
4246 case OP_STR2ATOM: /* string->atom */
4247 {
4248 char *s = strvalue (x);
4249 long pf = 0;
4250
4251 if (cdr (args) != NIL)
4252 {
4253 /* we know cadr(args) is a natural number */
4254 /* see if it is 2, 8, 10, or 16, or error */
4255 pf = ivalue_unchecked (cadr (args));
4256
4257 if (pf == 16 || pf == 10 || pf == 8 || pf == 2)
4258 {
4259 /* base is OK */
4260 }
4261 else
4262 pf = -1;
4263 }
4264
4265 if (pf < 0)
4266 Error_1 ("string->atom: bad base:", cadr (args));
4267 else if (*s == '#') /* no use of base! */
4268 s_return (mk_sharp_const (SCHEME_A_ s + 1));
4269 else
4270 {
4271 if (pf == 0 || pf == 10)
4272 s_return (mk_atom (SCHEME_A_ s));
4273 else
4274 {
4275 char *ep;
4276 long iv = strtol (s, &ep, (int) pf);
4277
4278 if (*ep == 0)
4279 s_return (mk_integer (SCHEME_A_ iv));
4280 else
4281 s_return (S_F);
4282 }
4283 }
4284 }
4285
4286 case OP_SYM2STR: /* symbol->string */
4287 x = mk_string (SCHEME_A_ symname (x));
4288 setimmutable (x);
4289 s_return (x);
4290
4291 case OP_ATOM2STR: /* atom->string */
4292 {
4293 long pf = 0;
4294
4295 if (cdr (args) != NIL)
4296 {
4297 /* we know cadr(args) is a natural number */
4298 /* see if it is 2, 8, 10, or 16, or error */
4299 pf = ivalue_unchecked (cadr (args));
4300
4301 if (is_number (x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2))
4302 {
4303 /* base is OK */
4304 }
4305 else
4306 pf = -1;
4307 }
4308
4309 if (pf < 0)
4310 Error_1 ("atom->string: bad base:", cadr (args));
4311 else if (is_number (x) || is_character (x) || is_string (x) || is_symbol (x))
4312 {
4313 char *p;
4314 int len;
4315
4316 atom2str (SCHEME_A_ x, pf, &p, &len);
4317 s_return (mk_counted_string (SCHEME_A_ p, len));
4318 }
4319 else
4320 Error_1 ("atom->string: not an atom:", x);
4321 }
4322
4323 case OP_MKSTRING: /* make-string */
4324 {
4325 int fill = cdr (args) != NIL ? charvalue (cadr (args)) : ' ';
4326 int len = ivalue_unchecked (x);
4327
4328 s_return (mk_empty_string (SCHEME_A_ len, fill));
4329 }
4330
4331 case OP_STRLEN: /* string-length */
4332 s_return (mk_integer (SCHEME_A_ strlength (x)));
4333
4334 case OP_STRREF: /* string-ref */
4335 {
4336 char *str = strvalue (x);
4337 int index = ivalue_unchecked (cadr (args));
4338
4339 if (index >= strlength (x))
4340 Error_1 ("string-ref: out of bounds:", cadr (args));
4341
4342 s_return (mk_character (SCHEME_A_ ((unsigned char *)str)[index]));
4343 }
4344
4345 case OP_STRSET: /* string-set! */
4346 {
4347 char *str = strvalue (x);
4348 int index = ivalue_unchecked (cadr (args));
4349 int c;
4350
4351 if (is_immutable (x))
4352 Error_1 ("string-set!: unable to alter immutable string:", x);
4353
4354 if (index >= strlength (x))
4355 Error_1 ("string-set!: out of bounds:", cadr (args));
4356
4357 c = charvalue (caddr (args));
4358
4359 str[index] = c;
4360 s_return (car (args));
4361 }
4362
4363 case OP_STRAPPEND: /* string-append */
4364 {
4365 /* in 1.29 string-append was in Scheme in init.scm but was too slow */
4366 int len = 0;
4367 pointer newstr;
4368 char *pos;
4369
4370 /* compute needed length for new string */
4371 for (x = args; x != NIL; x = cdr (x))
4372 len += strlength (car (x));
4373
4374 newstr = mk_empty_string (SCHEME_A_ len, ' ');
4375
4376 /* store the contents of the argument strings into the new string */
4377 for (pos = strvalue (newstr), x = args; x != NIL; pos += strlength (car (x)), x = cdr (x))
4378 memcpy (pos, strvalue (car (x)), strlength (car (x)));
4379
4380 s_return (newstr);
4381 }
4382
4383 case OP_SUBSTR: /* substring */
4384 {
4385 char *str = strvalue (x);
4386 int index0 = ivalue_unchecked (cadr (args));
4387 int index1;
4388 int len;
4389
4390 if (index0 > strlength (x))
4391 Error_1 ("substring: start out of bounds:", cadr (args));
4392
4393 if (cddr (args) != NIL)
4394 {
4395 index1 = ivalue_unchecked (caddr (args));
4396
4397 if (index1 > strlength (x) || index1 < index0)
4398 Error_1 ("substring: end out of bounds:", caddr (args));
4399 }
4400 else
4401 index1 = strlength (x);
4402
4403 len = index1 - index0;
4404 x = mk_empty_string (SCHEME_A_ len, ' ');
4405 memcpy (strvalue (x), str + index0, len);
4406 strvalue (x)[len] = 0;
4407
4408 s_return (x);
4409 }
4410
4411 case OP_VECTOR: /* vector */
4412 {
4413 int i;
4414 pointer vec;
4415 int len = list_length (SCHEME_A_ args);
4416
4417 if (len < 0)
4418 Error_1 ("vector: not a proper list:", args);
4419
4420 vec = mk_vector (SCHEME_A_ len);
4421
4422 #if USE_ERROR_CHECKING
4423 if (SCHEME_V->no_memory)
4424 s_return (S_SINK);
4425 #endif
4426
4427 for (x = args, i = 0; is_pair (x); x = cdr (x), i++)
4428 vector_set (vec, i, car (x));
4429
4430 s_return (vec);
4431 }
4432
4433 case OP_MKVECTOR: /* make-vector */
4434 {
4435 pointer fill = NIL;
4436 pointer vec;
4437 int len = ivalue_unchecked (x);
4438
4439 if (cdr (args) != NIL)
4440 fill = cadr (args);
4441
4442 vec = mk_vector (SCHEME_A_ len);
4443
4444 #if USE_ERROR_CHECKING
4445 if (SCHEME_V->no_memory)
4446 s_return (S_SINK);
4447 #endif
4448
4449 if (fill != NIL)
4450 fill_vector (vec, 0, fill);
4451
4452 s_return (vec);
4453 }
4454
4455 case OP_VECLEN: /* vector-length */
4456 s_return (mk_integer (SCHEME_A_ veclength (x)));
4457
4458 case OP_VECRESIZE:
4459 vector_resize (x, ivalue_unchecked (cadr (args)), caddr (args));
4460 s_return (x);
4461
4462 case OP_VECREF: /* vector-ref */
4463 {
4464 int index = ivalue_unchecked (cadr (args));
4465
4466 if (index >= veclength (car (args)) && USE_ERROR_CHECKING)
4467 Error_1 ("vector-ref: out of bounds:", cadr (args));
4468
4469 s_return (vector_get (x, index));
4470 }
4471
4472 case OP_VECSET: /* vector-set! */
4473 {
4474 int index = ivalue_unchecked (cadr (args));
4475
4476 if (is_immutable (x))
4477 Error_1 ("vector-set!: unable to alter immutable vector:", x);
4478
4479 if (index >= veclength (car (args)) && USE_ERROR_CHECKING)
4480 Error_1 ("vector-set!: out of bounds:", cadr (args));
4481
4482 vector_set (x, index, caddr (args));
4483 s_return (x);
4484 }
4485 }
4486
4487 if (USE_ERROR_CHECKING) abort ();
4488 }
4489
4490 static int
4491 opexe_2 (SCHEME_P_ enum scheme_opcodes op)
4492 {
4493 pointer x = SCHEME_V->args;
4494
4495 for (;;)
4496 {
4497 num v = nvalue (car (x));
4498 x = cdr (x);
4499
4500 if (x == NIL)
4501 break;
4502
4503 int r = num_cmp (v, nvalue (car (x)));
4504
4505 switch (op)
4506 {
4507 case OP_NUMEQ: r = r == 0; break;
4508 case OP_LESS: r = r < 0; break;
4509 case OP_GRE: r = r > 0; break;
4510 case OP_LEQ: r = r <= 0; break;
4511 case OP_GEQ: r = r >= 0; break;
4512 }
4513
4514 if (!r)
4515 s_return (S_F);
4516 }
4517
4518 s_return (S_T);
4519 }
4520
4521 static int
4522 opexe_3 (SCHEME_P_ enum scheme_opcodes op)
4523 {
4524 pointer args = SCHEME_V->args;
4525 pointer a = car (args);
4526 pointer d = cdr (args);
4527 int r;
4528
4529 switch (op)
4530 {
4531 case OP_NOT: /* not */ r = is_false (a) ; break;
4532 case OP_BOOLP: /* boolean? */ r = a == S_F || a == S_T ; break;
4533 case OP_EOFOBJP: /* eof-object? */ r = a == S_EOF ; break;
4534 case OP_NULLP: /* null? */ r = a == NIL ; break;
4535 case OP_SYMBOLP: /* symbol? */ r = is_symbol (a) ; break;
4536 case OP_GENSYMP: /* gensym? */ r = is_gensym (SCHEME_A_ a); break;
4537 case OP_NUMBERP: /* number? */ r = is_number (a) ; break;
4538 case OP_STRINGP: /* string? */ r = is_string (a) ; break;
4539 case OP_INTEGERP: /* integer? */ r = is_integer (a) ; break;
4540 case OP_REALP: /* real? */ r = is_number (a) ; break; /* all numbers are real */
4541 case OP_CHARP: /* char? */ r = is_character (a) ; break;
4542
4543 #if USE_CHAR_CLASSIFIERS
4544 case OP_CHARAP: /* char-alphabetic? */ r = Cisalpha (ivalue_unchecked (a)); break;
4545 case OP_CHARNP: /* char-numeric? */ r = Cisdigit (ivalue_unchecked (a)); break;
4546 case OP_CHARWP: /* char-whitespace? */ r = Cisspace (ivalue_unchecked (a)); break;
4547 case OP_CHARUP: /* char-upper-case? */ r = Cisupper (ivalue_unchecked (a)); break;
4548 case OP_CHARLP: /* char-lower-case? */ r = Cislower (ivalue_unchecked (a)); break;
4549 #endif
4550
4551 #if USE_PORTS
4552 case OP_PORTP: /* port? */ r = is_port (a) ; break;
4553 case OP_INPORTP: /* input-port? */ r = is_inport (a) ; break;
4554 case OP_OUTPORTP: /* output-port? */ r = is_outport (a); break;
4555 #endif
4556
4557 case OP_PROCP: /* procedure? */
4558
4559 /*--
4560 * continuation should be procedure by the example
4561 * (call-with-current-continuation procedure?) ==> #t
4562 * in R^3 report sec. 6.9
4563 */
4564 r = is_proc (a) || is_closure (a) || is_continuation (a) || is_foreign (a);
4565 break;
4566
4567 case OP_PAIRP: /* pair? */ r = is_pair (a) ; break;
4568 case OP_LISTP: /* list? */ r = list_length (SCHEME_A_ a) >= 0; break;
4569 case OP_ENVP: /* environment? */ r = is_environment (a) ; break;
4570 case OP_VECTORP: /* vector? */ r = is_vector (a) ; break;
4571 case OP_EQ: /* eq? */ r = a == cadr (args) ; break;
4572 case OP_EQV: /* eqv? */ r = eqv (a, cadr (args)) ; break;
4573 }
4574
4575 s_retbool (r);
4576 }
4577
4578 static int
4579 opexe_4 (SCHEME_P_ enum scheme_opcodes op)
4580 {
4581 pointer args = SCHEME_V->args;
4582 pointer a = car (args);
4583 pointer x, y;
4584
4585 switch (op)
4586 {
4587 case OP_FORCE: /* force */
4588 SCHEME_V->code = a;
4589
4590 if (is_promise (SCHEME_V->code))
4591 {
4592 /* Should change type to closure here */
4593 s_save (SCHEME_A_ OP_SAVE_FORCED, NIL, SCHEME_V->code);
4594 SCHEME_V->args = NIL;
4595 s_goto (OP_APPLY);
4596 }
4597 else
4598 s_return (SCHEME_V->code);
4599
4600 case OP_SAVE_FORCED: /* Save forced value replacing promise */
4601 *CELL (SCHEME_V->code) = *CELL (SCHEME_V->value);
4602 s_return (SCHEME_V->value);
4603
4604 #if USE_PORTS
4605
4606 case OP_WRITE: /* write */
4607 case OP_DISPLAY: /* display */
4608 case OP_WRITE_CHAR: /* write-char */
4609 if (is_pair (cdr (SCHEME_V->args)))
4610 {
4611 if (cadr (SCHEME_V->args) != SCHEME_V->outport)
4612 {
4613 x = cons (SCHEME_V->outport, NIL);
4614 s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
4615 SCHEME_V->outport = cadr (SCHEME_V->args);
4616 }
4617 }
4618
4619 SCHEME_V->args = a;
4620
4621 if (op == OP_WRITE)
4622 SCHEME_V->print_flag = 1;
4623 else
4624 SCHEME_V->print_flag = 0;
4625
4626 s_goto (OP_P0LIST);
4627
4628 case OP_NEWLINE: /* newline */
4629 if (is_pair (args))
4630 {
4631 if (a != SCHEME_V->outport)
4632 {
4633 x = cons (SCHEME_V->outport, NIL);
4634 s_save (SCHEME_A_ OP_SET_OUTPORT, x, NIL);
4635 SCHEME_V->outport = a;
4636 }
4637 }
4638
4639 putstr (SCHEME_A_ "\n");
4640 s_return (S_T);
4641 #endif
4642
4643 case OP_ERR0: /* error */
4644 SCHEME_V->retcode = -1;
4645
4646 if (!is_string (a))
4647 {
4648 args = cons (mk_string (SCHEME_A_ " -- "), args);
4649 setimmutable (car (args));
4650 }
4651
4652 putstr (SCHEME_A_ "Error: ");
4653 putstr (SCHEME_A_ strvalue (car (args)));
4654 SCHEME_V->args = cdr (args);
4655 s_goto (OP_ERR1);
4656
4657 case OP_ERR1: /* error */
4658 putstr (SCHEME_A_ " ");
4659
4660 if (args != NIL)
4661 {
4662 s_save (SCHEME_A_ OP_ERR1, cdr (args), NIL);
4663 SCHEME_V->args = a;
4664 SCHEME_V->print_flag = 1;
4665 s_goto (OP_P0LIST);
4666 }
4667 else
4668 {
4669 putstr (SCHEME_A_ "\n");
4670
4671 if (SCHEME_V->interactive_repl)
4672 s_goto (OP_T0LVL);
4673 else
4674 return -1;
4675 }
4676
4677 case OP_REVERSE: /* reverse */
4678 s_return (reverse (SCHEME_A_ a));
4679
4680 case OP_LIST_STAR: /* list* */
4681 s_return (list_star (SCHEME_A_ SCHEME_V->args));
4682
4683 case OP_APPEND: /* append */
4684 x = NIL;
4685 y = args;
4686
4687 if (y == x)
4688 s_return (x);
4689
4690 /* cdr() in the while condition is not a typo. If car() */
4691 /* is used (append '() 'a) will return the wrong result. */
4692 while (cdr (y) != NIL)
4693 {
4694 x = revappend (SCHEME_A_ x, car (y));
4695 y = cdr (y);
4696
4697 if (x == S_F)
4698 Error_0 ("non-list argument to append");
4699 }
4700
4701 s_return (reverse_in_place (SCHEME_A_ car (y), x));
4702
4703 #if USE_PLIST
4704
4705 case OP_PUT: /* put */
4706 if (!hasprop (a) || !hasprop (cadr (args)))
4707 Error_0 ("illegal use of put");
4708
4709 for (x = symprop (a), y = cadr (args); x != NIL; x = cdr (x))
4710 {
4711 if (caar (x) == y)
4712 break;
4713 }
4714
4715 if (x != NIL)
4716 cdar (x) = caddr (args);
4717 else
4718 symprop (a) = cons (cons (y, caddr (args)), symprop (a));
4719
4720 s_return (S_T);
4721
4722 case OP_GET: /* get */
4723 if (!hasprop (a) || !hasprop (cadr (args)))
4724 Error_0 ("illegal use of get");
4725
4726 for (x = symprop (a), y = cadr (args); x != NIL; x = cdr (x))
4727 if (caar (x) == y)
4728 break;
4729
4730 if (x != NIL)
4731 s_return (cdar (x));
4732 else
4733 s_return (NIL);
4734
4735 #endif /* USE_PLIST */
4736
4737 case OP_QUIT: /* quit */
4738 if (is_pair (args))
4739 SCHEME_V->retcode = ivalue (a);
4740
4741 return -1;
4742
4743 case OP_GC: /* gc */
4744 gc (SCHEME_A_ NIL, NIL);
4745 s_return (S_T);
4746
4747 case OP_GCVERB: /* gc-verbose */
4748 {
4749 int was = SCHEME_V->gc_verbose;
4750
4751 SCHEME_V->gc_verbose = (a != S_F);
4752 s_retbool (was);
4753 }
4754
4755 case OP_NEWSEGMENT: /* new-segment */
4756 #if 0
4757 if (!is_pair (args) || !is_number (a))
4758 Error_0 ("new-segment: argument must be a number");
4759 #endif
4760 s_retbool (alloc_cellseg (SCHEME_A));
4761
4762 case OP_OBLIST: /* oblist */
4763 s_return (oblist_all_symbols (SCHEME_A));
4764
4765 #if USE_PORTS
4766
4767 case OP_CURR_INPORT: /* current-input-port */
4768 s_return (SCHEME_V->inport);
4769
4770 case OP_CURR_OUTPORT: /* current-output-port */
4771 s_return (SCHEME_V->outport);
4772
4773 case OP_OPEN_INFILE: /* open-input-file */
4774 case OP_OPEN_OUTFILE: /* open-output-file */
4775 case OP_OPEN_INOUTFILE: /* open-input-output-file */
4776 {
4777 int prop = 0;
4778 pointer p;
4779
4780 switch (op)
4781 {
4782 case OP_OPEN_INFILE:
4783 prop = port_input;
4784 break;
4785
4786 case OP_OPEN_OUTFILE:
4787 prop = port_output;
4788 break;
4789
4790 case OP_OPEN_INOUTFILE:
4791 prop = port_input | port_output;
4792 break;
4793 }
4794
4795 p = port_from_filename (SCHEME_A_ strvalue (a), prop);
4796
4797 s_return (p == NIL ? S_F : p);
4798 }
4799
4800 # if USE_STRING_PORTS
4801
4802 case OP_OPEN_INSTRING: /* open-input-string */
4803 case OP_OPEN_INOUTSTRING: /* open-input-output-string */
4804 {
4805 int prop = 0;
4806 pointer p;
4807
4808 switch (op)
4809 {
4810 case OP_OPEN_INSTRING:
4811 prop = port_input;
4812 break;
4813
4814 case OP_OPEN_INOUTSTRING:
4815 prop = port_input | port_output;
4816 break;
4817 }
4818
4819 p = port_from_string (SCHEME_A_ strvalue (a),
4820 strvalue (a) + strlength (a), prop);
4821
4822 s_return (p == NIL ? S_F : p);
4823 }
4824
4825 case OP_OPEN_OUTSTRING: /* open-output-string */
4826 {
4827 pointer p;
4828
4829 if (a == NIL)
4830 p = port_from_scratch (SCHEME_A);
4831 else
4832 p = port_from_string (SCHEME_A_ strvalue (a),
4833 strvalue (a) + strlength (a), port_output);
4834
4835 s_return (p == NIL ? S_F : p);
4836 }
4837
4838 case OP_GET_OUTSTRING: /* get-output-string */
4839 {
4840 port *p = port (a);
4841
4842 if (p->kind & port_string)
4843 {
4844 off_t size;
4845 char *str;
4846
4847 size = p->rep.string.curr - p->rep.string.start + 1;
4848 str = malloc (size);
4849
4850 if (str != NULL)
4851 {
4852 pointer s;
4853
4854 memcpy (str, p->rep.string.start, size - 1);
4855 str[size - 1] = '\0';
4856 s = mk_string (SCHEME_A_ str);
4857 free (str);
4858 s_return (s);
4859 }
4860 }
4861
4862 s_return (S_F);
4863 }
4864
4865 # endif
4866
4867 case OP_CLOSE_INPORT: /* close-input-port */
4868 port_close (SCHEME_A_ a, port_input);
4869 s_return (S_T);
4870
4871 case OP_CLOSE_OUTPORT: /* close-output-port */
4872 port_close (SCHEME_A_ a, port_output);
4873 s_return (S_T);
4874 #endif
4875
4876 case OP_INT_ENV: /* interaction-environment */
4877 s_return (SCHEME_V->global_env);
4878
4879 case OP_CURR_ENV: /* current-environment */
4880 s_return (SCHEME_V->envir);
4881
4882 }
4883
4884 if (USE_ERROR_CHECKING) abort ();
4885 }
4886
4887 static int
4888 opexe_5 (SCHEME_P_ enum scheme_opcodes op)
4889 {
4890 pointer args = SCHEME_V->args;
4891 pointer x;
4892
4893 if (SCHEME_V->nesting != 0)
4894 {
4895 int n = SCHEME_V->nesting;
4896
4897 SCHEME_V->nesting = 0;
4898 SCHEME_V->retcode = -1;
4899 Error_1 ("unmatched parentheses:", mk_integer (SCHEME_A_ n));
4900 }
4901
4902 switch (op)
4903 {
4904 /* ========== reading part ========== */
4905 #if USE_PORTS
4906 case OP_READ:
4907 if (!is_pair (args))
4908 s_goto (OP_READ_INTERNAL);
4909
4910 if (!is_inport (car (args)))
4911 Error_1 ("read: not an input port:", car (args));
4912
4913 if (car (args) == SCHEME_V->inport)
4914 s_goto (OP_READ_INTERNAL);
4915
4916 x = SCHEME_V->inport;
4917 SCHEME_V->inport = car (args);
4918 x = cons (x, NIL);
4919 s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
4920 s_goto (OP_READ_INTERNAL);
4921
4922 case OP_READ_CHAR: /* read-char */
4923 case OP_PEEK_CHAR: /* peek-char */
4924 {
4925 int c;
4926
4927 if (is_pair (args))
4928 {
4929 if (car (args) != SCHEME_V->inport)
4930 {
4931 x = SCHEME_V->inport;
4932 x = cons (x, NIL);
4933 s_save (SCHEME_A_ OP_SET_INPORT, x, NIL);
4934 SCHEME_V->inport = car (args);
4935 }
4936 }
4937
4938 c = inchar (SCHEME_A);
4939
4940 if (c == EOF)
4941 s_return (S_EOF);
4942
4943 if (SCHEME_V->op == OP_PEEK_CHAR)
4944 backchar (SCHEME_A_ c);
4945
4946 s_return (mk_character (SCHEME_A_ c));
4947 }
4948
4949 case OP_CHAR_READY: /* char-ready? */
4950 {
4951 pointer p = SCHEME_V->inport;
4952 int res;
4953
4954 if (is_pair (args))
4955 p = car (args);
4956
4957 res = port (p)->kind & port_string;
4958
4959 s_retbool (res);
4960 }
4961
4962 case OP_SET_INPORT: /* set-input-port */
4963 SCHEME_V->inport = car (args);
4964 s_return (SCHEME_V->value);
4965
4966 case OP_SET_OUTPORT: /* set-output-port */
4967 SCHEME_V->outport = car (args);
4968 s_return (SCHEME_V->value);
4969 #endif
4970
4971 case OP_RDSEXPR:
4972 switch (SCHEME_V->tok)
4973 {
4974 case TOK_EOF:
4975 s_return (S_EOF);
4976 /* NOTREACHED */
4977
4978 case TOK_VEC:
4979 s_save (SCHEME_A_ OP_RDVEC, NIL, NIL);
4980 /* fall through */
4981
4982 case TOK_LPAREN:
4983 SCHEME_V->tok = token (SCHEME_A);
4984
4985 if (SCHEME_V->tok == TOK_RPAREN)
4986 s_return (NIL);
4987 else if (SCHEME_V->tok == TOK_DOT)
4988 Error_0 ("syntax error: illegal dot expression");
4989 else
4990 {
4991 SCHEME_V->nesting_stack[SCHEME_V->file_i]++;
4992 s_save (SCHEME_A_ OP_RDLIST, NIL, NIL);
4993 s_goto (OP_RDSEXPR);
4994 }
4995
4996 case TOK_QUOTE:
4997 s_save (SCHEME_A_ OP_RDQUOTE, NIL, NIL);
4998 SCHEME_V->tok = token (SCHEME_A);
4999 s_goto (OP_RDSEXPR);
5000
5001 case TOK_BQUOTE:
5002 SCHEME_V->tok = token (SCHEME_A);
5003
5004 if (SCHEME_V->tok == TOK_VEC)
5005 {
5006 s_save (SCHEME_A_ OP_RDQQUOTEVEC, NIL, NIL);
5007 SCHEME_V->tok = TOK_LPAREN;
5008 s_goto (OP_RDSEXPR);
5009 }
5010 else
5011 s_save (SCHEME_A_ OP_RDQQUOTE, NIL, NIL);
5012
5013 s_goto (OP_RDSEXPR);
5014
5015 case TOK_COMMA:
5016 s_save (SCHEME_A_ OP_RDUNQUOTE, NIL, NIL);
5017 SCHEME_V->tok = token (SCHEME_A);
5018 s_goto (OP_RDSEXPR);
5019
5020 case TOK_ATMARK:
5021 s_save (SCHEME_A_ OP_RDUQTSP, NIL, NIL);
5022 SCHEME_V->tok = token (SCHEME_A);
5023 s_goto (OP_RDSEXPR);
5024
5025 case TOK_ATOM:
5026 s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ 0, DELIMITERS)));
5027
5028 case TOK_DOTATOM:
5029 SCHEME_V->strbuff[0] = '.';
5030 s_return (mk_atom (SCHEME_A_ readstr_upto (SCHEME_A_ 1, DELIMITERS)));
5031
5032 case TOK_STRATOM:
5033 x = readstrexp (SCHEME_A_ '|');
5034 //TODO: haven't checked whether the garbage collector could interfere
5035 s_return (mk_atom (SCHEME_A_ strvalue (x)));
5036
5037 case TOK_DQUOTE:
5038 x = readstrexp (SCHEME_A_ '"');
5039
5040 if (x == S_F)
5041 Error_0 ("Error reading string");
5042
5043 setimmutable (x);
5044 s_return (x);
5045
5046 case TOK_SHARP:
5047 {
5048 pointer f = find_slot_in_env (SCHEME_A_ SCHEME_V->envir, SCHEME_V->SHARP_HOOK, 1);
5049
5050 if (f == NIL)
5051 Error_0 ("undefined sharp expression");
5052 else
5053 {
5054 SCHEME_V->code = cons (slot_value_in_env (f), NIL);
5055 s_goto (OP_EVAL);
5056 }
5057 }
5058
5059 case TOK_SHARP_CONST:
5060 if ((x = mk_sharp_const (SCHEME_A_ readstr_upto (SCHEME_A_ 0, DELIMITERS))) == NIL)
5061 Error_0 ("undefined sharp expression");
5062 else
5063 s_return (x);
5064
5065 default:
5066 Error_0 ("syntax error: illegal token");
5067 }
5068
5069 break;
5070
5071 case OP_RDLIST:
5072 SCHEME_V->args = cons (SCHEME_V->value, args);
5073 SCHEME_V->tok = token (SCHEME_A);
5074
5075 switch (SCHEME_V->tok)
5076 {
5077 case TOK_EOF:
5078 s_return (S_EOF);
5079
5080 case TOK_RPAREN:
5081 {
5082 int c = inchar (SCHEME_A);
5083
5084 if (c != '\n')
5085 backchar (SCHEME_A_ c);
5086 #if SHOW_ERROR_LINE
5087 else if (SCHEME_V->load_stack[SCHEME_V->file_i].kind & port_file)
5088 SCHEME_V->load_stack[SCHEME_V->file_i].rep.stdio.curr_line++;
5089 #endif
5090
5091 SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5092 s_return (reverse_in_place (SCHEME_A_ NIL, SCHEME_V->args));
5093 }
5094
5095 case TOK_DOT:
5096 s_save (SCHEME_A_ OP_RDDOT, SCHEME_V->args, NIL);
5097 SCHEME_V->tok = token (SCHEME_A);
5098 s_goto (OP_RDSEXPR);
5099
5100 default:
5101 s_save (SCHEME_A_ OP_RDLIST, SCHEME_V->args, NIL);
5102 s_goto (OP_RDSEXPR);
5103 }
5104
5105 case OP_RDDOT:
5106 if (token (SCHEME_A) != TOK_RPAREN)
5107 Error_0 ("syntax error: illegal dot expression");
5108
5109 SCHEME_V->nesting_stack[SCHEME_V->file_i]--;
5110 s_return (reverse_in_place (SCHEME_A_ SCHEME_V->value, args));
5111
5112 case OP_RDQUOTE:
5113 s_return (cons (SCHEME_V->QUOTE, cons (SCHEME_V->value, NIL)));
5114
5115 case OP_RDQQUOTE:
5116 s_return (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)));
5117
5118 case OP_RDQQUOTEVEC:
5119 s_return (cons (mk_symbol (SCHEME_A_ "apply"),
5120 cons (mk_symbol (SCHEME_A_ "vector"),
5121 cons (cons (SCHEME_V->QQUOTE, cons (SCHEME_V->value, NIL)), NIL))));
5122
5123 case OP_RDUNQUOTE:
5124 s_return (cons (SCHEME_V->UNQUOTE, cons (SCHEME_V->value, NIL)));
5125
5126 case OP_RDUQTSP:
5127 s_return (cons (SCHEME_V->UNQUOTESP, cons (SCHEME_V->value, NIL)));
5128
5129 case OP_RDVEC:
5130 /*SCHEME_V->code=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5131 s_goto(OP_EVAL); Cannot be quoted */
5132 /*x=cons(mk_proc(SCHEME_A_ OP_VECTOR),SCHEME_V->value);
5133 s_return(x); Cannot be part of pairs */
5134 /*SCHEME_V->code=mk_proc(SCHEME_A_ OP_VECTOR);
5135 SCHEME_V->args=SCHEME_V->value;
5136 s_goto(OP_APPLY); */
5137 SCHEME_V->args = SCHEME_V->value;
5138 s_goto (OP_VECTOR);
5139
5140 /* ========== printing part ========== */
5141 case OP_P0LIST:
5142 if (is_vector (args))
5143 {
5144 putstr (SCHEME_A_ "#(");
5145 SCHEME_V->args = cons (args, mk_integer (SCHEME_A_ 0));
5146 s_goto (OP_PVECFROM);
5147 }
5148 else if (is_environment (args))
5149 {
5150 putstr (SCHEME_A_ "#<ENVIRONMENT>");
5151 s_return (S_T);
5152 }
5153 else if (!is_pair (args))
5154 {
5155 printatom (SCHEME_A_ args, SCHEME_V->print_flag);
5156 s_return (S_T);
5157 }
5158 else
5159 {
5160 pointer a = car (args);
5161 pointer b = cdr (args);
5162 int ok_abbr = ok_abbrev (b);
5163 SCHEME_V->args = car (b);
5164
5165 if (a == SCHEME_V->QUOTE && ok_abbr)
5166 putstr (SCHEME_A_ "'");
5167 else if (a == SCHEME_V->QQUOTE && ok_abbr)
5168 putstr (SCHEME_A_ "`");
5169 else if (a == SCHEME_V->UNQUOTE && ok_abbr)
5170 putstr (SCHEME_A_ ",");
5171 else if (a == SCHEME_V->UNQUOTESP && ok_abbr)
5172 putstr (SCHEME_A_ ",@");
5173 else
5174 {
5175 putstr (SCHEME_A_ "(");
5176 s_save (SCHEME_A_ OP_P1LIST, b, NIL);
5177 SCHEME_V->args = a;
5178 }
5179
5180 s_goto (OP_P0LIST);
5181 }
5182
5183 case OP_P1LIST:
5184 if (is_pair (args))
5185 {
5186 s_save (SCHEME_A_ OP_P1LIST, cdr (args), NIL);
5187 putstr (SCHEME_A_ " ");
5188 SCHEME_V->args = car (args);
5189 s_goto (OP_P0LIST);
5190 }
5191 else if (is_vector (args))
5192 {
5193 s_save (SCHEME_A_ OP_P1LIST, NIL, NIL);
5194 putstr (SCHEME_A_ " . ");
5195 s_goto (OP_P0LIST);
5196 }
5197 else
5198 {
5199 if (args != NIL)
5200 {
5201 putstr (SCHEME_A_ " . ");
5202 printatom (SCHEME_A_ args, SCHEME_V->print_flag);
5203 }
5204
5205 putstr (SCHEME_A_ ")");
5206 s_return (S_T);
5207 }
5208
5209 case OP_PVECFROM:
5210 {
5211 int i = ivalue_unchecked (cdr (args));
5212 pointer vec = car (args);
5213 int len = veclength (vec);
5214
5215 if (i == len)
5216 {
5217 putstr (SCHEME_A_ ")");
5218 s_return (S_T);
5219 }
5220 else
5221 {
5222 pointer elem = vector_get (vec, i);
5223
5224 ivalue_unchecked (cdr (args)) = i + 1;
5225 s_save (SCHEME_A_ OP_PVECFROM, args, NIL);
5226 SCHEME_V->args = elem;
5227
5228 if (i > 0)
5229 putstr (SCHEME_A_ " ");
5230
5231 s_goto (OP_P0LIST);
5232 }
5233 }
5234 }
5235
5236 if (USE_ERROR_CHECKING) abort ();
5237 }
5238
5239 static int
5240 opexe_6 (SCHEME_P_ enum scheme_opcodes op)
5241 {
5242 pointer args = SCHEME_V->args;
5243 pointer a = car (args);
5244 pointer x, y;
5245
5246 switch (op)
5247 {
5248 case OP_LIST_LENGTH: /* length *//* a.k */
5249 {
5250 long v = list_length (SCHEME_A_ a);
5251
5252 if (v < 0)
5253 Error_1 ("length: not a list:", a);
5254
5255 s_return (mk_integer (SCHEME_A_ v));
5256 }
5257
5258 case OP_ASSQ: /* assq *//* a.k */
5259 x = a;
5260
5261 for (y = cadr (args); is_pair (y); y = cdr (y))
5262 {
5263 if (!is_pair (car (y)))
5264 Error_0 ("unable to handle non pair element");
5265
5266 if (x == caar (y))
5267 break;
5268 }
5269
5270 if (is_pair (y))
5271 s_return (car (y));
5272 else
5273 s_return (S_F);
5274
5275
5276 case OP_GET_CLOSURE: /* get-closure-code *//* a.k */
5277 SCHEME_V->args = a;
5278
5279 if (SCHEME_V->args == NIL)
5280 s_return (S_F);
5281 else if (is_closure (SCHEME_V->args))
5282 s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5283 else if (is_macro (SCHEME_V->args))
5284 s_return (cons (SCHEME_V->LAMBDA, closure_code (SCHEME_V->value)));
5285 else
5286 s_return (S_F);
5287
5288 case OP_CLOSUREP: /* closure? */
5289 /*
5290 * Note, macro object is also a closure.
5291 * Therefore, (closure? <#MACRO>) ==> #t
5292 * (schmorp) well, obviously not, fix? TODO
5293 */
5294 s_retbool (is_closure (a));
5295
5296 case OP_MACROP: /* macro? */
5297 s_retbool (is_macro (a));
5298 }
5299
5300 if (USE_ERROR_CHECKING) abort ();
5301 }
5302
5303 /* dispatch functions (opexe_x) return new opcode, or 0 for same opcode, or -1 to stop */
5304 typedef int (*dispatch_func)(SCHEME_P_ enum scheme_opcodes);
5305
5306 typedef int (*test_predicate)(pointer);
5307 static int
5308 tst_any (pointer p)
5309 {
5310 return 1;
5311 }
5312
5313 static int
5314 tst_inonneg (pointer p)
5315 {
5316 return is_integer (p) && ivalue_unchecked (p) >= 0;
5317 }
5318
5319 static int
5320 tst_is_list (SCHEME_P_ pointer p)
5321 {
5322 return p == NIL || is_pair (p);
5323 }
5324
5325 /* Correspond carefully with following defines! */
5326 static struct
5327 {
5328 test_predicate fct;
5329 const char *kind;
5330 } tests[] = {
5331 { tst_any , 0 },
5332 { is_string , "string" },
5333 { is_symbol , "symbol" },
5334 { is_port , "port" },
5335 { is_inport , "input port" },
5336 { is_outport , "output port" },
5337 { is_environment, "environment" },
5338 { is_pair , "pair" },
5339 { 0 , "pair or '()" },
5340 { is_character , "character" },
5341 { is_vector , "vector" },
5342 { is_number , "number" },
5343 { is_integer , "integer" },
5344 { tst_inonneg , "non-negative integer" }
5345 };
5346
5347 #define TST_NONE 0 /* TST_NONE used for built-ins, 0 for internal ops */
5348 #define TST_ANY "\001"
5349 #define TST_STRING "\002"
5350 #define TST_SYMBOL "\003"
5351 #define TST_PORT "\004"
5352 #define TST_INPORT "\005"
5353 #define TST_OUTPORT "\006"
5354 #define TST_ENVIRONMENT "\007"
5355 #define TST_PAIR "\010"
5356 #define TST_LIST "\011"
5357 #define TST_CHAR "\012"
5358 #define TST_VECTOR "\013"
5359 #define TST_NUMBER "\014"
5360 #define TST_INTEGER "\015"
5361 #define TST_NATURAL "\016"
5362
5363 #define INF_ARG 0xff
5364 #define UNNAMED_OP ""
5365
5366 static const char opnames[] =
5367 #define OP_DEF(func,name,minarity,maxarity,argtest,op) name "\x00"
5368 #include "opdefines.h"
5369 #undef OP_DEF
5370 ;
5371
5372 static const char *
5373 opname (int idx)
5374 {
5375 const char *name = opnames;
5376
5377 /* should do this at compile time, but would require external program, right? */
5378 while (idx--)
5379 name += strlen (name) + 1;
5380
5381 return *name ? name : "ILLEGAL";
5382 }
5383
5384 static const char *
5385 procname (pointer x)
5386 {
5387 return opname (procnum (x));
5388 }
5389
5390 typedef struct
5391 {
5392 uint8_t func;
5393 /*dispatch_func func;*//*TODO: maybe optionally keep the pointer, for speed? */
5394 uint8_t builtin;
5395 #if USE_ERROR_CHECKING
5396 uint8_t min_arity;
5397 uint8_t max_arity;
5398 char arg_tests_encoding[3];
5399 #endif
5400 } op_code_info;
5401
5402 static const op_code_info dispatch_table[] = {
5403 #if USE_ERROR_CHECKING
5404 #define OP_DEF(func,name,minarity,maxarity,argtest,op) { func, sizeof (name) > 1, minarity, maxarity, argtest },
5405 #else
5406 #define OP_DEF(func,name,minarity,maxarity,argtest,op) { func, sizeof (name) > 1 },
5407 #endif
5408 #include "opdefines.h"
5409 #undef OP_DEF
5410 {0}
5411 };
5412
5413 /* kernel of this interpreter */
5414 static void ecb_hot
5415 Eval_Cycle (SCHEME_P_ enum scheme_opcodes op)
5416 {
5417 SCHEME_V->op = op;
5418
5419 for (;;)
5420 {
5421 const op_code_info *pcd = dispatch_table + SCHEME_V->op;
5422
5423 #if USE_ERROR_CHECKING
5424 if (pcd->builtin) /* if built-in function, check arguments */
5425 {
5426 char msg[STRBUFFSIZE];
5427 int n = list_length (SCHEME_A_ SCHEME_V->args);
5428
5429 /* Check number of arguments */
5430 if (ecb_expect_false (n < pcd->min_arity))
5431 {
5432 snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5433 opname (SCHEME_V->op), pcd->min_arity == pcd->max_arity ? "" : " at least", pcd->min_arity);
5434 xError_1 (SCHEME_A_ msg, 0);
5435 continue;
5436 }
5437 else if (ecb_expect_false (n > pcd->max_arity && pcd->max_arity != INF_ARG))
5438 {
5439 snprintf (msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
5440 opname (SCHEME_V->op), pcd->min_arity == pcd->max_arity ? "" : " at most", pcd->max_arity);
5441 xError_1 (SCHEME_A_ msg, 0);
5442 continue;
5443 }
5444 else
5445 {
5446 if (*pcd->arg_tests_encoding) /* literal 0 and TST_NONE treated the same */
5447 {
5448 int i = 0;
5449 int j;
5450 const char *t = pcd->arg_tests_encoding;
5451 pointer arglist = SCHEME_V->args;
5452
5453 do
5454 {
5455 pointer arg = car (arglist);
5456
5457 j = t[0];
5458
5459 /*TODO: tst_is_list has different prototype - fix if other tests acquire same prototype */
5460 if (j == TST_LIST[0])
5461 {
5462 if (!tst_is_list (SCHEME_A_ arg))
5463 break;
5464 }
5465 else
5466 {
5467 if (!tests[j - 1].fct (arg))
5468 break;
5469 }
5470
5471 if (t < pcd->arg_tests_encoding + sizeof (pcd->arg_tests_encoding) - 1 && t[1]) /* last test is replicated as necessary */
5472 t++;
5473
5474 arglist = cdr (arglist);
5475 i++;
5476 }
5477 while (i < n);
5478
5479 if (i < n)
5480 {
5481 snprintf (msg, STRBUFFSIZE, "%s: argument %d must be: %s", opname (SCHEME_V->op), i + 1, tests[j].kind);
5482 xError_1 (SCHEME_A_ msg, 0);
5483 continue;
5484 }
5485 }
5486 }
5487 }
5488 #endif
5489
5490 ok_to_freely_gc (SCHEME_A);
5491
5492 static const dispatch_func dispatch_funcs[] = {
5493 opexe_0,
5494 opexe_1,
5495 opexe_2,
5496 opexe_3,
5497 opexe_4,
5498 opexe_5,
5499 opexe_6,
5500 };
5501
5502 if (ecb_expect_false (dispatch_funcs [pcd->func] (SCHEME_A_ SCHEME_V->op) != 0))
5503 return;
5504
5505 if (SCHEME_V->no_memory && USE_ERROR_CHECKING)
5506 {
5507 putstr (SCHEME_A_ "No memory!\n");
5508 return;
5509 }
5510 }
5511 }
5512
5513 /* ========== Initialization of internal keywords ========== */
5514
5515 static void
5516 assign_syntax (SCHEME_P_ const char *name)
5517 {
5518 pointer x = oblist_add_by_name (SCHEME_A_ name);
5519 set_typeflag (x, typeflag (x) | T_SYNTAX);
5520 }
5521
5522 static void
5523 assign_proc (SCHEME_P_ enum scheme_opcodes op, const char *name)
5524 {
5525 pointer x = mk_symbol (SCHEME_A_ name);
5526 pointer y = mk_proc (SCHEME_A_ op);
5527 new_slot_in_env (SCHEME_A_ x, y);
5528 }
5529
5530 static pointer
5531 mk_proc (SCHEME_P_ enum scheme_opcodes op)
5532 {
5533 pointer y = get_cell (SCHEME_A_ NIL, NIL);
5534 set_typeflag (y, (T_PROC | T_ATOM));
5535 ivalue_unchecked (y) = op;
5536 return y;
5537 }
5538
5539 /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
5540 static int
5541 syntaxnum (pointer p)
5542 {
5543 const char *s = strvalue (p);
5544
5545 switch (strlength (p))
5546 {
5547 case 2:
5548 if (s[0] == 'i')
5549 return OP_IF0; /* if */
5550 else
5551 return OP_OR0; /* or */
5552
5553 case 3:
5554 if (s[0] == 'a')
5555 return OP_AND0; /* and */
5556 else
5557 return OP_LET0; /* let */
5558
5559 case 4:
5560 switch (s[3])
5561 {
5562 case 'e':
5563 return OP_CASE0; /* case */
5564
5565 case 'd':
5566 return OP_COND0; /* cond */
5567
5568 case '*':
5569 return OP_LET0AST;/* let* */
5570
5571 default:
5572 return OP_SET0; /* set! */
5573 }
5574
5575 case 5:
5576 switch (s[2])
5577 {
5578 case 'g':
5579 return OP_BEGIN; /* begin */
5580
5581 case 'l':
5582 return OP_DELAY; /* delay */
5583
5584 case 'c':
5585 return OP_MACRO0; /* macro */
5586
5587 default:
5588 return OP_QUOTE; /* quote */
5589 }
5590
5591 case 6:
5592 switch (s[2])
5593 {
5594 case 'm':
5595 return OP_LAMBDA; /* lambda */
5596
5597 case 'f':
5598 return OP_DEF0; /* define */
5599
5600 default:
5601 return OP_LET0REC;/* letrec */
5602 }
5603
5604 default:
5605 return OP_C0STREAM; /* cons-stream */
5606 }
5607 }
5608
5609 #if USE_MULTIPLICITY
5610 ecb_cold scheme *
5611 scheme_init_new ()
5612 {
5613 scheme *sc = malloc (sizeof (scheme));
5614
5615 if (!scheme_init (SCHEME_A))
5616 {
5617 free (SCHEME_A);
5618 return 0;
5619 }
5620 else
5621 return sc;
5622 }
5623 #endif
5624
5625 ecb_cold int
5626 scheme_init (SCHEME_P)
5627 {
5628 int i, n = sizeof (dispatch_table) / sizeof (dispatch_table[0]);
5629 pointer x;
5630
5631 /* this memset is not strictly correct, as we assume (intcache)
5632 * that memset 0 will also set pointers to 0, but memset does
5633 * of course not guarantee that. screw such systems.
5634 */
5635 memset (SCHEME_V, 0, sizeof (*SCHEME_V));
5636
5637 num_set_fixnum (num_zero, 1);
5638 num_set_ivalue (num_zero, 0);
5639 num_set_fixnum (num_one, 1);
5640 num_set_ivalue (num_one, 1);
5641
5642 #if USE_INTERFACE
5643 SCHEME_V->vptr = &vtbl;
5644 #endif
5645 SCHEME_V->gensym_cnt = 0;
5646 SCHEME_V->last_cell_seg = -1;
5647 SCHEME_V->free_cell = NIL;
5648 SCHEME_V->fcells = 0;
5649 SCHEME_V->no_memory = 0;
5650 SCHEME_V->inport = NIL;
5651 SCHEME_V->outport = NIL;
5652 SCHEME_V->save_inport = NIL;
5653 SCHEME_V->loadport = NIL;
5654 SCHEME_V->nesting = 0;
5655 SCHEME_V->interactive_repl = 0;
5656
5657 if (!alloc_cellseg (SCHEME_A))
5658 {
5659 #if USE_ERROR_CHECKING
5660 SCHEME_V->no_memory = 1;
5661 return 0;
5662 #endif
5663 }
5664
5665 SCHEME_V->gc_verbose = 0;
5666 dump_stack_initialize (SCHEME_A);
5667 SCHEME_V->code = NIL;
5668 SCHEME_V->args = NIL;
5669 SCHEME_V->envir = NIL;
5670 SCHEME_V->tracing = 0;
5671
5672 /* init NIL */
5673 set_typeflag (NIL, T_ATOM | T_MARK);
5674 set_car (NIL, NIL);
5675 set_cdr (NIL, NIL);
5676 /* init T */
5677 set_typeflag (S_T, T_ATOM | T_MARK);
5678 set_car (S_T, S_T);
5679 set_cdr (S_T, S_T);
5680 /* init F */
5681 set_typeflag (S_F, T_ATOM | T_MARK);
5682 set_car (S_F, S_F);
5683 set_cdr (S_F, S_F);
5684 /* init EOF_OBJ */
5685 set_typeflag (S_EOF, T_ATOM | T_MARK);
5686 set_car (S_EOF, S_EOF);
5687 set_cdr (S_EOF, S_EOF);
5688 /* init sink */
5689 set_typeflag (S_SINK, T_PAIR | T_MARK);
5690 set_car (S_SINK, NIL);
5691
5692 /* init c_nest */
5693 SCHEME_V->c_nest = NIL;
5694
5695 SCHEME_V->oblist = oblist_initial_value (SCHEME_A);
5696 /* init global_env */
5697 new_frame_in_env (SCHEME_A_ NIL);
5698 SCHEME_V->global_env = SCHEME_V->envir;
5699 /* init else */
5700 x = mk_symbol (SCHEME_A_ "else");
5701 new_slot_in_env (SCHEME_A_ x, S_T);
5702
5703 {
5704 static const char *syntax_names[] = {
5705 "lambda", "quote", "define", "if", "begin", "set!",
5706 "let", "let*", "letrec", "cond", "delay", "and",
5707 "or", "cons-stream", "macro", "case"
5708 };
5709
5710 for (i = 0; i < sizeof (syntax_names) / sizeof (*syntax_names); ++i)
5711 assign_syntax (SCHEME_A_ syntax_names[i]);
5712 }
5713
5714 // TODO: should iterate via strlen, to avoid n² complexity
5715 for (i = 0; i < n; i++)
5716 if (dispatch_table[i].builtin)
5717 assign_proc (SCHEME_A_ i, opname (i));
5718
5719 /* initialization of global pointers to special symbols */
5720 SCHEME_V->LAMBDA = mk_symbol (SCHEME_A_ "lambda");
5721 SCHEME_V->QUOTE = mk_symbol (SCHEME_A_ "quote");
5722 SCHEME_V->QQUOTE = mk_symbol (SCHEME_A_ "quasiquote");
5723 SCHEME_V->UNQUOTE = mk_symbol (SCHEME_A_ "unquote");
5724 SCHEME_V->UNQUOTESP = mk_symbol (SCHEME_A_ "unquote-splicing");
5725 SCHEME_V->FEED_TO = mk_symbol (SCHEME_A_ "=>");
5726 SCHEME_V->COLON_HOOK = mk_symbol (SCHEME_A_ "*colon-hook*");
5727 SCHEME_V->ERROR_HOOK = mk_symbol (SCHEME_A_ "*error-hook*");
5728 SCHEME_V->SHARP_HOOK = mk_symbol (SCHEME_A_ "*sharp-hook*");
5729 SCHEME_V->COMPILE_HOOK = mk_symbol (SCHEME_A_ "*compile-hook*");
5730
5731 return !SCHEME_V->no_memory;
5732 }
5733
5734 #if USE_PORTS
5735 void
5736 scheme_set_input_port_file (SCHEME_P_ int fin)
5737 {
5738 SCHEME_V->inport = port_from_file (SCHEME_A_ fin, port_input);
5739 }
5740
5741 void
5742 scheme_set_input_port_string (SCHEME_P_ char *start, char *past_the_end)
5743 {
5744 SCHEME_V->inport = port_from_string (SCHEME_A_ start, past_the_end, port_input);
5745 }
5746
5747 void
5748 scheme_set_output_port_file (SCHEME_P_ int fout)
5749 {
5750 SCHEME_V->outport = port_from_file (SCHEME_A_ fout, port_output);
5751 }
5752
5753 void
5754 scheme_set_output_port_string (SCHEME_P_ char *start, char *past_the_end)
5755 {
5756 SCHEME_V->outport = port_from_string (SCHEME_A_ start, past_the_end, port_output);
5757 }
5758 #endif
5759
5760 void
5761 scheme_set_external_data (SCHEME_P_ void *p)
5762 {
5763 SCHEME_V->ext_data = p;
5764 }
5765
5766 ecb_cold void
5767 scheme_deinit (SCHEME_P)
5768 {
5769 int i;
5770
5771 #if SHOW_ERROR_LINE
5772 char *fname;
5773 #endif
5774
5775 SCHEME_V->oblist = NIL;
5776 SCHEME_V->global_env = NIL;
5777 dump_stack_free (SCHEME_A);
5778 SCHEME_V->envir = NIL;
5779 SCHEME_V->code = NIL;
5780 SCHEME_V->args = NIL;
5781 SCHEME_V->value = NIL;
5782
5783 if (is_port (SCHEME_V->inport))
5784 set_typeflag (SCHEME_V->inport, T_ATOM);
5785
5786 SCHEME_V->inport = NIL;
5787 SCHEME_V->outport = NIL;
5788
5789 if (is_port (SCHEME_V->save_inport))
5790 set_typeflag (SCHEME_V->save_inport, T_ATOM);
5791
5792 SCHEME_V->save_inport = NIL;
5793
5794 if (is_port (SCHEME_V->loadport))
5795 set_typeflag (SCHEME_V->loadport, T_ATOM);
5796
5797 SCHEME_V->loadport = NIL;
5798 SCHEME_V->gc_verbose = 0;
5799 gc (SCHEME_A_ NIL, NIL);
5800
5801 for (i = 0; i <= SCHEME_V->last_cell_seg; i++)
5802 free (SCHEME_V->alloc_seg[i]);
5803
5804 #if SHOW_ERROR_LINE
5805 for (i = 0; i <= SCHEME_V->file_i; i++)
5806 {
5807 if (SCHEME_V->load_stack[i].kind & port_file)
5808 {
5809 fname = SCHEME_V->load_stack[i].rep.stdio.filename;
5810
5811 if (fname)
5812 free (fname);
5813 }
5814 }
5815 #endif
5816 }
5817
5818 void
5819 scheme_load_file (SCHEME_P_ int fin)
5820 {
5821 scheme_load_named_file (SCHEME_A_ fin, 0);
5822 }
5823
5824 void
5825 scheme_load_named_file (SCHEME_P_ int fin, const char *filename)
5826 {
5827 dump_stack_reset (SCHEME_A);
5828 SCHEME_V->envir = SCHEME_V->global_env;
5829 SCHEME_V->file_i = 0;
5830 SCHEME_V->load_stack[0].unget = -1;
5831 SCHEME_V->load_stack[0].kind = port_input | port_file;
5832 SCHEME_V->load_stack[0].rep.stdio.file = fin;
5833 #if USE_PORTS
5834 SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
5835 #endif
5836 SCHEME_V->retcode = 0;
5837
5838 #if USE_PORTS
5839 if (fin == STDIN_FILENO)
5840 SCHEME_V->interactive_repl = 1;
5841 #endif
5842
5843 #if USE_PORTS
5844 #if SHOW_ERROR_LINE
5845 SCHEME_V->load_stack[0].rep.stdio.curr_line = 0;
5846
5847 if (fin != STDIN_FILENO && filename)
5848 SCHEME_V->load_stack[0].rep.stdio.filename = store_string (SCHEME_A_ strlen (filename), filename, 0);
5849 #endif
5850 #endif
5851
5852 SCHEME_V->inport = SCHEME_V->loadport;
5853 SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
5854 Eval_Cycle (SCHEME_A_ OP_T0LVL);
5855 set_typeflag (SCHEME_V->loadport, T_ATOM);
5856
5857 if (SCHEME_V->retcode == 0)
5858 SCHEME_V->retcode = SCHEME_V->nesting != 0;
5859 }
5860
5861 void
5862 scheme_load_string (SCHEME_P_ const char *cmd)
5863 {
5864 dump_stack_reset (SCHEME_A);
5865 SCHEME_V->envir = SCHEME_V->global_env;
5866 SCHEME_V->file_i = 0;
5867 SCHEME_V->load_stack[0].kind = port_input | port_string;
5868 SCHEME_V->load_stack[0].rep.string.start = (char *)cmd; /* This func respects const */
5869 SCHEME_V->load_stack[0].rep.string.past_the_end = (char *)cmd + strlen (cmd);
5870 SCHEME_V->load_stack[0].rep.string.curr = (char *)cmd;
5871 #if USE_PORTS
5872 SCHEME_V->loadport = mk_port (SCHEME_A_ SCHEME_V->load_stack);
5873 #endif
5874 SCHEME_V->retcode = 0;
5875 SCHEME_V->interactive_repl = 0;
5876 SCHEME_V->inport = SCHEME_V->loadport;
5877 SCHEME_V->args = mk_integer (SCHEME_A_ SCHEME_V->file_i);
5878 Eval_Cycle (SCHEME_A_ OP_T0LVL);
5879 set_typeflag (SCHEME_V->loadport, T_ATOM);
5880
5881 if (SCHEME_V->retcode == 0)
5882 SCHEME_V->retcode = SCHEME_V->nesting != 0;
5883 }
5884
5885 void
5886 scheme_define (SCHEME_P_ pointer envir, pointer symbol, pointer value)
5887 {
5888 pointer x;
5889
5890 x = find_slot_in_env (SCHEME_A_ envir, symbol, 0);
5891
5892 if (x != NIL)
5893 set_slot_in_env (SCHEME_A_ x, value);
5894 else
5895 new_slot_spec_in_env (SCHEME_A_ envir, symbol, value);
5896 }
5897
5898 #if !STANDALONE
5899
5900 void
5901 scheme_register_foreign_func (scheme * sc, scheme_registerable * sr)
5902 {
5903 scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ sr->name), mk_foreign_func (SCHEME_A_ sr->f));
5904 }
5905
5906 void
5907 scheme_register_foreign_func_list (scheme * sc, scheme_registerable * list, int count)
5908 {
5909 int i;
5910
5911 for (i = 0; i < count; i++)
5912 scheme_register_foreign_func (SCHEME_A_ list + i);
5913 }
5914
5915 pointer
5916 scheme_apply0 (SCHEME_P_ const char *procname)
5917 {
5918 return scheme_eval (SCHEME_A_ cons (mk_symbol (SCHEME_A_ procname), NIL));
5919 }
5920
5921 void
5922 save_from_C_call (SCHEME_P)
5923 {
5924 pointer saved_data = cons (car (S_SINK),
5925 cons (SCHEME_V->envir,
5926 SCHEME_V->dump));
5927
5928 /* Push */
5929 SCHEME_V->c_nest = cons (saved_data, SCHEME_V->c_nest);
5930 /* Truncate the dump stack so TS will return here when done, not
5931 directly resume pre-C-call operations. */
5932 dump_stack_reset (SCHEME_A);
5933 }
5934
5935 void
5936 restore_from_C_call (SCHEME_P)
5937 {
5938 set_car (S_SINK, caar (SCHEME_V->c_nest));
5939 SCHEME_V->envir = cadar (SCHEME_V->c_nest);
5940 SCHEME_V->dump = cdr (cdar (SCHEME_V->c_nest));
5941 /* Pop */
5942 SCHEME_V->c_nest = cdr (SCHEME_V->c_nest);
5943 }
5944
5945 /* "func" and "args" are assumed to be already eval'ed. */
5946 pointer
5947 scheme_call (SCHEME_P_ pointer func, pointer args)
5948 {
5949 int old_repl = SCHEME_V->interactive_repl;
5950
5951 SCHEME_V->interactive_repl = 0;
5952 save_from_C_call (SCHEME_A);
5953 SCHEME_V->envir = SCHEME_V->global_env;
5954 SCHEME_V->args = args;
5955 SCHEME_V->code = func;
5956 SCHEME_V->retcode = 0;
5957 Eval_Cycle (SCHEME_A_ OP_APPLY);
5958 SCHEME_V->interactive_repl = old_repl;
5959 restore_from_C_call (SCHEME_A);
5960 return SCHEME_V->value;
5961 }
5962
5963 pointer
5964 scheme_eval (SCHEME_P_ pointer obj)
5965 {
5966 int old_repl = SCHEME_V->interactive_repl;
5967
5968 SCHEME_V->interactive_repl = 0;
5969 save_from_C_call (SCHEME_A);
5970 SCHEME_V->args = NIL;
5971 SCHEME_V->code = obj;
5972 SCHEME_V->retcode = 0;
5973 Eval_Cycle (SCHEME_A_ OP_EVAL);
5974 SCHEME_V->interactive_repl = old_repl;
5975 restore_from_C_call (SCHEME_A);
5976 return SCHEME_V->value;
5977 }
5978
5979 #endif
5980
5981 /* ========== Main ========== */
5982
5983 #if STANDALONE
5984
5985 int
5986 main (int argc, char **argv)
5987 {
5988 # if USE_MULTIPLICITY
5989 scheme ssc;
5990 scheme *const SCHEME_V = &ssc;
5991 # else
5992 # endif
5993 int fin;
5994 char *file_name = InitFile;
5995 int retcode;
5996 int isfile = 1;
5997 system ("ps v $PPID");//D
5998
5999 if (argc == 2 && strcmp (argv[1], "-?") == 0)
6000 {
6001 putstr (SCHEME_A_ "Usage: tinyscheme -?\n");
6002 putstr (SCHEME_A_ "or: tinyscheme [<file1> <file2> ...]\n");
6003 putstr (SCHEME_A_ "followed by\n");
6004 putstr (SCHEME_A_ " -1 <file> [<arg1> <arg2> ...]\n");
6005 putstr (SCHEME_A_ " -c <Scheme commands> [<arg1> <arg2> ...]\n");
6006 putstr (SCHEME_A_ "assuming that the executable is named tinyscheme.\n");
6007 putstr (SCHEME_A_ "Use - as filename for stdin.\n");
6008 return 1;
6009 }
6010
6011 if (!scheme_init (SCHEME_A))
6012 {
6013 putstr (SCHEME_A_ "Could not initialize!\n");
6014 return 2;
6015 }
6016
6017 # if USE_PORTS
6018 scheme_set_input_port_file (SCHEME_A_ STDIN_FILENO);
6019 scheme_set_output_port_file (SCHEME_A_ STDOUT_FILENO);
6020 # endif
6021
6022 argv++;
6023
6024 #if 0
6025 if (access (file_name, 0) != 0)
6026 {
6027 char *p = getenv ("TINYSCHEMEINIT");
6028
6029 if (p != 0)
6030 file_name = p;
6031 }
6032 #endif
6033
6034 do
6035 {
6036 #if USE_PORTS
6037 if (strcmp (file_name, "-") == 0)
6038 fin = STDIN_FILENO;
6039 else if (strcmp (file_name, "-1") == 0 || strcmp (file_name, "-c") == 0)
6040 {
6041 pointer args = NIL;
6042
6043 isfile = file_name[1] == '1';
6044 file_name = *argv++;
6045
6046 if (strcmp (file_name, "-") == 0)
6047 fin = STDIN_FILENO;
6048 else if (isfile)
6049 fin = open (file_name, O_RDONLY);
6050
6051 for (; *argv; argv++)
6052 {
6053 pointer value = mk_string (SCHEME_A_ * argv);
6054
6055 args = cons (value, args);
6056 }
6057
6058 args = reverse_in_place (SCHEME_A_ NIL, args);
6059 scheme_define (SCHEME_A_ SCHEME_V->global_env, mk_symbol (SCHEME_A_ "*args*"), args);
6060
6061 }
6062 else
6063 fin = open (file_name, O_RDONLY);
6064 #endif
6065
6066 if (isfile && fin < 0)
6067 {
6068 putstr (SCHEME_A_ "Could not open file "); putstr (SCHEME_A_ file_name); putstr (SCHEME_A_ "\n");
6069 }
6070 else
6071 {
6072 if (isfile)
6073 scheme_load_named_file (SCHEME_A_ fin, file_name);
6074 else
6075 scheme_load_string (SCHEME_A_ file_name);
6076
6077 #if USE_PORTS
6078 if (!isfile || fin != STDIN_FILENO)
6079 {
6080 if (SCHEME_V->retcode != 0)
6081 {
6082 putstr (SCHEME_A_ "Errors encountered reading "); putstr (SCHEME_A_ file_name); putstr (SCHEME_A_ "\n");
6083 }
6084
6085 if (isfile)
6086 close (fin);
6087 }
6088 #endif
6089 }
6090
6091 file_name = *argv++;
6092 }
6093 while (file_name != 0);
6094
6095 if (argc == 1)
6096 scheme_load_named_file (SCHEME_A_ STDIN_FILENO, 0);
6097
6098 retcode = SCHEME_V->retcode;
6099 scheme_deinit (SCHEME_A);
6100
6101 return retcode;
6102 }
6103
6104 #endif
6105
6106 /*
6107 Local variables:
6108 c-file-style: "k&r"
6109 End:
6110 */