~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/script-fu/tinyscheme/scheme.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* T I N Y S C H E M E    1 . 3 8
 
2
 *   Dimitrios Souflis (dsouflis@acm.org)
 
3
 *   Based on MiniScheme (original credits follow)
 
4
 * (MINISCM)               coded by Atsushi Moriwaki (11/5/1989)
 
5
 * (MINISCM)           E-MAIL :  moriwaki@kurims.kurims.kyoto-u.ac.jp
 
6
 * (MINISCM) This version has been modified by R.C. Secrist.
 
7
 * (MINISCM)
 
8
 * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
 
9
 * (MINISCM)
 
10
 * (MINISCM) This is a revised and modified version by Akira KIDA.
 
11
 * (MINISCM)   current version is 0.85k4 (15 May 1994)
 
12
 *
 
13
 */
 
14
 
 
15
/* ******** READ THE FOLLOWING BEFORE MODIFYING THIS FILE! ******** */
 
16
/* This copy of TinyScheme has been modified to support UTF-8 coded */
 
17
/* character strings. As a result, the length of a string in bytes  */
 
18
/* may not be the same as the length of a string in characters. You */
 
19
/* must keep this in mind at all times while making any changes to  */
 
20
/* the routines in this file, or when adding new features.          */
 
21
/*                                                                  */
 
22
/* UTF-8 modifications made by Kevin Cozens (kcozens@interlog.com)  */
 
23
/* **************************************************************** */
 
24
 
 
25
#include "config.h"
 
26
 
 
27
#define _SCHEME_SOURCE
 
28
#if HAVE_UNISTD_H
 
29
# include <unistd.h>
 
30
#endif
 
31
#ifdef WIN32
 
32
# include <io.h>
 
33
# define access(f,a) _access(f,a)
 
34
#endif
 
35
#if USE_DL
 
36
# include "dynload.h"
 
37
#endif
 
38
#if USE_MATH
 
39
# include <math.h>
 
40
#endif
 
41
#include <limits.h>
 
42
#include <float.h>
 
43
#include <ctype.h>
 
44
 
 
45
#include <libintl.h>
 
46
 
 
47
#include "scheme-private.h"
 
48
 
 
49
/* Used for documentation purposes, to signal functions in 'interface' */
 
50
#define INTERFACE
 
51
 
 
52
#define TOK_EOF     (-1)
 
53
#define TOK_LPAREN  0
 
54
#define TOK_RPAREN  1
 
55
#define TOK_DOT     2
 
56
#define TOK_ATOM    3
 
57
#define TOK_QUOTE   4
 
58
#define TOK_COMMENT 5
 
59
#define TOK_DQUOTE  6
 
60
#define TOK_BQUOTE  7
 
61
#define TOK_COMMA   8
 
62
#define TOK_ATMARK  9
 
63
#define TOK_SHARP   10
 
64
#define TOK_SHARP_CONST 11
 
65
#define TOK_VEC     12
 
66
 
 
67
# define BACKQUOTE '`'
 
68
 
 
69
/*
 
70
 *  Basic memory allocation units
 
71
 */
 
72
 
 
73
#define banner "TinyScheme 1.38 (with UTF-8 support)"
 
74
 
 
75
#include <string.h>
 
76
#include <stdlib.h>
 
77
#define stricmp g_ascii_strcasecmp
 
78
 
 
79
 
 
80
#define min(a, b)  ((a <= b) ? a : b)
 
81
 
 
82
#if USE_STRLWR
 
83
/*
 
84
#error FIXME: Can't just use g_utf8_strdown since it allocates a new string
 
85
#define strlwr(s)  g_utf8_strdown(s, -1)
 
86
*/
 
87
#else
 
88
#define strlwr(s)  s
 
89
#endif
 
90
 
 
91
#ifndef prompt
 
92
# define prompt "> "
 
93
#endif
 
94
 
 
95
#ifndef InitFile
 
96
# define InitFile "init.scm"
 
97
#endif
 
98
 
 
99
#ifndef FIRST_CELLSEGS
 
100
# define FIRST_CELLSEGS 3
 
101
#endif
 
102
 
 
103
enum scheme_types {
 
104
  T_STRING=1,
 
105
  T_NUMBER=2,
 
106
  T_SYMBOL=3,
 
107
  T_PROC=4,
 
108
  T_PAIR=5,
 
109
  T_CLOSURE=6,
 
110
  T_CONTINUATION=7,
 
111
  T_FOREIGN=8,
 
112
  T_CHARACTER=9,
 
113
  T_PORT=10,
 
114
  T_VECTOR=11,
 
115
  T_MACRO=12,
 
116
  T_PROMISE=13,
 
117
  T_ENVIRONMENT=14,
 
118
  T_LAST_SYSTEM_TYPE=14
 
119
};
 
120
 
 
121
/* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
 
122
#define ADJ 32
 
123
#define TYPE_BITS 5
 
124
#define T_MASKTYPE      31    /* 0000000000011111 */
 
125
#define T_SYNTAX      4096    /* 0001000000000000 */
 
126
#define T_IMMUTABLE   8192    /* 0010000000000000 */
 
127
#define T_ATOM       16384    /* 0100000000000000 */   /* only for gc */
 
128
#define CLRATOM      49151    /* 1011111111111111 */   /* only for gc */
 
129
#define MARK         32768    /* 1000000000000000 */
 
130
#define UNMARK       32767    /* 0111111111111111 */
 
131
 
 
132
SCHEME_EXPORT void (*ts_output_routine) (FILE *, char *, int);
 
133
 
 
134
static num num_add(num a, num b);
 
135
static num num_mul(num a, num b);
 
136
static num num_div(num a, num b);
 
137
static num num_intdiv(num a, num b);
 
138
static num num_sub(num a, num b);
 
139
static num num_rem(num a, num b);
 
140
static num num_mod(num a, num b);
 
141
static int num_eq(num a, num b);
 
142
static int num_gt(num a, num b);
 
143
static int num_ge(num a, num b);
 
144
static int num_lt(num a, num b);
 
145
static int num_le(num a, num b);
 
146
 
 
147
#if USE_MATH
 
148
static double round_per_R5RS(double x);
 
149
#endif
 
150
static int is_zero_double(double x);
 
151
 
 
152
static num num_zero;
 
153
static num num_one;
 
154
 
 
155
/* macros for cell operations */
 
156
#define typeflag(p)      ((p)->_flag)
 
157
#define type(p)          (typeflag(p)&T_MASKTYPE)
 
158
 
 
159
INTERFACE INLINE int is_string(pointer p)     { return (type(p)==T_STRING); }
 
160
#define strvalue(p)      ((p)->_object._string._svalue)
 
161
#define strkey(p)        ((p)->_object._string._skey)
 
162
#define strlength(p)     ((p)->_object._string._length)
 
163
 
 
164
INTERFACE static int is_list(scheme *sc, pointer p);
 
165
INTERFACE INLINE int is_vector(pointer p)    { return (type(p)==T_VECTOR); }
 
166
INTERFACE static void fill_vector(pointer vec, pointer obj);
 
167
INTERFACE static pointer vector_elem(pointer vec, int ielem);
 
168
INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
 
169
INTERFACE INLINE int is_number(pointer p)    { return (type(p)==T_NUMBER); }
 
170
INTERFACE INLINE int is_integer(pointer p) {
 
171
  return ((p)->_object._number.is_fixnum);
 
172
}
 
173
INTERFACE INLINE int is_real(pointer p) {
 
174
  return (!(p)->_object._number.is_fixnum);
 
175
}
 
176
 
 
177
INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
 
178
INTERFACE INLINE int string_length(pointer p) { return strlength(p); }
 
179
INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
 
180
INLINE num nvalue(pointer p)       { return ((p)->_object._number); }
 
181
INTERFACE long ivalue(pointer p)      { return (is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
 
182
INTERFACE double rvalue(pointer p)    { return (!is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
 
183
#define ivalue_unchecked(p)       ((p)->_object._number.value.ivalue)
 
184
#define rvalue_unchecked(p)       ((p)->_object._number.value.rvalue)
 
185
#define set_integer(p)   (p)->_object._number.is_fixnum=1;
 
186
#define set_real(p)      (p)->_object._number.is_fixnum=0;
 
187
INTERFACE  gunichar charvalue(pointer p)  { return (gunichar)ivalue_unchecked(p); }
 
188
 
 
189
INTERFACE INLINE int is_port(pointer p)     { return (type(p)==T_PORT); }
 
190
#define is_inport(p) (type(p)==T_PORT && p->_object._port->kind&port_input)
 
191
#define is_outport(p) (type(p)==T_PORT && p->_object._port->kind&port_output)
 
192
 
 
193
INTERFACE INLINE int is_pair(pointer p)     { return (type(p)==T_PAIR); }
 
194
#define car(p)           ((p)->_object._cons._car)
 
195
#define cdr(p)           ((p)->_object._cons._cdr)
 
196
INTERFACE pointer pair_car(pointer p)   { return car(p); }
 
197
INTERFACE pointer pair_cdr(pointer p)   { return cdr(p); }
 
198
INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
 
199
INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
 
200
 
 
201
INTERFACE INLINE int is_symbol(pointer p)   { return (type(p)==T_SYMBOL); }
 
202
INTERFACE INLINE char *symname(pointer p)   { return strvalue(car(p)); }
 
203
/* For now, we don't want foreign functions to access a strings key */
 
204
INLINE           char *symkey(pointer p)    { return strkey(car(p)); }
 
205
#if USE_PLIST
 
206
SCHEME_EXPORT INLINE int hasprop(pointer p)     { return (typeflag(p)&T_SYMBOL); }
 
207
#define symprop(p)       cdr(p)
 
208
#endif
 
209
 
 
210
INTERFACE INLINE int is_syntax(pointer p)   { return (typeflag(p)&T_SYNTAX); }
 
211
INTERFACE INLINE int is_proc(pointer p)     { return (type(p)==T_PROC); }
 
212
INTERFACE INLINE int is_foreign(pointer p)  { return (type(p)==T_FOREIGN); }
 
213
INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
 
214
#define procnum(p)       ivalue(p)
 
215
static const char *procname(pointer x);
 
216
 
 
217
INTERFACE INLINE int is_closure(pointer p)  { return (type(p)==T_CLOSURE); }
 
218
INTERFACE INLINE int is_macro(pointer p)    { return (type(p)==T_MACRO); }
 
219
INTERFACE INLINE pointer closure_code(pointer p)   { return car(p); }
 
220
INTERFACE INLINE pointer closure_env(pointer p)    { return cdr(p); }
 
221
 
 
222
INTERFACE INLINE int is_continuation(pointer p)    { return (type(p)==T_CONTINUATION); }
 
223
#define cont_dump(p)     cdr(p)
 
224
 
 
225
/* To do: promise should be forced ONCE only */
 
226
INTERFACE INLINE int is_promise(pointer p)  { return (type(p)==T_PROMISE); }
 
227
 
 
228
INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
 
229
#define setenvironment(p)    typeflag(p) = T_ENVIRONMENT
 
230
 
 
231
#define is_atom(p)       (typeflag(p)&T_ATOM)
 
232
#define setatom(p)       typeflag(p) |= T_ATOM
 
233
#define clratom(p)       typeflag(p) &= CLRATOM
 
234
 
 
235
#define is_mark(p)       (typeflag(p)&MARK)
 
236
#define setmark(p)       typeflag(p) |= MARK
 
237
#define clrmark(p)       typeflag(p) &= UNMARK
 
238
 
 
239
INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
 
240
/*#define setimmutable(p)  typeflag(p) |= T_IMMUTABLE*/
 
241
INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
 
242
 
 
243
#define caar(p)          car(car(p))
 
244
#define cadr(p)          car(cdr(p))
 
245
#define cdar(p)          cdr(car(p))
 
246
#define cddr(p)          cdr(cdr(p))
 
247
#define cadar(p)         car(cdr(car(p)))
 
248
#define caddr(p)         car(cdr(cdr(p)))
 
249
#define cadaar(p)        car(cdr(car(car(p))))
 
250
#define cadddr(p)        car(cdr(cdr(cdr(p))))
 
251
#define cddddr(p)        cdr(cdr(cdr(cdr(p))))
 
252
 
 
253
#if USE_CHAR_CLASSIFIERS
 
254
static INLINE int Cisalpha(gunichar c) { return g_unichar_isalpha(c); }
 
255
static INLINE int Cisdigit(gunichar c) { return g_unichar_isdigit(c); }
 
256
static INLINE int Cisspace(gunichar c) { return g_unichar_isspace(c); }
 
257
static INLINE int Cisupper(gunichar c) { return g_unichar_isupper(c); }
 
258
static INLINE int Cislower(gunichar c) { return g_unichar_islower(c); }
 
259
#endif
 
260
 
 
261
#if USE_ASCII_NAMES
 
262
static const char *charnames[32]={
 
263
 "nul",
 
264
 "soh",
 
265
 "stx",
 
266
 "etx",
 
267
 "eot",
 
268
 "enq",
 
269
 "ack",
 
270
 "bel",
 
271
 "bs",
 
272
 "ht",
 
273
 "lf",
 
274
 "vt",
 
275
 "ff",
 
276
 "cr",
 
277
 "so",
 
278
 "si",
 
279
 "dle",
 
280
 "dc1",
 
281
 "dc2",
 
282
 "dc3",
 
283
 "dc4",
 
284
 "nak",
 
285
 "syn",
 
286
 "etb",
 
287
 "can",
 
288
 "em",
 
289
 "sub",
 
290
 "esc",
 
291
 "fs",
 
292
 "gs",
 
293
 "rs",
 
294
 "us"
 
295
};
 
296
 
 
297
static int is_ascii_name(const char *name, int *pc) {
 
298
  int i;
 
299
  for(i=0; i<32; i++) {
 
300
     if(stricmp(name,charnames[i])==0) {
 
301
          *pc=i;
 
302
          return 1;
 
303
     }
 
304
  }
 
305
  if(stricmp(name,"del")==0) {
 
306
     *pc=127;
 
307
     return 1;
 
308
  }
 
309
  return 0;
 
310
}
 
311
 
 
312
#endif
 
313
 
 
314
static const char utf8_length[128] =
 
315
{
 
316
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80-0x8f */
 
317
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90-0x9f */
 
318
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xa0-0xaf */
 
319
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xb0-0xbf */
 
320
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xc0-0xcf */
 
321
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0xd0-0xdf */
 
322
    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 0xe0-0xef */
 
323
    3,3,3,3,3,3,3,3,4,4,4,4,5,5,0,0  /* 0xf0-0xff */
 
324
};
 
325
 
 
326
static int file_push(scheme *sc, const char *fname);
 
327
static void file_pop(scheme *sc);
 
328
static int file_interactive(scheme *sc);
 
329
static INLINE int is_one_of(char *s, gunichar c);
 
330
static int alloc_cellseg(scheme *sc, int n);
 
331
static long binary_decode(const char *s);
 
332
static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
 
333
static pointer _get_cell(scheme *sc, pointer a, pointer b);
 
334
static pointer reserve_cells(scheme *sc, int n);
 
335
static pointer get_consecutive_cells(scheme *sc, int n);
 
336
static pointer find_consecutive_cells(scheme *sc, int n);
 
337
static void finalize_cell(scheme *sc, pointer a);
 
338
static int count_consecutive_cells(pointer x, int needed);
 
339
static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
 
340
static pointer mk_number(scheme *sc, num n);
 
341
static pointer mk_empty_string(scheme *sc, int len, gunichar fill);
 
342
static char *store_string(scheme *sc, int len, const char *str, gunichar fill);
 
343
static pointer mk_vector(scheme *sc, int len);
 
344
static pointer mk_atom(scheme *sc, char *q);
 
345
static pointer mk_sharp_const(scheme *sc, char *name);
 
346
static pointer mk_port(scheme *sc, port *p);
 
347
static pointer port_from_filename(scheme *sc, const char *fn, int prop);
 
348
static pointer port_from_file(scheme *sc, FILE *, int prop);
 
349
static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
 
350
static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
 
351
static port *port_rep_from_file(scheme *sc, FILE *, int prop);
 
352
static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
 
353
static void port_close(scheme *sc, pointer p, int flag);
 
354
static void mark(pointer a);
 
355
static void gc(scheme *sc, pointer a, pointer b);
 
356
static gunichar inchar(scheme *sc);
 
357
static void backchar(scheme *sc, gunichar c);
 
358
static char *readstr_upto(scheme *sc, char *delim);
 
359
static pointer readstrexp(scheme *sc);
 
360
static INLINE void skipspace(scheme *sc);
 
361
static int token(scheme *sc);
 
362
static void printslashstring(scheme *sc, char *s, int len);
 
363
static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen);
 
364
static void printatom(scheme *sc, pointer l, int f);
 
365
static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
 
366
static pointer mk_closure(scheme *sc, pointer c, pointer e);
 
367
static pointer mk_continuation(scheme *sc, pointer d);
 
368
static pointer reverse(scheme *sc, pointer a);
 
369
static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
 
370
static pointer append(scheme *sc, pointer a, pointer b);
 
371
static int list_length(scheme *sc, pointer a);
 
372
static int eqv(pointer a, pointer b);
 
373
static INLINE void dump_stack_mark(scheme *);
 
374
static pointer opexe_0(scheme *sc, enum scheme_opcodes op);
 
375
static pointer opexe_1(scheme *sc, enum scheme_opcodes op);
 
376
static pointer opexe_2(scheme *sc, enum scheme_opcodes op);
 
377
static pointer opexe_3(scheme *sc, enum scheme_opcodes op);
 
378
static pointer opexe_4(scheme *sc, enum scheme_opcodes op);
 
379
static pointer opexe_5(scheme *sc, enum scheme_opcodes op);
 
380
static pointer opexe_6(scheme *sc, enum scheme_opcodes op);
 
381
static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
 
382
static void assign_syntax(scheme *sc, char *name);
 
383
static int syntaxnum(pointer p);
 
384
static void assign_proc(scheme *sc, enum scheme_opcodes, char *name);
 
385
scheme *scheme_init_new(void);
 
386
#if !STANDALONE
 
387
void scheme_call(scheme *sc, pointer func, pointer args);
 
388
#endif
 
389
 
 
390
#define num_ivalue(n)       (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
 
391
#define num_rvalue(n)       (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
 
392
 
 
393
static num num_add(num a, num b) {
 
394
 num ret;
 
395
 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
 
396
 if(ret.is_fixnum) {
 
397
     ret.value.ivalue= a.value.ivalue+b.value.ivalue;
 
398
 } else {
 
399
     ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
 
400
 }
 
401
 return ret;
 
402
}
 
403
 
 
404
static num num_mul(num a, num b) {
 
405
 num ret;
 
406
 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
 
407
 if(ret.is_fixnum) {
 
408
     ret.value.ivalue= a.value.ivalue*b.value.ivalue;
 
409
 } else {
 
410
     ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
 
411
 }
 
412
 return ret;
 
413
}
 
414
 
 
415
static num num_div(num a, num b) {
 
416
 num ret;
 
417
 ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
 
418
 if(ret.is_fixnum) {
 
419
     ret.value.ivalue= a.value.ivalue/b.value.ivalue;
 
420
 } else {
 
421
     ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
 
422
 }
 
423
 return ret;
 
424
}
 
425
 
 
426
static num num_intdiv(num a, num b) {
 
427
 num ret;
 
428
 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
 
429
 if(ret.is_fixnum) {
 
430
     ret.value.ivalue= a.value.ivalue/b.value.ivalue;
 
431
 } else {
 
432
     ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
 
433
 }
 
434
 return ret;
 
435
}
 
436
 
 
437
static num num_sub(num a, num b) {
 
438
 num ret;
 
439
 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
 
440
 if(ret.is_fixnum) {
 
441
     ret.value.ivalue= a.value.ivalue-b.value.ivalue;
 
442
 } else {
 
443
     ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
 
444
 }
 
445
 return ret;
 
446
}
 
447
 
 
448
static num num_rem(num a, num b) {
 
449
 num ret;
 
450
 long e1, e2, res;
 
451
 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
 
452
 e1=num_ivalue(a);
 
453
 e2=num_ivalue(b);
 
454
 res=e1%e2;
 
455
 /* modulo should have same sign as second operand */
 
456
 if (res > 0) {
 
457
     if (e1 < 0) {
 
458
        res -= labs(e2);
 
459
     }
 
460
 } else if (res < 0) {
 
461
     if (e1 > 0) {
 
462
        res += labs(e2);
 
463
     }
 
464
 }
 
465
 ret.value.ivalue=res;
 
466
 return ret;
 
467
}
 
468
 
 
469
static num num_mod(num a, num b) {
 
470
 num ret;
 
471
 long e1, e2, res;
 
472
 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
 
473
 e1=num_ivalue(a);
 
474
 e2=num_ivalue(b);
 
475
 res=e1%e2;
 
476
 if(res*e2<0) {    /* modulo should have same sign as second operand */
 
477
     e2=labs(e2);
 
478
     if(res>0) {
 
479
          res-=e2;
 
480
     } else {
 
481
          res+=e2;
 
482
     }
 
483
 }
 
484
 ret.value.ivalue=res;
 
485
 return ret;
 
486
}
 
487
 
 
488
static int num_eq(num a, num b) {
 
489
 int ret;
 
490
 int is_fixnum=a.is_fixnum && b.is_fixnum;
 
491
 if(is_fixnum) {
 
492
     ret= a.value.ivalue==b.value.ivalue;
 
493
 } else {
 
494
     ret=num_rvalue(a)==num_rvalue(b);
 
495
 }
 
496
 return ret;
 
497
}
 
498
 
 
499
 
 
500
static int num_gt(num a, num b) {
 
501
 int ret;
 
502
 int is_fixnum=a.is_fixnum && b.is_fixnum;
 
503
 if(is_fixnum) {
 
504
     ret= a.value.ivalue>b.value.ivalue;
 
505
 } else {
 
506
     ret=num_rvalue(a)>num_rvalue(b);
 
507
 }
 
508
 return ret;
 
509
}
 
510
 
 
511
static int num_ge(num a, num b) {
 
512
 return !num_lt(a,b);
 
513
}
 
514
 
 
515
static int num_lt(num a, num b) {
 
516
 int ret;
 
517
 int is_fixnum=a.is_fixnum && b.is_fixnum;
 
518
 if(is_fixnum) {
 
519
     ret= a.value.ivalue<b.value.ivalue;
 
520
 } else {
 
521
     ret=num_rvalue(a)<num_rvalue(b);
 
522
 }
 
523
 return ret;
 
524
}
 
525
 
 
526
static int num_le(num a, num b) {
 
527
 return !num_gt(a,b);
 
528
}
 
529
 
 
530
#if USE_MATH
 
531
/* Round to nearest. Round to even if midway */
 
532
static double round_per_R5RS(double x) {
 
533
 double fl=floor(x);
 
534
 double ce=ceil(x);
 
535
 double dfl=x-fl;
 
536
 double dce=ce-x;
 
537
 if(dfl>dce) {
 
538
     return ce;
 
539
 } else if(dfl<dce) {
 
540
     return fl;
 
541
 } else {
 
542
     if(fmod(fl,2.0)==0.0) {       /* I imagine this holds */
 
543
          return fl;
 
544
     } else {
 
545
          return ce;
 
546
     }
 
547
 }
 
548
}
 
549
#endif
 
550
 
 
551
static int is_zero_double(double x) {
 
552
 return x<DBL_MIN && x>-DBL_MIN;
 
553
}
 
554
 
 
555
static long binary_decode(const char *s) {
 
556
 long x=0;
 
557
 
 
558
 while(*s!=0 && (*s=='1' || *s=='0')) {
 
559
     x<<=1;
 
560
     x+=*s-'0';
 
561
     s++;
 
562
 }
 
563
 
 
564
 return x;
 
565
}
 
566
 
 
567
/* allocate new cell segment */
 
568
static int alloc_cellseg(scheme *sc, int n) {
 
569
     pointer newp;
 
570
     pointer last;
 
571
     pointer p;
 
572
     char *cp;
 
573
     long i;
 
574
     int k;
 
575
     int adj=ADJ;
 
576
 
 
577
     if(adj<sizeof(struct cell)) {
 
578
       adj=sizeof(struct cell);
 
579
     }
 
580
 
 
581
     for (k = 0; k < n; k++) {
 
582
          if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
 
583
               return k;
 
584
          cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj);
 
585
          if (cp == 0)
 
586
               return k;
 
587
          i = ++sc->last_cell_seg ;
 
588
          sc->alloc_seg[i] = cp;
 
589
          /* adjust in TYPE_BITS-bit boundary */
 
590
          if(((unsigned)cp)%adj!=0) {
 
591
            cp=(char*)(adj*((unsigned long)cp/adj+1));
 
592
          }
 
593
        /* insert new segment in address order */
 
594
          newp=(pointer)cp;
 
595
        sc->cell_seg[i] = newp;
 
596
        while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
 
597
              p = sc->cell_seg[i];
 
598
            sc->cell_seg[i] = sc->cell_seg[i - 1];
 
599
            sc->cell_seg[--i] = p;
 
600
        }
 
601
          sc->fcells += CELL_SEGSIZE;
 
602
        last = newp + CELL_SEGSIZE - 1;
 
603
          for (p = newp; p <= last; p++) {
 
604
               typeflag(p) = 0;
 
605
               cdr(p) = p + 1;
 
606
               car(p) = sc->NIL;
 
607
          }
 
608
        /* insert new cells in address order on free list */
 
609
        if (sc->free_cell == sc->NIL || p < sc->free_cell) {
 
610
             cdr(last) = sc->free_cell;
 
611
             sc->free_cell = newp;
 
612
        } else {
 
613
              p = sc->free_cell;
 
614
              while (cdr(p) != sc->NIL && newp > cdr(p))
 
615
                   p = cdr(p);
 
616
              cdr(last) = cdr(p);
 
617
              cdr(p) = newp;
 
618
        }
 
619
     }
 
620
     return n;
 
621
}
 
622
 
 
623
static INLINE pointer get_cell(scheme *sc, pointer a, pointer b) {
 
624
  if (sc->free_cell != sc->NIL) {
 
625
    pointer x = sc->free_cell;
 
626
    sc->free_cell = cdr(x);
 
627
    --sc->fcells;
 
628
    return (x);
 
629
  }
 
630
  return _get_cell (sc, a, b);
 
631
}
 
632
 
 
633
 
 
634
/* get new cell.  parameter a, b is marked by gc. */
 
635
static pointer _get_cell(scheme *sc, pointer a, pointer b) {
 
636
  pointer x;
 
637
 
 
638
  if(sc->no_memory) {
 
639
    return sc->sink;
 
640
  }
 
641
 
 
642
  if (sc->free_cell == sc->NIL) {
 
643
    gc(sc,a, b);
 
644
    if (sc->fcells < sc->last_cell_seg*8
 
645
        || sc->free_cell == sc->NIL) {
 
646
      /* if only a few recovered, get more to avoid fruitless gc's */
 
647
      if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) {
 
648
        sc->no_memory=1;
 
649
        return sc->sink;
 
650
      }
 
651
    }
 
652
  }
 
653
  x = sc->free_cell;
 
654
  sc->free_cell = cdr(x);
 
655
  --sc->fcells;
 
656
  return (x);
 
657
}
 
