ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.1
Committed: Wed Nov 25 05:02:56 2015 UTC (8 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

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