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