658
 
 
659
/* make sure that there is a given number of cells free */
 
660
static pointer reserve_cells(scheme *sc, int n) {
 
661
       if(sc->no_memory) {
 
662
               return sc->NIL;
 
663
       }
 
664
 
 
665
       /* Are there enough cells available? */
 
666
       if (sc->fcells < n) {
 
667
               /* If not, try gc'ing some */
 
668
               gc(sc, sc->NIL, sc->NIL);
 
669
               if (sc->fcells < n) {
 
670
                       /* If there still aren't, try getting more heap */
 
671
                       if (!alloc_cellseg(sc,1)) {
 
672
                               sc->no_memory=1;
 
673
                               return sc->NIL;
 
674
                       }
 
675
               }
 
676
               if (sc->fcells < n) {
 
677
                       /* If all fail, report failure */
 
678
                       sc->no_memory=1;
 
679
                       return sc->NIL;
 
680
               }
 
681
       }
 
682
       return (sc->T);
 
683
}
 
684
 
 
685
static pointer get_consecutive_cells(scheme *sc, int n) {
 
686
  pointer x;
 
687
 
 
688
  if(sc->no_memory) {
 
689
    return sc->sink;
 
690
  }
 
691
 
 
692
  /* Are there any cells available? */
 
693
  x=find_consecutive_cells(sc,n);
 
694
  if (x == sc->NIL) {
 
695
    /* If not, try gc'ing some */
 
696
    gc(sc, sc->NIL, sc->NIL);
 
697
    x=find_consecutive_cells(sc,n);
 
698
    if (x == sc->NIL) {
 
699
      /* If there still aren't, try getting more heap */
 
700
      if (!alloc_cellseg(sc,1)) {
 
701
        sc->no_memory=1;
 
702
        return sc->sink;
 
703
      }
 
704
    }
 
705
    x=find_consecutive_cells(sc,n);
 
706
    if (x == sc->NIL) {
 
707
      /* If all fail, report failure */
 
708
      sc->no_memory=1;
 
709
      return sc->sink;
 
710
    }
 
711
  }
 
712
  return (x);
 
713
}
 
714
 
 
715
static int count_consecutive_cells(pointer x, int needed) {
 
716
 int n=1;
 
717
 while(cdr(x)==x+1) {
 
718
     x=cdr(x);
 
719
     n++;
 
720
     if(n>needed) return n;
 
721
 }
 
722
 return n;
 
723
}
 
724
 
 
725
static pointer find_consecutive_cells(scheme *sc, int n) {
 
726
  pointer *pp;
 
727
  int cnt;
 
728
 
 
729
  pp=&sc->free_cell;
 
730
  while(*pp!=sc->NIL) {
 
731
    cnt=count_consecutive_cells(*pp,n);
 
732
    if(cnt>=n) {
 
733
      pointer x=*pp;
 
734
      *pp=cdr(*pp+n-1);
 
735
      sc->fcells -= n;
 
736
      return x;
 
737
    }
 
738
    pp=&cdr(*pp+cnt-1);
 
739
  }
 
740
  return sc->NIL;
 
741
}
 
742
 
 
743
/* get new cons cell */
 
744
pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
 
745
  pointer x = get_cell(sc,a, b);
 
746
 
 
747
  typeflag(x) = T_PAIR;
 
748
  if(immutable) {
 
749
    setimmutable(x);
 
750
  }
 
751
  car(x) = a;
 
752
  cdr(x) = b;
 
753
  return (x);
 
754
}
 
755
 
 
756
/* ========== oblist implementation  ========== */
 
757
 
 
758
#ifndef USE_OBJECT_LIST
 
759
 
 
760
static int hash_fn(const char *key, int table_size);
 
761
 
 
762
static pointer oblist_initial_value(scheme *sc)
 
763
{
 
764
  return mk_vector(sc, 461); /* probably should be bigger */
 
765
}
 
766
 
 
767
/* returns the new symbol */
 
768
static pointer oblist_add_by_name(scheme *sc, const char *name)
 
769
{
 
770
  pointer x;
 
771
  int location;
 
772
 
 
773
  x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
 
774
  typeflag(x) = T_SYMBOL;
 
775
  setimmutable(car(x));
 
776
 
 
777
  location = hash_fn(name, ivalue_unchecked(sc->oblist));
 
778
  set_vector_elem(sc->oblist, location,
 
779
                  immutable_cons(sc, x, vector_elem(sc->oblist, location)));
 
780
  return x;
 
781
}
 
782
 
 
783
static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
 
784
{
 
785
  int location;
 
786
  pointer x;
 
787
  char *s;
 
788
  char *key;
 
789
 
 
790
  /* case-insensitive, per R5RS section 2. */
 
791
  s = g_utf8_casefold(name, -1);
 
792
  key = g_utf8_collate_key(s, -1);
 
793
  g_free(s);
 
794
 
 
795
  location = hash_fn(name, ivalue_unchecked(sc->oblist));
 
796
  for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) {
 
797
    s = symkey(car(x));
 
798
    if(strcmp(key, s) == 0) {
 
799
      g_free(key);
 
800
      return car(x);
 
801
    }
 
802
  }
 
803
  g_free(key);
 
804
  return sc->NIL;
 
805
}
 
806
 
 
807
static pointer oblist_all_symbols(scheme *sc)
 
808
{
 
809
  int i;
 
810
  pointer x;
 
811
  pointer ob_list = sc->NIL;
 
812
 
 
813
  for (i = 0; i < ivalue_unchecked(sc->oblist); i++) {
 
814
    for (x  = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) {
 
815
      ob_list = cons(sc, x, ob_list);
 
816
    }
 
817
  }
 
818
  return ob_list;
 
819
}
 
820
 
 
821
#else
 
822
 
 
823
static pointer oblist_initial_value(scheme *sc)
 
824
{
 
825
  return sc->NIL;
 
826
}
 
827
 
 
828
static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
 
829
{
 
830
     pointer x;
 
831
     char    *s;
 
832
     char    *key;
 
833
 
 
834
     /* case-insensitive, per R5RS section 2. */
 
835
     s = g_utf8_casefold(name, -1);
 
836
     key = g_utf8_collate_key(s, -1);
 
837
     g_free(s);
 
838
 
 
839
     for (x = sc->oblist; x != sc->NIL; x = cdr(x)) {
 
840
        s = symkey(car(x));
 
841
        if(strcmp(key, s) == 0) {
 
842
          g_free(key);
 
843
          return car(x);
 
844
        }
 
845
     }
 
846
     g_free(key);
 
847
     return sc->NIL;
 
848
}
 
849
 
 
850
/* returns the new symbol */
 
851
static pointer oblist_add_by_name(scheme *sc, const char *name)
 
852
{
 
853
  pointer x;
 
854
 
 
855
  x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
 
856
  typeflag(x) = T_SYMBOL;
 
857
  setimmutable(car(x));
 
858
  sc->oblist = immutable_cons(sc, x, sc->oblist);
 
859
  return x;
 
860
}
 
861
 
 
862
static pointer oblist_all_symbols(scheme *sc)
 
863
{
 
864
  return sc->oblist;
 
865
}
 
866
 
 
867
#endif
 
868
 
 
869
static pointer mk_port(scheme *sc, port *p) {
 
870
  pointer x = get_cell(sc, sc->NIL, sc->NIL);
 
871
 
 
872
  typeflag(x) = T_PORT|T_ATOM;
 
873
  x->_object._port=p;
 
874
  return (x);
 
875
}
 
876
 
 
877
pointer mk_foreign_func(scheme *sc, foreign_func f) {
 
878
  pointer x = get_cell(sc, sc->NIL, sc->NIL);
 
879
 
 
880
  typeflag(x) = (T_FOREIGN | T_ATOM);
 
881
  x->_object._ff=f;
 
882
  return (x);
 
883
}
 
884
 
 
885
INTERFACE pointer mk_character(scheme *sc, gunichar c) {
 
886
  pointer x = get_cell(sc,sc->NIL, sc->NIL);
 
887
 
 
888
  typeflag(x) = (T_CHARACTER | T_ATOM);
 
889
  ivalue_unchecked(x)= c;
 
890
  set_integer(x);
 
891
  return (x);
 
892
}
 
893
 
 
894
/* get number atom (integer) */
 
895
INTERFACE pointer mk_integer(scheme *sc, long num) {
 
896
  pointer x = get_cell(sc,sc->NIL, sc->NIL);
 
897
 
 
898
  typeflag(x) = (T_NUMBER | T_ATOM);
 
899
  ivalue_unchecked(x)= num;
 
900
  set_integer(x);
 
901
  return (x);
 
902
}
 
903
 
 
904
INTERFACE pointer mk_real(scheme *sc, double n) {
 
905
  pointer x = get_cell(sc,sc->NIL, sc->NIL);
 
906
 
 
907
  typeflag(x) = (T_NUMBER | T_ATOM);
 
908
  rvalue_unchecked(x)= n;
 
909
  set_real(x);
 
910
  return (x);
 
911
}
 
912
 
 
913
static pointer mk_number(scheme *sc, num n) {
 
914
 if(n.is_fixnum) {
 
915
     return mk_integer(sc,n.value.ivalue);
 
916
 } else {
 
917
     return mk_real(sc,n.value.rvalue);
 
918
 }
 
919
}
 
920
 
 
921
void set_safe_foreign (scheme *sc, pointer data) {
 
922
  if (sc->safe_foreign == sc->NIL) {
 
923
    fprintf (stderr, "get_safe_foreign called outside a foreign function\n");
 
924
  } else {
 
925
    car (sc->safe_foreign) = data;
 
926
  }
 
927
}
 
928
 
 
929
 
 
930
/* char_cnt is length of string in chars. */
 
931
/* str points to a NUL terminated string. */
 
932
/* Only uses fill_char if str is NULL.    */
 
933
static char *store_string(scheme *sc, int char_cnt,
 
934
                          const char *str, gunichar fill) {
 
935
     int  len;
 
936
     int  i;
 
937
     gchar utf8[7];
 
938
     gchar *q;
 
939
     gchar *q2;
 
940
 
 
941
     if(str!=0) {
 
942
       q2 = g_utf8_offset_to_pointer(str, (long)char_cnt);
 
943
       (void)g_utf8_validate(str, -1, (const gchar **)&q);
 
944
       if (q <= q2)
 
945
          len = q - str;
 
946
       else
 
947
          len = q2 - str;
 
948
       q=(gchar*)sc->malloc(len+1);
 
949
     }
 
950
     else {
 
951
       len = g_unichar_to_utf8(fill, utf8);
 
952
       q=(gchar*)sc->malloc(char_cnt*len+1);
 
953
     }
 
954
     if(q==0) {
 
955
       sc->no_memory=1;
 
956
       return sc->strbuff;
 
957
     }
 
958
     if(str!=0) {
 
959
       memcpy(q, str, len);
 
960
       q[len]=0;
 
961
     } else {
 
962
       q2 = q;
 
963
       for (i = 0; i < char_cnt; ++i)
 
964
       {
 
965
         memcpy(q2, utf8, len);
 
966
         q2 += len;
 
967
       }
 
968
       *q2=0;
 
969
     }
 
970
     return (q);
 
971
}
 
972
 
 
973
/* get new string */
 
974
INTERFACE pointer mk_string(scheme *sc, const char *str) {
 
975
     return mk_counted_string(sc,str,g_utf8_strlen(str, -1));
 
976
}
 
977
 
 
978
/* len is the length of str in characters */
 
979
INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
 
980
     pointer x = get_cell(sc, sc->NIL, sc->NIL);
 
981
     char   *s;
 
982
 
 
983
     strvalue(x) = store_string(sc,len,str,0);
 
984
     s = g_utf8_casefold(strvalue(x), -1);
 
985
     strkey(x) = g_utf8_collate_key(s, -1);
 
986
     typeflag(x) = (T_STRING | T_ATOM);
 
987
     strlength(x) = len;
 
988
     g_free(s);
 
989
     return (x);
 
990
}
 
991
 
 
992
static pointer mk_empty_string(scheme *sc, int len, gunichar fill) {
 
993
     pointer x = get_cell(sc, sc->NIL, sc->NIL);
 
994
     char   *s;
 
995
 
 
996
     strvalue(x) = store_string(sc,len,0,fill);
 
997
     s = g_utf8_casefold(strvalue(x), -1);
 
998
     strkey(x) = g_utf8_collate_key(s, -1);
 
999
     typeflag(x) = (T_STRING | T_ATOM);
 
1000
     strlength(x) = len;
 
1001
     g_free(s);
 
1002
     return (x);
 
1003
}
 
1004
 
 
1005
INTERFACE static pointer mk_vector(scheme *sc, int len) {
 
1006
     pointer x=get_consecutive_cells(sc,len/2+len%2+1);
 
1007
     typeflag(x) = (T_VECTOR | T_ATOM);
 
1008
     ivalue_unchecked(x)=len;
 
1009
     set_integer(x);
 
1010
     fill_vector(x,sc->NIL);
 
1011
     return x;
 
1012
}
 
1013
 
 
1014
INTERFACE static void fill_vector(pointer vec, pointer obj) {
 
1015
     int i;
 
1016
     int num=ivalue(vec)/2+ivalue(vec)%2;
 
1017
     for(i=0; i<num; i++) {
 
1018
          typeflag(vec+1+i) = T_PAIR;
 
1019
          setimmutable(vec+1+i);
 
1020
          car(vec+1+i)=obj;
 
1021
          cdr(vec+1+i)=obj;
 
1022
     }
 
1023
}
 
1024
 
 
1025
INTERFACE static pointer vector_elem(pointer vec, int ielem) {
 
1026
     int n=ielem/2;
 
1027
     if(ielem%2==0) {
 
1028
          return car(vec+1+n);
 
1029
     } else {
 
1030
          return cdr(vec+1+n);
 
1031
     }
 
1032
}
 
1033
 
 
1034
INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
 
1035
     int n=ielem/2;
 
1036
     if(ielem%2==0) {
 
1037
          return car(vec+1+n)=a;
 
1038
     } else {
 
1039
          return cdr(vec+1+n)=a;
 
1040
     }
 
1041
}
 
1042
 
 
1043
/* get new symbol */
 
1044
INTERFACE pointer mk_symbol(scheme *sc, const char *name) {
 
1045
     pointer x;
 
1046
 
 
1047
     /* first check oblist */
 
1048
     x = oblist_find_by_name(sc, name);
 
1049
     if (x != sc->NIL) {
 
1050
          return (x);
 
1051
     } else {
 
1052
          x = oblist_add_by_name(sc, name);
 
1053
          return (x);
 
1054
     }
 
1055
}
 
1056
 
 
1057
INTERFACE pointer gensym(scheme *sc) {
 
1058
     pointer x;
 
1059
     char name[40];
 
1060
 
 
1061
     for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) {
 
1062
          sprintf(name,"gensym-%ld",sc->gensym_cnt);
 
1063
 
 
1064
          /* first check oblist */
 
1065
          x = oblist_find_by_name(sc, name);
 
1066
 
 
1067
          if (x != sc->NIL) {
 
1068
               continue;
 
1069
          } else {
 
1070
               x = oblist_add_by_name(sc, name);
 
1071
               return (x);
 
1072
          }
 
1073
     }
 
1074
 
 
1075
     return sc->NIL;
 
1076
}
 
1077
 
 
1078
/* make symbol or number atom from string */
 
1079
static pointer mk_atom(scheme *sc, char *q) {
 
1080
     char    c, *p;
 
1081
     int has_dec_point=0;
 
1082
     int has_fp_exp = 0;
 
1083
 
 
1084
#if USE_COLON_HOOK
 
1085
     if((p=strstr(q,"::"))!=0) {
 
1086
          *p=0;
 
1087
          return cons(sc, sc->COLON_HOOK,
 
1088
                          cons(sc,
 
1089
                              cons(sc,
 
1090
                                   sc->QUOTE,
 
1091
                                   cons(sc, mk_atom(sc,p+2), sc->NIL)),
 
1092
                              cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL)));
 
1093
     }
 
1094
#endif
 
1095
 
 
1096
     p = q;
 
1097
     c = *p++;
 
1098
     if ((c == '+') || (c == '-')) {
 
1099
       c = *p++;
 
1100
       if (c == '.') {
 
1101
         has_dec_point=1;
 
1102
         c = *p++;
 
1103
       }
 
1104
       if (!isdigit(c)) {
 
1105
         return (mk_symbol(sc, strlwr(q)));
 
1106
       }
 
1107
     } else if (c == '.') {
 
1108
       has_dec_point=1;
 
1109
       c = *p++;
 
1110
       if (!isdigit(c)) {
 
1111
         return (mk_symbol(sc, strlwr(q)));
 
1112
       }
 
1113
     } else if (!isdigit(c)) {
 
1114
       return (mk_symbol(sc, strlwr(q)));
 
1115
     }
 
1116
 
 
1117
     for ( ; (c = *p) != 0; ++p) {
 
1118
          if (!isdigit(c)) {
 
1119
               if(c=='.') {
 
1120
                    if(!has_dec_point) {
 
1121
                         has_dec_point=1;
 
1122
                         continue;
 
1123
                    }
 
1124
               }
 
1125
               else if ((c == 'e') || (c == 'E')) {
 
1126
                       if(!has_fp_exp) {
 
1127
                          has_dec_point = 1; /* decimal point illegal
 
1128
                                                from now on */
 
1129
                          p++;
 
1130
                          if ((*p == '-') || (*p == '+') || isdigit(*p)) {
 
1131
                             continue;
 
1132
                          }
 
1133
                       }
 
1134
               }
 
1135
               return (mk_symbol(sc, strlwr(q)));
 
1136
          }
 
1137
     }
 
1138
     if(has_dec_point) {
 
1139
       return mk_real(sc,g_ascii_strtod(q,NULL));
 
1140
     }
 
1141
     return (mk_integer(sc, atol(q)));
 
1142
}
 
1143
 
 
1144
/* make constant */
 
1145
static pointer mk_sharp_const(scheme *sc, char *name) {
 
1146
     long    x;
 
1147
     char    tmp[256];
 
1148
 
 
1149
     if (!strcmp(name, "t"))
 
1150
          return (sc->T);
 
1151
     else if (!strcmp(name, "f"))
 
1152
          return (sc->F);
 
1153
     else if (*name == 'o') {/* #o (octal) */
 
1154
          sprintf(tmp, "0%s", name+1);
 
1155
          sscanf(tmp, "%lo", &x);
 
1156
          return (mk_integer(sc, x));
 
1157
     } else if (*name == 'd') {    /* #d (decimal) */
 
1158
          sscanf(name+1, "%ld", &x);
 
1159
          return (mk_integer(sc, x));
 
1160
     } else if (*name == 'x') {    /* #x (hex) */
 
1161
          sprintf(tmp, "0x%s", name+1);
 
1162
          sscanf(tmp, "%lx", &x);
 
1163
          return (mk_integer(sc, x));
 
1164
     } else if (*name == 'b') {    /* #b (binary) */
 
1165
          x = binary_decode(name+1);
 
1166
          return (mk_integer(sc, x));
 
1167
     } else if (*name == '\\') { /* #\w (character) */
 
1168
          gunichar c=0;
 
1169
          if(stricmp(name+1,"space")==0) {
 
1170
               c=' ';
 
1171
          } else if(stricmp(name+1,"newline")==0) {
 
1172
               c='\n';
 
1173
          } else if(stricmp(name+1,"return")==0) {
 
1174
               c='\r';
 
1175
          } else if(stricmp(name+1,"tab")==0) {
 
1176
               c='\t';
 
1177
     } else if(name[1]=='x' && name[2]!=0) {
 
1178
          int c1=0;
 
1179
          if(sscanf(name+2,"%x",&c1)==1 && c1<256) {
 
1180
               c=c1;
 
1181
          } else {
 
1182
               return sc->NIL;
 
1183
     }
 
1184
#if USE_ASCII_NAMES
 
1185
          } else if(is_ascii_name(name+1,&c)) {
 
1186
               /* nothing */
 
1187
#endif
 
1188
          } else if(name[2]==0) {
 
1189
               c=name[1];
 
1190
          } else {
 
1191
               return sc->NIL;
 
1192
          }
 
1193
          return mk_character(sc,c);
 
1194
     } else
 
1195
          return (sc->NIL);
 
1196
}
 
1197
 
 
1198
/* ========== garbage collector ========== */
 
1199
 
 
1200
/*--
 
1201
 *  We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
 
1202
 *  sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
 
1203
 *  for marking.
 
1204
 */
 
1205
static void mark(pointer a) {
 
1206
     pointer t, q, p;
 
1207
 
 
1208
     t = (pointer) 0;
 
1209
     p = a;
 
1210
E2:  setmark(p);
 
1211
     if(is_vector(p)) {
 
1212
          int i;
 
1213
          int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2;
 
1214
          for(i=0; i<num; i++) {
 
1215
               /* Vector cells will be treated like ordinary cells */
 
1216
               mark(p+1+i);
 
1217
          }
 
1218
     }
 
1219
     if (is_atom(p))
 
1220
          goto E6;
 
1221
     /* E4: down car */
 
1222
     q = car(p);
 
1223
     if (q && !is_mark(q)) {
 
1224
          setatom(p);  /* a note that we have moved car */
 
1225
          car(p) = t;
 
1226
          t = p;
 
1227
          p = q;
 
1228
          goto E2;
 
1229
     }
 
1230
 E5:  q = cdr(p); /* down cdr */
 
1231
     if (q && !is_mark(q)) {
 
1232
          cdr(p) = t;
 
1233
          t = p;
 
1234
          p = q;
 
1235
          goto E2;
 
1236
     }
 
1237
E6:   /* up.  Undo the link switching from steps E4 and E5. */
 
1238
     if (!t)
 
1239
          return;
 
1240
     q = t;
 
1241
     if (is_atom(q)) {
 
1242
          clratom(q);
 
1243
          t = car(q);
 
1244
          car(q) = p;
 
1245
          p = q;
 
1246
          goto E5;
 
1247
     } else {
 
1248
          t = cdr(q);
 
1249
          cdr(q) = p;
 
1250
          p = q;
 
1251
          goto E6;
 
1252
     }
 
1253
}
 
