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