ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/microscheme/scheme.c
Revision: 1.14
Committed: Thu Nov 26 08:56:32 2015 UTC (8 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.13: +99 -141 lines
Log Message:
*** empty log message ***

File Contents

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