1254
 
 
1255
/* garbage collection. parameter a, b is marked. */
 
1256
static void gc(scheme *sc, pointer a, pointer b) {
 
1257
  pointer p;
 
1258
  int i;
 
1259
 
 
1260
  if(sc->gc_verbose) {
 
1261
    putstr(sc, "gc...");
 
1262
  }
 
1263
 
 
1264
  /* mark system globals */
 
1265
  mark(sc->oblist);
 
1266
  mark(sc->global_env);
 
1267
 
 
1268
  /* mark current registers */
 
1269
  mark(sc->args);
 
1270
  mark(sc->envir);
 
1271
  mark(sc->code);
 
1272
  dump_stack_mark(sc);
 
1273
  mark(sc->value);
 
1274
  mark(sc->safe_foreign);
 
1275
  mark(sc->inport);
 
1276
  mark(sc->save_inport);
 
1277
  mark(sc->outport);
 
1278
  mark(sc->loadport);
 
1279
 
 
1280
  /* mark variables a, b */
 
1281
  mark(a);
 
1282
  mark(b);
 
1283
 
 
1284
  /* garbage collect */
 
1285
  clrmark(sc->NIL);
 
1286
  sc->fcells = 0;
 
1287
  sc->free_cell = sc->NIL;
 
1288
  /* free-list is kept sorted by address so as to maintain consecutive
 
1289
     ranges, if possible, for use with vectors. Here we scan the cells
 
1290
     (which are also kept sorted by address) downwards to build the
 
1291
     free-list in sorted order.
 
1292
  */
 
1293
  for (i = sc->last_cell_seg; i >= 0; i--) {
 
1294
    p = sc->cell_seg[i] + CELL_SEGSIZE;
 
1295
    while (--p >= sc->cell_seg[i]) {
 
1296
      if (is_mark(p)) {
 
1297
        clrmark(p);
 
1298
      } else {
 
1299
        /* reclaim cell */
 
1300
        if (typeflag(p) != 0) {
 
1301
          finalize_cell(sc, p);
 
1302
          typeflag(p) = 0;
 
1303
          car(p) = sc->NIL;
 
1304
        }
 
1305
        ++sc->fcells;
 
1306
        cdr(p) = sc->free_cell;
 
1307
        sc->free_cell = p;
 
1308
      }
 
1309
    }
 
1310
  }
 
1311
 
 
1312
  if (sc->gc_verbose) {
 
1313
    char msg[80];
 
1314
    sprintf(msg,"done: %ld cells were recovered.\n", sc->fcells);
 
1315
    putstr(sc,msg);
 
1316
  }
 
1317
}
 
1318
 
 
1319
static void finalize_cell(scheme *sc, pointer a) {
 
1320
  if(is_string(a)) {
 
1321
    sc->free(strvalue(a));
 
1322
    g_free(strkey(a)); /* mem was allocated via glib */
 
1323
  } else if(is_port(a)) {
 
1324
    if(a->_object._port->kind&port_file
 
1325
       && a->_object._port->rep.stdio.closeit) {
 
1326
      port_close(sc,a,port_input|port_output);
 
1327
    }
 
1328
    sc->free(a->_object._port);
 
1329
  }
 
1330
}
 
1331
 
 
1332
/* ========== Routines for Reading ========== */
 
1333
 
 
1334
static int file_push(scheme *sc, const char *fname) {
 
1335
  FILE *fin=fopen(fname,"rb");
 
1336
  if(fin!=0) {
 
1337
    sc->file_i++;
 
1338
    sc->load_stack[sc->file_i].kind=port_file|port_input;
 
1339
    sc->load_stack[sc->file_i].rep.stdio.file=fin;
 
1340
    sc->load_stack[sc->file_i].rep.stdio.closeit=1;
 
1341
    sc->nesting_stack[sc->file_i]=0;
 
1342
    sc->loadport->_object._port=sc->load_stack+sc->file_i;
 
1343
  }
 
1344
  return fin!=0;
 
1345
}
 
1346
 
 
1347
static void file_pop(scheme *sc) {
 
1348
 sc->nesting=sc->nesting_stack[sc->file_i];
 
1349
 if(sc->file_i!=0) {
 
1350
   port_close(sc,sc->loadport,port_input);
 
1351
   sc->file_i--;
 
1352
   sc->loadport->_object._port=sc->load_stack+sc->file_i;
 
1353
   if(file_interactive(sc)) {
 
1354
     putstr(sc,prompt);
 
1355
   }
 
1356
 }
 
1357
}
 
1358
 
 
1359
static int file_interactive(scheme *sc) {
 
1360
 return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin
 
1361
     && sc->inport->_object._port->kind&port_file;
 
1362
}
 
1363
 
 
1364
static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
 
1365
  FILE *f;
 
1366
  char *rw;
 
1367
  port *pt;
 
1368
  if(prop==(port_input|port_output)) {
 
1369
    rw="a+b";
 
1370
  } else if(prop==port_output) {
 
1371
    rw="wb";
 
1372
  } else {
 
1373
    rw="rb";
 
1374
  }
 
1375
  f=fopen(fn,rw);
 
1376
  if(f==0) {
 
1377
    return 0;
 
1378
  }
 
1379
  pt=port_rep_from_file(sc,f,prop);
 
1380
  pt->rep.stdio.closeit=1;
 
1381
  return pt;
 
1382
}
 
1383
 
 
1384
static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
 
1385
  port *pt;
 
1386
  pt=port_rep_from_filename(sc,fn,prop);
 
1387
  if(pt==0) {
 
1388
    return sc->NIL;
 
1389
  }
 
1390
  return mk_port(sc,pt);
 
1391
}
 
1392
 
 
1393
static port *port_rep_from_file(scheme *sc, FILE *f, int prop) {
 
1394
  char *rw;
 
1395
  port *pt;
 
1396
  pt=(port*)sc->malloc(sizeof(port));
 
1397
  if(pt==0) {
 
1398
    return 0;
 
1399
  }
 
1400
  if(prop==(port_input|port_output)) {
 
1401
    rw="a+";
 
1402
  } else if(prop==port_output) {
 
1403
    rw="w";
 
1404
  } else {
 
1405
    rw="r";
 
1406
  }
 
1407
  pt->kind=port_file|prop;
 
1408
  pt->rep.stdio.file=f;
 
1409
  pt->rep.stdio.closeit=0;
 
1410
  return pt;
 
1411
}
 
1412
 
 
1413
static pointer port_from_file(scheme *sc, FILE *f, int prop) {
 
1414
  port *pt;
 
1415
  pt=port_rep_from_file(sc,f,prop);
 
1416
  if(pt==0) {
 
1417
    return sc->NIL;
 
1418
  }
 
1419
  return mk_port(sc,pt);
 
1420
}
 
1421
 
 
1422
static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
 
1423
  port *pt;
 
1424
  pt=(port*)sc->malloc(sizeof(port));
 
1425
  if(pt==0) {
 
1426
    return 0;
 
1427
  }
 
1428
  pt->kind=port_string|prop;
 
1429
  pt->rep.string.start=start;
 
1430
  pt->rep.string.curr=start;
 
1431
  pt->rep.string.past_the_end=past_the_end;
 
1432
  return pt;
 
1433
}
 
1434
 
 
1435
static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
 
1436
  port *pt;
 
1437
  pt=port_rep_from_string(sc,start,past_the_end,prop);
 
1438
  if(pt==0) {
 
1439
    return sc->NIL;
 
1440
  }
 
1441
  return mk_port(sc,pt);
 
1442
}
 
1443
 
 
1444
static void port_close(scheme *sc, pointer p, int flag) {
 
1445
  port *pt=p->_object._port;
 
1446
  pt->kind&=~flag;
 
1447
  if((pt->kind & (port_input|port_output))==0) {
 
1448
    if(pt->kind&port_file) {
 
1449
      fclose(pt->rep.stdio.file);
 
1450
    }
 
1451
    pt->kind=port_free;
 
1452
  }
 
1453
}
 
1454
 
 
1455
static gunichar basic_inchar(port *pt) {
 
1456
  int  len;
 
1457
 
 
1458
  if(pt->kind&port_file) {
 
1459
    char utf8[7];
 
1460
    char *s;
 
1461
    int  i;
 
1462
 
 
1463
    utf8[0] = fgetc(pt->rep.stdio.file);
 
1464
    if (utf8[0] & 0x80)
 
1465
    {
 
1466
       len = utf8_length[ utf8[0]&0x7F ];
 
1467
       s = &utf8[1];
 
1468
       for (i = 0; i < len; ++i)
 
1469
         *s++ = fgetc(pt->rep.stdio.file);
 
1470
       /* FIXME: Check for bad character and search for next good char. */
 
1471
       return g_utf8_get_char_validated(utf8, len+1);
 
1472
    }
 
1473
    return (gunichar)utf8[0];
 
1474
  } else {
 
1475
    if(*pt->rep.string.curr==0
 
1476
       || pt->rep.string.curr==pt->rep.string.past_the_end) {
 
1477
      return EOF;
 
1478
    } else {
 
1479
      gunichar c;
 
1480
 
 
1481
      len = pt->rep.string.past_the_end - pt->rep.string.curr;
 
1482
      c = g_utf8_get_char_validated(pt->rep.string.curr, len);
 
1483
 
 
1484
      if (c < 0)
 
1485
      {
 
1486
        pt->rep.string.curr = g_utf8_find_next_char(pt->rep.string.curr,
 
1487
                                                    pt->rep.string.past_the_end);
 
1488
        if (pt->rep.string.curr == NULL)
 
1489
            pt->rep.string.curr = pt->rep.string.past_the_end;
 
1490
        c = ' ';
 
1491
      }
 
1492
      else
 
1493
      {
 
1494
        len = g_unichar_to_utf8(c, NULL);
 
1495
        pt->rep.string.curr += len;
 
1496
      }
 
1497
 
 
1498
      return c;
 
1499
    }
 
1500
  }
 
1501
}
 
1502
 
 
1503
/* get new character from input file */
 
1504
static gunichar inchar(scheme *sc) {
 
1505
  gunichar c;
 
1506
  port *pt;
 
1507
 again:
 
1508
  pt=sc->inport->_object._port;
 
1509
  if(pt->kind&port_file && pt->rep.stdio.file == stdin)
 
1510
  {
 
1511
    if (sc->bc_flag)
 
1512
    {
 
1513
      sc->bc_flag = 0;
 
1514
      c = sc->backchar;
 
1515
    }
 
1516
    else
 
1517
      c=basic_inchar(pt);
 
1518
  }
 
1519
  else
 
1520
    c=basic_inchar(pt);
 
1521
  if(c==EOF && sc->inport==sc->loadport && sc->file_i!=0) {
 
1522
    file_pop(sc);
 
1523
    if(sc->nesting!=0) {
 
1524
      return EOF;
 
1525
    } else {
 
1526
      return '\n';
 
1527
    }
 
1528
    goto again;
 
1529
  }
 
1530
  return c;
 
1531
}
 
1532
 
 
1533
/* back character to input buffer */
 
1534
static void backchar(scheme *sc, gunichar c) {
 
1535
  port *pt;
 
1536
  gint  charlen;
 
1537
 
 
1538
  if(c==EOF) return;
 
1539
  charlen = g_unichar_to_utf8(c, NULL);
 
1540
  pt=sc->inport->_object._port;
 
1541
  if(pt->kind&port_file) {
 
1542
    if (pt->rep.stdio.file == stdin)
 
1543
    {
 
1544
      sc->backchar = c;
 
1545
      sc->bc_flag = 1;
 
1546
    }
 
1547
    else {
 
1548
      if (ftell(pt->rep.stdio.file) >= (long)charlen)
 
1549
         fseek(pt->rep.stdio.file, 0L-(long)charlen, SEEK_CUR);
 
1550
    }
 
1551
  } else {
 
1552
    if(pt->rep.string.curr!=pt->rep.string.start) {
 
1553
      if(pt->rep.string.curr-pt->rep.string.start >= charlen)
 
1554
        pt->rep.string.curr -= charlen;
 
1555
      else
 
1556
        pt->rep.string.curr = pt->rep.string.start;
 
1557
    }
 
1558
  }
 
1559
}
 
1560
 
 
1561
/* len is number of UTF-8 characters in string pointed to by chars */
 
1562
static void putchars(scheme *sc, const char *chars, int char_cnt) {
 
1563
  int   l;
 
1564
  char *s;
 
1565
  port *pt=sc->outport->_object._port;
 
1566
 
 
1567
  if (char_cnt <= 0)
 
1568
      return;
 
1569
 
 
1570
#if !STANDALONE
 
1571
  /* Output characters to console mode (if enabled) */
 
1572
  if (ts_output_routine != NULL)    /* Should this be left in?? ~~~~~ */
 
1573
     (*ts_output_routine) (pt->rep.stdio.file, (char *)chars, char_cnt);
 
1574
#endif
 
1575
 
 
1576
  char_cnt = g_utf8_offset_to_pointer(chars, (long)char_cnt) - chars;
 
1577
 
 
1578
  if (sc->print_error) {
 
1579
      l = strlen(sc->linebuff);
 
1580
      s = &sc->linebuff[l];
 
1581
      memcpy(s, chars, min(char_cnt, LINESIZE-l-1));
 
1582
      return;
 
1583
  }
 
1584
 
 
1585
  if(pt->kind&port_file) {
 
1586
    fwrite(chars,1,char_cnt,pt->rep.stdio.file);
 
1587
    fflush(pt->rep.stdio.file);
 
1588
  } else {
 
1589
    l = pt->rep.string.past_the_end - pt->rep.string.curr;
 
1590
    if (l > 0)
 
1591
       memcpy(pt->rep.string.curr, chars, min(char_cnt, l));
 
1592
  }
 
1593
}
 
1594
 
 
1595
INTERFACE void putcharacter(scheme *sc, gunichar c) {
 
1596
  char utf8[7];
 
1597
 
 
1598
  (void)g_unichar_to_utf8(c, utf8);
 
1599
  putchars(sc, utf8, 1);
 
1600
}
 
1601
 
 
1602
INTERFACE void putstr(scheme *sc, const char *s) {
 
1603
  putchars(sc, s, g_utf8_strlen(s, -1));
 
1604
}
 
1605
 
 
1606
/* read characters up to delimiter, but cater to character constants */
 
1607
static char *readstr_upto(scheme *sc, char *delim) {
 
1608
  char *p = sc->strbuff;
 
1609
  gunichar c = 0;
 
1610
  gunichar c_prev = 0;
 
1611
  int  len = 0;
 
1612
 
 
1613
#if 0
 
1614
  while (!is_one_of(delim, (*p++ = inchar(sc))))
 
1615
      ;
 
1616
  if(p==sc->strbuff+2 && p[-2]=='\\') {
 
1617
    *p=0;
 
1618
  } else {
 
1619
    backchar(sc,p[-1]);
 
1620
    *--p = '\0';
 
1621
  }
 
1622
#else
 
1623
  do {
 
1624
    c_prev = c;
 
1625
    c = inchar(sc);
 
1626
    len = g_unichar_to_utf8(c, p);
 
1627
    p += len;
 
1628
  } while (c && !is_one_of(delim, c));
 
1629
 
 
1630
  if(p==sc->strbuff+2 && c_prev=='\\')
 
1631
    *p = '\0';
 
1632
  else
 
1633
  {
 
1634
    backchar(sc,c);    /* put back the delimiter */
 
1635
    p[-len] = '\0';
 
1636
  }
 
1637
#endif
 
1638
  return sc->strbuff;
 
1639
}
 
1640
 
 
1641
/* read string expression "xxx...xxx" */
 
1642
static pointer readstrexp(scheme *sc) {
 
1643
  char *p = sc->strbuff;
 
1644
  gunichar c;
 
1645
  int c1=0;
 
1646
  int len;
 
1647
  enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2, st_oct3 } state=st_ok;
 
1648
 
 
1649
  for (;;) {
 
1650
    c=inchar(sc);
 
1651
    if(c==EOF || p-sc->strbuff>sizeof(sc->strbuff)-1) {
 
1652
      return sc->F;
 
1653
    }
 
1654
    switch(state) {
 
1655
    case st_ok:
 
1656
      switch(c) {
 
1657
      case '\\':
 
1658
        state=st_bsl;
 
1659
        break;
 
1660
      case '"':
 
1661
        *p=0;
 
1662
        return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
 
1663
      default:
 
1664
        len = g_unichar_to_utf8(c, p);
 
1665
        p += len;
 
1666
        break;
 
1667
      }
 
1668
      break;
 
1669
    case st_bsl:
 
1670
      switch(c) {
 
1671
      case '0':
 
1672
      case '1':
 
1673
      case '2':
 
1674
      case '3':
 
1675
      case '4':
 
1676
      case '5':
 
1677
      case '6':
 
1678
      case '7':
 
1679
        state=st_oct1;
 
1680
        c1=g_unichar_digit_value(c);
 
1681
        break;
 
1682
      case 'x':
 
1683
      case 'X':
 
1684
        state=st_x1;
 
1685
        c1=0;
 
1686
        break;
 
1687
      case 'n':
 
1688
        *p++='\n';
 
1689
        state=st_ok;
 
1690
        break;
 
1691
      case 't':
 
1692
        *p++='\t';
 
1693
        state=st_ok;
 
1694
        break;
 
1695
      case 'r':
 
1696
        *p++='\r';
 
1697
        state=st_ok;
 
1698
        break;
 
1699
      case '"':
 
1700
        *p++='"';
 
1701
        state=st_ok;
 
1702
        break;
 
1703
      default:
 
1704
        len = g_unichar_to_utf8(c, p);
 
1705
        p += len;
 
1706
        state=st_ok;
 
1707
        break;
 
1708
      }
 
1709
      break;
 
1710
    case st_x1:
 
1711
    case st_x2:
 
1712
      if (!g_unichar_isxdigit(c))
 
1713
         return sc->F;
 
1714
      c1=(c1<<4)+g_unichar_xdigit_value(c);
 
1715
      if(state==st_x1)
 
1716
        state=st_x2;
 
1717
      else {
 
1718
        *p++=c1;
 
1719
        state=st_ok;
 
1720
      }
 
1721
      break;
 
1722
    case st_oct1:
 
1723
    case st_oct2:
 
1724
    case st_oct3:
 
1725
      if (!g_unichar_isdigit(c) || g_unichar_digit_value(c) > 7)
 
1726
      {
 
1727
        if (state==st_oct1)
 
1728
           return sc->F;
 
1729
 
 
1730
        *p++=c1;
 
1731
        backchar(sc, c);
 
1732
        state=st_ok;
 
1733
      }
 
1734
      else
 
1735
      {
 
1736
        c1=(c1<<3)+g_unichar_digit_value(c);
 
1737
        switch (state)
 
1738
        {
 
1739
        case st_oct1:
 
1740
          state=st_oct2;
 
1741
          break;
 
1742
        case st_oct2:
 
1743
          state=st_oct3;
 
1744
          break;
 
1745
        default:
 
1746
          *p++=c1;
 
1747
          state=st_ok;
 
1748
          break;
 
1749
        }
 
1750
      }
 
1751
      break;
 
1752
    }
 
1753
  }
 
1754
}
 
1755
 
 
1756
/* check c is in chars */
 
1757
static INLINE int is_one_of(char *s, gunichar c) {
 
1758
  if (c==EOF)
 
1759
     return 1;
 
1760
 
 
1761
  if (g_utf8_strchr(s, -1, c) != NULL)
 
1762
     return (1);
 
1763
 
 
1764
  return (0);
 
1765
}
 
1766
 
 
1767
/* skip white characters */
 
1768
static INLINE void skipspace(scheme *sc) {
 
1769
     gunichar c;
 
1770
     while (g_unichar_isspace(c=inchar(sc)))
 
1771
          ;
 
1772
     if(c!=EOF) {
 
1773
          backchar(sc,c);
 
1774
     }
 
1775
}
 
1776
 
 
1777
/* get token */
 
1778
static int token(scheme *sc) {
 
1779
     gunichar c;
 
1780
     skipspace(sc);
 
1781
     switch (c=inchar(sc)) {
 
1782
     case EOF:
 
1783
          return (TOK_EOF);
 
1784
     case '(':
 
1785
          return (TOK_LPAREN);
 
1786
     case ')':
 
1787
          return (TOK_RPAREN);
 
1788
     case '.':
 
1789
          c=inchar(sc);
 
1790
          if(is_one_of(" \n\t",c)) {
 
1791
               return (TOK_DOT);
 
1792
          } else {
 
1793
               backchar(sc,c);
 
1794
               backchar(sc,'.');
 
1795
               return TOK_ATOM;
 
1796
          }
 
1797
     case '\'':
 
1798
          return (TOK_QUOTE);
 
1799
     case ';':
 
1800
          while ((c=inchar(sc)) != '\n' && c!=EOF)
 
1801
            ;
 
1802
          return (token(sc));
 
1803
     case '"':
 
1804
          return (TOK_DQUOTE);
 
1805
     case '_':
 
1806
          if ((c=inchar(sc)) == '"')
 
1807
               return (TOK_DQUOTE);
 
1808
          backchar(sc,c);
 
1809
          return (TOK_ATOM);
 
1810
     case BACKQUOTE:
 
1811
          return (TOK_BQUOTE);
 
1812
     case ',':
 
1813
          if ((c=inchar(sc)) == '@')
 
1814
               return (TOK_ATMARK);
 
1815
          else {
 
1816
               backchar(sc,c);
 
1817
               return (TOK_COMMA);
 
1818
          }
 
1819
     case '#':
 
1820
          c=inchar(sc);
 
1821
          if (c == '(') {
 
1822
               return (TOK_VEC);
 
1823
          } else if(c == '!') {
 
1824
               while ((c=inchar(sc)) != '\n' && c!=EOF)
 
1825
                   ;
 
1826
               return (token(sc));
 
1827
          } else {
 
1828
               backchar(sc,c);
 
1829
               if(is_one_of(" tfodxb\\",c)) {
 
1830
                    return TOK_SHARP_CONST;
 
1831
               } else {
 
1832
                    return (TOK_SHARP);
 
1833
               }
 
1834
          }
 
1835
     default:
 
1836
          backchar(sc,c);
 
1837
          return (TOK_ATOM);
 
1838
     }
 
1839
}
 
1840
 
 
1841
/* ========== Routines for Printing ========== */
 
1842
#define   ok_abbrev(x)   (is_pair(x) && cdr(x) == sc->NIL)
 
1843
 
 
1844
static void printslashstring(scheme *sc, char *p, int len) {
 
1845
  int i;
 
1846
  gunichar c;
 
1847
  char *s=(char*)p;
 
1848
 
 
1849
  putcharacter(sc,'"');
 
1850
  for (i=0; i<len; i++) {
 
1851
    c = g_utf8_get_char(s);
 
1852
    /* Is a check for a value of 0xff still valid in UTF8?? ~~~~~ */
 
1853
    if(c==0xff || c=='"' || c<' ' || c=='\\') {
 
1854
      putcharacter(sc,'\\');
 
1855
      switch(c) {
 
1856
      case '"':
 
1857
        putcharacter(sc,'"');
 
1858
        break;
 
1859
      case '\n':
 
1860
        putcharacter(sc,'n');
 
1861
        break;
 
1862
      case '\t':
 
1863
        putcharacter(sc,'t');
 
1864
        break;
 
1865
      case '\r':
 
1866
        putcharacter(sc,'r');
 
1867
        break;
 
1868
      case '\\':
 
1869
        putcharacter(sc,'\\');
 
1870
        break;
 
1871
      default: {
 
1872
          /* This still needs work ~~~~~ */
 
1873
          int d=c/16;
 
1874
          putcharacter(sc,'x');
 
1875
          if(d<10) {
 
1876
            putcharacter(sc,d+'0');
 
1877
          } else {
 
1878
            putcharacter(sc,d-10+'A');
 
1879
          }
 
1880
          d=c%16;
 
1881
          if(d<10) {
 
1882
            putcharacter(sc,d+'0');
 
1883
          } else {
 
1884
            putcharacter(sc,d-10+'A');
 
1885
          }
 
1886
        }
 
1887
      }
 
1888
    } else {
 
1889
      putcharacter(sc,c);
 
1890
    }
 
1891
    s = g_utf8_next_char(s);
 
1892
  }
 
1893
  putcharacter(sc,'"');
 
1894
}
 
1895
 
 
1896
 
 
1897
/* print atoms */
 
1898
static void printatom(scheme *sc, pointer l, int f) {
 
1899
  char *p;
 
1900
  int len;
 
1901
  atom2str(sc,l,f,&p,&len);
 
1902
  putchars(sc,p,len);
 
1903
}
 
1904
 
 
1905
 
 
1906
/* Uses internal buffer unless string pointer is already available */
 
1907
static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen) {
 
1908
     char *p;
 
1909
 
 
1910
     if (l == sc->NIL) {
 
1911
          p = "()";
 
1912
     } else if (l == sc->T) {
 
1913
          p = "#t";
 
1914
     } else if (l == sc->F) {
 
1915
          p = "#f";
 
1916
     } else if (l == sc->EOF_OBJ) {
 
1917
          p = "#<EOF>";
 
1918
     } else if (is_port(l)) {
 
1919
          p = sc->strbuff;
 
1920
          strcpy(p, "#<PORT>");
 
1921
     } else if (is_number(l)) {
 
1922
          p = sc->strbuff;
 
1923
          if(is_integer(l)) {
 
1924
               sprintf(p, "%ld", ivalue_unchecked(l));
 
1925
          } else {
 
1926
               g_ascii_formatd (p, sizeof (sc->strbuff), "%.10g",
 
1927
                                rvalue_unchecked(l));
 
1928
          }
 
1929
     } else if (is_string(l)) {
 
1930
          if (!f) {
 
1931
               p = strvalue(l);
 
1932
          } else { /* Hack, uses the fact that printing is needed */
 
1933
               *pp=sc->strbuff;
 
1934
               *plen=0;
 
1935
               printslashstring(sc, strvalue(l),
 
1936
                                g_utf8_strlen(strvalue(l), -1));
 
1937
               return;
 
1938
          }
 
1939
     } else if (is_character(l)) {
 
1940
          gunichar c=charvalue(l);
 
1941
          p = sc->strbuff;
 
1942
          if (!f) {
 
1943
               int len = g_unichar_to_utf8(c, p);
 
1944
               p[len]=0;
 
1945
          } else {
 
1946
               switch(c) {
 
1947
               case ' ':
 
1948
                    sprintf(p,"#\\space"); break;
 
1949
               case '\n':
 
1950
                    sprintf(p,"#\\newline"); break;
 
1951
               case '\r':
 
1952
                    sprintf(p,"#\\return"); break;
 
1953
               case '\t':
 
1954
                    sprintf(p,"#\\tab"); break;
 
1955
               default:
 
1956
#if USE_ASCII_NAMES
 
1957
                    if(c==127) {
 
1958
                         strcpy(p,"#\\del"); break;
 
1959
                    } else if(c<32) {
 
1960
                         strcpy(p,"#\\"); strcat(p,charnames[c]); break;
 
1961
                    }
 
1962
#else
 
1963
                    if(c<32) {
 
1964
                      sprintf(p,"#\\x%x",c); break;
 
1965
                    }
 
1966
#endif
 
1967
                    sprintf(p,"#\\%c",c); break;
 
1968
               }
 
1969
          }
 
1970
     } else if (is_symbol(l)) {
 
1971
          p = symname(l);
 
1972
     } else if (is_proc(l)) {
 
1973
          p = sc->strbuff;
 
1974
          sprintf(p, "#<%s PROCEDURE %ld>", procname(l),procnum(l));
 
1975
     } else if (is_macro(l)) {
 
1976
          p = "#<MACRO>";
 
1977
     } else if (is_closure(l)) {
 
1978
          p = "#<CLOSURE>";
 
1979
     } else if (is_promise(l)) {
 
1980
          p = "#<PROMISE>";
 
1981
     } else if (is_foreign(l)) {
 
1982
          p = sc->strbuff;
 
1983
          sprintf(p, "#<FOREIGN PROCEDURE %ld>", procnum(l));
 
1984
     } else if (is_continuation(l)) {
 
1985
          p = "#<CONTINUATION>";
 
1986
     } else {
 
1987
          p = "#<ERROR>";
 
1988
     }
 
1989
     *pp=p;
 
1990
     *plen=g_utf8_strlen(p, -1);
 
1991
}
 
1992
/* ========== Routines for Evaluation Cycle ========== */
 
1993
 
 
1994
/* make closure. c is code. e is environment */
 
1995
static pointer mk_closure(scheme *sc, pointer c, pointer e) {
 
1996
     pointer x = get_cell(sc, c, e);
 
1997
 
 
1998
     typeflag(x) = T_CLOSURE;
 
1999
     car(x) = c;
 
2000
     cdr(x) = e;
 
2001
     return (x);
 
2002
}
 
2003
 
 
2004
/* make continuation. */
 
2005
static pointer mk_continuation(scheme *sc, pointer d) {
 
2006
     pointer x = get_cell(sc, sc->NIL, d);
 
2007
 
 
2008
     typeflag(x) = T_CONTINUATION;
 
2009
     cont_dump(x) = d;
 
2010
     return (x);
 
2011
}
 
2012
 
 
2013
static pointer list_star(scheme *sc, pointer d) {
 
2014
  pointer p, q;
 
2015
  if(cdr(d)==sc->NIL) {
 
2016
    return car(d);
 
2017
  }
 
2018
  p=cons(sc,car(d),cdr(d));
 
2019
  q=p;
 
2020
  while(cdr(cdr(p))!=sc->NIL) {
 
2021
    d=cons(sc,car(p),cdr(p));
 
2022
    if(cdr(cdr(p))!=sc->NIL) {
 
2023
      p=cdr(d);
 
2024
    }
 
2025
  }
 
2026
  cdr(p)=car(cdr(p));
 
2027
  return q;
 
2028
}
 
2029
 
 
2030
/* reverse list -- produce new list */
 
2031
static pointer reverse(scheme *sc, pointer a) {
 
2032
/* a must be checked by gc */
 
2033
     pointer p = sc->NIL;
 
2034
 
 
2035
     for ( ; is_pair(a); a = cdr(a)) {
 
2036
          p = cons(sc, car(a), p);
 
2037
     }
 
2038
     return (p);
 
2039
}
 
2040
 
 
2041
/* reverse list --- in-place */
 
2042
static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
 
2043
     pointer p = list, result = term, q;
 
2044
 
 
2045
     while (p != sc->NIL) {
 
2046
          q = cdr(p);
 
2047
          cdr(p) = result;
 
2048
          result = p;
 
2049
          p = q;
 
2050
     }
 
2051
     return (result);
 
2052
}
 
2053
 
 
2054
/* append list -- produce new list */
 
2055
static pointer append(scheme *sc, pointer a, pointer b) {
 
2056
     pointer p = b, q;
 
2057
 
 
2058
     if (a != sc->NIL) {
 
2059
          a = reverse(sc, a);
 
2060
          while (a != sc->NIL) {
 
2061
               q = cdr(a);
 
2062
               cdr(a) = p;
 
2063
               p = a;
 
2064
               a = q;
 
2065
          }
 
2066
     }
 
2067
     return (p);
 
2068
}
 
2069
 
 
2070
/* equivalence of atoms */
 
2071
static int eqv(pointer a, pointer b) {
 
2072
     if (is_string(a)) {
 
2073
          if (is_string(b))
 
2074
               return (strvalue(a) == strvalue(b));
 
2075
          else
 
2076
               return (0);
 
2077
     } else if (is_number(a)) {
 
2078
          if (is_number(b))
 
2079
               return num_eq(nvalue(a),nvalue(b));
 
2080
          else
 
2081
               return (0);
 
2082
     } else if (is_character(a)) {
 
2083
          if (is_character(b))
 
2084
               return charvalue(a)==charvalue(b);
 
2085
          else
 
2086
               return (0);
 
2087
     } else if (is_port(a)) {
 
2088
          if (is_port(b))
 
2089
               return a==b;
 
2090
          else
 
2091
               return (0);
 
2092
     } else if (is_proc(a)) {
 
2093
          if (is_proc(b))
 
2094
               return procnum(a)==procnum(b);
 
2095
          else
 
2096
               return (0);
 
2097
     } else {
 
2098
          return (a == b);
 
2099
     }
 
2100
}
 
2101
 
 
2102
/* true or false value macro */
 
2103
/* () is #t in R5RS */
 
2104
#define is_true(p)       ((p) != sc->F)
 
2105
#define is_false(p)      ((p) == sc->F)
 
2106
 
 
2107
/* ========== Environment implementation  ========== */
 
2108
 
 
2109
#if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
 
2110
 
 
2111
#ifdef __GNUC__
 
2112
#warning FIXME: Update hash_fn() to handle UTF-8 coded keys
 
2113
#endif
 
2114
static int hash_fn(const char *key, int table_size)
 
2115
{
 
2116
  unsigned int hashed = 0;
 
2117
  const char *c;
 
2118
  int bits_per_int = sizeof(unsigned int)*8;
 
2119
 
 
2120
  for (c = key; *c; c++) {
 
2121
    /* letters have about 5 bits in them */
 
2122
    hashed = (hashed<<5) | (hashed>>(bits_per_int-5));
 
2123
    hashed ^= *c;
 
2124
  }
 
2125
  return hashed % table_size;
 
2126
}
 
2127
#endif
 
2128
 
 
2129
#ifndef USE_ALIST_ENV
 
2130
 
 
2131
/*
 
2132
 * In this implementation, each frame of the environment may be
 
2133
 * a hash table: a vector of alists hashed by variable name.
 
2134
 * In practice, we use a vector only for the initial frame;
 
2135
 * subsequent frames are too small and transient for the lookup
 
2136
 * speed to out-weigh the cost of making a new vector.
 
2137
 */
 
2138
 
 
2139
static void new_frame_in_env(scheme *sc, pointer old_env)
 
2140
{
 
2141
  pointer new_frame;
 
2142
 
 
2143
  /* The interaction-environment has about 300 variables in it. */
 
2144
  if (old_env == sc->NIL) {
 
2145
    new_frame = mk_vector(sc, 461);
 
2146
  } else {
 
2147
    new_frame = sc->NIL;
 
2148
  }
 
2149
 
 
2150
  sc->envir = immutable_cons(sc, new_frame, old_env);
 
2151
  setenvironment(sc->envir);
 
2152
}
 
2153
 
 
2154
static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
 
2155
                                        pointer variable, pointer value)
 
2156
{
 
2157
  pointer slot = immutable_cons(sc, variable, value);
 
2158
 
 
2159
  if (is_vector(car(env))) {
 
2160
    int location = hash_fn(symname(variable), ivalue_unchecked(car(env)));
 
2161
 
 
2162
    set_vector_elem(car(env), location,
 
2163
                    immutable_cons(sc, slot, vector_elem(car(env), location)));
 
2164
  } else {
 
2165
    car(env) = immutable_cons(sc, slot, car(env));
 
2166
  }
 
2167
}
 
2168
 
 
2169
static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
 
2170
{
 
2171
  pointer x,y;
 
2172
  int location;
 
2173
 
 
2174
  for (x = env; x != sc->NIL; x = cdr(x)) {
 
2175
    if (is_vector(car(x))) {
 
2176
      location = hash_fn(symname(hdl), ivalue_unchecked(car(x)));
 
2177
      y = vector_elem(car(x), location);
 
2178
    } else {
 
2179
      y = car(x);
 
2180
    }
 
2181
    for ( ; y != sc->NIL; y = cdr(y)) {
 
2182
              if (caar(y) == hdl) {
 
2183
                   break;
 
2184
              }
 
2185
         }
 
2186
         if (y != sc->NIL) {
 
2187
              break;
 
2188
         }
 
2189
         if(!all) {
 
2190
           return sc->NIL;
 
2191
         }
 
2192
    }
 
2193
    if (x != sc->NIL) {
 
2194
          return car(y);
 
2195
    }
 
2196
    return sc->NIL;
 
2197
}
 
2198
 
 
2199
#else /* USE_ALIST_ENV */
 
2200
 
 
2201
static INLINE void new_frame_in_env(scheme *sc, pointer old_env)
 
2202
{
 
2203
  sc->envir = immutable_cons(sc, sc->NIL, old_env);
 
2204
  setenvironment(sc->envir);
 
2205
}
 
2206
 
 
2207
static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
 
2208
                                        pointer variable, pointer value)
 
2209
{
 
2210
  car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env));
 
2211
}
 
2212
 
 
2213
static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
 
2214
{
 
2215
    pointer x,y;
 
2216
    for (x = env; x != sc->NIL; x = cdr(x)) {
 
2217
         for (y = car(x); y != sc->NIL; y = cdr(y)) {
 
2218
              if (caar(y) == hdl) {
 
2219
                   break;
 
2220
              }
 
2221
         }
 
2222
         if (y != sc->NIL) {
 
2223
              break;
 
2224
         }
 
2225
         if(!all) {
 
2226
           return sc->NIL;
 
2227
         }
 
2228
    }
 
2229
    if (x != sc->NIL) {
 
2230
          return car(y);
 
2231
    }
 
2232
    return sc->NIL;
 
2233
}
 
2234
 
 
2235
#endif /* USE_ALIST_ENV else */
 
2236
 
 
2237
static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value)
 
2238
{
 
2239
  new_slot_spec_in_env(sc, sc->envir, variable, value);
 
2240
}
 
2241
 
 
2242
static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value)
 
2243
{
 
2244
  cdr(slot) = value;
 
2245
}
 
2246
 
 
2247
static INLINE pointer slot_value_in_env(pointer slot)
 
2248
{
 
2249
  return cdr(slot);
 
2250
}
 
2251
 
 
2252
/* ========== Evaluation Cycle ========== */
 
2253
 
 
2254
 
 
2255
static pointer _Error_1(scheme *sc, const char *s, pointer a) {
 
2256
#if USE_ERROR_HOOK
 
2257
     pointer x;
 
2258
     pointer hdl=sc->ERROR_HOOK;
 
2259
 
 
2260
     x=find_slot_in_env(sc,sc->envir,hdl,1);
 
2261
    if (x != sc->NIL) {
 
2262
         if(a!=0) {
 
2263
               sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL);
 
2264
         } else {
 
2265
               sc->code = sc->NIL;
 
2266
         }
 
2267
         sc->code = cons(sc, mk_string(sc, (s)), sc->code);
 
2268
         setimmutable(car(sc->code));
 
2269
         sc->code = cons(sc, slot_value_in_env(x), sc->code);
 
2270
         sc->op = (int)OP_EVAL;
 
2271
         return sc->T;
 
2272
    }
 
2273
#endif
 
2274
 
 
2275
    if(a!=0) {
 
2276
          sc->args = cons(sc, (a), sc->NIL);
 
2277
    } else {
 
2278
          sc->args = sc->NIL;
 
2279
    }
 
2280
    sc->args = cons(sc, mk_string(sc, (s)), sc->args);
 
2281
    setimmutable(car(sc->args));
 
2282
    sc->op = (int)OP_ERR0;
 
2283
    return sc->T;
 
2284
}
 
2285
#define Error_1(sc,s,a)  return _Error_1(sc,s,a)
 
2286
#define Error_0(sc,s)    return _Error_1(sc,s,0)
 
2287
 
 
2288
/* Too small to turn into function */
 
2289
# define  BEGIN     do {
 
2290
# define  END  } while (0)
 
2291
#define s_goto(sc,a) BEGIN                                  \
 
2292
    sc->op = (int)(a);                                      \
 
2293
    return sc->T; END
 
2294
 
 
2295
#define s_return(sc,a) return _s_return(sc,a)
 
2296
 
 
2297
#ifndef USE_SCHEME_STACK
 
2298
 
 
2299
/* this structure holds all the interpreter's registers */
 
2300
struct dump_stack_frame {
 
2301
  enum scheme_opcodes op;
 
2302
  pointer args;
 
2303
  pointer envir;
 
2304
  pointer code;
 
2305
};
 
2306
 
 
2307
#define STACK_GROWTH 3
 
2308
 
 
2309
static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code)
 
2310
{
 
2311
  int nframes = (int)sc->dump;
 
2312
  struct dump_stack_frame *next_frame;
 
2313
 
 
2314
  /* enough room for the next frame? */
 
2315
  if (nframes >= sc->dump_size) {
 
2316
    sc->dump_size += STACK_GROWTH;
 
2317
    /* alas there is no sc->realloc */
 
2318
    sc->dump_base = realloc(sc->dump_base,
 
2319
                            sizeof(struct dump_stack_frame) * sc->dump_size);
 
2320
  }
 
2321
  next_frame = (struct dump_stack_frame *)sc->dump_base + nframes;
 
2322
  next_frame->op = op;
 
2323
  next_frame->args = args;
 
2324
  next_frame->envir = sc->envir;
 
2325
  next_frame->code = code;
 
2326
  sc->dump = (pointer)(nframes+1);
 
2327
}
 
2328
 
 
2329
static pointer _s_return(scheme *sc, pointer a)
 
2330
{
 
2331
  int nframes = (int)sc->dump;
 
2332
  struct dump_stack_frame *frame;
 
2333
 
 
2334
  sc->value = (a);
 
2335
  if (nframes <= 0) {
 
2336
    return sc->NIL;
 
2337
  }
 
2338
  nframes--;
 
2339
  frame = (struct dump_stack_frame *)sc->dump_base + nframes;
 
2340
  sc->op = frame->op;
 
2341
  sc->args = frame->args;
 
2342
  sc->envir = frame->envir;
 
2343
  sc->code = frame->code;
 
2344
  sc->dump = (pointer)nframes;
 
2345
  return sc->T;
 
2346
}
 
2347
 
 
2348
static INLINE void dump_stack_reset(scheme *sc)
 
2349
{
 
2350
  /* in this implementation, sc->dump is the number of frames on the stack */
 
2351
  sc->dump = (pointer)0;
 
2352
}
 
2353
 
 
2354
static INLINE void dump_stack_initialize(scheme *sc)
 
2355
{
 
2356
  sc->dump_size = 0;
 
2357
  sc->dump_base = NULL;
 
2358
  dump_stack_reset(sc);
 
2359
}
 
2360
 
 
2361
static void dump_stack_free(scheme *sc)
 
2362
{
 
2363
  free(sc->dump_base);
 
2364
  sc->dump_base = NULL;
 
2365
  sc->dump = (pointer)0;
 
2366
  sc->dump_size = 0;
 
2367
}
 
2368
 
 
2369
static INLINE void dump_stack_mark(scheme *sc)
 
2370
{
 
2371
  int nframes = (int)sc->dump;
 
2372
  int i;
 
2373
  for(i=0; i<nframes; i++) {
 
2374
    struct dump_stack_frame *frame;
 
2375
    frame = (struct dump_stack_frame *)sc->dump_base + i;
 
2376
    mark(frame->args);
 
2377
    mark(frame->envir);
 
2378
    mark(frame->code);
 
2379
  }
 
2380
}
 
2381
 
 
2382
#else
 
2383
 
 
2384
static INLINE void dump_stack_reset(scheme *sc)
 
2385
{
 
2386
  sc->dump = sc->NIL;
 
2387
}
 
2388
 
 
2389
static INLINE void dump_stack_initialize(scheme *sc)
 
2390
{
 
2391
  dump_stack_reset(sc);
 
2392
}
 
2393
 
 
2394
static void dump_stack_free(scheme *sc)
 
2395
{
 
2396
  sc->dump = sc->NIL;
 
2397
}
 
2398
 
 
2399
static pointer _s_return(scheme *sc, pointer a) {
 
2400
    sc->value = (a);
 
2401
    if(sc->dump==sc->NIL) return sc->NIL;
 
2402
    sc->op = ivalue(car(sc->dump));
 
2403
    sc->args = cadr(sc->dump);
 
2404
    sc->envir = caddr(sc->dump);
 
2405
    sc->code = cadddr(sc->dump);
 
2406
    sc->dump = cddddr(sc->dump);
 
2407
    return sc->T;
 
2408
}
 
2409
 
 
2410
static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
 
2411
    sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump));
 
2412
    sc->dump = cons(sc, (args), sc->dump);
 
2413
    sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump);
 
2414
}
 
2415
 
 
2416
static INLINE void dump_stack_mark(scheme *sc)
 
2417
{
 
2418
  mark(sc->dump);
 
2419
}
 
2420
#endif
 
2421
 
 
2422
#define s_retbool(tf)    s_return(sc,(tf) ? sc->T : sc->F)
 
2423
 
 
2424
static pointer opexe_0(scheme *sc, enum scheme_opcodes op) {
 
2425
     pointer x, y;
 
2426
 
 
2427
     switch (op) {
 
2428
     case OP_LOAD:       /* load */
 
2429
          if(file_interactive(sc)) {
 
2430
               fprintf(sc->outport->_object._port->rep.stdio.file,
 
2431
                       "Loading %s\n", strvalue(car(sc->args)));
 
2432
          }
 
2433
          if (!file_push(sc,strvalue(car(sc->args)))) {
 
2434
               Error_1(sc,"unable to open", car(sc->args));
 
2435
          }
 
2436
          s_goto(sc,OP_T0LVL);
 
2437
 
 
2438
     case OP_T0LVL: /* top level */
 
2439
          if(file_interactive(sc)) {
 
2440
               putstr(sc,"\n");
 
2441
          }
 
2442
          sc->nesting=0;
 
2443
          dump_stack_reset(sc);
 
2444
          sc->envir = sc->global_env;
 
2445
          sc->save_inport=sc->inport;
 
2446
          sc->inport = sc->loadport;
 
2447
          s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
 
2448
          s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
 
2449
          s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
 
2450
          if (file_interactive(sc)) {
 
2451
              putstr(sc,prompt);
 
2452
          }
 
2453
          s_goto(sc,OP_READ_INTERNAL);
 
2454
 
 
2455
     case OP_T1LVL: /* top level */
 
2456
          sc->code = sc->value;
 
2457
          sc->inport=sc->save_inport;
 
2458
          s_goto(sc,OP_EVAL);
 
2459
 
 
2460
     case OP_READ_INTERNAL:       /* internal read */
 
2461
          sc->tok = token(sc);
 
2462
          if(sc->tok==TOK_EOF) {
 
2463
               if(sc->inport==sc->loadport) {
 
2464
                    sc->args=sc->NIL;
 
2465
                    s_goto(sc,OP_QUIT);
 
2466
               } else {
 
2467
                    s_return(sc,sc->EOF_OBJ);
 
2468
               }
 
2469
          }
 
2470
          s_goto(sc,OP_RDSEXPR);
 
2471
 
 
2472
     case OP_GENSYM:
 
2473
          s_return(sc, gensym(sc));
 
2474
 
 
2475
     case OP_VALUEPRINT: /* print evaluation result */
 
2476
          /* OP_VALUEPRINT is always pushed, because when changing from
 
2477
             non-interactive to interactive mode, it needs to be
 
2478
             already on the stack */
 
2479
       if(sc->tracing) {
 
2480
         putstr(sc,"\nGives: ");
 
2481
       }
 
2482
       if(file_interactive(sc) || sc->print_output) {
 
2483
         sc->print_flag = 1;
 
2484
         sc->args = sc->value;
 
2485
         s_goto(sc,OP_P0LIST);
 
2486
       } else {
 
2487
         s_return(sc,sc->value);
 
2488
       }
 
2489
 
 
2490
     case OP_EVAL:       /* main part of evaluation */
 
2491
#if USE_TRACING
 
2492
       if(sc->tracing) {
 
2493
         /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
 
2494
         s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
 
2495
         sc->args=sc->code;
 
2496
         putstr(sc,"\nEval: ");
 
2497
         s_goto(sc,OP_P0LIST);
 
2498
       }
 
2499
       /* fall through */
 
2500
     case OP_REAL_EVAL:
 
2501
#endif
 
2502
          if (is_symbol(sc->code)) {    /* symbol */
 
2503
               x=find_slot_in_env(sc,sc->envir,sc->code,1);
 
2504
               if (x != sc->NIL) {
 
2505
                    s_return(sc,slot_value_in_env(x));
 
2506
               } else {
 
2507
                    Error_1(sc,"eval: unbound variable:", sc->code);
 
2508
               }
 
2509
          } else if (is_pair(sc->code)) {
 
2510
               if (is_syntax(x = car(sc->code))) {     /* SYNTAX */
 
2511
                    sc->code = cdr(sc->code);
 
2512
                    s_goto(sc,syntaxnum(x));
 
2513
               } else {/* first, eval top element and eval arguments */
 
2514
                    s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
 
2515
                    /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
 
2516
                    sc->code = car(sc->code);
 
2517
                    s_goto(sc,OP_EVAL);
 
2518
               }
 
2519
          } else {
 
2520
               s_return(sc,sc->code);
 
2521
          }
 
2522
 
 
2523
     case OP_E0ARGS:     /* eval arguments */
 
2524
          if (is_macro(sc->value)) {    /* macro expansion */
 
2525
               s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
 
2526
               sc->args = cons(sc,sc->code, sc->NIL);
 
2527
               sc->code = sc->value;
 
2528
               s_goto(sc,OP_APPLY);
 
2529
          } else {
 
2530
               sc->code = cdr(sc->code);
 
2531
               s_goto(sc,OP_E1ARGS);
 
2532
          }
 
2533
 
 
2534
     case OP_E1ARGS:     /* eval arguments */
 
2535
          sc->args = cons(sc, sc->value, sc->args);
 
2536
          if (is_pair(sc->code)) { /* continue */
 
2537
               s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
 
2538
               sc->code = car(sc->code);
 
2539
               sc->args = sc->NIL;
 
2540
               s_goto(sc,OP_EVAL);
 
2541
          } else {  /* end */
 
2542
               sc->args = reverse_in_place(sc, sc->NIL, sc->args);
 
2543
               sc->code = car(sc->args);
 
2544
               sc->args = cdr(sc->args);
 
2545
               s_goto(sc,OP_APPLY);
 
2546
          }
 
2547
 
 
2548
#if USE_TRACING
 
2549
     case OP_TRACING: {
 
2550
       int tr=sc->tracing;
 
2551
       sc->tracing=ivalue(car(sc->args));
 
2552
       s_return(sc,mk_integer(sc,tr));
 
2553
     }
 
2554
#endif
 
2555
 
 
2556
     case OP_APPLY:      /* apply 'code' to 'args' */
 
2557
#if USE_TRACING
 
2558
       if(sc->tracing) {
 
2559
         s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
 
2560
         sc->print_flag = 1;
 
2561
         /*         sc->args=cons(sc,sc->code,sc->args);*/
 
2562
         putstr(sc,"\nApply to: ");
 
2563
         s_goto(sc,OP_P0LIST);
 
2564
       }
 
2565
       /* fall through */
 
2566
     case OP_REAL_APPLY:
 
2567
#endif
 
2568
          if (is_proc(sc->code)) {
 
2569
               s_goto(sc,procnum(sc->code));   /* PROCEDURE */
 
2570
          } else if (is_foreign(sc->code)) {
 
2571
               sc->safe_foreign = cons (sc, sc->NIL, sc->safe_foreign);
 
2572
               x=sc->code->_object._ff(sc,sc->args);
 
2573
               sc->safe_foreign = cdr (sc->safe_foreign);
 
2574
               s_return(sc,x);
 
2575
          } else if (is_closure(sc->code) || is_macro(sc->code)
 
2576
                     || is_promise(sc->code)) { /* CLOSURE */
 
2577
            /* Should not accept promise */
 
2578
               /* make environment */
 
2579
               new_frame_in_env(sc, closure_env(sc->code));
 
2580
               for (x = car(closure_code(sc->code)), y = sc->args;
 
2581
                    is_pair(x); x = cdr(x), y = cdr(y)) {
 
2582
                    if (y == sc->NIL) {
 
2583
                         Error_0(sc,"not enough arguments");
 
2584
                    } else {
 
2585
                         new_slot_in_env(sc, car(x), car(y));
 
2586
                    }
 
2587
               }
 
2588
               if (x == sc->NIL) {
 
2589
                    /*--
 
2590
                     * if (y != sc->NIL) {
 
2591
                     *   Error_0(sc,"too many arguments");
 
2592
                     * }
 
2593
                     */
 
2594
               } else if (is_symbol(x))
 
2595
                    new_slot_in_env(sc, x, y);
 
2596
               else {
 
2597
                    Error_1(sc,"syntax error in closure: not a symbol:", x);
 
2598
               }
 
2599
               sc->code = cdr(closure_code(sc->code));
 
2600
               sc->args = sc->NIL;
 
2601
               s_goto(sc,OP_BEGIN);
 
2602
          } else if (is_continuation(sc->code)) { /* CONTINUATION */
 
2603
               sc->dump = cont_dump(sc->code);
 
2604
               s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
 
2605
          } else {
 
2606
               Error_0(sc,"illegal function");
 
2607
          }
 
2608
 
 
2609
     case OP_DOMACRO:    /* do macro */
 
2610
          sc->code = sc->value;
 
2611
          s_goto(sc,OP_EVAL);
 
2612
 
 
2613
     case OP_LAMBDA:     /* lambda */
 
2614
          s_return(sc,mk_closure(sc, sc->code, sc->envir));
 
2615
 
 
2616
     case OP_MKCLOSURE: /* make-closure */
 
2617
       x=car(sc->args);
 
2618
       if(car(x)==sc->LAMBDA) {
 
2619
         x=cdr(x);
 
2620
       }
 
2621
       if(cdr(sc->args)==sc->NIL) {
 
2622
         y=sc->envir;
 
2623
       } else {
 
2624
         y=cadr(sc->args);
 
2625
       }
 
2626
       s_return(sc,mk_closure(sc, x, y));
 
2627
 
 
2628
     case OP_QUOTE:      /* quote */
 
2629
          x=car(sc->code);
 
2630
          s_return(sc,car(sc->code));
 
2631
 
 
2632
     case OP_DEF0:  /* define */
 
2633
          if(is_immutable(car(sc->code)))
 
2634
                Error_1(sc,"define: unable to alter immutable", car(sc->code));
 
2635
          if (is_pair(car(sc->code))) {
 
2636
               x = caar(sc->code);
 
2637
               sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
 
2638
          } else {
 
2639
               x = car(sc->code);
 
2640
               sc->code = cadr(sc->code);
 
2641
          }
 
2642
          if (!is_symbol(x)) {
 
2643
               Error_0(sc,"variable is not a symbol");
 
2644
          }
 
2645
          s_save(sc,OP_DEF1, sc->NIL, x);
 
2646
          s_goto(sc,OP_EVAL);
 
2647
 
 
2648
     case OP_DEF1:  /* define */
 
2649
       x=find_slot_in_env(sc,sc->envir,sc->code,0);
 
2650
          if (x != sc->NIL) {
 
2651
               set_slot_in_env(sc, x, sc->value);
 
2652
          } else {
 
2653
               new_slot_in_env(sc, sc->code, sc->value);
 
2654
          }
 
2655
          s_return(sc,sc->code);
 
2656
 
 
2657
 
 
2658
     case OP_DEFP:  /* defined? */
 
2659
          x=sc->envir;
 
2660
          if(cdr(sc->args)!=sc->NIL) {
 
2661
               x=cadr(sc->args);
 
2662
          }
 
2663
          s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
 
2664
 
 
2665
     case OP_SET0:       /* set! */
 
2666
          if(is_immutable(car(sc->code)))
 
2667
                Error_1(sc,"set!: unable to alter immutable variable", car(sc->code));
 
2668
          s_save(sc,OP_SET1, sc->NIL, car(sc->code));
 
2669
          sc->code = cadr(sc->code);
 
2670
          s_goto(sc,OP_EVAL);
 
2671
 
 
2672
     case OP_SET1:       /* set! */
 
2673
          y=find_slot_in_env(sc,sc->envir,sc->code,1);
 
2674
          if (y != sc->NIL) {
 
2675
             set_slot_in_env(sc, y, sc->value);
 
2676
             s_return(sc,sc->value);
 
2677
          } else {
 
2678
             Error_1(sc,"set!: unbound variable:", sc->code);
 
2679
          }
 
2680
 
 
2681
     case OP_BEGIN:      /* begin */
 
2682
          if (!is_pair(sc->code)) {
 
2683
               s_return(sc,sc->code);
 
2684
          }
 
2685
          if (cdr(sc->code) != sc->NIL) {
 
2686
               s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
 
2687
          }
 
2688
          sc->code = car(sc->code);
 
2689
          s_goto(sc,OP_EVAL);
 
2690
 
 
2691
     case OP_IF0:        /* if */
 
2692
          s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
 
2693
          sc->code = car(sc->code);
 
2694
          s_goto(sc,OP_EVAL);
 
2695
 
 
2696
     case OP_IF1:        /* if */
 
2697
          if (is_true(sc->value))
 
2698
               sc->code = car(sc->code);
 
2699
          else
 
2700
               sc->code = cadr(sc->code);  /* (if #f 1) ==> () because
 
2701
                               * car(sc->NIL) = sc->NIL */
 
2702
          s_goto(sc,OP_EVAL);
 
2703
 
 
2704
     case OP_LET0:       /* let */
 
2705
          sc->args = sc->NIL;
 
2706
          sc->value = sc->code;
 
2707
          sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
 
2708
          s_goto(sc,OP_LET1);
 
2709
 
 
2710
     case OP_LET1:       /* let (calculate parameters) */
 
2711
          sc->args = cons(sc, sc->value, sc->args);
 
2712
          if (is_pair(sc->code)) { /* continue */
 
2713
               s_save(sc,OP_LET1, sc->args, cdr(sc->code));
 
2714
               sc->code = cadar(sc->code);
 
2715
               sc->args = sc->NIL;
 
2716
               s_goto(sc,OP_EVAL);
 
2717
          } else {  /* end */
 
2718
               sc->args = reverse_in_place(sc, sc->NIL, sc->args);
 
2719
               sc->code = car(sc->args);
 
2720
               sc->args = cdr(sc->args);
 
2721
               s_goto(sc,OP_LET2);
 
2722
          }
 
2723
 
 
2724
     case OP_LET2:       /* let */
 
2725
          new_frame_in_env(sc, sc->envir);
 
2726
          for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
 
2727
               y != sc->NIL; x = cdr(x), y = cdr(y)) {
 
2728
               new_slot_in_env(sc, caar(x), car(y));
 
2729
          }
 
2730
          if (is_symbol(car(sc->code))) {    /* named let */
 
2731
               for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
 
2732
 
 
2733
                    sc->args = cons(sc, caar(x), sc->args);
 
2734
               }
 
2735
               x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir);
 
2736
               new_slot_in_env(sc, car(sc->code), x);
 
2737
               sc->code = cddr(sc->code);
 
2738
               sc->args = sc->NIL;
 
2739
          } else {
 
2740
               sc->code = cdr(sc->code);
 
2741
               sc->args = sc->NIL;
 
2742
          }
 
2743
          s_goto(sc,OP_BEGIN);
 
2744
 
 
2745
     case OP_LET0AST:    /* let* */
 
2746
          if (car(sc->code) == sc->NIL) {
 
2747
               new_frame_in_env(sc, sc->envir);
 
2748
               sc->code = cdr(sc->code);
 
2749
               s_goto(sc,OP_BEGIN);
 
2750
          }
 
2751
          s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
 
2752
          sc->code = cadaar(sc->code);
 
2753
          s_goto(sc,OP_EVAL);
 
2754
 
 
2755
     case OP_LET1AST:    /* let* (make new frame) */
 
2756
          new_frame_in_env(sc, sc->envir);
 
2757
          s_goto(sc,OP_LET2AST);
 
2758
 
 
2759
     case OP_LET2AST:    /* let* (calculate parameters) */
 
2760
          new_slot_in_env(sc, caar(sc->code), sc->value);
 
2761
          sc->code = cdr(sc->code);
 
2762
          if (is_pair(sc->code)) { /* continue */
 
2763
               s_save(sc,OP_LET2AST, sc->args, sc->code);
 
2764
               sc->code = cadar(sc->code);
 
2765
               sc->args = sc->NIL;
 
2766
               s_goto(sc,OP_EVAL);
 
2767
          } else {  /* end */
 
2768
               sc->code = sc->args;
 
2769
               sc->args = sc->NIL;
 
2770
               s_goto(sc,OP_BEGIN);
 
2771
          }
 
2772
     default:
 
2773
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
2774
          Error_0(sc,sc->strbuff);
 
2775
     }
 
2776
     return sc->T;
 
2777
}
 
2778
 
 
2779
static pointer opexe_1(scheme *sc, enum scheme_opcodes op) {
 
2780
     pointer x, y;
 
2781
 
 
2782
     switch (op) {
 
2783
     case OP_LET0REC:    /* letrec */
 
2784
          new_frame_in_env(sc, sc->envir);
 
2785
          sc->args = sc->NIL;
 
2786
          sc->value = sc->code;
 
2787
          sc->code = car(sc->code);
 
2788
          s_goto(sc,OP_LET1REC);
 
2789
 
 
2790
     case OP_LET1REC:    /* letrec (calculate parameters) */
 
2791
          sc->args = cons(sc, sc->value, sc->args);
 
2792
          if (is_pair(sc->code)) { /* continue */
 
2793
               s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
 
2794
               sc->code = cadar(sc->code);
 
2795
               sc->args = sc->NIL;
 
2796
               s_goto(sc,OP_EVAL);
 
2797
          } else {  /* end */
 
2798
               sc->args = reverse_in_place(sc, sc->NIL, sc->args);
 
2799
               sc->code = car(sc->args);
 
2800
               sc->args = cdr(sc->args);
 
2801
               s_goto(sc,OP_LET2REC);
 
2802
          }
 
2803
 
 
2804
     case OP_LET2REC:    /* letrec */
 
2805
          for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
 
2806
               new_slot_in_env(sc, caar(x), car(y));
 
2807
          }
 
2808
          sc->code = cdr(sc->code);
 
2809
          sc->args = sc->NIL;
 
2810
          s_goto(sc,OP_BEGIN);
 
2811
 
 
2812
     case OP_COND0:      /* cond */
 
2813
          if (!is_pair(sc->code)) {
 
2814
               Error_0(sc,"syntax error in cond");
 
2815
          }
 
2816
          s_save(sc,OP_COND1, sc->NIL, sc->code);
 
2817
          sc->code = caar(sc->code);
 
2818
          s_goto(sc,OP_EVAL);
 
2819
 
 
2820
     case OP_COND1:      /* cond */
 
2821
          if (is_true(sc->value)) {
 
2822
               if ((sc->code = cdar(sc->code)) == sc->NIL) {
 
2823
                    s_return(sc,sc->value);
 
2824
               }
 
2825
               if(car(sc->code)==sc->FEED_TO) {
 
2826
                    if(!is_pair(cdr(sc->code))) {
 
2827
                         Error_0(sc,"syntax error in cond");
 
2828
                    }
 
2829
                    x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
 
2830
                    sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
 
2831
                    s_goto(sc,OP_EVAL);
 
2832
               }
 
2833
               s_goto(sc,OP_BEGIN);
 
2834
          } else {
 
2835
               if ((sc->code = cdr(sc->code)) == sc->NIL) {
 
2836
                    s_return(sc,sc->NIL);
 
2837
               } else {
 
2838
                    s_save(sc,OP_COND1, sc->NIL, sc->code);
 
2839
                    sc->code = caar(sc->code);
 
2840
                    s_goto(sc,OP_EVAL);
 
2841
               }
 
2842
          }
 
2843
 
 
2844
     case OP_DELAY:      /* delay */
 
2845
          x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
 
2846
          typeflag(x)=T_PROMISE;
 
2847
          s_return(sc,x);
 
2848
 
 
2849
     case OP_AND0:       /* and */
 
2850
          if (sc->code == sc->NIL) {
 
2851
               s_return(sc,sc->T);
 
2852
          }
 
2853
          s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
 
2854
          sc->code = car(sc->code);
 
2855
          s_goto(sc,OP_EVAL);
 
2856
 
 
2857
     case OP_AND1:       /* and */
 
2858
          if (is_false(sc->value)) {
 
2859
               s_return(sc,sc->value);
 
2860
          } else if (sc->code == sc->NIL) {
 
2861
               s_return(sc,sc->value);
 
2862
          } else {
 
2863
               s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
 
2864
               sc->code = car(sc->code);
 
2865
               s_goto(sc,OP_EVAL);
 
2866
          }
 
2867
 
 
2868
     case OP_OR0:        /* or */
 
2869
          if (sc->code == sc->NIL) {
 
2870
               s_return(sc,sc->F);
 
2871
          }
 
2872
          s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
 
2873
          sc->code = car(sc->code);
 
2874
          s_goto(sc,OP_EVAL);
 
2875
 
 
2876
     case OP_OR1:        /* or */
 
2877
          if (is_true(sc->value)) {
 
2878
               s_return(sc,sc->value);
 
2879
          } else if (sc->code == sc->NIL) {
 
2880
               s_return(sc,sc->value);
 
2881
          } else {
 
2882
               s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
 
2883
               sc->code = car(sc->code);
 
2884
               s_goto(sc,OP_EVAL);
 
2885
          }
 
2886
 
 
2887
     case OP_C0STREAM:   /* cons-stream */
 
2888
          s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
 
2889
          sc->code = car(sc->code);
 
2890
          s_goto(sc,OP_EVAL);
 
2891
 
 
2892
     case OP_C1STREAM:   /* cons-stream */
 
2893
          sc->args = sc->value;  /* save sc->value to register sc->args for gc */
 
2894
          x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
 
2895
          typeflag(x)=T_PROMISE;
 
2896
          s_return(sc,cons(sc, sc->args, x));
 
2897
 
 
2898
     case OP_MACRO0:     /* macro */
 
2899
          if (is_pair(car(sc->code))) {
 
2900
               x = caar(sc->code);
 
2901
               sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
 
2902
          } else {
 
2903
               x = car(sc->code);
 
2904
               sc->code = cadr(sc->code);
 
2905
          }
 
2906
          if (!is_symbol(x)) {
 
2907
               Error_0(sc,"variable is not a symbol");
 
2908
          }
 
2909
          s_save(sc,OP_MACRO1, sc->NIL, x);
 
2910
          s_goto(sc,OP_EVAL);
 
2911
 
 
2912
     case OP_MACRO1:     /* macro */
 
2913
          typeflag(sc->value) = T_MACRO;
 
2914
          x = find_slot_in_env(sc, sc->envir, sc->code, 0);
 
2915
          if (x != sc->NIL) {
 
2916
               set_slot_in_env(sc, x, sc->value);
 
2917
          } else {
 
2918
               new_slot_in_env(sc, sc->code, sc->value);
 
2919
          }
 
2920
          s_return(sc,sc->code);
 
2921
 
 
2922
     case OP_CASE0:      /* case */
 
2923
          s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
 
2924
          sc->code = car(sc->code);
 
2925
          s_goto(sc,OP_EVAL);
 
2926
 
 
2927
     case OP_CASE1:      /* case */
 
2928
          for (x = sc->code; x != sc->NIL; x = cdr(x)) {
 
2929
               if (!is_pair(y = caar(x))) {
 
2930
                    break;
 
2931
               }
 
2932
               for ( ; y != sc->NIL; y = cdr(y)) {
 
2933
                    if (eqv(car(y), sc->value)) {
 
2934
                         break;
 
2935
                    }
 
2936
               }
 
2937
               if (y != sc->NIL) {
 
2938
                    break;
 
2939
               }
 
2940
          }
 
2941
          if (x != sc->NIL) {
 
2942
               if (is_pair(caar(x))) {
 
2943
                    sc->code = cdar(x);
 
2944
                    s_goto(sc,OP_BEGIN);
 
2945
               } else {/* else */
 
2946
                    s_save(sc,OP_CASE2, sc->NIL, cdar(x));
 
2947
                    sc->code = caar(x);
 
2948
                    s_goto(sc,OP_EVAL);
 
2949
               }
 
2950
          } else {
 
2951
               s_return(sc,sc->NIL);
 
2952
          }
 
2953
 
 
2954
     case OP_CASE2:      /* case */
 
2955
          if (is_true(sc->value)) {
 
2956
               s_goto(sc,OP_BEGIN);
 
2957
          } else {
 
2958
               s_return(sc,sc->NIL);
 
2959
          }
 
2960
 
 
2961
     case OP_PAPPLY:     /* apply */
 
2962
          sc->code = car(sc->args);
 
2963
          sc->args = list_star(sc,cdr(sc->args));
 
2964
          /*sc->args = cadr(sc->args);*/
 
2965
          s_goto(sc,OP_APPLY);
 
2966
 
 
2967
     case OP_PEVAL: /* eval */
 
2968
          if(cdr(sc->args)!=sc->NIL) {
 
2969
               sc->envir=cadr(sc->args);
 
2970
          }
 
2971
          sc->code = car(sc->args);
 
2972
          s_goto(sc,OP_EVAL);
 
2973
 
 
2974
     case OP_CONTINUATION:    /* call-with-current-continuation */
 
2975
          sc->code = car(sc->args);
 
2976
          sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
 
2977
          s_goto(sc,OP_APPLY);
 
2978
 
 
2979
     default:
 
2980
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
2981
          Error_0(sc,sc->strbuff);
 
2982
     }
 
2983
     return sc->T;
 
2984
}
 
2985
 
 
2986
static pointer opexe_2(scheme *sc, enum scheme_opcodes op) {
 
2987
     pointer x;
 
2988
     num v;
 
2989
#if USE_MATH
 
2990
     double dd;
 
2991
#endif
 
2992
 
 
2993
     switch (op) {
 
2994
#if USE_MATH
 
2995
     case OP_INEX2EX:    /* inexact->exact */
 
2996
          x=car(sc->args);
 
2997
          if(is_integer(x)) {
 
2998
               s_return(sc,x);
 
2999
          } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
 
3000
               s_return(sc,mk_integer(sc,ivalue(x)));
 
3001
          } else {
 
3002
               Error_1(sc,"inexact->exact: not integral:",x);
 
3003
          }
 
3004
 
 
3005
     case OP_EXP:
 
3006
          x=car(sc->args);
 
3007
          s_return(sc, mk_real(sc, exp(rvalue(x))));
 
3008
 
 
3009
     case OP_LOG:
 
3010
          x=car(sc->args);
 
3011
          s_return(sc, mk_real(sc, log(rvalue(x))));
 
3012
 
 
3013
     case OP_SIN:
 
3014
          x=car(sc->args);
 
3015
          s_return(sc, mk_real(sc, sin(rvalue(x))));
 
3016
 
 
3017
     case OP_COS:
 
3018
          x=car(sc->args);
 
3019
          s_return(sc, mk_real(sc, cos(rvalue(x))));
 
3020
 
 
3021
     case OP_TAN:
 
3022
          x=car(sc->args);
 
3023
          s_return(sc, mk_real(sc, tan(rvalue(x))));
 
3024
 
 
3025
     case OP_ASIN:
 
3026
          x=car(sc->args);
 
3027
          s_return(sc, mk_real(sc, asin(rvalue(x))));
 
3028
 
 
3029
     case OP_ACOS:
 
3030
          x=car(sc->args);
 
3031
          s_return(sc, mk_real(sc, acos(rvalue(x))));
 
3032
 
 
3033
     case OP_ATAN:
 
3034
          x=car(sc->args);
 
3035
          if(cdr(sc->args)==sc->NIL) {
 
3036
               s_return(sc, mk_real(sc, atan(rvalue(x))));
 
3037
          } else {
 
3038
               pointer y=cadr(sc->args);
 
3039
               s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
 
3040
          }
 
3041
 
 
3042
     case OP_SQRT:
 
3043
          x=car(sc->args);
 
3044
          s_return(sc, mk_real(sc, sqrt(rvalue(x))));
 
3045
 
 
3046
     case OP_EXPT:
 
3047
          x=car(sc->args);
 
3048
          if(cdr(sc->args)==sc->NIL) {
 
3049
               Error_0(sc,"expt: needs two arguments");
 
3050
          } else {
 
3051
               pointer y=cadr(sc->args);
 
3052
               s_return(sc, mk_real(sc, pow(rvalue(x),rvalue(y))));
 
3053
          }
 
3054
 
 
3055
     case OP_FLOOR:
 
3056
          x=car(sc->args);
 
3057
          s_return(sc, mk_real(sc, floor(rvalue(x))));
 
3058
 
 
3059
     case OP_CEILING:
 
3060
          x=car(sc->args);
 
3061
          s_return(sc, mk_real(sc, ceil(rvalue(x))));
 
3062
 
 
3063
     case OP_TRUNCATE : {
 
3064
          double rvalue_of_x ;
 
3065
          x=car(sc->args);
 
3066
          rvalue_of_x = rvalue(x) ;
 
3067
          if (rvalue_of_x > 0) {
 
3068
            s_return(sc, mk_real(sc, floor(rvalue_of_x)));
 
3069
          } else {
 
3070
            s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
 
3071
          }
 
3072
     }
 
3073
 
 
3074
     case OP_ROUND:
 
3075
       x=car(sc->args);
 
3076
       s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
 
3077
#endif
 
3078
 
 
3079
     case OP_ADD:        /* + */
 
3080
       v=num_zero;
 
3081
       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
 
3082
         v=num_add(v,nvalue(car(x)));
 
3083
       }
 
3084
       s_return(sc,mk_number(sc, v));
 
3085
 
 
3086
     case OP_MUL:        /* * */
 
3087
       v=num_one;
 
3088
       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
 
3089
         v=num_mul(v,nvalue(car(x)));
 
3090
       }
 
3091
       s_return(sc,mk_number(sc, v));
 
3092
 
 
3093
     case OP_SUB:        /* - */
 
3094
       if(cdr(sc->args)==sc->NIL) {
 
3095
         x=sc->args;
 
3096
         v=num_zero;
 
3097
       } else {
 
3098
         x = cdr(sc->args);
 
3099
         v = nvalue(car(sc->args));
 
3100
       }
 
3101
       for (; x != sc->NIL; x = cdr(x)) {
 
3102
         v=num_sub(v,nvalue(car(x)));
 
3103
       }
 
3104
       s_return(sc,mk_number(sc, v));
 
3105
 
 
3106
     case OP_DIV:        /* / */
 
3107
       if(cdr(sc->args)==sc->NIL) {
 
3108
         x=sc->args;
 
3109
         v=num_one;
 
3110
       } else {
 
3111
         x = cdr(sc->args);
 
3112
         v = nvalue(car(sc->args));
 
3113
       }
 
3114
       for (; x != sc->NIL; x = cdr(x)) {
 
3115
         if (!is_zero_double(rvalue(car(x))))
 
3116
           v=num_div(v,nvalue(car(x)));
 
3117
         else {
 
3118
           Error_0(sc,"/: division by zero");
 
3119
         }
 
3120
       }
 
3121
       s_return(sc,mk_number(sc, v));
 
3122
 
 
3123
     case OP_INTDIV:        /* quotient */
 
3124
          if(cdr(sc->args)==sc->NIL) {
 
3125
               x=sc->args;
 
3126
               v=num_one;
 
3127
          } else {
 
3128
               x = cdr(sc->args);
 
3129
               v = nvalue(car(sc->args));
 
3130
          }
 
3131
          for (; x != sc->NIL; x = cdr(x)) {
 
3132
               if (ivalue(car(x)) != 0)
 
3133
                    v=num_intdiv(v,nvalue(car(x)));
 
3134
               else {
 
3135
                    Error_0(sc,"quotient: division by zero");
 
3136
               }
 
3137
          }
 
3138
          s_return(sc,mk_number(sc, v));
 
3139
 
 
3140
     case OP_REM:        /* remainder */
 
3141
          v = nvalue(car(sc->args));
 
3142
          if (ivalue(cadr(sc->args)) != 0)
 
3143
               v=num_rem(v,nvalue(cadr(sc->args)));
 
3144
          else {
 
3145
               Error_0(sc,"remainder: division by zero");
 
3146
          }
 
3147
          s_return(sc,mk_number(sc, v));
 
3148
 
 
3149
     case OP_MOD:        /* modulo */
 
3150
          v = nvalue(car(sc->args));
 
3151
          if (ivalue(cadr(sc->args)) != 0)
 
3152
               v=num_mod(v,nvalue(cadr(sc->args)));
 
3153
          else {
 
3154
               Error_0(sc,"modulo: division by zero");
 
3155
          }
 
3156
          s_return(sc,mk_number(sc, v));
 
3157
 
 
3158
     case OP_CAR:        /* car */
 
3159
       s_return(sc,caar(sc->args));
 
3160
 
 
3161
     case OP_CDR:        /* cdr */
 
3162
       s_return(sc,cdar(sc->args));
 
3163
 
 
3164
     case OP_CONS:       /* cons */
 
3165
          cdr(sc->args) = cadr(sc->args);
 
3166
          s_return(sc,sc->args);
 
3167
 
 
3168
     case OP_SETCAR:     /* set-car! */
 
3169
       if(!is_immutable(car(sc->args))) {
 
3170
         caar(sc->args) = cadr(sc->args);
 
3171
         s_return(sc,car(sc->args));
 
3172
       } else {
 
3173
         Error_0(sc,"set-car!: unable to alter immutable pair");
 
3174
       }
 
3175
 
 
3176
     case OP_SETCDR:     /* set-cdr! */
 
3177
       if(!is_immutable(car(sc->args))) {
 
3178
         cdar(sc->args) = cadr(sc->args);
 
3179
         s_return(sc,car(sc->args));
 
3180
       } else {
 
3181
         Error_0(sc,"set-cdr!: unable to alter immutable pair");
 
3182
       }
 
3183
 
 
3184
     case OP_CHAR2INT: { /* char->integer */
 
3185
          gunichar c;
 
3186
          c=ivalue(car(sc->args));
 
3187
          s_return(sc,mk_integer(sc,c));
 
3188
     }
 
3189
 
 
3190
     case OP_INT2CHAR: { /* integer->char */
 
3191
          gunichar c;
 
3192
          c=(gunichar)ivalue(car(sc->args));
 
3193
          s_return(sc,mk_character(sc,c));
 
3194
     }
 
3195
 
 
3196
     case OP_CHARUPCASE: {
 
3197
          gunichar c;
 
3198
          c=(gunichar)ivalue(car(sc->args));
 
3199
          c=g_unichar_toupper(c);
 
3200
          s_return(sc,mk_character(sc,c));
 
3201
     }
 
3202
 
 
3203
     case OP_CHARDNCASE: {
 
3204
          gunichar c;
 
3205
          c=(gunichar)ivalue(car(sc->args));
 
3206
          c=g_unichar_tolower(c);
 
3207
          s_return(sc,mk_character(sc,c));
 
3208
     }
 
3209
 
 
3210
     case OP_STR2SYM:  /* string->symbol */
 
3211
          s_return(sc,mk_symbol(sc,strvalue(car(sc->args))));
 
3212
 
 
3213
     case OP_STR2ATOM: /* string->atom */ {
 
3214
       char *s=strvalue(car(sc->args));
 
3215
       if(*s=='#') {
 
3216
         s_return(sc, mk_sharp_const(sc, s+1));
 
3217
       } else {
 
3218
         s_return(sc, mk_atom(sc, s));
 
3219
       }
 
3220
     }
 
3221
 
 
3222
     case OP_SYM2STR: /* symbol->string */
 
3223
          x=mk_string(sc,symname(car(sc->args)));
 
3224
          setimmutable(x);
 
3225
          s_return(sc,x);
 
3226
     case OP_ATOM2STR: /* atom->string */
 
3227
       x=car(sc->args);
 
3228
       if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
 
3229
         char *p;
 
3230
         int len;
 
3231
         atom2str(sc,x,0,&p,&len);
 
3232
         s_return(sc,mk_counted_string(sc,p,len));
 
3233
       } else {
 
3234
         Error_1(sc, "atom->string: not an atom:", x);
 
3235
       }
 
3236
 
 
3237
     case OP_MKSTRING: { /* make-string */
 
3238
          gunichar fill=' ';
 
3239
          int len;
 
3240
 
 
3241
          len=ivalue(car(sc->args));
 
3242
 
 
3243
          if(cdr(sc->args)!=sc->NIL) {
 
3244
               fill=charvalue(cadr(sc->args));
 
3245
          }
 
3246
          s_return(sc,mk_empty_string(sc,len,fill));
 
3247
     }
 
3248
 
 
3249
     case OP_STRLEN:  /* string-length */
 
3250
          s_return(sc,mk_integer(sc,g_utf8_strlen(strvalue(car(sc->args)), -1)));
 
3251
 
 
3252
     case OP_STRREF: { /* string-ref */
 
3253
          char *str;
 
3254
          int index;
 
3255
 
 
3256
          str=strvalue(car(sc->args));
 
3257
 
 
3258
          index=ivalue(cadr(sc->args));
 
3259
 
 
3260
          if(index>=g_utf8_strlen(strvalue(car(sc->args)), -1)) {
 
3261
               Error_1(sc,"string-ref: out of bounds:",cadr(sc->args));
 
3262
          }
 
3263
 
 
3264
          str = g_utf8_offset_to_pointer(str, (long)index);
 
3265
          s_return(sc,mk_character(sc, g_utf8_get_char(str)));
 
3266
     }
 
3267
 
 
3268
     case OP_STRSET: { /* string-set! */
 
3269
          pointer a;
 
3270
          char *str;
 
3271
          int   index;
 
3272
          gunichar c;
 
3273
          char  utf8[7];
 
3274
          int   utf8_len;
 
3275
          int   newlen;
 
3276
          char *p1, *p2;
 
3277
          int   p1_len;
 
3278
          int   p2_len;
 
3279
          char *newstr;
 
3280
 
 
3281
          a=car(sc->args);
 
3282
          if(is_immutable(a)) {
 
3283
               Error_1(sc,"string-set!: unable to alter immutable string:",a);
 
3284
          }
 
3285
 
 
3286
          str=strvalue(a);
 
3287
          index=ivalue(cadr(sc->args));
 
3288
          if(index>=g_utf8_strlen(str, -1)) {
 
3289
              Error_1(sc,"string-set!: out of bounds:",cadr(sc->args));
 
3290
          }
 
3291
 
 
3292
          c=charvalue(caddr(sc->args));
 
3293
          utf8_len = g_unichar_to_utf8(c, utf8);
 
3294
 
 
3295
          p1 = g_utf8_offset_to_pointer(str, (long)index);
 
3296
          p2 = g_utf8_offset_to_pointer(str, (long)index+1);
 
3297
          p1_len = p1-str;
 
3298
          p2_len = strlen(p2);
 
3299
 
 
3300
          newlen = p1_len+utf8_len+p2_len;
 
3301
          newstr = (char *)sc->malloc(newlen+1);
 
3302
          if (newstr == NULL) {
 
3303
             sc->no_memory=1;
 
3304
             Error_1(sc,"string-set!: No memory to alter string:",car(sc->args));
 
3305
          }
 
3306
 
 
3307
          if (p1_len > 0)
 
3308
             memcpy(newstr, str, p1_len);
 
3309
          memcpy(newstr+p1_len, utf8, utf8_len);
 
3310
          if (p2_len > 0)
 
3311
             memcpy(newstr+p1_len+utf8_len, p2, p2_len);
 
3312
          newstr[newlen] = '\0';
 
3313
 
 
3314
          free(strvalue(a));
 
3315
          g_free(strkey(a)); /* mem was allocated via glib */
 
3316
          strvalue(a)=newstr;
 
3317
          p1 = g_utf8_casefold(strvalue(a), -1);
 
3318
          strkey(a) = g_utf8_collate_key(p1, -1);
 
3319
          g_free(p1);
 
3320
          strlength(a)=newlen;
 
3321
 
 
3322
          s_return(sc,a);
 
3323
     }
 
3324
 
 
3325
     case OP_STRAPPEND: { /* string-append */
 
3326
       /* in 1.29 string-append was in Scheme in init.scm but was too slow */
 
3327
       int len = 0;
 
3328
       pointer newstr;
 
3329
       pointer car_x;
 
3330
       char *pos;
 
3331
 
 
3332
       /* compute needed length for new string */
 
3333
       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
 
3334
          len += strlength(car(x));
 
3335
       }
 
3336
       newstr = mk_empty_string(sc, len, ' ');
 
3337
       /* store the contents of the argument strings into the new string */
 
3338
       pos = strvalue(newstr);
 
3339
       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
 
3340
           car_x = car(x);
 
3341
           memcpy(pos, strvalue(car_x), strlength(car_x));
 
3342
           pos += strlength(car_x);
 
3343
       }
 
3344
       *pos = '\0';
 
3345
       s_return(sc, newstr);
 
3346
     }
 
3347
 
 
3348
     case OP_SUBSTR: { /* substring */
 
3349
          char *str;
 
3350
          char *beg;
 
3351
          char *end;
 
3352
          int index0;
 
3353
          int index1;
 
3354
          int len;
 
3355
          pointer x;
 
3356
 
 
3357
          str=strvalue(car(sc->args));
 
3358
 
 
3359
          index0=ivalue(cadr(sc->args));
 
3360
 
 
3361
          if(index0>g_utf8_strlen(str, -1)) {
 
3362
               Error_1(sc,"substring: start out of bounds:",cadr(sc->args));
 
3363
          }
 
3364
 
 
3365
          if(cddr(sc->args)!=sc->NIL) {
 
3366
               index1=ivalue(caddr(sc->args));
 
3367
               if(index1>g_utf8_strlen(str, -1) || index1<index0) {
 
3368
                    Error_1(sc,"substring: end out of bounds:",caddr(sc->args));
 
3369
               }
 
3370
          } else {
 
3371
               index1=g_utf8_strlen(str, -1);
 
3372
          }
 
3373
 
 
3374
          beg = g_utf8_offset_to_pointer(str, (long)index0);
 
3375
          end = g_utf8_offset_to_pointer(str, (long)index1);
 
3376
          len=end-beg;
 
3377
          x=mk_empty_string(sc,len,' ');
 
3378
          memcpy(strvalue(x),beg,len);
 
3379
          strvalue(x)[len] = '\0';
 
3380
 
 
3381
          s_return(sc,x);
 
3382
     }
 
3383
 
 
3384
     case OP_VECTOR: {   /* vector */
 
3385
          int i;
 
3386
          pointer vec;
 
3387
          int len=list_length(sc,sc->args);
 
3388
          if(len<0) {
 
3389
               Error_1(sc,"vector: not a proper list:",sc->args);
 
3390
          }
 
3391
          vec=mk_vector(sc,len);
 
3392
          for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
 
3393
               set_vector_elem(vec,i,car(x));
 
3394
          }
 
3395
          s_return(sc,vec);
 
3396
     }
 
3397
 
 
3398
     case OP_MKVECTOR: { /* make-vector */
 
3399
          pointer fill=sc->NIL;
 
3400
          int len;
 
3401
          pointer vec;
 
3402
 
 
3403
          len=ivalue(car(sc->args));
 
3404
 
 
3405
          if(cdr(sc->args)!=sc->NIL) {
 
3406
               fill=cadr(sc->args);
 
3407
          }
 
3408
          vec=mk_vector(sc,len);
 
3409
          if(fill!=sc->NIL) {
 
3410
               fill_vector(vec,fill);
 
3411
          }
 
3412
          s_return(sc,vec);
 
3413
     }
 
3414
 
 
3415
     case OP_VECLEN:  /* vector-length */
 
3416
          s_return(sc,mk_integer(sc,ivalue(car(sc->args))));
 
3417
 
 
3418
     case OP_VECREF: { /* vector-ref */
 
3419
          int index;
 
3420
 
 
3421
          index=ivalue(cadr(sc->args));
 
3422
 
 
3423
          if(index>=ivalue(car(sc->args))) {
 
3424
               Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args));
 
3425
          }
 
3426
 
 
3427
          s_return(sc,vector_elem(car(sc->args),index));
 
3428
     }
 
3429
 
 
3430
     case OP_VECSET: {   /* vector-set! */
 
3431
          int index;
 
3432
 
 
3433
          if(is_immutable(car(sc->args))) {
 
3434
               Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args));
 
3435
          }
 
3436
 
 
3437
          index=ivalue(cadr(sc->args));
 
3438
          if(index>=ivalue(car(sc->args))) {
 
3439
               Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args));
 
3440
          }
 
3441
 
 
3442
          set_vector_elem(car(sc->args),index,caddr(sc->args));
 
3443
          s_return(sc,car(sc->args));
 
3444
     }
 
3445
 
 
3446
     default:
 
3447
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
3448
          Error_0(sc,sc->strbuff);
 
3449
     }
 
3450
     return sc->T;
 
3451
}
 
3452
 
 
3453
static int is_list(scheme *sc, pointer a) {
 
3454
        pointer slow, fast;
 
3455
 
 
3456
        slow = fast = a;
 
3457
        while (1)
 
3458
        {
 
3459
                if (fast == sc->NIL)
 
3460
                        return 1;
 
3461
                if (!is_pair(fast))
 
3462
                        return 0;
 
3463
                fast = cdr(fast);
 
3464
                if (fast == sc->NIL)
 
3465
                        return 1;
 
3466
                if (!is_pair(fast))
 
3467
                        return 0;
 
3468
                fast = cdr(fast);
 
3469
 
 
3470
                slow = cdr(slow);
 
3471
                if (fast == slow)
 
3472
                {
 
3473
                        /* the fast pointer has looped back around and caught up
 
3474
                           with the slow pointer, hence the structure is circular,
 
3475
                           not of finite length, and therefore not a list */
 
3476
                        return 0;
 
3477
                }
 
3478
        }
 
3479
}
 
3480
 
 
3481
static int list_length(scheme *sc, pointer a) {
 
3482
    int i=0;
 
3483
        pointer slow, fast;
 
3484
 
 
3485
        slow = fast = a;
 
3486
        while (1)
 
3487
        {
 
3488
                if (fast == sc->NIL)
 
3489
                        return i;
 
3490
                if (!is_pair(fast))
 
3491
                        return i;
 
3492
                fast = cdr(fast);
 
3493
                ++i;
 
3494
                if (fast == sc->NIL)
 
3495
                        return i;
 
3496
                if (!is_pair(fast))
 
3497
                        return i;
 
3498
                ++i;
 
3499
                fast = cdr(fast);
 
3500
 
 
3501
                slow = cdr(slow);
 
3502
                if (fast == slow)
 
3503
                {
 
3504
                        /* the fast pointer has looped back around and caught up
 
3505
                           with the slow pointer, hence the structure is circular,
 
3506
                           not of finite length, and therefore not a list */
 
3507
                        return -1;
 
3508
                }
 
3509
        }
 
3510
}
 
3511
 
 
3512
static pointer opexe_3(scheme *sc, enum scheme_opcodes op) {
 
3513
     pointer x;
 
3514
     num v;
 
3515
     int (*comp_func)(num,num)=0;
 
3516
 
 
3517
     switch (op) {
 
3518
     case OP_NOT:        /* not */
 
3519
          s_retbool(is_false(car(sc->args)));
 
3520
     case OP_BOOLP:       /* boolean? */
 
3521
          s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
 
3522
     case OP_EOFOBJP:       /* boolean? */
 
3523
          s_retbool(car(sc->args) == sc->EOF_OBJ);
 
3524
     case OP_NULLP:       /* null? */
 
3525
          s_retbool(car(sc->args) == sc->NIL);
 
3526
     case OP_NUMEQ:      /* = */
 
3527
     case OP_LESS:       /* < */
 
3528
     case OP_GRE:        /* > */
 
3529
     case OP_LEQ:        /* <= */
 
3530
     case OP_GEQ:        /* >= */
 
3531
          switch(op) {
 
3532
               case OP_NUMEQ: comp_func=num_eq; break;
 
3533
               case OP_LESS:  comp_func=num_lt; break;
 
3534
               case OP_GRE:   comp_func=num_gt; break;
 
3535
               case OP_LEQ:   comp_func=num_le; break;
 
3536
               case OP_GEQ:   comp_func=num_ge; break;
 
3537
               default:       break;  /* Quiet the compiler */
 
3538
          }
 
3539
          x=sc->args;
 
3540
          v=nvalue(car(x));
 
3541
          x=cdr(x);
 
3542
 
 
3543
          for (; x != sc->NIL; x = cdr(x)) {
 
3544
               if(!comp_func(v,nvalue(car(x)))) {
 
3545
                    s_retbool(0);
 
3546
               }
 
3547
               v=nvalue(car(x));
 
3548
          }
 
3549
          s_retbool(1);
 
3550
     case OP_SYMBOLP:     /* symbol? */
 
3551
          s_retbool(is_symbol(car(sc->args)));
 
3552
     case OP_NUMBERP:     /* number? */
 
3553
          s_retbool(is_number(car(sc->args)));
 
3554
     case OP_STRINGP:     /* string? */
 
3555
          s_retbool(is_string(car(sc->args)));
 
3556
     case OP_INTEGERP:     /* integer? */
 
3557
          s_retbool(is_integer(car(sc->args)));
 
3558
     case OP_REALP:     /* real? */
 
3559
          s_retbool(is_number(car(sc->args))); /* All numbers are real */
 
3560
     case OP_CHARP:     /* char? */
 
3561
          s_retbool(is_character(car(sc->args)));
 
3562
#if USE_CHAR_CLASSIFIERS
 
3563
     case OP_CHARAP:     /* char-alphabetic? */
 
3564
          s_retbool(Cisalpha(ivalue(car(sc->args))));
 
3565
     case OP_CHARNP:     /* char-numeric? */
 
3566
          s_retbool(Cisdigit(ivalue(car(sc->args))));
 
3567
     case OP_CHARWP:     /* char-whitespace? */
 
3568
          s_retbool(Cisspace(ivalue(car(sc->args))));
 
3569
     case OP_CHARUP:     /* char-upper-case? */
 
3570
          s_retbool(Cisupper(ivalue(car(sc->args))));
 
3571
     case OP_CHARLP:     /* char-lower-case? */
 
3572
          s_retbool(Cislower(ivalue(car(sc->args))));
 
3573
#endif
 
3574
     case OP_PORTP:     /* port? */
 
3575
          s_retbool(is_port(car(sc->args)));
 
3576
     case OP_INPORTP:     /* input-port? */
 
3577
          s_retbool(is_inport(car(sc->args)));
 
3578
     case OP_OUTPORTP:     /* output-port? */
 
3579
          s_retbool(is_outport(car(sc->args)));
 
3580
     case OP_PROCP:       /* procedure? */
 
3581
          /*--
 
3582
              * continuation should be procedure by the example
 
3583
              * (call-with-current-continuation procedure?) ==> #t
 
3584
                 * in R^3 report sec. 6.9
 
3585
              */
 
3586
          s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
 
3587
                 || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
 
3588
     case OP_PAIRP:       /* pair? */
 
3589
          s_retbool(is_pair(car(sc->args)));
 
3590
     case OP_LISTP:       /* list? */
 
3591
          s_retbool(is_list(sc, car(sc->args)));
 
3592
     case OP_ENVP:        /* environment? */
 
3593
          s_retbool(is_environment(car(sc->args)));
 
3594
     case OP_VECTORP:     /* vector? */
 
3595
          s_retbool(is_vector(car(sc->args)));
 
3596
     case OP_EQ:         /* eq? */
 
3597
          s_retbool(car(sc->args) == cadr(sc->args));
 
3598
     case OP_EQV:        /* eqv? */
 
3599
          s_retbool(eqv(car(sc->args), cadr(sc->args)));
 
3600
     default:
 
3601
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
3602
          Error_0(sc,sc->strbuff);
 
3603
     }
 
3604
     return sc->T;
 
3605
}
 
3606
 
 
3607
static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
 
3608
     pointer x, y;
 
3609
 
 
3610
     switch (op) {
 
3611
     case OP_FORCE:      /* force */
 
3612
          sc->code = car(sc->args);
 
3613
          if (is_promise(sc->code)) {
 
3614
               /* Should change type to closure here */
 
3615
               s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
 
3616
               sc->args = sc->NIL;
 
3617
               s_goto(sc,OP_APPLY);
 
3618
          } else {
 
3619
               s_return(sc,sc->code);
 
3620
          }
 
3621
 
 
3622
     case OP_SAVE_FORCED:     /* Save forced value replacing promise */
 
3623
          memcpy(sc->code,sc->value,sizeof(struct cell));
 
3624
          s_return(sc,sc->value);
 
3625
 
 
3626
     case OP_WRITE:      /* write */
 
3627
     case OP_DISPLAY:    /* display */
 
3628
     case OP_WRITE_CHAR: /* write-char */
 
3629
          if(is_pair(cdr(sc->args))) {
 
3630
               if(cadr(sc->args)!=sc->outport) {
 
3631
                    x=cons(sc,sc->outport,sc->NIL);
 
3632
                    s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
 
3633
                    sc->outport=cadr(sc->args);
 
3634
               }
 
3635
          }
 
3636
          sc->args = car(sc->args);
 
3637
          if(op==OP_WRITE) {
 
3638
               sc->print_flag = 1;
 
3639
          } else {
 
3640
               sc->print_flag = 0;
 
3641
          }
 
3642
          s_goto(sc,OP_P0LIST);
 
3643
 
 
3644
     case OP_NEWLINE:    /* newline */
 
3645
          if(is_pair(sc->args)) {
 
3646
               if(car(sc->args)!=sc->outport) {
 
3647
                    x=cons(sc,sc->outport,sc->NIL);
 
3648
                    s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
 
3649
                    sc->outport=car(sc->args);
 
3650
               }
 
3651
          }
 
3652
          putstr(sc, "\n");
 
3653
          s_return(sc,sc->T);
 
3654
 
 
3655
     case OP_ERR0:  /* error */
 
3656
          sc->retcode=-1;
 
3657
          if (!is_string(car(sc->args))) {
 
3658
               sc->args=cons(sc,mk_string(sc," -- "),sc->args);
 
3659
               setimmutable(car(sc->args));
 
3660
          }
 
3661
          if (sc->print_error == 0)     /* Reset buffer if not already */
 
3662
              sc->linebuff[0] = '\0';   /* in error message output mode*/
 
3663
          sc->print_error = 1;
 
3664
          putstr(sc, "Error: ");
 
3665
          putstr(sc, strvalue(car(sc->args)));
 
3666
          sc->args = cdr(sc->args);
 
3667
          s_goto(sc,OP_ERR1);
 
3668
 
 
3669
     case OP_ERR1:  /* error */
 
3670
          putstr(sc, " ");
 
3671
          if (sc->args != sc->NIL) {
 
3672
               s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
 
3673
               sc->args = car(sc->args);
 
3674
               sc->print_flag = 1;
 
3675
               s_goto(sc,OP_P0LIST);
 
3676
          } else {
 
3677
               putstr(sc, "\n");
 
3678
               sc->print_error = 0;
 
3679
               if(sc->interactive_repl) {
 
3680
                    s_goto(sc,OP_T0LVL);
 
3681
               } else {
 
3682
                    return sc->NIL;
 
3683
               }
 
3684
          }
 
3685
 
 
3686
     case OP_REVERSE:    /* reverse */
 
3687
          s_return(sc,reverse(sc, car(sc->args)));
 
3688
 
 
3689
     case OP_LIST_STAR: /* list* */
 
3690
       s_return(sc,list_star(sc,sc->args));
 
3691
 
 
3692
     case OP_APPEND:     /* append */
 
3693
          if(sc->args==sc->NIL) {
 
3694
               s_return(sc,sc->NIL);
 
3695
          }
 
3696
          x=car(sc->args);
 
3697
          if(cdr(sc->args)==sc->NIL) {
 
3698
            s_return(sc,sc->args);
 
3699
          }
 
3700
          for (y = cdr(sc->args); y != sc->NIL; y = cdr(y)) {
 
3701
               x=append(sc,x,car(y));
 
3702
          }
 
3703
          s_return(sc,x);
 
3704
 
 
3705
#if USE_PLIST
 
3706
     case OP_PUT:        /* put */
 
3707
          if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
 
3708
               Error_0(sc,"illegal use of put");
 
3709
          }
 
3710
          for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
 
3711
               if (caar(x) == y) {
 
3712
                    break;
 
3713
               }
 
3714
          }
 
3715
          if (x != sc->NIL)
 
3716
               cdar(x) = caddr(sc->args);
 
3717
          else
 
3718
               symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)),
 
3719
                                symprop(car(sc->args)));
 
3720
          s_return(sc,sc->T);
 
3721
 
 
3722
     case OP_GET:        /* get */
 
3723
          if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
 
3724
               Error_0(sc,"illegal use of get");
 
3725
          }
 
3726
          for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
 
3727
               if (caar(x) == y) {
 
3728
                    break;
 
3729
               }
 
3730
          }
 
3731
          if (x != sc->NIL) {
 
3732
               s_return(sc,cdar(x));
 
3733
          } else {
 
3734
               s_return(sc,sc->NIL);
 
3735
          }
 
3736
#endif /* USE_PLIST */
 
3737
     case OP_QUIT:       /* quit */
 
3738
          if(is_pair(sc->args)) {
 
3739
               sc->retcode=ivalue(car(sc->args));
 
3740
          }
 
3741
          return (sc->NIL);
 
3742
 
 
3743
     case OP_GC:         /* gc */
 
3744
          gc(sc, sc->NIL, sc->NIL);
 
3745
          s_return(sc,sc->T);
 
3746
 
 
3747
     case OP_GCVERB:          /* gc-verbose */
 
3748
     {    int  was = sc->gc_verbose;
 
3749
 
 
3750
          sc->gc_verbose = (car(sc->args) != sc->F);
 
3751
          s_retbool(was);
 
3752
     }
 
3753
 
 
3754
     case OP_NEWSEGMENT: /* new-segment */
 
3755
          if (!is_pair(sc->args) || !is_number(car(sc->args))) {
 
3756
               Error_0(sc,"new-segment: argument must be a number");
 
3757
          }
 
3758
          alloc_cellseg(sc, (int) ivalue(car(sc->args)));
 
3759
          s_return(sc,sc->T);
 
3760
 
 
3761
     case OP_OBLIST: /* oblist */
 
3762
          s_return(sc, oblist_all_symbols(sc));
 
3763
 
 
3764
     case OP_CURR_INPORT: /* current-input-port */
 
3765
          s_return(sc,sc->inport);
 
3766
 
 
3767
     case OP_CURR_OUTPORT: /* current-output-port */
 
3768
          s_return(sc,sc->outport);
 
3769
 
 
3770
     case OP_OPEN_INFILE: /* open-input-file */
 
3771
     case OP_OPEN_OUTFILE: /* open-output-file */
 
3772
     case OP_OPEN_INOUTFILE: /* open-input-output-file */ {
 
3773
          int prop=0;
 
3774
          pointer p;
 
3775
          switch(op) {
 
3776
               case OP_OPEN_INFILE:     prop=port_input; break;
 
3777
               case OP_OPEN_OUTFILE:    prop=port_output; break;
 
3778
               case OP_OPEN_INOUTFILE:  prop=port_input|port_output; break;
 
3779
               default:                 break;  /* Quiet the compiler */
 
3780
          }
 
3781
          p=port_from_filename(sc,strvalue(car(sc->args)),prop);
 
3782
          if(p==sc->NIL) {
 
3783
               s_return(sc,sc->F);
 
3784
          }
 
3785
          s_return(sc,p);
 
3786
     }
 
3787
 
 
3788
#if USE_STRING_PORTS
 
3789
     case OP_OPEN_INSTRING: /* open-input-string */
 
3790
     case OP_OPEN_OUTSTRING: /* open-output-string */
 
3791
     case OP_OPEN_INOUTSTRING: /* open-input-output-string */ {
 
3792
          int prop=0;
 
3793
          pointer p;
 
3794
          switch(op) {
 
3795
               case OP_OPEN_INSTRING:     prop=port_input; break;
 
3796
               case OP_OPEN_OUTSTRING:    prop=port_output; break;
 
3797
               case OP_OPEN_INOUTSTRING:  prop=port_input|port_output; break;
 
3798
               default:                   break;  /* Quiet the compiler */
 
3799
          }
 
3800
          p=port_from_string(sc, strvalue(car(sc->args)),
 
3801
                     strvalue(car(sc->args))+strlength(car(sc->args)), prop);
 
3802
          if(p==sc->NIL) {
 
3803
               s_return(sc,sc->F);
 
3804
          }
 
3805
          s_return(sc,p);
 
3806
     }
 
3807
#endif
 
3808
 
 
3809
     case OP_CLOSE_INPORT: /* close-input-port */
 
3810
          port_close(sc,car(sc->args),port_input);
 
3811
          s_return(sc,sc->T);
 
3812
 
 
3813
     case OP_CLOSE_OUTPORT: /* close-output-port */
 
3814
          port_close(sc,car(sc->args),port_output);
 
3815
          s_return(sc,sc->T);
 
3816
 
 
3817
     case OP_INT_ENV: /* interaction-environment */
 
3818
          s_return(sc,sc->global_env);
 
3819
 
 
3820
     case OP_CURR_ENV: /* current-environment */
 
3821
          s_return(sc,sc->envir);
 
3822
 
 
3823
     default:
 
3824
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
3825
          Error_0(sc,sc->strbuff);
 
3826
     }
 
3827
     return sc->T;
 
3828
}
 
3829
 
 
3830
static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
 
3831
     pointer x;
 
3832
 
 
3833
     if(sc->nesting!=0) {
 
3834
          int n=sc->nesting;
 
3835
          sc->nesting=0;
 
3836
          sc->retcode=-1;
 
3837
          Error_1(sc,"unmatched parentheses:",mk_integer(sc,n));
 
3838
     }
 
3839
 
 
3840
     switch (op) {
 
3841
     /* ========== reading part ========== */
 
3842
     case OP_READ:
 
3843
          if(!is_pair(sc->args)) {
 
3844
               s_goto(sc,OP_READ_INTERNAL);
 
3845
          }
 
3846
          if(!is_inport(car(sc->args))) {
 
3847
               Error_1(sc,"read: not an input port:",car(sc->args));
 
3848
          }
 
3849
          if(car(sc->args)==sc->inport) {
 
3850
               s_goto(sc,OP_READ_INTERNAL);
 
3851
          }
 
3852
          x=sc->inport;
 
3853
          sc->inport=car(sc->args);
 
3854
          x=cons(sc,x,sc->NIL);
 
3855
          s_save(sc,OP_SET_INPORT, x, sc->NIL);
 
3856
          s_goto(sc,OP_READ_INTERNAL);
 
3857
 
 
3858
     case OP_READ_CHAR: /* read-char */
 
3859
     case OP_PEEK_CHAR: /* peek-char */ {
 
3860
          gunichar c;
 
3861
          if(is_pair(sc->args)) {
 
3862
               if(car(sc->args)!=sc->inport) {
 
3863
                    x=sc->inport;
 
3864
                    x=cons(sc,x,sc->NIL);
 
3865
                    s_save(sc,OP_SET_INPORT, x, sc->NIL);
 
3866
                    sc->inport=car(sc->args);
 
3867
               }
 
3868
          }
 
3869
          c=inchar(sc);
 
3870
          if(c==EOF) {
 
3871
               s_return(sc,sc->EOF_OBJ);
 
3872
          }
 
3873
          if(sc->op==OP_PEEK_CHAR) {
 
3874
               backchar(sc,c);
 
3875
          }
 
3876
          s_return(sc,mk_character(sc,c));
 
3877
     }
 
3878
 
 
3879
     case OP_CHAR_READY: /* char-ready? */ {
 
3880
          pointer p=sc->inport;
 
3881
          int res;
 
3882
          if(is_pair(sc->args)) {
 
3883
               p=car(sc->args);
 
3884
          }
 
3885
          res=p->_object._port->kind&port_string;
 
3886
          s_retbool(res);
 
3887
     }
 
3888
 
 
3889
     case OP_SET_INPORT: /* set-input-port */
 
3890
          sc->inport=car(sc->args);
 
3891
          s_return(sc,sc->value);
 
3892
 
 
3893
     case OP_SET_OUTPORT: /* set-output-port */
 
3894
          sc->outport=car(sc->args);
 
3895
          s_return(sc,sc->value);
 
3896
 
 
3897
     case OP_RDSEXPR:
 
3898
          switch (sc->tok) {
 
3899
          case TOK_EOF:
 
3900
               if(sc->inport==sc->loadport) {
 
3901
                    sc->args=sc->NIL;
 
3902
                    s_goto(sc,OP_QUIT);
 
3903
               } else {
 
3904
                    s_return(sc,sc->EOF_OBJ);
 
3905
               }
 
3906
/*
 
3907
 * Commented out because we now skip comments in the scanner
 
3908
 *
 
3909
          case TOK_COMMENT: {
 
3910
               gunichar c;
 
3911
               while ((c=inchar(sc)) != '\n' && c!=EOF)
 
3912
                    ;
 
3913
               sc->tok = token(sc);
 
3914
               s_goto(sc,OP_RDSEXPR);
 
3915
          }
 
3916
*/
 
3917
          case TOK_VEC:
 
3918
               s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
 
3919
               /* fall through */
 
3920
          case TOK_LPAREN:
 
3921
               sc->tok = token(sc);
 
3922
               if (sc->tok == TOK_RPAREN) {
 
3923
                    s_return(sc,sc->NIL);
 
3924
               } else if (sc->tok == TOK_DOT) {
 
3925
                    Error_0(sc,"syntax error: illegal dot expression");
 
3926
               } else {
 
3927
                    sc->nesting_stack[sc->file_i]++;
 
3928
                    s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
 
3929
                    s_goto(sc,OP_RDSEXPR);
 
3930
               }
 
3931
          case TOK_QUOTE:
 
3932
               s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
 
3933
               sc->tok = token(sc);
 
3934
               s_goto(sc,OP_RDSEXPR);
 
3935
          case TOK_BQUOTE:
 
3936
               sc->tok = token(sc);
 
3937
               if(sc->tok==TOK_VEC) {
 
3938
                 s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
 
3939
                 sc->tok=TOK_LPAREN;
 
3940
                 s_goto(sc,OP_RDSEXPR);
 
3941
               } else {
 
3942
                 s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
 
3943
               }
 
3944
               s_goto(sc,OP_RDSEXPR);
 
3945
          case TOK_COMMA:
 
3946
               s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
 
3947
               sc->tok = token(sc);
 
3948
               s_goto(sc,OP_RDSEXPR);
 
3949
          case TOK_ATMARK:
 
3950
               s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
 
3951
               sc->tok = token(sc);
 
3952
               s_goto(sc,OP_RDSEXPR);
 
3953
          case TOK_ATOM:
 
3954
               s_return(sc,mk_atom(sc, readstr_upto(sc, "();\t\n\r ")));
 
3955
          case TOK_DQUOTE:
 
3956
               x=readstrexp(sc);
 
3957
               if(x==sc->F) {
 
3958
                 Error_0(sc,"Error reading string");
 
3959
               }
 
3960
               setimmutable(x);
 
3961
               s_return(sc,x);
 
3962
          case TOK_SHARP: {
 
3963
               pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
 
3964
               if(f==sc->NIL) {
 
3965
                    Error_0(sc,"undefined sharp expression");
 
3966
               } else {
 
3967
                    sc->code=cons(sc,slot_value_in_env(f),sc->NIL);
 
3968
                    s_goto(sc,OP_EVAL);
 
3969
               }
 
3970
          }
 
3971
          case TOK_SHARP_CONST:
 
3972
               if ((x = mk_sharp_const(sc, readstr_upto(sc, "();\t\n\r "))) == sc->NIL) {
 
3973
                    Error_0(sc,"undefined sharp expression");
 
3974
               } else {
 
3975
                    s_return(sc,x);
 
3976
               }
 
3977
          default:
 
3978
               sprintf(sc->linebuff, "syntax error: illegal token %d", sc->tok);
 
3979
               Error_0(sc,sc->linebuff);
 
3980
          }
 
3981
          break;
 
3982
 
 
3983
     case OP_RDLIST: {
 
3984
          sc->args = cons(sc, sc->value, sc->args);
 
3985
          sc->tok = token(sc);
 
3986
/* We now skip comments in the scanner
 
3987
          while (sc->tok == TOK_COMMENT) {
 
3988
               gunichar c;
 
3989
               while ((c=inchar(sc)) != '\n' && c!=EOF)
 
3990
                    ;
 
3991
               sc->tok = token(sc);
 
3992
          }
 
3993
*/
 
3994
          if (sc->tok == TOK_RPAREN) {
 
3995
               gunichar c = inchar(sc);
 
3996
               if (c != '\n') backchar(sc,c);
 
3997
               sc->nesting_stack[sc->file_i]--;
 
3998
               s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
 
3999
          } else if (sc->tok == TOK_DOT) {
 
4000
               s_save(sc,OP_RDDOT, sc->args, sc->NIL);
 
4001
               sc->tok = token(sc);
 
4002
               s_goto(sc,OP_RDSEXPR);
 
4003
          } else {
 
4004
               s_save(sc,OP_RDLIST, sc->args, sc->NIL);
 
4005
               s_goto(sc,OP_RDSEXPR);
 
4006
          }
 
4007
     }
 
4008
 
 
4009
     case OP_RDDOT:
 
4010
          if (token(sc) != TOK_RPAREN) {
 
4011
               Error_0(sc,"syntax error: illegal dot expression");
 
4012
          } else {
 
4013
               sc->nesting_stack[sc->file_i]--;
 
4014
               s_return(sc,reverse_in_place(sc, sc->value, sc->args));
 
4015
          }
 
4016
 
 
4017
     case OP_RDQUOTE:
 
4018
          s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)));
 
4019
 
 
4020
     case OP_RDQQUOTE:
 
4021
          s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL)));
 
4022
 
 
4023
     case OP_RDQQUOTEVEC:
 
4024
       s_return(sc,cons(sc, mk_symbol(sc,"apply"),
 
4025
                        cons(sc, mk_symbol(sc,"vector"),
 
4026
                             cons(sc,cons(sc, sc->QQUOTE,
 
4027
                                  cons(sc,sc->value,sc->NIL)),
 
4028
                                  sc->NIL))));
 
4029
 
 
4030
     case OP_RDUNQUOTE:
 
4031
          s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL)));
 
4032
 
 
4033
     case OP_RDUQTSP:
 
4034
          s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL)));
 
4035
 
 
4036
     case OP_RDVEC:
 
4037
          /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
 
4038
          s_goto(sc,OP_EVAL); Cannot be quoted*/
 
4039
       /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
 
4040
         s_return(sc,x); Cannot be part of pairs*/
 
4041
       /*sc->code=mk_proc(sc,OP_VECTOR);
 
4042
       sc->args=sc->value;
 
4043
       s_goto(sc,OP_APPLY);*/
 
4044
       sc->args=sc->value;
 
4045
       s_goto(sc,OP_VECTOR);
 
4046
 
 
4047
     /* ========== printing part ========== */
 
4048
     case OP_P0LIST:
 
4049
          if(is_vector(sc->args)) {
 
4050
               putstr(sc,"#(");
 
4051
               sc->args=cons(sc,sc->args,mk_integer(sc,0));
 
4052
               s_goto(sc,OP_PVECFROM);
 
4053
          } else if(is_environment(sc->args)) {
 
4054
               putstr(sc,"#<ENVIRONMENT>");
 
4055
               s_return(sc,sc->T);
 
4056
          } else if (!is_pair(sc->args)) {
 
4057
               printatom(sc, sc->args, sc->print_flag);
 
4058
               s_return(sc,sc->T);
 
4059
          } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
 
4060
               putstr(sc, "'");
 
4061
               sc->args = cadr(sc->args);
 
4062
               s_goto(sc,OP_P0LIST);
 
4063
          } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
 
4064
               putstr(sc, "`");
 
4065
               sc->args = cadr(sc->args);
 
4066
               s_goto(sc,OP_P0LIST);
 
4067
          } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
 
4068
               putstr(sc, ",");
 
4069
               sc->args = cadr(sc->args);
 
4070
               s_goto(sc,OP_P0LIST);
 
4071
          } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
 
4072
               putstr(sc, ",@");
 
4073
               sc->args = cadr(sc->args);
 
4074
               s_goto(sc,OP_P0LIST);
 
4075
          } else {
 
4076
               putstr(sc, "(");
 
4077
               s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
 
4078
               sc->args = car(sc->args);
 
4079
               s_goto(sc,OP_P0LIST);
 
4080
          }
 
4081
 
 
4082
     case OP_P1LIST:
 
4083
          if (is_pair(sc->args)) {
 
4084
            s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
 
4085
            putstr(sc, " ");
 
4086
            sc->args = car(sc->args);
 
4087
            s_goto(sc,OP_P0LIST);
 
4088
          } else if(is_vector(sc->args)) {
 
4089
            s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
 
4090
            putstr(sc, " . ");
 
4091
            s_goto(sc,OP_P0LIST);
 
4092
          } else {
 
4093
            if (sc->args != sc->NIL) {
 
4094
              putstr(sc, " . ");
 
4095
              printatom(sc, sc->args, sc->print_flag);
 
4096
            }
 
4097
            putstr(sc, ")");
 
4098
            s_return(sc,sc->T);
 
4099
          }
 
4100
     case OP_PVECFROM: {
 
4101
          int i=ivalue_unchecked(cdr(sc->args));
 
4102
          pointer vec=car(sc->args);
 
4103
          int len=ivalue_unchecked(vec);
 
4104
          if(i==len) {
 
4105
               putstr(sc," )");
 
4106
               s_return(sc,sc->T);
 
4107
          } else {
 
4108
               pointer elem=vector_elem(vec,i);
 
4109
               ivalue_unchecked(cdr(sc->args))=i+1;
 
4110
               s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
 
4111
               sc->args=elem;
 
4112
               putstr(sc," ");
 
4113
               s_goto(sc,OP_P0LIST);
 
4114
          }
 
4115
     }
 
4116
 
 
4117
     default:
 
4118
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
4119
          Error_0(sc,sc->strbuff);
 
4120
 
 
4121
     }
 
4122
     return sc->T;
 
4123
}
 
4124
 
 
4125
static pointer opexe_6(scheme *sc, enum scheme_opcodes op) {
 
4126
     pointer x, y;
 
4127
     long v;
 
4128
 
 
4129
     switch (op) {
 
4130
     case OP_LIST_LENGTH:     /* length */   /* a.k */
 
4131
          v=list_length(sc,car(sc->args));
 
4132
          if(v<0) {
 
4133
               Error_1(sc,"length: not a list:",car(sc->args));
 
4134
          }
 
4135
          s_return(sc,mk_integer(sc, v));
 
4136
 
 
4137
     case OP_ASSQ:       /* assq */     /* a.k */
 
4138
          x = car(sc->args);
 
4139
          for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
 
4140
               if (!is_pair(car(y))) {
 
4141
                    Error_0(sc,"unable to handle non pair element");
 
4142
               }
 
4143
               if (x == caar(y))
 
4144
                    break;
 
4145
          }
 
4146
          if (is_pair(y)) {
 
4147
               s_return(sc,car(y));
 
4148
          } else {
 
4149
               s_return(sc,sc->F);
 
4150
          }
 
4151
 
 
4152
 
 
4153
     case OP_GET_CLOSURE:     /* get-closure-code */   /* a.k */
 
4154
          sc->args = car(sc->args);
 
4155
          if (sc->args == sc->NIL) {
 
4156
               s_return(sc,sc->F);
 
4157
          } else if (is_closure(sc->args)) {
 
4158
               s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
 
4159
          } else if (is_macro(sc->args)) {
 
4160
               s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
 
4161
          } else {
 
4162
               s_return(sc,sc->F);
 
4163
          }
 
4164
     case OP_CLOSUREP:        /* closure? */
 
4165
          /*
 
4166
           * Note, macro object is also a closure.
 
4167
           * Therefore, (closure? <#MACRO>) ==> #t
 
4168
           */
 
4169
          s_retbool(is_closure(car(sc->args)));
 
4170
     case OP_MACROP:          /* macro? */
 
4171
          s_retbool(is_macro(car(sc->args)));
 
4172
     default:
 
4173
          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
 
4174
          Error_0(sc,sc->strbuff);
 
4175
     }
 
4176
     return sc->T; /* NOTREACHED */
 
4177
}
 
4178
 
 
4179
typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes);
 
4180
 
 
4181
typedef int (*test_predicate)(pointer);
 
4182
static int is_any(pointer p) { return 1;}
 
4183
static int is_num_integer(pointer p) {
 
4184
  return is_number(p) && ((p)->_object._number.is_fixnum);
 
4185
}
 
4186
static int is_nonneg(pointer p) {
 
4187
  return is_num_integer(p) && ivalue(p)>=0;
 
4188
}
 
4189
 
 
4190
/* Correspond carefully with following defines! */
 
4191
static struct {
 
4192
  test_predicate fct;
 
4193
  const char *kind;
 
4194
} tests[]={
 
4195
  {0,0}, /* unused */
 
4196
  {is_any, 0},
 
4197
  {is_string, "string"},
 
4198
  {is_symbol, "symbol"},
 
4199
  {is_port, "port"},
 
4200
  {0,"input port"},
 
4201
  {0,"output_port"},
 
4202
  {is_environment, "environment"},
 
4203
  {is_pair, "pair"},
 
4204
  {0, "pair or '()"},
 
4205
  {is_character, "character"},
 
4206
  {is_vector, "vector"},
 
4207
  {is_number, "number"},
 
4208
  {is_num_integer, "integer"},
 
4209
  {is_nonneg, "non-negative integer"},
 
4210
};
 
4211
 
 
4212
#define TST_NONE 0
 
4213
#define TST_ANY "\001"
 
4214
#define TST_STRING "\002"
 
4215
#define TST_SYMBOL "\003"
 
4216
#define TST_PORT "\004"
 
4217
#define TST_INPORT "\005"
 
4218
#define TST_OUTPORT "\006"
 
4219
#define TST_ENVIRONMENT "\007"
 
4220
#define TST_PAIR "\010"
 
4221
#define TST_LIST "\011"
 
4222
#define TST_CHAR "\012"
 
4223
#define TST_VECTOR "\013"
 
4224
#define TST_NUMBER "\014"
 
4225
#define TST_INTEGER "\015"
 
4226
#define TST_NATURAL "\016"
 
4227
 
 
4228
typedef struct {
 
4229
  dispatch_func func;
 
4230
  char *name;
 
4231
  int min_arity;
 
4232
  int max_arity;
 
4233
  char *arg_tests_encoding;
 
4234
} op_code_info;
 
4235
 
 
4236
#define INF_ARG 0xffff
 
4237
 
 
4238
static op_code_info dispatch_table[]= {
 
4239
#define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
 
4240
#include "opdefines.h"
 
4241
  { 0 }
 
4242
};
 
4243
 
 
4244
static const char *procname(pointer x) {
 
4245
 int n=procnum(x);
 
4246
 const char *name=dispatch_table[n].name;
 
4247
 if(name==0) {
 
4248
     name="ILLEGAL!";
 
4249
 }
 
4250
 return name;
 
4251
}
 
4252
 
 
4253
/* kernel of this interpreter */
 
4254
static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
 
4255
  int count=0;
 
4256
  int old_op;
 
4257
 
 
4258
  sc->op = op;
 
4259
  for (;;) {
 
4260
    op_code_info *pcd=dispatch_table+sc->op;
 
4261
    if (pcd->name!=0) { /* if built-in function, check arguments */
 
4262
      char msg[512];
 
4263
      int ok=1;
 
4264
      int n=list_length(sc,sc->args);
 
4265
 
 
4266
      /* Check number of arguments */
 
4267
      if(n<pcd->min_arity) {
 
4268
        ok=0;
 
4269
        sprintf(msg,"%s: needs%s %d argument(s)",
 
4270
                pcd->name,
 
4271
                pcd->min_arity==pcd->max_arity?"":" at least",
 
4272
                pcd->min_arity);
 
4273
      }
 
4274
      if(ok && n>pcd->max_arity) {
 
4275
        ok=0;
 
4276
        sprintf(msg,"%s: needs%s %d argument(s)",
 
4277
                pcd->name,
 
4278
                pcd->min_arity==pcd->max_arity?"":" at most",
 
4279
                pcd->max_arity);
 
4280
      }
 
4281
      if(ok) {
 
4282
        if(pcd->arg_tests_encoding!=0) {
 
4283
          int i=0;
 
4284
          int j;
 
4285
          const char *t=pcd->arg_tests_encoding;
 
4286
          pointer arglist=sc->args;
 
4287
          do {
 
4288
            pointer arg=car(arglist);
 
4289
            j=(int)t[0];
 
4290
            if(j==TST_INPORT[0]) {
 
4291
              if(!is_inport(arg)) break;
 
4292
            } else if(j==TST_OUTPORT[0]) {
 
4293
              if(!is_outport(arg)) break;
 
4294
            } else if(j==TST_LIST[0]) {
 
4295
              if(arg!=sc->NIL && !is_pair(arg)) break;
 
4296
            } else {
 
4297
              if(!tests[j].fct(arg)) break;
 
4298
            }
 
4299
 
 
4300
            if(t[1]!=0) {/* last test is replicated as necessary */
 
4301
              t++;
 
4302
            }
 
4303
            arglist=cdr(arglist);
 
4304
            i++;
 
4305
          } while(i<n);
 
4306
          if(i<n) {
 
4307
            ok=0;
 
4308
            sprintf(msg,"%s: argument %d must be: %s",
 
4309
                    pcd->name,
 
4310
                    i+1,
 
4311
                    tests[j].kind);
 
4312
          }
 
4313
        }
 
4314
      }
 
4315
      if(!ok) {
 
4316
        if(_Error_1(sc,msg,0)==sc->NIL) {
 
4317
          return;
 
4318
        }
 
4319
        pcd=dispatch_table+sc->op;
 
4320
      }
 
4321
    }
 
4322
    old_op=sc->op;
 
4323
    if (pcd->func(sc, (enum scheme_opcodes)sc->op) == sc->NIL) {
 
4324
      return;
 
4325
    }
 
4326
    if(sc->no_memory) {
 
4327
      fprintf(stderr,"No memory!\n");
 
4328
      return;
 
4329
    }
 
4330
    count++;
 
4331
  }
 
4332
}
 
4333
 
 
4334
/* ========== Initialization of internal keywords ========== */
 
4335
 
 
4336
static void assign_syntax(scheme *sc, char *name) {
 
4337
     pointer x;
 
4338
 
 
4339
     x = oblist_add_by_name(sc, name);
 
4340
     typeflag(x) |= T_SYNTAX;
 
4341
}
 
4342
 
 
4343
static void assign_proc(scheme *sc, enum scheme_opcodes op, char *name) {
 
4344
     pointer x, y;
 
4345
 
 
4346
     x = mk_symbol(sc, name);
 
4347
     y = mk_proc(sc,op);
 
4348
     new_slot_in_env(sc, x, y);
 
4349
}
 
4350
 
 
4351
static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
 
4352
     pointer y;
 
4353
 
 
4354
     y = get_cell(sc, sc->NIL, sc->NIL);
 
4355
     typeflag(y) = (T_PROC | T_ATOM);
 
4356
     ivalue_unchecked(y) = (long) op;
 
4357
     set_integer(y);
 
4358
     return y;
 
4359
}
 
4360
 
 
4361
/* Hard-coded for the given keywords. Remember to rewrite if more are added! */
 
4362
static int syntaxnum(pointer p) {
 
4363
     const char *s=strvalue(car(p));
 
4364
     switch(strlength(car(p))) {
 
4365
     case 2:
 
4366
          if(s[0]=='i') return OP_IF0;        /* if */
 
4367
          else return OP_OR0;                 /* or */
 
4368
     case 3:
 
4369
          if(s[0]=='a') return OP_AND0;      /* and */
 
4370
          else return OP_LET0;               /* let */
 
4371
     case 4:
 
4372
          switch(s[3]) {
 
4373
          case 'e': return OP_CASE0;         /* case */
 
4374
          case 'd': return OP_COND0;         /* cond */
 
4375
          case '*': return OP_LET0AST;       /* let* */
 
4376
          default: return OP_SET0;           /* set! */
 
4377
          }
 
4378
     case 5:
 
4379
          switch(s[2]) {
 
4380
          case 'g': return OP_BEGIN;         /* begin */
 
4381
          case 'l': return OP_DELAY;         /* delay */
 
4382
          case 'c': return OP_MACRO0;        /* macro */
 
4383
          default: return OP_QUOTE;          /* quote */
 
4384
          }
 
4385
     case 6:
 
4386
          switch(s[2]) {
 
4387
          case 'm': return OP_LAMBDA;        /* lambda */
 
4388
          case 'f': return OP_DEF0;          /* define */
 
4389
          default: return OP_LET0REC;        /* letrec */
 
4390
          }
 
4391
     default:
 
4392
          return OP_C0STREAM;                /* cons-stream */
 
4393
     }
 
4394
}
 
4395
 
 
4396
/* initialization of TinyScheme */
 
4397
#if USE_INTERFACE
 
4398
INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
 
4399
 return cons(sc,a,b);
 
4400
}
 
4401
INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
 
4402
 return immutable_cons(sc,a,b);
 
4403
}
 
4404
 
 
4405
static struct scheme_interface vtbl ={
 
4406
  scheme_define,
 
4407
  s_cons,
 
4408
  s_immutable_cons,
 
4409
  reserve_cells,
 
4410
  mk_integer,
 
4411
  mk_real,
 
4412
  mk_symbol,
 
4413
  gensym,
 
4414
  mk_string,
 
4415
  mk_counted_string,
 
4416
  mk_character,
 
4417
  mk_vector,
 
4418
  mk_foreign_func,
 
4419
  mk_closure,
 
4420
  putstr,
 
4421
  putcharacter,
 
4422
 
 
4423
  is_string,
 
4424
  string_length,
 
4425
  string_value,
 
4426
  is_number,
 
4427
  nvalue,
 
4428
  ivalue,
 
4429
  rvalue,
 
4430
  is_integer,
 
4431
  is_real,
 
4432
  is_character,
 
4433
  charvalue,
 
4434
  is_list,
 
4435
  is_vector,
 
4436
  list_length,
 
4437
  ivalue,
 
4438
  fill_vector,
 
4439
  vector_elem,
 
4440
  set_vector_elem,
 
4441
 
 
4442
  is_port,
 
4443
 
 
4444
  is_pair,
 
4445
  pair_car,
 
4446
  pair_cdr,
 
4447
  set_car,
 
4448
  set_cdr,
 
4449
 
 
4450
  is_symbol,
 
4451
  symname,
 
4452
 
 
4453
  is_syntax,
 
4454
  is_proc,
 
4455
  is_foreign,
 
4456
  syntaxname,
 
4457
  is_closure,
 
4458
  is_macro,
 
4459
  closure_code,
 
4460
  closure_env,
 
4461
 
 
4462
  is_continuation,
 
4463
  is_promise,
 
4464
  is_environment,
 
4465
  is_immutable,
 
4466
  setimmutable,
 
4467
 
 
4468
  scheme_load_file,
 
4469
  scheme_load_string
 
4470
};
 
4471
#endif
 
4472
 
 
4473
scheme *scheme_init_new(void) {
 
4474
  scheme *sc=(scheme*)malloc(sizeof(scheme));
 
4475
  if(!scheme_init(sc)) {
 
4476
    free(sc);
 
4477
    return 0;
 
4478
  } else {
 
4479
    return sc;
 
4480
  }
 
4481
}
 
4482
 
 
4483
scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
 
4484
  scheme *sc=(scheme*)malloc(sizeof(scheme));
 
4485
  if(!scheme_init_custom_alloc(sc,malloc,free)) {
 
4486
    free(sc);
 
4487
    return 0;
 
4488
  } else {
 
4489
    return sc;
 
4490
  }
 
4491
}
 
4492
 
 
4493
 
 
4494
int scheme_init(scheme *sc) {
 
4495
 return scheme_init_custom_alloc(sc,malloc,free);
 
4496
}
 
4497
 
 
4498
int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
 
4499
  int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
 
4500
  pointer x;
 
4501
 
 
4502
  num_zero.is_fixnum=1;
 
4503
  num_zero.value.ivalue=0;
 
4504
  num_one.is_fixnum=1;
 
4505
  num_one.value.ivalue=1;
 
4506
 
 
4507
#if USE_INTERFACE
 
4508
  sc->vptr=&vtbl;
 
4509
#endif
 
4510
  sc->gensym_cnt=0;
 
4511
  sc->malloc=malloc;
 
4512
  sc->free=free;
 
4513
  sc->last_cell_seg = -1;
 
4514
  sc->sink = &sc->_sink;
 
4515
  sc->NIL = &sc->_NIL;
 
4516
  sc->T = &sc->_HASHT;
 
4517
  sc->F = &sc->_HASHF;
 
4518
  sc->EOF_OBJ=&sc->_EOF_OBJ;
 
4519
  sc->free_cell = &sc->_NIL;
 
4520
  sc->fcells = 0;
 
4521
  sc->no_memory=0;
 
4522
  sc->inport=sc->NIL;
 
4523
  sc->outport=sc->NIL;
 
4524
  sc->save_inport=sc->NIL;
 
4525
  sc->loadport=sc->NIL;
 
4526
  sc->nesting=0;
 
4527
  sc->interactive_repl=0;
 
4528
  sc->print_output=0;
 
4529
  sc->print_error=0;
 
4530
 
 
4531
  if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
 
4532
    sc->no_memory=1;
 
4533
    return 0;
 
4534
  }
 
4535
  sc->gc_verbose = 0;
 
4536
  dump_stack_initialize(sc);
 
4537
  sc->code = sc->NIL;
 
4538
  sc->tracing=0;
 
4539
  sc->bc_flag = 0;
 
4540
  sc->safe_foreign = sc->NIL;
 
4541
 
 
4542
  /* init sc->NIL */
 
4543
  typeflag(sc->NIL) = (T_ATOM | MARK);
 
4544
  car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
 
4545
  /* init T */
 
4546
  typeflag(sc->T) = (T_ATOM | MARK);
 
4547
  car(sc->T) = cdr(sc->T) = sc->T;
 
4548
  /* init F */
 
4549
  typeflag(sc->F) = (T_ATOM | MARK);
 
4550
  car(sc->F) = cdr(sc->F) = sc->F;
 
4551
  sc->oblist = oblist_initial_value(sc);
 
4552
  /* init global_env */
 
4553
  new_frame_in_env(sc, sc->NIL);
 
4554
  sc->global_env = sc->envir;
 
4555
  /* init else */
 
4556
  x = mk_symbol(sc,"else");
 
4557
  new_slot_in_env(sc, x, sc->T);
 
4558
 
 
4559
  assign_syntax(sc, "lambda");
 
4560
  assign_syntax(sc, "quote");
 
4561
  assign_syntax(sc, "define");
 
4562
  assign_syntax(sc, "if");
 
4563
  assign_syntax(sc, "begin");
 
4564
  assign_syntax(sc, "set!");
 
4565
  assign_syntax(sc, "let");
 
4566
  assign_syntax(sc, "let*");
 
4567
  assign_syntax(sc, "letrec");
 
4568
  assign_syntax(sc, "cond");
 
4569
  assign_syntax(sc, "delay");
 
4570
  assign_syntax(sc, "and");
 
4571
  assign_syntax(sc, "or");
 
4572
  assign_syntax(sc, "cons-stream");
 
4573
  assign_syntax(sc, "macro");
 
4574
  assign_syntax(sc, "case");
 
4575
 
 
4576
  for(i=0; i<n; i++) {
 
4577
    if(dispatch_table[i].name!=0) {
 
4578
      assign_proc(sc, (enum scheme_opcodes)i, dispatch_table[i].name);
 
4579
    }
 
4580
  }
 
4581
 
 
4582
  /* initialization of global pointers to special symbols */
 
4583
  sc->LAMBDA = mk_symbol(sc, "lambda");
 
4584
  sc->QUOTE = mk_symbol(sc, "quote");
 
4585
  sc->QQUOTE = mk_symbol(sc, "quasiquote");
 
4586
  sc->UNQUOTE = mk_symbol(sc, "unquote");
 
4587
  sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
 
4588
  sc->FEED_TO = mk_symbol(sc, "=>");
 
4589
  sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
 
4590
  sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
 
4591
  sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
 
4592
 
 
4593
  return !sc->no_memory;
 
4594
}
 
4595
 
 
4596
SCHEME_EXPORT void scheme_set_input_port_file(scheme *sc, FILE *fin) {
 
4597
  sc->inport=port_from_file(sc,fin,port_input);
 
4598
}
 
4599
 
 
4600
void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
 
4601
  sc->inport=port_from_string(sc,start,past_the_end,port_input);
 
4602
}
 
4603
 
 
4604
SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fout) {
 
4605
  sc->outport=port_from_file(sc,fout,port_output);
 
4606
}
 
4607
 
 
4608
void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
 
4609
  sc->outport=port_from_string(sc,start,past_the_end,port_output);
 
4610
}
 
4611
 
 
4612
void scheme_set_external_data(scheme *sc, void *p) {
 
4613
 sc->ext_data=p;
 
4614
}
 
4615
 
 
4616
void scheme_deinit(scheme *sc) {
 
4617
  int i;
 
4618
 
 
4619
  sc->oblist=sc->NIL;
 
4620
  sc->global_env=sc->NIL;
 
4621
  dump_stack_free(sc);
 
4622
  sc->envir=sc->NIL;
 
4623
  sc->code=sc->NIL;
 
4624
  sc->args=sc->NIL;
 
4625
  sc->value=sc->NIL;
 
4626
  if(is_port(sc->inport)) {
 
4627
    typeflag(sc->inport) = T_ATOM;
 
4628
  }
 
4629
  sc->inport=sc->NIL;
 
4630
  sc->outport=sc->NIL;
 
4631
  if(is_port(sc->save_inport)) {
 
4632
    typeflag(sc->save_inport) = T_ATOM;
 
4633
  }
 
4634
  sc->save_inport=sc->NIL;
 
4635
  if(is_port(sc->loadport)) {
 
4636
    typeflag(sc->loadport) = T_ATOM;
 
4637
  }
 
4638
  sc->loadport=sc->NIL;
 
4639
  sc->gc_verbose=0;
 
4640
  gc(sc,sc->NIL,sc->NIL);
 
4641
 
 
4642
  for(i=0; i<=sc->last_cell_seg; i++) {
 
4643
    sc->free(sc->alloc_seg[i]);
 
4644
  }
 
4645
}
 
4646
 
 
4647
void scheme_load_file(scheme *sc, FILE *fin) {
 
4648
  dump_stack_reset(sc);
 
4649
  sc->envir = sc->global_env;
 
4650
  sc->file_i=0;
 
4651
  sc->load_stack[0].kind=port_input|port_file;
 
4652
  sc->load_stack[0].rep.stdio.file=fin;
 
4653
  sc->loadport=mk_port(sc,sc->load_stack);
 
4654
  sc->retcode=0;
 
4655
  if(fin==stdin) {
 
4656
    sc->interactive_repl=1;
 
4657
  }
 
4658
  sc->inport=sc->loadport;
 
4659
  Eval_Cycle(sc, OP_T0LVL);
 
4660
  typeflag(sc->loadport)=T_ATOM;
 
4661
  if(sc->retcode==0) {
 
4662
    sc->retcode=sc->nesting!=0;
 
4663
  }
 
4664
}
 
4665
 
 
4666
void scheme_load_string(scheme *sc, const char *cmd) {
 
4667
  dump_stack_reset(sc);
 
4668
  sc->envir = sc->global_env;
 
4669
  sc->file_i=0;
 
4670
  sc->load_stack[0].kind=port_input|port_string;
 
4671
  sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */
 
4672
  sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd);
 
4673
  sc->load_stack[0].rep.string.curr=(char*)cmd;
 
4674
  sc->loadport=mk_port(sc,sc->load_stack);
 
4675
  sc->retcode=0;
 
4676
  sc->interactive_repl=0;
 
4677
  sc->inport=sc->loadport;
 
4678
  Eval_Cycle(sc, OP_T0LVL);
 
4679
  typeflag(sc->loadport)=T_ATOM;
 
4680
  if(sc->retcode==0) {
 
4681
    sc->retcode=sc->nesting!=0;
 
4682
  }
 
4683
}
 
4684
 
 
4685
void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
 
4686
     pointer x;
 
4687
 
 
4688
     x=find_slot_in_env(sc,envir,symbol,0);
 
4689
     if (x != sc->NIL) {
 
4690
          set_slot_in_env(sc, x, value);
 
4691
     } else {
 
4692
          new_slot_spec_in_env(sc, envir, symbol, value);
 
4693
     }
 
4694
}
 
4695
 
 
4696
#if !STANDALONE
 
4697
void scheme_apply0(scheme *sc, const char *procname) {
 
4698
     pointer carx=mk_symbol(sc,procname);
 
4699
     pointer cdrx=sc->NIL;
 
4700
 
 
4701
     dump_stack_reset(sc);
 
4702
     sc->envir = sc->global_env;
 
4703
     sc->code = cons(sc,carx,cdrx);
 
4704
     sc->interactive_repl=0;
 
4705
     sc->retcode=0;
 
4706
     Eval_Cycle(sc,OP_EVAL);
 
4707
     }
 
4708
 
 
4709
void scheme_call(scheme *sc, pointer func, pointer args) {
 
4710
   dump_stack_reset(sc);
 
4711
   sc->envir = sc->global_env;
 
4712
   sc->args = args;
 
4713
   sc->code = func;
 
4714
   sc->interactive_repl =0;
 
4715
   sc->retcode = 0;
 
4716
   Eval_Cycle(sc, OP_APPLY);
 
4717
}
 
4718
#endif
 
4719
 
 
4720
/* ========== Main ========== */
 
4721
 
 
4722
#if STANDALONE
 
4723
 
 
4724
#if defined(__APPLE__) && !defined (OSX)
 
4725
int main(int argc, char **argv)
 
4726
{
 
4727
     extern MacTS_main(int argc, char **argv);
 
4728
     char**    argv;
 
4729
     int argc = ccommand(&argv);
 
4730
     MacTS_main(argc,argv);
 
4731
     return 0;
 
4732
}
 
4733
int MacTS_main(int argc, char **argv) {
 
4734
#else
 
4735
int main(int argc, char **argv) {
 
4736
#endif
 
4737
  scheme sc;
 
4738
  FILE *fin;
 
4739
  char *file_name=InitFile;
 
4740
  int retcode;
 
4741
  int isfile=1;
 
4742
 
 
4743
  if(argc==1) {
 
4744
    printf(banner);
 
4745
  }
 
4746
  if(argc==2 && strcmp(argv[1],"-?")==0) {
 
4747
    printf("Usage: %s [-? | <file1> <file2> ... | -1 <file> <arg1> <arg2> ...]\n\tUse - as filename for stdin.\n",argv[0]);
 
4748
    return 1;
 
4749
  }
 
4750
  if(!scheme_init(&sc)) {
 
4751
    fprintf(stderr,"Could not initialize!\n");
 
4752
    return 2;
 
4753
  }
 
4754
  scheme_set_input_port_file(&sc, stdin);
 
4755
  scheme_set_output_port_file(&sc, stdout);
 
4756
#if USE_DL
 
4757
  scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext));
 
4758
#endif
 
4759
  argv++;
 
4760
  if(access(file_name,0)!=0) {
 
4761
    char *p=getenv("TINYSCHEMEINIT");
 
4762
    if(p!=0) {
 
4763
      file_name=p;
 
4764
    }
 
4765
  }
 
4766
  do {
 
4767
    if(strcmp(file_name,"-")==0) {
 
4768
      fin=stdin;
 
4769
    } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
 
4770
      pointer args=sc.NIL;
 
4771
      isfile=file_name[1]=='1';
 
4772
      file_name=*argv++;
 
4773
      if(strcmp(file_name,"-")==0) {
 
4774
        fin=stdin;
 
4775
      } else if(isfile) {
 
4776
        fin=fopen(file_name,"r");
 
4777
      }
 
4778
      for(;*argv;argv++) {
 
4779
        pointer value=mk_string(&sc,*argv);
 
4780
        args=cons(&sc,value,args);
 
4781
      }
 
4782
      args=reverse_in_place(&sc,sc.NIL,args);
 
4783
      scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
 
4784
 
 
4785
    } else {
 
4786
      fin=fopen(file_name,"r");
 
4787
    }
 
4788
    if(isfile && fin==0) {
 
4789
      fprintf(stderr,"Could not open file %s\n",file_name);
 
4790
    } else {
 
4791
      if(isfile) {
 
4792
        scheme_load_file(&sc,fin);
 
4793
      } else {
 
4794
        scheme_load_string(&sc,file_name);
 
4795
      }
 
4796
      if(!isfile || fin!=stdin) {
 
4797
        if(sc.retcode!=0) {
 
4798
          fprintf(stderr,"Errors encountered reading %s\n",file_name);
 
4799
        }
 
4800
        if(isfile) {
 
4801
          fclose(fin);
 
4802
        }
 
4803
      }
 
4804
    }
 
4805
    file_name=*argv++;
 
4806
  } while(file_name!=0);
 
4807
  if(argc==1) {
 
4808
    scheme_load_file(&sc,stdin);
 
4809
  }
 
4810
  retcode=sc.retcode;
 
4811
  scheme_deinit(&sc);
 
4812
 
 
4813
  return retcode;
 
4814
}
 
4815
 
 
4816
#endif