tree checksum vpatch file split hunks

all signers: asciilifeform

antecedents:

press order:

asciilifeform_shiva_part_1_of_2asciilifeform

patch:

-
+ 68FBCBEBE57013E70F798EC673D6C554CF0B118F41A56BAF92D53686F8D24FDA670ED6DDA23C6CBAB630DFAF8CBF6D6A52A6815AC3680B24DAD99B1305DE6279
bitcoin/src/obj-shiva/.gitignore
(0 . 0)(1 . 2)
5 *
6 !.gitignore
-
+ 3D7A61B123D7D1724A079C211678DD85085E56F4C2229C46D9DF7A7257E83461E0F19237C90B58A17E977B19715651539317003A69FFFD06C3CC96D0EA54839B
bitcoin/src/shiva/BUILDING
(0 . 0)(1 . 139)
11 Building TinyScheme
12 -------------------
13
14 The included makefile includes logic for Linux, Solaris and Win32, and can
15 readily serve as an example for other OSes, especially Unixes. There are
16 a lot of compile-time flags in TinyScheme (preprocessor defines) that can trim
17 unwanted features. See next section. 'make all' and 'make clean' function as
18 expected.
19
20 Autoconfing TinyScheme was once proposed, but the distribution would not be
21 so small anymore. There are few platform dependencies in TinyScheme, and in
22 general compiles out of the box.
23
24 Customizing
25 -----------
26
27 The following symbols are defined to default values in scheme.h.
28 Use the -D flag of cc to set to either 1 or 0.
29
30 STANDALONE
31 Define this to produce a standalone interpreter.
32
33 USE_MATH
34 Includes math routines.
35
36 USE_CHAR_CLASSIFIERS
37 Includes character classifier procedures.
38
39 USE_ASCII_NAMES
40 Enable extended character notation based on ASCII names.
41
42 USE_STRING_PORTS
43 Enables string ports.
44
45 USE_ERROR_HOOK
46 To force system errors through user-defined error handling.
47 (see "Error handling")
48
49 USE_TRACING
50 To enable use of TRACING.
51
52 USE_COLON_HOOK
53 Enable use of qualified identifiers. (see "Colon Qualifiers - Packages")
54 Defining this as 0 has the rather drastic consequence that any code using
55 packages will stop working, and will have to be modified. It should only
56 be used if you *absolutely* need to use '::' in identifiers.
57
58 USE_STRCASECMP
59 Defines stricmp as strcasecmp, for Unix.
60
61 STDIO_ADDS_CR
62 Informs TinyScheme that stdio translates "\n" to "\r\n". For DOS/Windows.
63
64 USE_DL
65 Enables dynamically loaded routines. If you define this symbol, you
66 should also include dynload.c in your compile.
67
68 USE_PLIST
69 Enables property lists (not Standard Scheme stuff). Off by default.
70
71 USE_NO_FEATURES
72 Shortcut to disable USE_MATH, USE_CHAR_CLASSIFIERS, USE_ASCII_NAMES,
73 USE_STRING_PORTS, USE_ERROR_HOOK, USE_TRACING, USE_COLON_HOOK,
74 USE_DL.
75
76 USE_SCHEME_STACK
77 Enables 'cons' stack (the alternative is a faster calling scheme, which
78 breaks continuations). Undefine it if you don't care about strict compatibility
79 but you do care about faster execution.
80
81
82 OS-X tip
83 --------
84 I don't have access to OS-X, but Brian Maher submitted the following tip:
85
86 [1] Download and install fink (I installed fink in
87 /usr/local/fink)
88 [2] Install the 'dlcompat' package using fink as such:
89 > fink install dlcompat
90 [3] Make the following changes to the
91 tinyscheme-1.32.tar.gz
92
93 diff -r tinyscheme-1.32/dynload.c
94 tinyscheme-1.32-new/dynload.c
95 24c24
96 < #define SUN_DL
97 ---
98 >
99 Only in tinyscheme-1.32-new/: dynload.o
100 Only in tinyscheme-1.32-new/: libtinyscheme.a Only in tinyscheme-1.32-new/: libtinyscheme.so diff -r tinyscheme-1.32/makefile tinyscheme-1.32-new/makefile
101 33,34c33,43
102 < LD = gcc
103 < LDFLAGS = -shared
104 ---
105 > #LD = gcc
106 > #LDFLAGS = -shared
107 > #DEBUG=-g -Wno-char-subscripts -O
108 > #SYS_LIBS= -ldl
109 > #PLATFORM_FEATURES= -DSUN_DL=1
110 >
111 > # Mac OS X
112 > CC = gcc
113 > CFLAGS = -I/usr/local/fink/include
114 > LD = gcc
115 > LDFLAGS = -L/usr/local/fink/lib
116 37c46
117 < PLATFORM_FEATURES= -DSUN_DL=1
118 ---
119 > PLATFORM_FEATURES= -DSUN_DL=1 -DOSX
120 60c69
121 < $(CC) -I. -c $(DEBUG) $(FEATURES)
122 $(DL_FLAGS) $<
123 ---
124 > $(CC) $(CFLAGS) -I. -c $(DEBUG)
125 $(FEATURES) $(DL_FLAGS) $<
126 66c75
127 < $(CC) -o $@ $(DEBUG) $(OBJS) $(SYS_LIBS)
128 ---
129 > $(CC) $(LDFLAGS) -o $@ $(DEBUG) $(OBJS)
130 $(SYS_LIBS)
131 Only in tinyscheme-1.32-new/: scheme
132 diff -r tinyscheme-1.32/scheme.c
133 tinyscheme-1.32-new/scheme.c
134 60,61c60,61
135 < #ifndef macintosh
136 < # include <malloc.h>
137 ---
138 > #ifdef OSX
139 > /* Do nothing */
140 62a63,65
141 > # ifndef macintosh
142 > # include <malloc.h>
143 > # else
144 77c80,81
145 < #endif /* macintosh */
146 ---
147 > # endif /* macintosh */
148 > #endif /* !OSX */
149 Only in tinyscheme-1.32-new/: scheme.o
-
+ 038EC4FD302239A956B99C57D8481FD5A5942BE9776174845CED951D584E16D4330A01C410321225FC601BA2CD96F37A4BAAFC9C6A32E305BCE41DB63314C08B
bitcoin/src/shiva/CHANGES
(0 . 0)(1 . 326)
154 Change Log
155 ----------
156
157 Version 1.41
158 Bugs fixed:
159 #3020389 - Added makefile section for Mac OS X (SL)
160 #3286135 - Fixed num_mod routine which caused errors in use of modulo
161 #3290232 - Corrected version number shown on startup (GM)
162 #3394882 - Added missing #if in opdefines.h around get and put (DC)
163 #3395547 - Fix for the modulo procedure (DC)
164 #3400290 - Optimized append to make it an O(n) operation (DC)
165 #3493926 - Corrected flag used when building shared files on OSX (J)
166
167 R5RS related changes:
168 #2866196 - Parser does not handle delimiters correctly
169 #3395548 - Add a decimal point to inexact numbers in atom2str (DC)
170 #3399331 - Make min/max return inexact when any argument is inexact
171 #3399332 - Compatability fix for expt.
172 #3399335 - Optional radix for string->number and number->string (DC)
173 #3400202 - Append with one argument should not return a list (DC)
174 #3400284 - Compatability fix for integer?
175
176 Other changes:
177 - Added flags to makefile for MinGW/MSYS (TC)
178 - Moved variable declarations to avoid warnings with some compilers
179 - Don't print space after initial #( when printing vectors.
180 - Minor optimization for is_nonneg().
181 - No need to round integers in OP_ROUND (#3400284)
182 - Fixes to code that reports line number with error (RC)
183
184 Contributors:
185 Kevin Cozens, Gordon McNutt, Doug Currie, Sean Long, Tim Cas, Joey,
186 Richard Copley, and CMarinier.
187
188 Version 1.40
189 Bugs fixed:
190 #1964950 - Stop core dumps due to bad syntax in LET (and variants)
191 #2826594 - allow reverse to work on empty list (Tony Garnock-Jones)
192 Potential problem of arglist to foreign calls being wrongly GC'ed.
193 Fixed bug that read could loop forever (tehom).
194
195 API changes:
196 Exposed is_list and list_length.
197 Added scheme_register_foreign_func_list and declarations for it (tehom)
198 Defined *compile-hook* (tehom)
199
200 Other changes:
201 Updated is_list and list_length to handle circular lists.
202 Nested calling thru C has been made now safer (tehom)
203 Peter Michaux cleaned up port_rep_from_file
204 Added unwind-protect (tehom)
205 Some cleanups to in/outport and Eval_Cycle by Peter Michaux
206 Report error line number (Mostly by Sanel Zukan, back-compatibility by Tehom)
207
208 Contributors:
209 Kevin Cozens, Dimitrios Souflis, Tom Breton, Peter Michaux, Sanel Zukan,
210 and Tony Garnock-Jones.
211
212 Version 1.39
213 Bugs fixed:
214 Fix for the load bug
215 Fixed parsing of octal coded characters. Fixes bug #1818018.
216 Added tests for when mk_vector is out of memory. Can't rely on sc->sink.
217 Fix for bug #1794369
218 Finished feature-request 1599947: scheme_apply0 etc return values.
219 Partly provided feature-request 1599947: Expose list_length, eqv, etc
220 Provided feature-request 1599945, Scheme->C->Scheme calling.
221 Fix for bug 1593861 (behavior of is_integer)
222 Fix for bug 1589711
223 Error checking of binding spec syntax in LET and LETREC. The bad syntax
224 was causing a segmentation fault in Linux. Complete fixes for bug #1817986.
225 Error checking of binding spec syntax in LET*
226 Bad syntax was causing core dump in Linux.
227 Fix for nasty gc bug
228
229 R5RS changes:
230 R5RS requires numbers to be of equal value AND of the same type (ie. both
231 exact or inexact) in order to return #t from eqv?. R5RS compliance fix.
232 String output ports now conform to SRFI-6
233
234 Other changes:
235 Drew Yao fixed buffer overflow problems in mk_sharp_const.
236 put OP_T0LVL in charge of reacting to EOF
237 file_push checks array bounds (patch from Ray Lehtiniemi)
238 Changed to always use snprintf (Patch due to Ramiro bsd1628)
239 Updated usage information using text from the Manual.txt file.
240
241 Version 1.38
242 Interim release until the rewrite, mostly incorporating modifications
243 from Kevin Cozens. Small addition for Cygwin in the makefile, and
244 modifications by Andrew Guenther for Apple platforms.
245
246 Version 1.37
247 Joe Buehler submitted reserve_cells.
248
249 Version 1.36
250 Joe Buehler fixed a patch in the allocator.
251 Alexander Shendi moved the comment handling in the scanner, which
252 fixed an obscure bug for which Mike E had provided a patch as well.
253 Kevin Cozens has submitted some fixes and modifications which have
254 not been incorporated yet in their entirety.
255
256 Version 1.35
257 Todd Showalter discovered that the number of free cells reported
258 after GC was incorrect, which could also cause unnecessary allocations.
259
260 Version 1.34
261 Long missing version. Lots of bugfixes have accumulated in my email, so
262 I had to start using them. In this version, Keenan Pepper has submitted
263 a bugfix for the string comparison library procedure, Wouter Boeke
264 modified some code that was casting to the wrong type and crashed on
265 some machines, "SheppardCo" submitted a replacement "modulo" code and
266 Scott Fenton submitted lots of corrections that shut up some compiler
267 warnings. Brian Maher submitted instructions on how to build on OS-X.
268 I have to dig deeper into my mailbox and find earlier emails, too.
269
270 Version 1.33
271 Charles Hayden fixed a nasty GC bug of the new stack frame, while in
272 the process of porting TinyScheme to C++. He also submitted other
273 changes, and other people also had comments or requests, but the GC
274 bug was so important that this version is put through the door to
275 correct it.
276
277 Version 1.32
278 Stephen Gildea put some quality time on TinyScheme again, and made
279 a whole lot of changes to the interpreter that made it noticeably
280 faster.
281
282 Version 1.31
283 Patches to the hastily-done version 1.30. Stephen Gildea fixed
284 some things done wrongly, and Richard Russo fixed the makefile
285 for building on Windows. Property lists (heritage from MiniScheme)
286 are now optional and have dissappeared from the interface. They
287 should be considered as deprecated.
288
289 Version 1.30
290 After many months, I followed Preston Bannister's advice of
291 using macros and a single source text to keep the enums and the
292 dispatch table in sync, and I used his contributed "opdefines.h".
293 Timothy Downs contributed a helpful function, "scheme_call".
294 Stephen Gildea contributed new versions of the makefile and
295 practically all other sources. He created a built-in STRING-APPEND,
296 and fixed a lot of other bugs.
297 Ruhi Bloodworth reported fixes necessary for OS X and a small
298 bug in dynload.c.
299
300 Version 1.29
301 The previous version contained a lot of corrections, but there
302 were a lot more that still wait on a sheet of paper lost in a
303 carton someplace after my house move... Manuel Heras-Gilsanz
304 noticed this and resent his own contribution, which relies on
305 another bugfix that v.1.28 was missing: a problem with string
306 output, that this version fixes. I hope other people will take
307 the time to resend their contributions, if they didn't make it
308 to v.1.28.
309
310 Version 1.28
311 Many people have contacted me with bugfixes or remarks in
312 the three months I was inactive. A lot of them spotted that
313 scheme_deinit crashed while reporting gc results. They suggested
314 that sc->outport be set to NIL in scheme_deinit, which I did.
315 Dennis Taylor remarked that OP_VALUEPRINT reset sc->value instead
316 of preserving it. He submitted a modification which I adopted
317 partially. David Hovemeyer sent me many little changes, that you
318 will find in version 1.28, and Partice Stoessel modified the
319 float reader to conform to R5RS.
320
321 Version 1.27
322 Version 1.27 is the successor of 1.25. Bug fixes only, but I had to
323 release them so that everybody can profit. 'Backchar' tried to write
324 back to the string, which obviously didn't work for const strings.
325 'Substring' didn't check for crossed start and end indices. Defines
326 changed to restore the ability to compile under MSVC.
327
328 Version 1.26
329 Version 1.26 was never released. I changed a lot of things, in fact
330 too much, even the garbage collector, and hell broke loose. I'll
331 try a more gradual approach next time.
332
333 Version 1.25
334 Types have been homogenized to be able to accommodate a different
335 representation. Plus, promises are no longer closures. Unfortunately,
336 I discovered that continuations and force/delay do not pass the SCM
337 test (and never did)... However, on the bright side, what little
338 modifications I did had a large impact on the footprint:
339 USE_NO_FEATURES now produces an object file of 63960 bytes on Linux!
340
341 Version 1.24
342 SCM tests now pass again after change in atom2str.
343
344 Version 1.23
345 Finally I managed to mess it up with my version control. Version
346 1.22 actually lacked some of the things I have been fixing in the
347 meantime. This should be considered as a complete replacement for
348 1.22.
349
350 Version 1.22
351 The new ports had a bug in LOAD. MK_CLOSURE is introduced.
352 Shawn Wagner inquired about string->number and number->string.
353 I added string->atom and atom->string and defined the number
354 functions from them. Doing that, I fixed WRITE applied to symbols
355 (it didn't quote them). Unfortunately, minimum build is now
356 slightly larger than 64k... I postpone action because Jason's idea
357 might solve it elegantly.
358
359 Version 1.21
360 Jason Felice submitted a radically different datatype representation
361 which he had implemented. While discussing its pros and cons, it
362 became apparent that the current implementation of ports suffered
363 from a grave fault: ports were not garbage-collected. I changed the
364 ports to be heap-allocated, which enabled the use of string ports
365 for loading. Jason also fixed errors in the garbage collection of
366 vectors. USE_VERBATIM is gone. "ssp_compiler.c" has a better solution
367 on HTML generation. A bug involving backslash notation in strings
368 has been fixed. '-c' flag now executes next argument as a stream of
369 Scheme commands. Foreign functions are now also heap allocated,
370 and scheme_define is used to define everything.
371
372 Version 1.20
373 Tracing has been added. The toplevel loop has been slightly
374 rearranged. Backquote reading for vector templates has been
375 sanitized. Symbol interning is now correct. Arithmetic functions
376 have been corrected. APPLY, MAP, FOR-EACH, numeric comparison
377 functions fixed. String reader/writer understands \xAA notation.
378
379 Version 1.19
380 Carriage Return now delimits identifiers. DOS-formatted Scheme files
381 can be used by Unix. Random number generator added to library.
382 Fixed some glitches of the new type-checking scheme. Fixed erroneous
383 (append '() 'a) behavior. Will continue with r4rstest.scm to
384 fix errors.
385
386 Version 1.18
387 The FFI has been extended. USE_VERBOSE_GC has gone. Anyone wanting
388 the same functionality can put (gcverbose #t) in init.scm.
389 print-width was removed, along with three corresponding op-codes.
390 Extended character constants with ASCII names were added.
391 mk_counted_string paves the way for full support of binary strings.
392 As much as possible of the type-checking chores were delegated
393 to the inner loop, thus reducing the code size to less than 4200 loc!
394
395 Version 1.17
396 Dynamically-loaded extensions are more fully integrated.
397 TinyScheme is now distributed under the BSD open-source license.
398
399 Version 1.16
400 Dynamically-loaded extensions introduced (USE_DL).
401 Santeri Paavolainen found a race condition: When a cons is executed,
402 and each of the two arguments is a constructing function, GC could
403 happen before all arguments are evaluated and cons() is called, and
404 the evaluated arguments would all be reclaimed!
405 Fortunately, such a case was rare in the code, although it is
406 a pitfall in new code and code in foreign functions. Currently, only
407 one such case remains, when COLON_HOOK is defined.
408
409 Version 1.15
410 David Gould also contributed some changes that speed up operation.
411 Kirk Zurell fixed HASPROP.
412 The Garbage Collection didn't collect all the garbage...fixed.
413
414 Version 1.14
415 Unfortunately, after Andre fixed the GC it became obvious that the
416 algorithm was too slow... Fortunately, David Gould found a way to
417 speed it up.
418
419 Version 1.13
420 Silly bug involving division by zero resolved by Roland Kaufman.
421 Macintoch support from Shmulik Regev.
422 Float parser bug fixed by Alexander Shendi.
423 GC bug from Andru Luvisi.
424
425 Version 1.12
426 Cis* incorrectly called isalpha() instead of isascii()
427 Added USE_CHAR_CLASSIFIERS, USE_STRING_PORTS.
428
429 Version 1.11
430 BSDI defines isnumber... changed all similar functions to is_*
431 EXPT now has correct definition. Added FLOOR,CEILING,TRUNCATE
432 and ROUND, courtesy of Bengt Kleberg. Preprocessor symbols now
433 have values 1 or 0, and can be set as compiler defines (proposed
434 by Andy Ganor *months* ago). 'prompt' and 'InitFile' can now be
435 defined during compilation, too.
436
437 Version 1.10
438 Another bug when file ends with comment!
439 Added DEFINE-MACRO in init.scm, courtesy of Andy Gaynor.
440
441 Version 1.09
442 Removed bug when READ met EOF. lcm.
443
444 Version 1.08
445 quotient,remainder and modulo. gcd.
446
447 Version 1.07
448 '=>' in cond now exists
449 list? now checks for circularity
450 some reader bugs removed
451 Reader is more consistent wrt vectors
452 Quote and Quasiquote work with vectors
453
454 Version 1.06
455 #! is now skipped
456 generic-assoc bug removed
457 strings are now managed differently, hack.txt is removed
458 various delicate points fixed
459
460 Version 1.05
461 Support for scripts, *args*, "-1" option.
462 Various R5RS procedures.
463 *sharp-hook*
464 Handles unmatched parentheses.
465 New architecture for procedures.
466
467 Version 1.04
468 Added missing T_ATOM bits...
469 Added vectors
470 Free-list is sorted by address, since vectors need consecutive cells.
471 (quit <exitcode>) for use with scripts
472
473 Version 1.03 (26 Aug 1998):
474 Extended .h with useful functions for FFI
475 Library: with-input-* etc.
476 Finished R5RS I/O, added string ports.
477
478 Version 1.02 (25 Aug 1998):
479 First part of R5RS I/O.
-
+ 8318EB755F17767FAC29DFC265973F0355BC973BFA42895E9D353126A9CA4969CE53332D255F5DF8B0C3E3715B5F2C168A5BC30BE5C8DB8C39B27D4D1FA48173
bitcoin/src/shiva/COPYING
(0 . 0)(1 . 31)
484 LICENSE TERMS
485
486 Copyright (c) 2000, Dimitrios Souflis
487 All rights reserved.
488
489 Redistribution and use in source and binary forms, with or without
490 modification, are permitted provided that the following conditions are
491 met:
492
493 Redistributions of source code must retain the above copyright notice,
494 this list of conditions and the following disclaimer.
495
496 Redistributions in binary form must reproduce the above copyright
497 notice, this list of conditions and the following disclaimer in the
498 documentation and/or other materials provided with the distribution.
499
500 Neither the name of Dimitrios Souflis nor the names of the
501 contributors may be used to endorse or promote products derived from
502 this software without specific prior written permission.
503
504 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
505 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
506 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
507 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
508 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
509 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
510 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
511 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
512 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
513 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
514 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+ 37B242324EBF0BAB3BC67812F23111C84D70420348F47F1CB617856E9F18A5E11A30D2CD0CEBB802BC435588BFC49AF3A50D8EB24674A795B83102809C52D3AE
bitcoin/src/shiva/hack.txt
(0 . 0)(1 . 244)
519
520 How to hack TinyScheme
521 ----------------------
522
523 TinyScheme is easy to learn and modify. It is structured like a
524 meta-interpreter, only it is written in C. All data are Scheme
525 objects, which facilitates both understanding/modifying the
526 code and reifying the interpreter workings.
527
528 In place of a dry description, we will pace through the addition
529 of a useful new datatype: garbage-collected memory blocks.
530 The interface will be:
531
532 (make-block <n> [<fill>]) makes a new block of the specified size
533 optionally filling it with a specified byte
534 (block? <obj>)
535 (block-length <block>)
536 (block-ref <block> <index>) retrieves byte at location
537 (block-set! <block> <index> <byte>) modifies byte at location
538
539 In the sequel, lines that begin with '>' denote lines to add to the
540 code. Lines that begin with '|' are just citations of existing code.
541 Lines that begin with X denote lines to be removed from the code.
542
543 First of all, we need to assign a typeid to our new type. Typeids
544 in TinyScheme are small integers declared in the scheme_types enum
545 located near the top of the scheme.c file; it begins with T_STRING.
546 Add a new entry at the end, say T_MEMBLOCK. Remember to adjust the
547 value of T_LAST_SYTEM_TYPE when adding new entries. There can be at
548 most 31 types, but you don't have to worry about that limit yet.
549
550 | T_ENVIRONMENT=14,
551 X T_LAST_SYSTEM_TYPE=14
552 > T_MEMBLOCK=15,
553 > T_LAST_SYSTEM_TYPE=15
554 | };
555
556
557 Then, some helper macros would be useful. Go to where is_string()
558 and the rest are defined and add:
559
560 > INTERFACE INLINE int is_memblock(pointer p) { return (type(p)==T_MEMBLOCK); }
561
562 This actually is a function, because it is meant to be exported by
563 scheme.h. If no foreign function will ever manipulate a memory block,
564 you can instead define it as a macro:
565
566 > #define is_memblock(p) (type(p)==T_MEMBLOCK)
567
568 Then we make space for the new type in the main data structure:
569 struct cell. As it happens, the _string part of the union _object
570 (that is used to hold character strings) has two fields that suit us:
571
572 | struct {
573 | char *_svalue;
574 | int _keynum;
575 | } _string;
576
577 We can use _svalue to hold the actual pointer and _keynum to hold its
578 length. If we couln't reuse existing fields, we could always add other
579 alternatives in union _object.
580
581 We then proceed to write the function that actually makes a new block.
582 For conformance reasons, we name it mk_memblock
583
584 > static pointer mk_memblock(scheme *sc, int len, char fill) {
585 > pointer x;
586 > char *p=(char*)sc->malloc(len);
587 >
588 > if(p==0) {
589 > return sc->NIL;
590 > }
591 > x = get_cell(sc, sc->NIL, sc->NIL);
592 >
593 > typeflag(x) = T_MEMBLOCK|T_ATOM;
594 > strvalue(x)=p;
595 > keynum(x)=len;
596 > memset(p,fill,len);
597 > return (x);
598 > }
599
600 The memory used by the MEMBLOCK will have to be freed when the cell
601 is reclaimed during garbage collection. There is a placeholder for
602 that staff, function finalize_cell(), currently handling strings only.
603
604 | static void finalize_cell(scheme *sc, pointer a) {
605 | if(is_string(a)) {
606 | sc->free(strvalue(a));
607 > } else if(is_memblock(a)) {
608 > sc->free(strvalue(a));
609 | } else if(is_port(a)) {
610
611 There are no MEMBLOCK literals, so we don't concern ourselves with
612 the READER part (yet!). We must cater to the PRINTER, though. We
613 add one case more in atom2str().
614
615 | } else if (iscontinuation(l)) {
616 | p = "#<CONTINUATION>";
617 > } else if (is_memblock(l)) {
618 > p = "#<MEMORY BLOCK>";
619 | } else {
620
621 Whenever a MEMBLOCK is displayed, it will look like that.
622 Now, we must add the interface functions: constructor, predicate,
623 accessor, modifier. We must in fact create new op-codes for the virtual
624 machine underlying TinyScheme. Since version 1.30, TinyScheme uses
625 macros and a single source text to keep the enums and the dispatch table
626 in sync. The op-codes are defined in the opdefines.h file with one line
627 for each op-code. The lines in the file have six columns between the
628 starting _OPDEF( and ending ): A, B, C, D, E, and OP.
629 Note that this file uses unusually long lines to accomodate all the
630 information; adjust your editor to handle this.
631
632 The purpose of the columns is:
633 - Column A is the name of the subroutine that handles the op-code.
634 - Column B is the name of the op-code function.
635 - Columns C and D are the minimum and maximum number of arguments
636 that are accepted by the op-code.
637 - Column E is a set of flags that tells the interpreter the type of
638 each of the arguments expected by the op-code.
639 - Column OP is used in the scheme_opcodes enum located in the
640 scheme-private.h file.
641
642 Op-codes are really just tags for a huge C switch, only this switch
643 is broken up in to a number of different opexe_X functions. The
644 correspondence is made in table "dispatch_table". There, we assign
645 the new op-codes to opexe_2, where the equivalent ones for vectors
646 are situated. We also assign a name for them, and specify the minimum
647 and maximum arity (number of expected arguments). INF_ARG as a maximum
648 arity means "unlimited".
649
650 For reasons of consistency, we add the new op-codes right after those
651 for vectors:
652
653 | _OP_DEF(opexe_2, "vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET )
654 > _OP_DEF(opexe_2, "make-block", 1, 2, TST_NATURAL TST_CHAR, OP_MKBLOCK )
655 > _OP_DEF(opexe_2, "block-length", 1, 1, T_MEMBLOCK, OP_BLOCKLEN )
656 > _OP_DEF(opexe_2, "block-ref", 2, 2, T_MEMBLOCK TST_NATURAL, OP_BLOCKREF )
657 > _OP_DEF(opexe_2, "block-set!", 1, 1, T_MEMBLOCK TST_NATURAL TST_CHAR, OP_BLOCKSET )
658 | _OP_DEF(opexe_3, "not", 1, 1, TST_NONE, OP_NOT )
659
660 We add the predicate along with the other predicates in opexe_3:
661
662 | _OP_DEF(opexe_3, "vector?", 1, 1, TST_ANY, OP_VECTORP )
663 > _OP_DEF(opexe_3, "block?", 1, 1, TST_ANY, OP_BLOCKP )
664 | _OP_DEF(opexe_3, "eq?", 2, 2, TST_ANY, OP_EQ )
665
666 All that remains is to write the actual code to do the processing and
667 add it to the switch statement in opexe_2, after the OP_VECSET case.
668
669 > case OP_MKBLOCK: { /* make-block */
670 > int fill=0;
671 > int len;
672 >
673 > if(!isnumber(car(sc->args))) {
674 > Error_1(sc,"make-block: not a number:",car(sc->args));
675 > }
676 > len=ivalue(car(sc->args));
677 > if(len<=0) {
678 > Error_1(sc,"make-block: not positive:",car(sc->args));
679 > }
680 >
681 > if(cdr(sc->args)!=sc->NIL) {
682 > if(!isnumber(cadr(sc->args)) || ivalue(cadr(sc->args))<0) {
683 > Error_1(sc,"make-block: not a positive number:",cadr(sc->args));
684 > }
685 > fill=charvalue(cadr(sc->args))%255;
686 > }
687 > s_return(sc,mk_memblock(sc,len,(char)fill));
688 > }
689 >
690 > case OP_BLOCKLEN: /* block-length */
691 > if(!ismemblock(car(sc->args))) {
692 > Error_1(sc,"block-length: not a memory block:",car(sc->args));
693 > }
694 > s_return(sc,mk_integer(sc,keynum(car(sc->args))));
695 >
696 > case OP_BLOCKREF: { /* block-ref */
697 > char *str;
698 > int index;
699 >
700 > if(!ismemblock(car(sc->args))) {
701 > Error_1(sc,"block-ref: not a memory block:",car(sc->args));
702 > }
703 > str=strvalue(car(sc->args));
704 >
705 > if(cdr(sc->args)==sc->NIL) {
706 > Error_0(sc,"block-ref: needs two arguments");
707 > }
708 > if(!isnumber(cadr(sc->args))) {
709 > Error_1(sc,"block-ref: not a number:",cadr(sc->args));
710 > }
711 > index=ivalue(cadr(sc->args));
712 >
713 > if(index<0 || index>=keynum(car(sc->args))) {
714 > Error_1(sc,"block-ref: out of bounds:",cadr(sc->args));
715 > }
716 >
717 > s_return(sc,mk_integer(sc,str[index]));
718 > }
719 >
720 > case OP_BLOCKSET: { /* block-set! */
721 > char *str;
722 > int index;
723 > int c;
724 >
725 > if(!ismemblock(car(sc->args))) {
726 > Error_1(sc,"block-set!: not a memory block:",car(sc->args));
727 > }
728 > if(isimmutable(car(sc->args))) {
729 > Error_1(sc,"block-set!: unable to alter immutable memory block:",car(sc->args));
730 > }
731 > str=strvalue(car(sc->args));
732 >
733 > if(cdr(sc->args)==sc->NIL) {
734 > Error_0(sc,"block-set!: needs three arguments");
735 > }
736 > if(!isnumber(cadr(sc->args))) {
737 > Error_1(sc,"block-set!: not a number:",cadr(sc->args));
738 > }
739 > index=ivalue(cadr(sc->args));
740 > if(index<0 || index>=keynum(car(sc->args))) {
741 > Error_1(sc,"block-set!: out of bounds:",cadr(sc->args));
742 > }
743 >
744 > if(cddr(sc->args)==sc->NIL) {
745 > Error_0(sc,"block-set!: needs three arguments");
746 > }
747 > if(!isinteger(caddr(sc->args))) {
748 > Error_1(sc,"block-set!: not an integer:",caddr(sc->args));
749 > }
750 > c=ivalue(caddr(sc->args))%255;
751 >
752 > str[index]=(char)c;
753 > s_return(sc,car(sc->args));
754 > }
755
756 Finally, do the same for the predicate in opexe_3.
757
758 | case OP_VECTORP: /* vector? */
759 | s_retbool(is_vector(car(sc->args)));
760 > case OP_BLOCKP: /* block? */
761 > s_retbool(is_memblock(car(sc->args)));
762 | case OP_EQ: /* eq? */
-
+ 816C72CA3FE3ED9F9A2C1C1E779ADCA1279EDABAF547E70D5BBEBD00300C2062D7C2BA51A3ED200472639640577FB3643D780E204546ACA62807978BA3F54449
bitcoin/src/shiva/init.scm
(0 . 0)(1 . 716)
767 ; Initialization file for TinySCHEME 1.41
768
769 ; Per R5RS, up to four deep compositions should be defined
770 (define (caar x) (car (car x)))
771 (define (cadr x) (car (cdr x)))
772 (define (cdar x) (cdr (car x)))
773 (define (cddr x) (cdr (cdr x)))
774 (define (caaar x) (car (car (car x))))
775 (define (caadr x) (car (car (cdr x))))
776 (define (cadar x) (car (cdr (car x))))
777 (define (caddr x) (car (cdr (cdr x))))
778 (define (cdaar x) (cdr (car (car x))))
779 (define (cdadr x) (cdr (car (cdr x))))
780 (define (cddar x) (cdr (cdr (car x))))
781 (define (cdddr x) (cdr (cdr (cdr x))))
782 (define (caaaar x) (car (car (car (car x)))))
783 (define (caaadr x) (car (car (car (cdr x)))))
784 (define (caadar x) (car (car (cdr (car x)))))
785 (define (caaddr x) (car (car (cdr (cdr x)))))
786 (define (cadaar x) (car (cdr (car (car x)))))
787 (define (cadadr x) (car (cdr (car (cdr x)))))
788 (define (caddar x) (car (cdr (cdr (car x)))))
789 (define (cadddr x) (car (cdr (cdr (cdr x)))))
790 (define (cdaaar x) (cdr (car (car (car x)))))
791 (define (cdaadr x) (cdr (car (car (cdr x)))))
792 (define (cdadar x) (cdr (car (cdr (car x)))))
793 (define (cdaddr x) (cdr (car (cdr (cdr x)))))
794 (define (cddaar x) (cdr (cdr (car (car x)))))
795 (define (cddadr x) (cdr (cdr (car (cdr x)))))
796 (define (cdddar x) (cdr (cdr (cdr (car x)))))
797 (define (cddddr x) (cdr (cdr (cdr (cdr x)))))
798
799 ;;;; Utility to ease macro creation
800 (define (macro-expand form)
801 ((eval (get-closure-code (eval (car form)))) form))
802
803 (define (macro-expand-all form)
804 (if (macro? form)
805 (macro-expand-all (macro-expand form))
806 form))
807
808 (define *compile-hook* macro-expand-all)
809
810
811 (macro (unless form)
812 `(if (not ,(cadr form)) (begin ,@(cddr form))))
813
814 (macro (when form)
815 `(if ,(cadr form) (begin ,@(cddr form))))
816
817 ; DEFINE-MACRO Contributed by Andy Gaynor
818 (macro (define-macro dform)
819 (if (symbol? (cadr dform))
820 `(macro ,@(cdr dform))
821 (let ((form (gensym)))
822 `(macro (,(caadr dform) ,form)
823 (apply (lambda ,(cdadr dform) ,@(cddr dform)) (cdr ,form))))))
824
825 ; Utilities for math. Notice that inexact->exact is primitive,
826 ; but exact->inexact is not.
827 (define exact? integer?)
828 (define (inexact? x) (and (real? x) (not (integer? x))))
829 (define (even? n) (= (remainder n 2) 0))
830 (define (odd? n) (not (= (remainder n 2) 0)))
831 (define (zero? n) (= n 0))
832 (define (positive? n) (> n 0))
833 (define (negative? n) (< n 0))
834 (define complex? number?)
835 (define rational? real?)
836 (define (abs n) (if (>= n 0) n (- n)))
837 (define (exact->inexact n) (* n 1.0))
838 (define (<> n1 n2) (not (= n1 n2)))
839
840 ; min and max must return inexact if any arg is inexact; use (+ n 0.0)
841 (define (max . lst)
842 (foldr (lambda (a b)
843 (if (> a b)
844 (if (exact? b) a (+ a 0.0))
845 (if (exact? a) b (+ b 0.0))))
846 (car lst) (cdr lst)))
847 (define (min . lst)
848 (foldr (lambda (a b)
849 (if (< a b)
850 (if (exact? b) a (+ a 0.0))
851 (if (exact? a) b (+ b 0.0))))
852 (car lst) (cdr lst)))
853
854 (define (succ x) (+ x 1))
855 (define (pred x) (- x 1))
856 (define gcd
857 (lambda a
858 (if (null? a)
859 0
860 (let ((aa (abs (car a)))
861 (bb (abs (cadr a))))
862 (if (= bb 0)
863 aa
864 (gcd bb (remainder aa bb)))))))
865 (define lcm
866 (lambda a
867 (if (null? a)
868 1
869 (let ((aa (abs (car a)))
870 (bb (abs (cadr a))))
871 (if (or (= aa 0) (= bb 0))
872 0
873 (abs (* (quotient aa (gcd aa bb)) bb)))))))
874
875
876 (define (string . charlist)
877 (list->string charlist))
878
879 (define (list->string charlist)
880 (let* ((len (length charlist))
881 (newstr (make-string len))
882 (fill-string!
883 (lambda (str i len charlist)
884 (if (= i len)
885 str
886 (begin (string-set! str i (car charlist))
887 (fill-string! str (+ i 1) len (cdr charlist)))))))
888 (fill-string! newstr 0 len charlist)))
889
890 (define (string-fill! s e)
891 (let ((n (string-length s)))
892 (let loop ((i 0))
893 (if (= i n)
894 s
895 (begin (string-set! s i e) (loop (succ i)))))))
896
897 (define (string->list s)
898 (let loop ((n (pred (string-length s))) (l '()))
899 (if (= n -1)
900 l
901 (loop (pred n) (cons (string-ref s n) l)))))
902
903 (define (string-copy str)
904 (string-append str))
905
906 (define (string->anyatom str pred)
907 (let* ((a (string->atom str)))
908 (if (pred a) a
909 (error "string->xxx: not a xxx" a))))
910
911 (define (string->number str . base)
912 (let ((n (string->atom str (if (null? base) 10 (car base)))))
913 (if (number? n) n #f)))
914
915 (define (anyatom->string n pred)
916 (if (pred n)
917 (atom->string n)
918 (error "xxx->string: not a xxx" n)))
919
920 (define (number->string n . base)
921 (atom->string n (if (null? base) 10 (car base))))
922
923
924 (define (char-cmp? cmp a b)
925 (cmp (char->integer a) (char->integer b)))
926 (define (char-ci-cmp? cmp a b)
927 (cmp (char->integer (char-downcase a)) (char->integer (char-downcase b))))
928
929 (define (char=? a b) (char-cmp? = a b))
930 (define (char<? a b) (char-cmp? < a b))
931 (define (char>? a b) (char-cmp? > a b))
932 (define (char<=? a b) (char-cmp? <= a b))
933 (define (char>=? a b) (char-cmp? >= a b))
934
935 (define (char-ci=? a b) (char-ci-cmp? = a b))
936 (define (char-ci<? a b) (char-ci-cmp? < a b))
937 (define (char-ci>? a b) (char-ci-cmp? > a b))
938 (define (char-ci<=? a b) (char-ci-cmp? <= a b))
939 (define (char-ci>=? a b) (char-ci-cmp? >= a b))
940
941 ; Note the trick of returning (cmp x y)
942 (define (string-cmp? chcmp cmp a b)
943 (let ((na (string-length a)) (nb (string-length b)))
944 (let loop ((i 0))
945 (cond
946 ((= i na)
947 (if (= i nb) (cmp 0 0) (cmp 0 1)))
948 ((= i nb)
949 (cmp 1 0))
950 ((chcmp = (string-ref a i) (string-ref b i))
951 (loop (succ i)))
952 (else
953 (chcmp cmp (string-ref a i) (string-ref b i)))))))
954
955
956 (define (string=? a b) (string-cmp? char-cmp? = a b))
957 (define (string<? a b) (string-cmp? char-cmp? < a b))
958 (define (string>? a b) (string-cmp? char-cmp? > a b))
959 (define (string<=? a b) (string-cmp? char-cmp? <= a b))
960 (define (string>=? a b) (string-cmp? char-cmp? >= a b))
961
962 (define (string-ci=? a b) (string-cmp? char-ci-cmp? = a b))
963 (define (string-ci<? a b) (string-cmp? char-ci-cmp? < a b))
964 (define (string-ci>? a b) (string-cmp? char-ci-cmp? > a b))
965 (define (string-ci<=? a b) (string-cmp? char-ci-cmp? <= a b))
966 (define (string-ci>=? a b) (string-cmp? char-ci-cmp? >= a b))
967
968 (define (list . x) x)
969
970 (define (foldr f x lst)
971 (if (null? lst)
972 x
973 (foldr f (f x (car lst)) (cdr lst))))
974
975 (define (unzip1-with-cdr . lists)
976 (unzip1-with-cdr-iterative lists '() '()))
977
978 (define (unzip1-with-cdr-iterative lists cars cdrs)
979 (if (null? lists)
980 (cons cars cdrs)
981 (let ((car1 (caar lists))
982 (cdr1 (cdar lists)))
983 (unzip1-with-cdr-iterative
984 (cdr lists)
985 (append cars (list car1))
986 (append cdrs (list cdr1))))))
987
988 (define (map proc . lists)
989 (if (null? lists)
990 (apply proc)
991 (if (null? (car lists))
992 '()
993 (let* ((unz (apply unzip1-with-cdr lists))
994 (cars (car unz))
995 (cdrs (cdr unz)))
996 (cons (apply proc cars) (apply map (cons proc cdrs)))))))
997
998 (define (for-each proc . lists)
999 (if (null? lists)
1000 (apply proc)
1001 (if (null? (car lists))
1002 #t
1003 (let* ((unz (apply unzip1-with-cdr lists))
1004 (cars (car unz))
1005 (cdrs (cdr unz)))
1006 (apply proc cars) (apply map (cons proc cdrs))))))
1007
1008 (define (list-tail x k)
1009 (if (zero? k)
1010 x
1011 (list-tail (cdr x) (- k 1))))
1012
1013 (define (list-ref x k)
1014 (car (list-tail x k)))
1015
1016 (define (last-pair x)
1017 (if (pair? (cdr x))
1018 (last-pair (cdr x))
1019 x))
1020
1021 (define (head stream) (car stream))
1022
1023 (define (tail stream) (force (cdr stream)))
1024
1025 (define (vector-equal? x y)
1026 (and (vector? x) (vector? y) (= (vector-length x) (vector-length y))
1027 (let ((n (vector-length x)))
1028 (let loop ((i 0))
1029 (if (= i n)
1030 #t
1031 (and (equal? (vector-ref x i) (vector-ref y i))
1032 (loop (succ i))))))))
1033
1034 (define (list->vector x)
1035 (apply vector x))
1036
1037 (define (vector-fill! v e)
1038 (let ((n (vector-length v)))
1039 (let loop ((i 0))
1040 (if (= i n)
1041 v
1042 (begin (vector-set! v i e) (loop (succ i)))))))
1043
1044 (define (vector->list v)
1045 (let loop ((n (pred (vector-length v))) (l '()))
1046 (if (= n -1)
1047 l
1048 (loop (pred n) (cons (vector-ref v n) l)))))
1049
1050 ;; The following quasiquote macro is due to Eric S. Tiedemann.
1051 ;; Copyright 1988 by Eric S. Tiedemann; all rights reserved.
1052 ;;
1053 ;; Subsequently modified to handle vectors: D. Souflis
1054
1055 (macro
1056 quasiquote
1057 (lambda (l)
1058 (define (mcons f l r)
1059 (if (and (pair? r)
1060 (eq? (car r) 'quote)
1061 (eq? (car (cdr r)) (cdr f))
1062 (pair? l)
1063 (eq? (car l) 'quote)
1064 (eq? (car (cdr l)) (car f)))
1065 (if (or (procedure? f) (number? f) (string? f))
1066 f
1067 (list 'quote f))
1068 (if (eqv? l vector)
1069 (apply l (eval r))
1070 (list 'cons l r)
1071 )))
1072 (define (mappend f l r)
1073 (if (or (null? (cdr f))
1074 (and (pair? r)
1075 (eq? (car r) 'quote)
1076 (eq? (car (cdr r)) '())))
1077 l
1078 (list 'append l r)))
1079 (define (foo level form)
1080 (cond ((not (pair? form))
1081 (if (or (procedure? form) (number? form) (string? form))
1082 form
1083 (list 'quote form))
1084 )
1085 ((eq? 'quasiquote (car form))
1086 (mcons form ''quasiquote (foo (+ level 1) (cdr form))))
1087 (#t (if (zero? level)
1088 (cond ((eq? (car form) 'unquote) (car (cdr form)))
1089 ((eq? (car form) 'unquote-splicing)
1090 (error "Unquote-splicing wasn't in a list:"
1091 form))
1092 ((and (pair? (car form))
1093 (eq? (car (car form)) 'unquote-splicing))
1094 (mappend form (car (cdr (car form)))
1095 (foo level (cdr form))))
1096 (#t (mcons form (foo level (car form))
1097 (foo level (cdr form)))))
1098 (cond ((eq? (car form) 'unquote)
1099 (mcons form ''unquote (foo (- level 1)
1100 (cdr form))))
1101 ((eq? (car form) 'unquote-splicing)
1102 (mcons form ''unquote-splicing
1103 (foo (- level 1) (cdr form))))
1104 (#t (mcons form (foo level (car form))
1105 (foo level (cdr form)))))))))
1106 (foo 0 (car (cdr l)))))
1107
1108 ;;;;;Helper for the dynamic-wind definition. By Tom Breton (Tehom)
1109 (define (shared-tail x y)
1110 (let ((len-x (length x))
1111 (len-y (length y)))
1112 (define (shared-tail-helper x y)
1113 (if
1114 (eq? x y)
1115 x
1116 (shared-tail-helper (cdr x) (cdr y))))
1117
1118 (cond
1119 ((> len-x len-y)
1120 (shared-tail-helper
1121 (list-tail x (- len-x len-y))
1122 y))
1123 ((< len-x len-y)
1124 (shared-tail-helper
1125 x
1126 (list-tail y (- len-y len-x))))
1127 (#t (shared-tail-helper x y)))))
1128
1129 ;;;;;Dynamic-wind by Tom Breton (Tehom)
1130
1131 ;;Guarded because we must only eval this once, because doing so
1132 ;;redefines call/cc in terms of old call/cc
1133 (unless (defined? 'dynamic-wind)
1134 (let
1135 ;;These functions are defined in the context of a private list of
1136 ;;pairs of before/after procs.
1137 ( (*active-windings* '())
1138 ;;We'll define some functions into the larger environment, so
1139 ;;we need to know it.
1140 (outer-env (current-environment)))
1141
1142 ;;Poor-man's structure operations
1143 (define before-func car)
1144 (define after-func cdr)
1145 (define make-winding cons)
1146
1147 ;;Manage active windings
1148 (define (activate-winding! new)
1149 ((before-func new))
1150 (set! *active-windings* (cons new *active-windings*)))
1151 (define (deactivate-top-winding!)
1152 (let ((old-top (car *active-windings*)))
1153 ;;Remove it from the list first so it's not active during its
1154 ;;own exit.
1155 (set! *active-windings* (cdr *active-windings*))
1156 ((after-func old-top))))
1157
1158 (define (set-active-windings! new-ws)
1159 (unless (eq? new-ws *active-windings*)
1160 (let ((shared (shared-tail new-ws *active-windings*)))
1161
1162 ;;Define the looping functions.
1163 ;;Exit the old list. Do deeper ones last. Don't do
1164 ;;any shared ones.
1165 (define (pop-many)
1166 (unless (eq? *active-windings* shared)
1167 (deactivate-top-winding!)
1168 (pop-many)))
1169 ;;Enter the new list. Do deeper ones first so that the
1170 ;;deeper windings will already be active. Don't do any
1171 ;;shared ones.
1172 (define (push-many new-ws)
1173 (unless (eq? new-ws shared)
1174 (push-many (cdr new-ws))
1175 (activate-winding! (car new-ws))))
1176
1177 ;;Do it.
1178 (pop-many)
1179 (push-many new-ws))))
1180
1181 ;;The definitions themselves.
1182 (eval
1183 `(define call-with-current-continuation
1184 ;;It internally uses the built-in call/cc, so capture it.
1185 ,(let ((old-c/cc call-with-current-continuation))
1186 (lambda (func)
1187 ;;Use old call/cc to get the continuation.
1188 (old-c/cc
1189 (lambda (continuation)
1190 ;;Call func with not the continuation itself
1191 ;;but a procedure that adjusts the active
1192 ;;windings to what they were when we made
1193 ;;this, and only then calls the
1194 ;;continuation.
1195 (func
1196 (let ((current-ws *active-windings*))
1197 (lambda (x)
1198 (set-active-windings! current-ws)
1199 (continuation x)))))))))
1200 outer-env)
1201 ;;We can't just say "define (dynamic-wind before thunk after)"
1202 ;;because the lambda it's defined to lives in this environment,
1203 ;;not in the global environment.
1204 (eval
1205 `(define dynamic-wind
1206 ,(lambda (before thunk after)
1207 ;;Make a new winding
1208 (activate-winding! (make-winding before after))
1209 (let ((result (thunk)))
1210 ;;Get rid of the new winding.
1211 (deactivate-top-winding!)
1212 ;;The return value is that of thunk.
1213 result)))
1214 outer-env)))
1215
1216 (define call/cc call-with-current-continuation)
1217
1218
1219 ;;;;; atom? and equal? written by a.k
1220
1221 ;;;; atom?
1222 (define (atom? x)
1223 (not (pair? x)))
1224
1225 ;;;; equal?
1226 (define (equal? x y)
1227 (cond
1228 ((pair? x)
1229 (and (pair? y)
1230 (equal? (car x) (car y))
1231 (equal? (cdr x) (cdr y))))
1232 ((vector? x)
1233 (and (vector? y) (vector-equal? x y)))
1234 ((string? x)
1235 (and (string? y) (string=? x y)))
1236 (else (eqv? x y))))
1237
1238 ;;;; (do ((var init inc) ...) (endtest result ...) body ...)
1239 ;;
1240 (macro do
1241 (lambda (do-macro)
1242 (apply (lambda (do vars endtest . body)
1243 (let ((do-loop (gensym)))
1244 `(letrec ((,do-loop
1245 (lambda ,(map (lambda (x)
1246 (if (pair? x) (car x) x))
1247 `,vars)
1248 (if ,(car endtest)
1249 (begin ,@(cdr endtest))
1250 (begin
1251 ,@body
1252 (,do-loop
1253 ,@(map (lambda (x)
1254 (cond
1255 ((not (pair? x)) x)
1256 ((< (length x) 3) (car x))
1257 (else (car (cdr (cdr x))))))
1258 `,vars)))))))
1259 (,do-loop
1260 ,@(map (lambda (x)
1261 (if (and (pair? x) (cdr x))
1262 (car (cdr x))
1263 '()))
1264 `,vars)))))
1265 do-macro)))
1266
1267 ;;;; generic-member
1268 (define (generic-member cmp obj lst)
1269 (cond
1270 ((null? lst) #f)
1271 ((cmp obj (car lst)) lst)
1272 (else (generic-member cmp obj (cdr lst)))))
1273
1274 (define (memq obj lst)
1275 (generic-member eq? obj lst))
1276 (define (memv obj lst)
1277 (generic-member eqv? obj lst))
1278 (define (member obj lst)
1279 (generic-member equal? obj lst))
1280
1281 ;;;; generic-assoc
1282 (define (generic-assoc cmp obj alst)
1283 (cond
1284 ((null? alst) #f)
1285 ((cmp obj (caar alst)) (car alst))
1286 (else (generic-assoc cmp obj (cdr alst)))))
1287
1288 (define (assq obj alst)
1289 (generic-assoc eq? obj alst))
1290 (define (assv obj alst)
1291 (generic-assoc eqv? obj alst))
1292 (define (assoc obj alst)
1293 (generic-assoc equal? obj alst))
1294
1295 (define (acons x y z) (cons (cons x y) z))
1296
1297 ;;;; Handy for imperative programs
1298 ;;;; Used as: (define-with-return (foo x y) .... (return z) ...)
1299 (macro (define-with-return form)
1300 `(define ,(cadr form)
1301 (call/cc (lambda (return) ,@(cddr form)))))
1302
1303 ;;;; Simple exception handling
1304 ;
1305 ; Exceptions are caught as follows:
1306 ;
1307 ; (catch (do-something to-recover and-return meaningful-value)
1308 ; (if-something goes-wrong)
1309 ; (with-these calls))
1310 ;
1311 ; "Catch" establishes a scope spanning multiple call-frames
1312 ; until another "catch" is encountered.
1313 ;
1314 ; Exceptions are thrown with:
1315 ;
1316 ; (throw "message")
1317 ;
1318 ; If used outside a (catch ...), reverts to (error "message)
1319
1320 (define *handlers* (list))
1321
1322 (define (push-handler proc)
1323 (set! *handlers* (cons proc *handlers*)))
1324
1325 (define (pop-handler)
1326 (let ((h (car *handlers*)))
1327 (set! *handlers* (cdr *handlers*))
1328 h))
1329
1330 (define (more-handlers?)
1331 (pair? *handlers*))
1332
1333 (define (throw . x)
1334 (if (more-handlers?)
1335 (apply (pop-handler))
1336 (apply error x)))
1337
1338 (macro (catch form)
1339 (let ((label (gensym)))
1340 `(call/cc (lambda (exit)
1341 (push-handler (lambda () (exit ,(cadr form))))
1342 (let ((,label (begin ,@(cddr form))))
1343 (pop-handler)
1344 ,label)))))
1345
1346 (define *error-hook* throw)
1347
1348
1349 ;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL
1350
1351 (macro (make-environment form)
1352 `(apply (lambda ()
1353 ,@(cdr form)
1354 (current-environment))))
1355
1356 (define-macro (eval-polymorphic x . envl)
1357 (display envl)
1358 (let* ((env (if (null? envl) (current-environment) (eval (car envl))))
1359 (xval (eval x env)))
1360 (if (closure? xval)
1361 (make-closure (get-closure-code xval) env)
1362 xval)))
1363
1364 ; Redefine this if you install another package infrastructure
1365 ; Also redefine 'package'
1366 (define *colon-hook* eval)
1367
1368 ;;;;; I/O
1369
1370 (define (input-output-port? p)
1371 (and (input-port? p) (output-port? p)))
1372
1373 (define (close-port p)
1374 (cond
1375 ((input-output-port? p) (close-input-port (close-output-port p)))
1376 ((input-port? p) (close-input-port p))
1377 ((output-port? p) (close-output-port p))
1378 (else (throw "Not a port" p))))
1379
1380 (define (call-with-input-file s p)
1381 (let ((inport (open-input-file s)))
1382 (if (eq? inport #f)
1383 #f
1384 (let ((res (p inport)))
1385 (close-input-port inport)
1386 res))))
1387
1388 (define (call-with-output-file s p)
1389 (let ((outport (open-output-file s)))
1390 (if (eq? outport #f)
1391 #f
1392 (let ((res (p outport)))
1393 (close-output-port outport)
1394 res))))
1395
1396 (define (with-input-from-file s p)
1397 (let ((inport (open-input-file s)))
1398 (if (eq? inport #f)
1399 #f
1400 (let ((prev-inport (current-input-port)))
1401 (set-input-port inport)
1402 (let ((res (p)))
1403 (close-input-port inport)
1404 (set-input-port prev-inport)
1405 res)))))
1406
1407 (define (with-output-to-file s p)
1408 (let ((outport (open-output-file s)))
1409 (if (eq? outport #f)
1410 #f
1411 (let ((prev-outport (current-output-port)))
1412 (set-output-port outport)
1413 (let ((res (p)))
1414 (close-output-port outport)
1415 (set-output-port prev-outport)
1416 res)))))
1417
1418 (define (with-input-output-from-to-files si so p)
1419 (let ((inport (open-input-file si))
1420 (outport (open-input-file so)))
1421 (if (not (and inport outport))
1422 (begin
1423 (close-input-port inport)
1424 (close-output-port outport)
1425 #f)
1426 (let ((prev-inport (current-input-port))
1427 (prev-outport (current-output-port)))
1428 (set-input-port inport)
1429 (set-output-port outport)
1430 (let ((res (p)))
1431 (close-input-port inport)
1432 (close-output-port outport)
1433 (set-input-port prev-inport)
1434 (set-output-port prev-outport)
1435 res)))))
1436
1437 ; Random number generator (maximum cycle)
1438 (define *seed* 1)
1439 (define (random-next)
1440 (let* ((a 16807) (m 2147483647) (q (quotient m a)) (r (modulo m a)))
1441 (set! *seed*
1442 (- (* a (- *seed*
1443 (* (quotient *seed* q) q)))
1444 (* (quotient *seed* q) r)))
1445 (if (< *seed* 0) (set! *seed* (+ *seed* m)))
1446 *seed*))
1447 ;; SRFI-0
1448 ;; COND-EXPAND
1449 ;; Implemented as a macro
1450 (define *features* '(srfi-0))
1451
1452 (define-macro (cond-expand . cond-action-list)
1453 (cond-expand-runtime cond-action-list))
1454
1455 (define (cond-expand-runtime cond-action-list)
1456 (if (null? cond-action-list)
1457 #t
1458 (if (cond-eval (caar cond-action-list))
1459 `(begin ,@(cdar cond-action-list))
1460 (cond-expand-runtime (cdr cond-action-list)))))
1461
1462 (define (cond-eval-and cond-list)
1463 (foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list))
1464
1465 (define (cond-eval-or cond-list)
1466 (foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list))
1467
1468 (define (cond-eval condition)
1469 (cond
1470 ((symbol? condition)
1471 (if (member condition *features*) #t #f))
1472 ((eq? condition #t) #t)
1473 ((eq? condition #f) #f)
1474 (else (case (car condition)
1475 ((and) (cond-eval-and (cdr condition)))
1476 ((or) (cond-eval-or (cdr condition)))
1477 ((not) (if (not (null? (cddr condition)))
1478 (error "cond-expand : 'not' takes 1 argument")
1479 (not (cond-eval (cadr condition)))))
1480 (else (error "cond-expand : unknown operator" (car condition)))))))
1481
1482 (gc-verbose #f)
-
+ C48269A2C2F362F53C3E68E188B54351006342812EEAEA1CC41418C4CF1BFD0E780CF215AAD11E50FB0C53E1EEF05874121958BEE709E35E131D32B85831BC46
bitcoin/src/shiva/Manual.txt
(0 . 0)(1 . 452)
1487
1488
1489 TinySCHEME Version 1.41
1490
1491 "Safe if used as prescribed"
1492 -- Philip K. Dick, "Ubik"
1493
1494 This software is open source, covered by a BSD-style license.
1495 Please read accompanying file COPYING.
1496 -------------------------------------------------------------------------------
1497
1498 This Scheme interpreter is based on MiniSCHEME version 0.85k4
1499 (see miniscm.tar.gz in the Scheme Repository)
1500 Original credits in file MiniSCHEMETribute.txt.
1501
1502 D. Souflis (dsouflis@acm.org)
1503
1504 -------------------------------------------------------------------------------
1505 What is TinyScheme?
1506 -------------------
1507
1508 TinyScheme is a lightweight Scheme interpreter that implements as large
1509 a subset of R5RS as was possible without getting very large and
1510 complicated. It is meant to be used as an embedded scripting interpreter
1511 for other programs. As such, it does not offer IDEs or extensive toolkits
1512 although it does sport a small top-level loop, included conditionally.
1513 A lot of functionality in TinyScheme is included conditionally, to allow
1514 developers freedom in balancing features and footprint.
1515
1516 As an embedded interpreter, it allows multiple interpreter states to
1517 coexist in the same program, without any interference between them.
1518 Programmatically, foreign functions in C can be added and values
1519 can be defined in the Scheme environment. Being a quite small program,
1520 it is easy to comprehend, get to grips with, and use.
1521
1522 Known bugs
1523 ----------
1524
1525 TinyScheme is known to misbehave when memory is exhausted.
1526
1527
1528 Things that keep missing, or that need fixing
1529 ---------------------------------------------
1530
1531 There are no hygienic macros. No rational or
1532 complex numbers. No unwind-protect and call-with-values.
1533
1534 Maybe (a subset of) SLIB will work with TinySCHEME...
1535
1536 Decent debugging facilities are missing. Only tracing is supported
1537 natively.
1538
1539
1540 Scheme Reference
1541 ----------------
1542
1543 If something seems to be missing, please refer to the code and
1544 "init.scm", since some are library functions. Refer to the MiniSCHEME
1545 readme as a last resort.
1546
1547 Environments
1548 (interaction-environment)
1549 See R5RS. In TinySCHEME, immutable list of association lists.
1550
1551 (current-environment)
1552 The environment in effect at the time of the call. An example of its
1553 use and its utility can be found in the sample code that implements
1554 packages in "init.scm":
1555
1556 (macro (package form)
1557 `(apply (lambda ()
1558 ,@(cdr form)
1559 (current-environment))))
1560
1561 The environment containing the (local) definitions inside the closure
1562 is returned as an immutable value.
1563
1564 (defined? <symbol>) (defined? <symbol> <environment>)
1565 Checks whether the given symbol is defined in the current (or given)
1566 environment.
1567
1568 Symbols
1569 (gensym)
1570 Returns a new interned symbol each time. Will probably move to the
1571 library when string->symbol is implemented.
1572
1573 Directives
1574 (gc)
1575 Performs garbage collection immediatelly.
1576
1577 (gcverbose) (gcverbose <bool>)
1578 The argument (defaulting to #t) controls whether GC produces
1579 visible outcome.
1580
1581 (quit) (quit <num>)
1582 Stops the interpreter and sets the 'retcode' internal field (defaults
1583 to 0). When standalone, 'retcode' is returned as exit code to the OS.
1584
1585 (tracing <num>)
1586 1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1).
1587
1588 Mathematical functions
1589 Since rationals and complexes are absent, the respective functions
1590 are also missing.
1591 Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling,
1592 trunc, round and also sqrt and expt when USE_MATH=1.
1593 Number-theoretical quotient, remainder and modulo, gcd, lcm.
1594 Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?,
1595 exact->inexact. inexact->exact is a core function.
1596
1597 Type predicates
1598 boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?,
1599 char?,port?,input-port?,output-port?,procedure?,pair?,environment?',
1600 vector?. Also closure?, macro?.
1601
1602 Types
1603 Types supported:
1604
1605 Numbers (integers and reals)
1606 Symbols
1607 Pairs
1608 Strings
1609 Characters
1610 Ports
1611 Eof object
1612 Environments
1613 Vectors
1614
1615 Literals
1616 String literals can contain escaped quotes \" as usual, but also
1617 \n, \r, \t, \xDD (hex representations) and \DDD (octal representations).
1618 Note also that it is possible to include literal newlines in string
1619 literals, e.g.
1620
1621 (define s "String with newline here
1622 and here
1623 that can function like a HERE-string")
1624
1625 Character literals contain #\space and #\newline and are supplemented
1626 with #\return and #\tab, with obvious meanings. Hex character
1627 representations are allowed (e.g. #\x20 is #\space).
1628 When USE_ASCII_NAMES is defined, various control characters can be
1629 referred to by their ASCII name.
1630 0 #\nul 17 #\dc1
1631 1 #\soh 18 #\dc2
1632 2 #\stx 19 #\dc3
1633 3 #\etx 20 #\dc4
1634 4 #\eot 21 #\nak
1635 5 #\enq 22 #\syn
1636 6 #\ack 23 #\etv
1637 7 #\bel 24 #\can
1638 8 #\bs 25 #\em
1639 9 #\ht 26 #\sub
1640 10 #\lf 27 #\esc
1641 11 #\vt 28 #\fs
1642 12 #\ff 29 #\gs
1643 13 #\cr 30 #\rs
1644 14 #\so 31 #\us
1645 15 #\si
1646 16 #\dle 127 #\del
1647
1648 Numeric literals support #x #o #b and #d. Flonums are currently read only
1649 in decimal notation. Full grammar will be supported soon.
1650
1651 Quote, quasiquote etc.
1652 As usual.
1653
1654 Immutable values
1655 Immutable pairs cannot be modified by set-car! and set-cdr!.
1656 Immutable strings cannot be modified via string-set!
1657
1658 I/O
1659 As per R5RS, plus String Ports (see below).
1660 current-input-port, current-output-port,
1661 close-input-port, close-output-port, input-port?, output-port?,
1662 open-input-file, open-output-file.
1663 read, write, display, newline, write-char, read-char, peek-char.
1664 char-ready? returns #t only for string ports, because there is no
1665 portable way in stdio to determine if a character is available.
1666 Also open-input-output-file, set-input-port, set-output-port (not R5RS)
1667 Library: call-with-input-file, call-with-output-file,
1668 with-input-from-file, with-output-from-file and
1669 with-input-output-from-to-files, close-port and input-output-port?
1670 (not R5RS).
1671 String Ports: open-input-string, open-output-string, get-output-string,
1672 open-input-output-string. Strings can be used with I/O routines.
1673
1674 Vectors
1675 make-vector, vector, vector-length, vector-ref, vector-set!, list->vector,
1676 vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS)
1677
1678 Strings
1679 string, make-string, list->string, string-length, string-ref, string-set!,
1680 substring, string->list, string-fill!, string-append, string-copy.
1681 string=?, string<?, string>?, string>?, string<=?, string>=?.
1682 (No string-ci*? yet). string->number, number->string. Also atom->string,
1683 string->atom (not R5RS).
1684
1685 Symbols
1686 symbol->string, string->symbol
1687
1688 Characters
1689 integer->char, char->integer.
1690 char=?, char<?, char>?, char<=?, char>=?.
1691 (No char-ci*?)
1692
1693 Pairs & Lists
1694 cons, car, cdr, list, length, map, for-each, foldr, list-tail,
1695 list-ref, last-pair, reverse, append.
1696 Also member, memq, memv, based on generic-member, assoc, assq, assv
1697 based on generic-assoc.
1698
1699 Streams
1700 head, tail, cons-stream
1701
1702 Control features
1703 Apart from procedure?, also macro? and closure?
1704 map, for-each, force, delay, call-with-current-continuation (or call/cc),
1705 eval, apply. 'Forcing' a value that is not a promise produces the value.
1706 There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in
1707 the presence of continuations would require support from the abstract
1708 machine itself.
1709
1710 Property lists
1711 TinyScheme inherited from MiniScheme property lists for symbols.
1712 put, get.
1713
1714 Dynamically-loaded extensions
1715 (load-extension <filename without extension>)
1716 Loads a DLL declaring foreign procedures. On Unix/Linux, one can make use
1717 of the ld.so.conf file or the LD_RUN_PATH system variable in order to place
1718 the library in a directory other than the current one. Please refer to the
1719 appropriate 'man' page.
1720
1721 Esoteric procedures
1722 (oblist)
1723 Returns the oblist, an immutable list of all the symbols.
1724
1725 (macro-expand <form>)
1726 Returns the expanded form of the macro call denoted by the argument
1727
1728 (define-with-return (<procname> <args>...) <body>)
1729 Like plain 'define', but makes the continuation available as 'return'
1730 inside the procedure. Handy for imperative programs.
1731
1732 (new-segment <num>)
1733 Allocates more memory segments.
1734
1735 defined?
1736 See "Environments"
1737
1738 (get-closure-code <closure>)
1739 Gets the code as scheme data.
1740
1741 (make-closure <code> <environment>)
1742 Makes a new closure in the given environment.
1743
1744 Obsolete procedures
1745 (print-width <object>)
1746
1747 Programmer's Reference
1748 ----------------------
1749
1750 The interpreter state is initialized with "scheme_init".
1751 Custom memory allocation routines can be installed with an alternate
1752 initialization function: "scheme_init_custom_alloc".
1753 Files can be loaded with "scheme_load_file". Strings containing Scheme
1754 code can be loaded with "scheme_load_string". It is a good idea to
1755 "scheme_load" init.scm before anything else.
1756
1757 External data for keeping external state (of use to foreign functions)
1758 can be installed with "scheme_set_external_data".
1759 Foreign functions are installed with "assign_foreign". Additional
1760 definitions can be added to the interpreter state, with "scheme_define"
1761 (this is the way HTTP header data and HTML form data are passed to the
1762 Scheme script in the Altera SQL Server). If you wish to define the
1763 foreign function in a specific environment (to enhance modularity),
1764 use "assign_foreign_env".
1765
1766 The procedure "scheme_apply0" has been added with persistent scripts in
1767 mind. Persistent scripts are loaded once, and every time they are needed
1768 to produce HTTP output, appropriate data are passed through global
1769 definitions and function "main" is called to do the job. One could
1770 add easily "scheme_apply1" etc.
1771
1772 The interpreter state should be deinitialized with "scheme_deinit".
1773
1774 DLLs containing foreign functions should define a function named
1775 init_<base-name>. E.g. foo.dll should define init_foo, and bar.so
1776 should define init_bar. This function should assign_foreign any foreign
1777 function contained in the DLL.
1778
1779 The first dynamically loaded extension available for TinyScheme is
1780 a regular expression library. Although it's by no means an
1781 established standard, this library is supposed to be installed in
1782 a directory mirroring its name under the TinyScheme location.
1783
1784
1785 Foreign Functions
1786 -----------------
1787
1788 The user can add foreign functions in C. For example, a function
1789 that squares its argument:
1790
1791 pointer square(scheme *sc, pointer args) {
1792 if(args!=sc->NIL) {
1793 if(sc->isnumber(sc->pair_car(args))) {
1794 double v=sc->rvalue(sc->pair_car(args));
1795 return sc->mk_real(sc,v*v);
1796 }
1797 }
1798 return sc->NIL;
1799 }
1800
1801 Foreign functions are now defined as closures:
1802
1803 sc->interface->scheme_define(
1804 sc,
1805 sc->global_env,
1806 sc->interface->mk_symbol(sc,"square"),
1807 sc->interface->mk_foreign_func(sc, square));
1808
1809
1810 Foreign functions can use the external data in the "scheme" struct
1811 to implement any kind of external state.
1812
1813 External data are set with the following function:
1814 void scheme_set_external_data(scheme *sc, void *p);
1815
1816 As of v.1.17, the canonical way for a foreign function in a DLL to
1817 manipulate Scheme data is using the function pointers in sc->interface.
1818
1819 Standalone
1820 ----------
1821
1822 Usage: tinyscheme -?
1823 or: tinyscheme [<file1> <file2> ...]
1824 followed by
1825 -1 <file> [<arg1> <arg2> ...]
1826 -c <Scheme commands> [<arg1> <arg2> ...]
1827 assuming that the executable is named tinyscheme.
1828
1829 Use - in the place of a filename to denote stdin.
1830 The -1 flag is meant for #! usage in shell scripts. If you specify
1831 #! /somewhere/tinyscheme -1
1832 then tinyscheme will be called to process the file. For example, the
1833 following script echoes the Scheme list of its arguments.
1834
1835 #! /somewhere/tinyscheme -1
1836 (display *args*)
1837
1838 The -c flag permits execution of arbitrary Scheme code.
1839
1840
1841 Error Handling
1842 --------------
1843
1844 Errors are recovered from without damage. The user can install his
1845 own handler for system errors, by defining *error-hook*. Defining
1846 to '() gives the default behavior, which is equivalent to "error".
1847 USE_ERROR_HOOK must be defined.
1848
1849 A simple exception handling mechanism can be found in "init.scm".
1850 A new syntactic form is introduced:
1851
1852 (catch <expr returned exceptionally>
1853 <expr1> <expr2> ... <exprN>)
1854
1855 "Catch" establishes a scope spanning multiple call-frames
1856 until another "catch" is encountered.
1857
1858 Exceptions are thrown with:
1859
1860 (throw "message")
1861
1862 If used outside a (catch ...), reverts to (error "message").
1863
1864 Example of use:
1865
1866 (define (foo x) (write x) (newline) (/ x 0))
1867
1868 (catch (begin (display "Error!\n") 0)
1869 (write "Before foo ... ")
1870 (foo 5)
1871 (write "After foo"))
1872
1873 The exception mechanism can be used even by system errors, by
1874
1875 (define *error-hook* throw)
1876
1877 which makes use of the error hook described above.
1878
1879 If necessary, the user can devise his own exception mechanism with
1880 tagged exceptions etc.
1881
1882
1883 Reader extensions
1884 -----------------
1885
1886 When encountering an unknown character after '#', the user-specified
1887 procedure *sharp-hook* (if any), is called to read the expression.
1888 This can be used to extend the reader to handle user-defined constants
1889 or whatever. It should be a procedure without arguments, reading from
1890 the current input port (which will be the load-port).
1891
1892
1893 Colon Qualifiers - Packages
1894 ---------------------------
1895
1896 When USE_COLON_HOOK=1:
1897 The lexer now recognizes the construction <qualifier>::<symbol> and
1898 transforms it in the following manner (T is the transformation function):
1899
1900 T(<qualifier>::<symbol>) = (*colon-hook* 'T(<symbol>) <qualifier>)
1901
1902 where <qualifier> is a symbol not containing any double-colons.
1903
1904 As the definition is recursive, qualifiers can be nested.
1905 The user can define his own *colon-hook*, to handle qualified names.
1906 By default, "init.scm" defines *colon-hook* as EVAL. Consequently,
1907 the qualifier must denote a Scheme environment, such as one returned
1908 by (interaction-environment). "Init.scm" defines a new syntantic form,
1909 PACKAGE, as a simple example. It is used like this:
1910
1911 (define toto
1912 (package
1913 (define foo 1)
1914 (define bar +)))
1915
1916 foo ==> Error, "foo" undefined
1917 (eval 'foo) ==> Error, "foo" undefined
1918 (eval 'foo toto) ==> 1
1919 toto::foo ==> 1
1920 ((eval 'bar toto) 2 (eval 'foo toto)) ==> 3
1921 (toto::bar 2 toto::foo) ==> 3
1922 (eval (bar 2 foo) toto) ==> 3
1923
1924 If the user installs another package infrastructure, he must define
1925 a new 'package' procedure or macro to retain compatibility with supplied
1926 code.
1927
1928 Note: Older versions used ':' as a qualifier. Unfortunately, the use
1929 of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially
1930 precludes its use as a real qualifier.
1931
1932
1933
1934
1935
1936
1937
1938
-
+ 1E6959CA3EC52251E162D6C766CAF558F6FC222D337DBBCB313807C0B7F555F508E05865176D3DF5E92C8A2AA94E27529323A8A2E2F4264FDC1256276CF6B63B
bitcoin/src/shiva/MiniSCHEMETribute.txt
(0 . 0)(1 . 88)
1943 TinyScheme would not exist if it wasn't for MiniScheme. I had just
1944 written the HTTP server for Ovrimos SQL Server, and I was lamenting the
1945 lack of a scripting language. Server-side Javascript would have been the
1946 preferred solution, had there been a Javascript interpreter I could
1947 lay my hands on. But there weren't. Perl would have been another solution,
1948 but it was probably ten times bigger that the program it was supposed to
1949 be embedded in. There would also be thorny licencing issues.
1950
1951 So, the obvious thing to do was find a trully small interpreter. Forth
1952 was a language I had once quasi-implemented, but the difficulty of
1953 handling dynamic data and the weirdness of the language put me off. I then
1954 looked around for a LISP interpreter, the next thing I knew was easy to
1955 implement. Alas, the LeLisp I knew from my days in UPMC (Universite Pierre
1956 et Marie Curie) had given way to Common Lisp, a megalith of a language!
1957 Then my search lead me to Scheme, a language I knew was very orthogonal
1958 and clean. When I found Mini-Scheme, a single C file of some 2400 loc, I
1959 fell in love with it! What if it lacked floating-point numbers and
1960 strings! The rest, as they say, is history.
1961
1962 Below are the original credits. Don't email Akira KIDA, the address has
1963 changed.
1964
1965 ---------- Mini-Scheme Interpreter Version 0.85 ----------
1966
1967 coded by Atsushi Moriwaki (11/5/1989)
1968
1969 E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
1970
1971 THIS SOFTWARE IS IN THE PUBLIC DOMAIN
1972 ------------------------------------
1973 This software is completely free to copy, modify and/or re-distribute.
1974 But I would appreciate it if you left my name on the code as the author.
1975
1976 This version has been modified by R.C. Secrist.
1977
1978 Mini-Scheme is now maintained by Akira KIDA.
1979
1980 This is a revised and modified version by Akira KIDA.
1981 current version is 0.85k4 (15 May 1994)
1982
1983 Please send suggestions, bug reports and/or requests to:
1984 <SDI00379@niftyserve.or.jp>
1985
1986
1987 Features compared to MiniSCHEME
1988 -------------------------------
1989
1990 All code is now reentrant. Interpreter state is held in a 'scheme'
1991 struct, and many interpreters can coexist in the same program, possibly
1992 in different threads. The user can specify user-defined memory allocation
1993 primitives. (see "Programmer's Reference")
1994
1995 The reader is more consistent.
1996
1997 Strings, characters and flonums are supported. (see "Types")
1998
1999 Files being loaded can be nested up to some depth.
2000
2001 R5RS I/O is there, plus String Ports. (see "Scheme Reference","I/O")
2002
2003 Vectors exist.
2004
2005 As a standalone application, it supports command-line arguments.
2006 (see "Standalone")
2007
2008 Running out of memory is now handled.
2009
2010 The user can add foreign functions in C. (see "Foreign Functions")
2011
2012 The code has been changed slightly, core functions have been moved
2013 to the library, behavior has been aligned with R5RS etc.
2014
2015 Support has been added for user-defined error recovery.
2016 (see "Error Handling")
2017
2018 Support has been added for modular programming.
2019 (see "Colon Qualifiers - Packages")
2020
2021 To enable this, EVAL has changed internally, and can
2022 now take two arguments, as per R5RS. Environments are supported.
2023 (see "Colon Qualifiers - Packages")
2024
2025 Promises are now evaluated once only.
2026
2027 (macro (foo form) ...) is now equivalent to (macro foo (lambda(form) ...))
2028
2029 The reader can be extended using new #-expressions
2030 (see "Reader extensions")
-
+ 1BBAEF06AB4B1E168A42B4CD74605BDB7D55412544FF177E2CE07CE7AA07A7FD7B8B44CFBA2B7E28DC057FCC8B4CFA0E00ED66DAC30933E909DD13C81A99760B
bitcoin/src/shiva/opdefines.h
(0 . 0)(1 . 195)
2035 _OP_DEF(opexe_0, "load", 1, 1, TST_STRING, OP_LOAD )
2036 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_T0LVL )
2037 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_T1LVL )
2038 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_READ_INTERNAL )
2039 _OP_DEF(opexe_0, "gensym", 0, 0, 0, OP_GENSYM )
2040 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_VALUEPRINT )
2041 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_EVAL )
2042 #if USE_TRACING
2043 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_REAL_EVAL )
2044 #endif
2045 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_E0ARGS )
2046 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_E1ARGS )
2047 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_APPLY )
2048 #if USE_TRACING
2049 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_REAL_APPLY )
2050 _OP_DEF(opexe_0, "tracing", 1, 1, TST_NATURAL, OP_TRACING )
2051 #endif
2052 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DOMACRO )
2053 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LAMBDA )
2054 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LAMBDA1 )
2055 _OP_DEF(opexe_0, "make-closure", 1, 2, TST_PAIR TST_ENVIRONMENT, OP_MKCLOSURE )
2056 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_QUOTE )
2057 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DEF0 )
2058 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_DEF1 )
2059 _OP_DEF(opexe_0, "defined?", 1, 2, TST_SYMBOL TST_ENVIRONMENT, OP_DEFP )
2060 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_BEGIN )
2061 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_IF0 )
2062 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_IF1 )
2063 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_SET0 )
2064 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_SET1 )
2065 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET0 )
2066 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET1 )
2067 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET2 )
2068 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET0AST )
2069 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET1AST )
2070 _OP_DEF(opexe_0, 0, 0, 0, 0, OP_LET2AST )
2071 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET0REC )
2072 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET1REC )
2073 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_LET2REC )
2074 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_COND0 )
2075 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_COND1 )
2076 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_DELAY )
2077 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_AND0 )
2078 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_AND1 )
2079 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_OR0 )
2080 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_OR1 )
2081 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_C0STREAM )
2082 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_C1STREAM )
2083 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_MACRO0 )
2084 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_MACRO1 )
2085 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE0 )
2086 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE1 )
2087 _OP_DEF(opexe_1, 0, 0, 0, 0, OP_CASE2 )
2088 _OP_DEF(opexe_1, "eval", 1, 2, TST_ANY TST_ENVIRONMENT, OP_PEVAL )
2089 _OP_DEF(opexe_1, "apply", 1, INF_ARG, TST_NONE, OP_PAPPLY )
2090 _OP_DEF(opexe_1, "call-with-current-continuation", 1, 1, TST_NONE, OP_CONTINUATION )
2091 #if USE_MATH
2092 _OP_DEF(opexe_2, "inexact->exact", 1, 1, TST_NUMBER, OP_INEX2EX )
2093 _OP_DEF(opexe_2, "exp", 1, 1, TST_NUMBER, OP_EXP )
2094 _OP_DEF(opexe_2, "log", 1, 1, TST_NUMBER, OP_LOG )
2095 _OP_DEF(opexe_2, "sin", 1, 1, TST_NUMBER, OP_SIN )
2096 _OP_DEF(opexe_2, "cos", 1, 1, TST_NUMBER, OP_COS )
2097 _OP_DEF(opexe_2, "tan", 1, 1, TST_NUMBER, OP_TAN )
2098 _OP_DEF(opexe_2, "asin", 1, 1, TST_NUMBER, OP_ASIN )
2099 _OP_DEF(opexe_2, "acos", 1, 1, TST_NUMBER, OP_ACOS )
2100 _OP_DEF(opexe_2, "atan", 1, 2, TST_NUMBER, OP_ATAN )
2101 _OP_DEF(opexe_2, "sqrt", 1, 1, TST_NUMBER, OP_SQRT )
2102 _OP_DEF(opexe_2, "expt", 2, 2, TST_NUMBER, OP_EXPT )
2103 _OP_DEF(opexe_2, "floor", 1, 1, TST_NUMBER, OP_FLOOR )
2104 _OP_DEF(opexe_2, "ceiling", 1, 1, TST_NUMBER, OP_CEILING )
2105 _OP_DEF(opexe_2, "truncate", 1, 1, TST_NUMBER, OP_TRUNCATE )
2106 _OP_DEF(opexe_2, "round", 1, 1, TST_NUMBER, OP_ROUND )
2107 #endif
2108 _OP_DEF(opexe_2, "+", 0, INF_ARG, TST_NUMBER, OP_ADD )
2109 _OP_DEF(opexe_2, "-", 1, INF_ARG, TST_NUMBER, OP_SUB )
2110 _OP_DEF(opexe_2, "*", 0, INF_ARG, TST_NUMBER, OP_MUL )
2111 _OP_DEF(opexe_2, "/", 1, INF_ARG, TST_NUMBER, OP_DIV )
2112 _OP_DEF(opexe_2, "quotient", 1, INF_ARG, TST_INTEGER, OP_INTDIV )
2113 _OP_DEF(opexe_2, "remainder", 2, 2, TST_INTEGER, OP_REM )
2114 _OP_DEF(opexe_2, "modulo", 2, 2, TST_INTEGER, OP_MOD )
2115 _OP_DEF(opexe_2, "car", 1, 1, TST_PAIR, OP_CAR )
2116 _OP_DEF(opexe_2, "cdr", 1, 1, TST_PAIR, OP_CDR )
2117 _OP_DEF(opexe_2, "cons", 2, 2, TST_NONE, OP_CONS )
2118 _OP_DEF(opexe_2, "set-car!", 2, 2, TST_PAIR TST_ANY, OP_SETCAR )
2119 _OP_DEF(opexe_2, "set-cdr!", 2, 2, TST_PAIR TST_ANY, OP_SETCDR )
2120 _OP_DEF(opexe_2, "char->integer", 1, 1, TST_CHAR, OP_CHAR2INT )
2121 _OP_DEF(opexe_2, "integer->char", 1, 1, TST_NATURAL, OP_INT2CHAR )
2122 _OP_DEF(opexe_2, "char-upcase", 1, 1, TST_CHAR, OP_CHARUPCASE )
2123 _OP_DEF(opexe_2, "char-downcase", 1, 1, TST_CHAR, OP_CHARDNCASE )
2124 _OP_DEF(opexe_2, "symbol->string", 1, 1, TST_SYMBOL, OP_SYM2STR )
2125 _OP_DEF(opexe_2, "atom->string", 1, 2, TST_ANY TST_NATURAL, OP_ATOM2STR )
2126 _OP_DEF(opexe_2, "string->symbol", 1, 1, TST_STRING, OP_STR2SYM )
2127 _OP_DEF(opexe_2, "string->atom", 1, 2, TST_STRING TST_NATURAL, OP_STR2ATOM )
2128 _OP_DEF(opexe_2, "make-string", 1, 2, TST_NATURAL TST_CHAR, OP_MKSTRING )
2129 _OP_DEF(opexe_2, "string-length", 1, 1, TST_STRING, OP_STRLEN )
2130 _OP_DEF(opexe_2, "string-ref", 2, 2, TST_STRING TST_NATURAL, OP_STRREF )
2131 _OP_DEF(opexe_2, "string-set!", 3, 3, TST_STRING TST_NATURAL TST_CHAR, OP_STRSET )
2132 _OP_DEF(opexe_2, "string-append", 0, INF_ARG, TST_STRING, OP_STRAPPEND )
2133 _OP_DEF(opexe_2, "substring", 2, 3, TST_STRING TST_NATURAL, OP_SUBSTR )
2134 _OP_DEF(opexe_2, "vector", 0, INF_ARG, TST_NONE, OP_VECTOR )
2135 _OP_DEF(opexe_2, "make-vector", 1, 2, TST_NATURAL TST_ANY, OP_MKVECTOR )
2136 _OP_DEF(opexe_2, "vector-length", 1, 1, TST_VECTOR, OP_VECLEN )
2137 _OP_DEF(opexe_2, "vector-ref", 2, 2, TST_VECTOR TST_NATURAL, OP_VECREF )
2138 _OP_DEF(opexe_2, "vector-set!", 3, 3, TST_VECTOR TST_NATURAL TST_ANY, OP_VECSET )
2139 _OP_DEF(opexe_3, "not", 1, 1, TST_NONE, OP_NOT )
2140 _OP_DEF(opexe_3, "boolean?", 1, 1, TST_NONE, OP_BOOLP )
2141 _OP_DEF(opexe_3, "eof-object?", 1, 1, TST_NONE, OP_EOFOBJP )
2142 _OP_DEF(opexe_3, "null?", 1, 1, TST_NONE, OP_NULLP )
2143 _OP_DEF(opexe_3, "=", 2, INF_ARG, TST_NUMBER, OP_NUMEQ )
2144 _OP_DEF(opexe_3, "<", 2, INF_ARG, TST_NUMBER, OP_LESS )
2145 _OP_DEF(opexe_3, ">", 2, INF_ARG, TST_NUMBER, OP_GRE )
2146 _OP_DEF(opexe_3, "<=", 2, INF_ARG, TST_NUMBER, OP_LEQ )
2147 _OP_DEF(opexe_3, ">=", 2, INF_ARG, TST_NUMBER, OP_GEQ )
2148 _OP_DEF(opexe_3, "symbol?", 1, 1, TST_ANY, OP_SYMBOLP )
2149 _OP_DEF(opexe_3, "number?", 1, 1, TST_ANY, OP_NUMBERP )
2150 _OP_DEF(opexe_3, "string?", 1, 1, TST_ANY, OP_STRINGP )
2151 _OP_DEF(opexe_3, "integer?", 1, 1, TST_ANY, OP_INTEGERP )
2152 _OP_DEF(opexe_3, "real?", 1, 1, TST_ANY, OP_REALP )
2153 _OP_DEF(opexe_3, "char?", 1, 1, TST_ANY, OP_CHARP )
2154 #if USE_CHAR_CLASSIFIERS
2155 _OP_DEF(opexe_3, "char-alphabetic?", 1, 1, TST_CHAR, OP_CHARAP )
2156 _OP_DEF(opexe_3, "char-numeric?", 1, 1, TST_CHAR, OP_CHARNP )
2157 _OP_DEF(opexe_3, "char-whitespace?", 1, 1, TST_CHAR, OP_CHARWP )
2158 _OP_DEF(opexe_3, "char-upper-case?", 1, 1, TST_CHAR, OP_CHARUP )
2159 _OP_DEF(opexe_3, "char-lower-case?", 1, 1, TST_CHAR, OP_CHARLP )
2160 #endif
2161 _OP_DEF(opexe_3, "port?", 1, 1, TST_ANY, OP_PORTP )
2162 _OP_DEF(opexe_3, "input-port?", 1, 1, TST_ANY, OP_INPORTP )
2163 _OP_DEF(opexe_3, "output-port?", 1, 1, TST_ANY, OP_OUTPORTP )
2164 _OP_DEF(opexe_3, "procedure?", 1, 1, TST_ANY, OP_PROCP )
2165 _OP_DEF(opexe_3, "pair?", 1, 1, TST_ANY, OP_PAIRP )
2166 _OP_DEF(opexe_3, "list?", 1, 1, TST_ANY, OP_LISTP )
2167 _OP_DEF(opexe_3, "environment?", 1, 1, TST_ANY, OP_ENVP )
2168 _OP_DEF(opexe_3, "vector?", 1, 1, TST_ANY, OP_VECTORP )
2169 _OP_DEF(opexe_3, "eq?", 2, 2, TST_ANY, OP_EQ )
2170 _OP_DEF(opexe_3, "eqv?", 2, 2, TST_ANY, OP_EQV )
2171 _OP_DEF(opexe_4, "force", 1, 1, TST_ANY, OP_FORCE )
2172 _OP_DEF(opexe_4, 0, 0, 0, 0, OP_SAVE_FORCED )
2173 _OP_DEF(opexe_4, "write", 1, 2, TST_ANY TST_OUTPORT, OP_WRITE )
2174 _OP_DEF(opexe_4, "write-char", 1, 2, TST_CHAR TST_OUTPORT, OP_WRITE_CHAR )
2175 _OP_DEF(opexe_4, "display", 1, 2, TST_ANY TST_OUTPORT, OP_DISPLAY )
2176 _OP_DEF(opexe_4, "newline", 0, 1, TST_OUTPORT, OP_NEWLINE )
2177 _OP_DEF(opexe_4, "error", 1, INF_ARG, TST_NONE, OP_ERR0 )
2178 _OP_DEF(opexe_4, 0, 0, 0, 0, OP_ERR1 )
2179 _OP_DEF(opexe_4, "reverse", 1, 1, TST_LIST, OP_REVERSE )
2180 _OP_DEF(opexe_4, "list*", 1, INF_ARG, TST_NONE, OP_LIST_STAR )
2181 _OP_DEF(opexe_4, "append", 0, INF_ARG, TST_NONE, OP_APPEND )
2182 #if USE_PLIST
2183 _OP_DEF(opexe_4, "put", 3, 3, TST_NONE, OP_PUT )
2184 _OP_DEF(opexe_4, "get", 2, 2, TST_NONE, OP_GET )
2185 #endif
2186 _OP_DEF(opexe_4, "quit", 0, 1, TST_NUMBER, OP_QUIT )
2187 _OP_DEF(opexe_4, "gc", 0, 0, 0, OP_GC )
2188 _OP_DEF(opexe_4, "gc-verbose", 0, 1, TST_NONE, OP_GCVERB )
2189 _OP_DEF(opexe_4, "new-segment", 0, 1, TST_NUMBER, OP_NEWSEGMENT )
2190 _OP_DEF(opexe_4, "oblist", 0, 0, 0, OP_OBLIST )
2191 _OP_DEF(opexe_4, "current-input-port", 0, 0, 0, OP_CURR_INPORT )
2192 _OP_DEF(opexe_4, "current-output-port", 0, 0, 0, OP_CURR_OUTPORT )
2193 _OP_DEF(opexe_4, "open-input-file", 1, 1, TST_STRING, OP_OPEN_INFILE )
2194 _OP_DEF(opexe_4, "open-output-file", 1, 1, TST_STRING, OP_OPEN_OUTFILE )
2195 _OP_DEF(opexe_4, "open-input-output-file", 1, 1, TST_STRING, OP_OPEN_INOUTFILE )
2196 #if USE_STRING_PORTS
2197 _OP_DEF(opexe_4, "open-input-string", 1, 1, TST_STRING, OP_OPEN_INSTRING )
2198 _OP_DEF(opexe_4, "open-input-output-string", 1, 1, TST_STRING, OP_OPEN_INOUTSTRING )
2199 _OP_DEF(opexe_4, "open-output-string", 0, 1, TST_STRING, OP_OPEN_OUTSTRING )
2200 _OP_DEF(opexe_4, "get-output-string", 1, 1, TST_OUTPORT, OP_GET_OUTSTRING )
2201 #endif
2202 _OP_DEF(opexe_4, "close-input-port", 1, 1, TST_INPORT, OP_CLOSE_INPORT )
2203 _OP_DEF(opexe_4, "close-output-port", 1, 1, TST_OUTPORT, OP_CLOSE_OUTPORT )
2204 _OP_DEF(opexe_4, "interaction-environment", 0, 0, 0, OP_INT_ENV )
2205 _OP_DEF(opexe_4, "current-environment", 0, 0, 0, OP_CURR_ENV )
2206 _OP_DEF(opexe_5, "read", 0, 1, TST_INPORT, OP_READ )
2207 _OP_DEF(opexe_5, "read-char", 0, 1, TST_INPORT, OP_READ_CHAR )
2208 _OP_DEF(opexe_5, "peek-char", 0, 1, TST_INPORT, OP_PEEK_CHAR )
2209 _OP_DEF(opexe_5, "char-ready?", 0, 1, TST_INPORT, OP_CHAR_READY )
2210 _OP_DEF(opexe_5, "set-input-port", 1, 1, TST_INPORT, OP_SET_INPORT )
2211 _OP_DEF(opexe_5, "set-output-port", 1, 1, TST_OUTPORT, OP_SET_OUTPORT )
2212 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDSEXPR )
2213 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDLIST )
2214 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDDOT )
2215 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQUOTE )
2216 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQQUOTE )
2217 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDQQUOTEVEC )
2218 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDUNQUOTE )
2219 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDUQTSP )
2220 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_RDVEC )
2221 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_P0LIST )
2222 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_P1LIST )
2223 _OP_DEF(opexe_5, 0, 0, 0, 0, OP_PVECFROM )
2224 _OP_DEF(opexe_6, "length", 1, 1, TST_LIST, OP_LIST_LENGTH )
2225 _OP_DEF(opexe_6, "assq", 2, 2, TST_NONE, OP_ASSQ )
2226 _OP_DEF(opexe_6, "get-closure-code", 1, 1, TST_NONE, OP_GET_CLOSURE )
2227 _OP_DEF(opexe_6, "closure?", 1, 1, TST_NONE, OP_CLOSUREP )
2228 _OP_DEF(opexe_6, "macro?", 1, 1, TST_NONE, OP_MACROP )
2229 #undef _OP_DEF
-
+ B9F2C8885474FD6B4F7D36955799716E68161BE8F8CFCE3640ADE942FE0064A00D64C7DABC3EC36B24797760B99EA6C79D74A8F984DCC3AEAC2EEF183B3ED70B
bitcoin/src/shiva/scheme.c
(0 . 0)(1 . 5023)
2234 /*
2235 This version de-crudded for therealbitcoin.org.
2236 Applied interactive REPL fixups for port redirect mode.
2237 */
2238
2239 /* T I N Y S C H E M E 1 . 4 1
2240 * Dimitrios Souflis (dsouflis@acm.org)
2241 * Based on MiniScheme (original credits follow)
2242 * (MINISCM) coded by Atsushi Moriwaki (11/5/1989)
2243 * (MINISCM) E-MAIL : moriwaki@kurims.kurims.kyoto-u.ac.jp
2244 * (MINISCM) This version has been modified by R.C. Secrist.
2245 * (MINISCM)
2246 * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
2247 * (MINISCM)
2248 * (MINISCM) This is a revised and modified version by Akira KIDA.
2249 * (MINISCM) current version is 0.85k4 (15 May 1994)
2250 *
2251 */
2252
2253 #define _SCHEME_SOURCE
2254 #include "scheme-knobs.h"
2255 #include "scheme-private.h"
2256
2257 #include <unistd.h>
2258 #include <sys/types.h>
2259
2260 #if USE_MATH
2261 # include <math.h>
2262 #endif
2263
2264 #include <limits.h>
2265 #include <float.h>
2266 #include <ctype.h>
2267
2268 #if USE_STRCASECMP
2269 #include <strings.h>
2270 #define stricmp strcasecmp
2271 #endif
2272
2273 const char* tiny_scheme_version = PACKAGE_VERSION;
2274
2275 /* Used for documentation purposes, to signal functions in 'interface' */
2276 #define INTERFACE
2277
2278 #define TOK_EOF (-1)
2279 #define TOK_LPAREN 0
2280 #define TOK_RPAREN 1
2281 #define TOK_DOT 2
2282 #define TOK_ATOM 3
2283 #define TOK_QUOTE 4
2284 #define TOK_COMMENT 5
2285 #define TOK_DQUOTE 6
2286 #define TOK_BQUOTE 7
2287 #define TOK_COMMA 8
2288 #define TOK_ATMARK 9
2289 #define TOK_SHARP 10
2290 #define TOK_SHARP_CONST 11
2291 #define TOK_VEC 12
2292
2293 #define BACKQUOTE '`'
2294 #define DELIMITERS "()\";\f\t\v\n\r "
2295
2296 /*
2297 * Basic memory allocation units
2298 */
2299
2300 #define banner "TinyScheme 1.41"
2301
2302 #include <string.h>
2303 #include <stdlib.h>
2304
2305 #if USE_STRLWR
2306 static const char *strlwr(char *s) {
2307 const char *p=s;
2308 while(*s) {
2309 *s=tolower(*s);
2310 s++;
2311 }
2312 return p;
2313 }
2314 #endif
2315
2316 #ifndef prompt
2317 # define prompt "ts> "
2318 #endif
2319
2320 #ifndef InitFile
2321 # define InitFile "init.scm"
2322 #endif
2323
2324 #ifndef FIRST_CELLSEGS
2325 # define FIRST_CELLSEGS 3
2326 #endif
2327
2328 enum scheme_types {
2329 T_STRING=1,
2330 T_NUMBER=2,
2331 T_SYMBOL=3,
2332 T_PROC=4,
2333 T_PAIR=5,
2334 T_CLOSURE=6,
2335 T_CONTINUATION=7,
2336 T_FOREIGN=8,
2337 T_CHARACTER=9,
2338 T_PORT=10,
2339 T_VECTOR=11,
2340 T_MACRO=12,
2341 T_PROMISE=13,
2342 T_ENVIRONMENT=14,
2343 T_LAST_SYSTEM_TYPE=14
2344 };
2345
2346 /* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
2347 #define ADJ 32
2348 #define TYPE_BITS 5
2349 #define T_MASKTYPE 31 /* 0000000000011111 */
2350 #define T_SYNTAX 4096 /* 0001000000000000 */
2351 #define T_IMMUTABLE 8192 /* 0010000000000000 */
2352 #define T_ATOM 16384 /* 0100000000000000 */ /* only for gc */
2353 #define CLRATOM 49151 /* 1011111111111111 */ /* only for gc */
2354 #define MARK 32768 /* 1000000000000000 */
2355 #define UNMARK 32767 /* 0111111111111111 */
2356
2357
2358 static num num_add(num a, num b);
2359 static num num_mul(num a, num b);
2360 static num num_div(num a, num b);
2361 static num num_intdiv(num a, num b);
2362 static num num_sub(num a, num b);
2363 static num num_rem(num a, num b);
2364 static num num_mod(num a, num b);
2365 static int num_eq(num a, num b);
2366 static int num_gt(num a, num b);
2367 static int num_ge(num a, num b);
2368 static int num_lt(num a, num b);
2369 static int num_le(num a, num b);
2370
2371 #if USE_MATH
2372 static double round_per_R5RS(double x);
2373 #endif
2374 static int is_zero_double(double x);
2375 static INLINE int num_is_integer(pointer p) {
2376 return ((p)->_object._number.is_fixnum);
2377 }
2378
2379 static num num_zero;
2380 static num num_one;
2381
2382 /* macros for cell operations */
2383 #define typeflag(p) ((p)->_flag)
2384 #define type(p) (typeflag(p)&T_MASKTYPE)
2385
2386 INTERFACE INLINE int is_string(pointer p) { return (type(p)==T_STRING); }
2387 #define strvalue(p) ((p)->_object._string._svalue)
2388 #define strlength(p) ((p)->_object._string._length)
2389
2390 INTERFACE static int is_list(scheme *sc, pointer p);
2391 INTERFACE INLINE int is_vector(pointer p) { return (type(p)==T_VECTOR); }
2392 INTERFACE static void fill_vector(pointer vec, pointer obj);
2393 INTERFACE static pointer vector_elem(pointer vec, int ielem);
2394 INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
2395 INTERFACE INLINE int is_number(pointer p) { return (type(p)==T_NUMBER); }
2396 INTERFACE INLINE int is_integer(pointer p) {
2397 if (!is_number(p))
2398 return 0;
2399 if (num_is_integer(p) || (double)ivalue(p) == rvalue(p))
2400 return 1;
2401 return 0;
2402 }
2403
2404 INTERFACE INLINE int is_real(pointer p) {
2405 return is_number(p) && (!(p)->_object._number.is_fixnum);
2406 }
2407
2408 INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
2409 INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
2410 INLINE num nvalue(pointer p) { return ((p)->_object._number); }
2411 INTERFACE long ivalue(pointer p) { return (num_is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
2412 INTERFACE double rvalue(pointer p) { return (!num_is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
2413 #define ivalue_unchecked(p) ((p)->_object._number.value.ivalue)
2414 #define rvalue_unchecked(p) ((p)->_object._number.value.rvalue)
2415 #define set_num_integer(p) (p)->_object._number.is_fixnum=1;
2416 #define set_num_real(p) (p)->_object._number.is_fixnum=0;
2417 INTERFACE long charvalue(pointer p) { return ivalue_unchecked(p); }
2418
2419 INTERFACE INLINE int is_port(pointer p) { return (type(p)==T_PORT); }
2420 INTERFACE INLINE int is_inport(pointer p) { return is_port(p) && p->_object._port->kind & port_input; }
2421 INTERFACE INLINE int is_outport(pointer p) { return is_port(p) && p->_object._port->kind & port_output; }
2422
2423 INTERFACE INLINE int is_pair(pointer p) { return (type(p)==T_PAIR); }
2424 #define car(p) ((p)->_object._cons._car)
2425 #define cdr(p) ((p)->_object._cons._cdr)
2426 INTERFACE pointer pair_car(pointer p) { return car(p); }
2427 INTERFACE pointer pair_cdr(pointer p) { return cdr(p); }
2428 INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
2429 INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
2430
2431 INTERFACE INLINE int is_symbol(pointer p) { return (type(p)==T_SYMBOL); }
2432 INTERFACE INLINE char *symname(pointer p) { return strvalue(car(p)); }
2433 #if USE_PLIST
2434 SCHEME_EXPORT INLINE int hasprop(pointer p) { return (typeflag(p)&T_SYMBOL); }
2435 #define symprop(p) cdr(p)
2436 #endif
2437
2438 INTERFACE INLINE int is_syntax(pointer p) { return (typeflag(p)&T_SYNTAX); }
2439 INTERFACE INLINE int is_proc(pointer p) { return (type(p)==T_PROC); }
2440 INTERFACE INLINE int is_foreign(pointer p) { return (type(p)==T_FOREIGN); }
2441 INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
2442 #define procnum(p) ivalue(p)
2443 static const char *procname(pointer x);
2444
2445 INTERFACE INLINE int is_closure(pointer p) { return (type(p)==T_CLOSURE); }
2446 INTERFACE INLINE int is_macro(pointer p) { return (type(p)==T_MACRO); }
2447 INTERFACE INLINE pointer closure_code(pointer p) { return car(p); }
2448 INTERFACE INLINE pointer closure_env(pointer p) { return cdr(p); }
2449
2450 INTERFACE INLINE int is_continuation(pointer p) { return (type(p)==T_CONTINUATION); }
2451 #define cont_dump(p) cdr(p)
2452
2453 /* To do: promise should be forced ONCE only */
2454 INTERFACE INLINE int is_promise(pointer p) { return (type(p)==T_PROMISE); }
2455
2456 INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
2457 #define setenvironment(p) typeflag(p) = T_ENVIRONMENT
2458
2459 #define is_atom(p) (typeflag(p)&T_ATOM)
2460 #define setatom(p) typeflag(p) |= T_ATOM
2461 #define clratom(p) typeflag(p) &= CLRATOM
2462
2463 #define is_mark(p) (typeflag(p)&MARK)
2464 #define setmark(p) typeflag(p) |= MARK
2465 #define clrmark(p) typeflag(p) &= UNMARK
2466
2467 INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
2468 /*#define setimmutable(p) typeflag(p) |= T_IMMUTABLE*/
2469 INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
2470
2471 #define caar(p) car(car(p))
2472 #define cadr(p) car(cdr(p))
2473 #define cdar(p) cdr(car(p))
2474 #define cddr(p) cdr(cdr(p))
2475 #define cadar(p) car(cdr(car(p)))
2476 #define caddr(p) car(cdr(cdr(p)))
2477 #define cdaar(p) cdr(car(car(p)))
2478 #define cadaar(p) car(cdr(car(car(p))))
2479 #define cadddr(p) car(cdr(cdr(cdr(p))))
2480 #define cddddr(p) cdr(cdr(cdr(cdr(p))))
2481
2482 #if USE_CHAR_CLASSIFIERS
2483 static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); }
2484 static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); }
2485 static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); }
2486 static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); }
2487 static INLINE int Cislower(int c) { return isascii(c) && islower(c); }
2488 #endif
2489
2490 #if USE_ASCII_NAMES
2491 static const char *charnames[32]={
2492 "nul",
2493 "soh",
2494 "stx",
2495 "etx",
2496 "eot",
2497 "enq",
2498 "ack",
2499 "bel",
2500 "bs",
2501 "ht",
2502 "lf",
2503 "vt",
2504 "ff",
2505 "cr",
2506 "so",
2507 "si",
2508 "dle",
2509 "dc1",
2510 "dc2",
2511 "dc3",
2512 "dc4",
2513 "nak",
2514 "syn",
2515 "etb",
2516 "can",
2517 "em",
2518 "sub",
2519 "esc",
2520 "fs",
2521 "gs",
2522 "rs",
2523 "us"
2524 };
2525
2526 static int is_ascii_name(const char *name, int *pc) {
2527 int i;
2528 for(i=0; i<32; i++) {
2529 if(stricmp(name,charnames[i])==0) {
2530 *pc=i;
2531 return 1;
2532 }
2533 }
2534 if(stricmp(name,"del")==0) {
2535 *pc=127;
2536 return 1;
2537 }
2538 return 0;
2539 }
2540
2541 #endif
2542
2543 static int file_push(scheme *sc, const char *fname);
2544 static void file_pop(scheme *sc);
2545 static int file_interactive(scheme *sc);
2546 static INLINE int is_one_of(char *s, int c);
2547 static int alloc_cellseg(scheme *sc, int n);
2548 static long binary_decode(const char *s);
2549 static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
2550 static pointer _get_cell(scheme *sc, pointer a, pointer b);
2551 static pointer reserve_cells(scheme *sc, int n);
2552 static pointer get_consecutive_cells(scheme *sc, int n);
2553 static pointer find_consecutive_cells(scheme *sc, int n);
2554 static void finalize_cell(scheme *sc, pointer a);
2555 static int count_consecutive_cells(pointer x, int needed);
2556 static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
2557 static pointer mk_number(scheme *sc, num n);
2558 static char *store_string(scheme *sc, int len, const char *str, char fill);
2559 static pointer mk_vector(scheme *sc, int len);
2560 static pointer mk_atom(scheme *sc, char *q);
2561 static pointer mk_sharp_const(scheme *sc, char *name);
2562 static pointer mk_port(scheme *sc, port *p);
2563 static pointer port_from_filename(scheme *sc, const char *fn, int prop);
2564 static pointer port_from_file(scheme *sc, FILE *, int prop);
2565 static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
2566 static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
2567 static port *port_rep_from_file(scheme *sc, FILE *, int prop);
2568 static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
2569 static void port_close(scheme *sc, pointer p, int flag);
2570 static void mark(pointer a);
2571 static void gc(scheme *sc, pointer a, pointer b);
2572 static int basic_inchar(port *pt);
2573 static int inchar(scheme *sc);
2574 static void backchar(scheme *sc, int c);
2575 static char *readstr_upto(scheme *sc, char *delim);
2576 static pointer readstrexp(scheme *sc);
2577 static INLINE int skipspace(scheme *sc);
2578 static int token(scheme *sc);
2579 static void printslashstring(scheme *sc, char *s, int len);
2580 static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen);
2581 static void printatom(scheme *sc, pointer l, int f);
2582 static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
2583 static pointer mk_closure(scheme *sc, pointer c, pointer e);
2584 static pointer mk_continuation(scheme *sc, pointer d);
2585 static pointer reverse(scheme *sc, pointer a);
2586 static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
2587 static pointer revappend(scheme *sc, pointer a, pointer b);
2588 static void dump_stack_mark(scheme *);
2589 static pointer opexe_0(scheme *sc, enum scheme_opcodes op);
2590 static pointer opexe_1(scheme *sc, enum scheme_opcodes op);
2591 static pointer opexe_2(scheme *sc, enum scheme_opcodes op);
2592 static pointer opexe_3(scheme *sc, enum scheme_opcodes op);
2593 static pointer opexe_4(scheme *sc, enum scheme_opcodes op);
2594 static pointer opexe_5(scheme *sc, enum scheme_opcodes op);
2595 static pointer opexe_6(scheme *sc, enum scheme_opcodes op);
2596 static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
2597 static void assign_syntax(scheme *sc, char *name);
2598 static int syntaxnum(pointer p);
2599 static void assign_proc(scheme *sc, enum scheme_opcodes, char *name);
2600
2601 #define num_ivalue(n) (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
2602 #define num_rvalue(n) (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
2603
2604 static num num_add(num a, num b) {
2605 num ret;
2606 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
2607 if(ret.is_fixnum) {
2608 ret.value.ivalue= a.value.ivalue+b.value.ivalue;
2609 } else {
2610 ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
2611 }
2612 return ret;
2613 }
2614
2615 static num num_mul(num a, num b) {
2616 num ret;
2617 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
2618 if(ret.is_fixnum) {
2619 ret.value.ivalue= a.value.ivalue*b.value.ivalue;
2620 } else {
2621 ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
2622 }
2623 return ret;
2624 }
2625
2626 static num num_div(num a, num b) {
2627 num ret;
2628 ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
2629 if(ret.is_fixnum) {
2630 ret.value.ivalue= a.value.ivalue/b.value.ivalue;
2631 } else {
2632 ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
2633 }
2634 return ret;
2635 }
2636
2637 static num num_intdiv(num a, num b) {
2638 num ret;
2639 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
2640 if(ret.is_fixnum) {
2641 ret.value.ivalue= a.value.ivalue/b.value.ivalue;
2642 } else {
2643 ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
2644 }
2645 return ret;
2646 }
2647
2648 static num num_sub(num a, num b) {
2649 num ret;
2650 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
2651 if(ret.is_fixnum) {
2652 ret.value.ivalue= a.value.ivalue-b.value.ivalue;
2653 } else {
2654 ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
2655 }
2656 return ret;
2657 }
2658
2659 static num num_rem(num a, num b) {
2660 num ret;
2661 long e1, e2, res;
2662 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
2663 e1=num_ivalue(a);
2664 e2=num_ivalue(b);
2665 res=e1%e2;
2666 /* remainder should have same sign as second operand */
2667 if (res > 0) {
2668 if (e1 < 0) {
2669 res -= labs(e2);
2670 }
2671 } else if (res < 0) {
2672 if (e1 > 0) {
2673 res += labs(e2);
2674 }
2675 }
2676 ret.value.ivalue=res;
2677 return ret;
2678 }
2679
2680 static num num_mod(num a, num b) {
2681 num ret;
2682 long e1, e2, res;
2683 ret.is_fixnum=a.is_fixnum && b.is_fixnum;
2684 e1=num_ivalue(a);
2685 e2=num_ivalue(b);
2686 res=e1%e2;
2687 /* modulo should have same sign as second operand */
2688 if (res * e2 < 0) {
2689 res += e2;
2690 }
2691 ret.value.ivalue=res;
2692 return ret;
2693 }
2694
2695 static int num_eq(num a, num b) {
2696 int ret;
2697 int is_fixnum=a.is_fixnum && b.is_fixnum;
2698 if(is_fixnum) {
2699 ret= a.value.ivalue==b.value.ivalue;
2700 } else {
2701 ret=num_rvalue(a)==num_rvalue(b);
2702 }
2703 return ret;
2704 }
2705
2706
2707 static int num_gt(num a, num b) {
2708 int ret;
2709 int is_fixnum=a.is_fixnum && b.is_fixnum;
2710 if(is_fixnum) {
2711 ret= a.value.ivalue>b.value.ivalue;
2712 } else {
2713 ret=num_rvalue(a)>num_rvalue(b);
2714 }
2715 return ret;
2716 }
2717
2718 static int num_ge(num a, num b) {
2719 return !num_lt(a,b);
2720 }
2721
2722 static int num_lt(num a, num b) {
2723 int ret;
2724 int is_fixnum=a.is_fixnum && b.is_fixnum;
2725 if(is_fixnum) {
2726 ret= a.value.ivalue<b.value.ivalue;
2727 } else {
2728 ret=num_rvalue(a)<num_rvalue(b);
2729 }
2730 return ret;
2731 }
2732
2733 static int num_le(num a, num b) {
2734 return !num_gt(a,b);
2735 }
2736
2737 #if USE_MATH
2738 /* Round to nearest. Round to even if midway */
2739 static double round_per_R5RS(double x) {
2740 double fl=floor(x);
2741 double ce=ceil(x);
2742 double dfl=x-fl;
2743 double dce=ce-x;
2744 if(dfl>dce) {
2745 return ce;
2746 } else if(dfl<dce) {
2747 return fl;
2748 } else {
2749 if(fmod(fl,2.0)==0.0) { /* I imagine this holds */
2750 return fl;
2751 } else {
2752 return ce;
2753 }
2754 }
2755 }
2756 #endif
2757
2758 static int is_zero_double(double x) {
2759 return x<DBL_MIN && x>-DBL_MIN;
2760 }
2761
2762 static long binary_decode(const char *s) {
2763 long x=0;
2764
2765 while(*s!=0 && (*s=='1' || *s=='0')) {
2766 x<<=1;
2767 x+=*s-'0';
2768 s++;
2769 }
2770
2771 return x;
2772 }
2773
2774 /* allocate new cell segment */
2775 static int alloc_cellseg(scheme *sc, int n) {
2776 pointer newp;
2777 pointer last;
2778 pointer p;
2779 char *cp;
2780 long i;
2781 int k;
2782 int adj=ADJ;
2783
2784 if(adj<sizeof(struct cell)) {
2785 adj=sizeof(struct cell);
2786 }
2787
2788 for (k = 0; k < n; k++) {
2789 if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
2790 return k;
2791 cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj);
2792 if (cp == 0)
2793 return k;
2794 i = ++sc->last_cell_seg ;
2795 sc->alloc_seg[i] = cp;
2796 /* adjust in TYPE_BITS-bit boundary */
2797 if(((unsigned long)cp)%adj!=0) {
2798 cp=(char*)(adj*((unsigned long)cp/adj+1));
2799 }
2800 /* insert new segment in address order */
2801 newp=(pointer)cp;
2802 sc->cell_seg[i] = newp;
2803 while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
2804 p = sc->cell_seg[i];
2805 sc->cell_seg[i] = sc->cell_seg[i - 1];
2806 sc->cell_seg[--i] = p;
2807 }
2808 sc->fcells += CELL_SEGSIZE;
2809 last = newp + CELL_SEGSIZE - 1;
2810 for (p = newp; p <= last; p++) {
2811 typeflag(p) = 0;
2812 cdr(p) = p + 1;
2813 car(p) = sc->NIL;
2814 }
2815 /* insert new cells in address order on free list */
2816 if (sc->free_cell == sc->NIL || p < sc->free_cell) {
2817 cdr(last) = sc->free_cell;
2818 sc->free_cell = newp;
2819 } else {
2820 p = sc->free_cell;
2821 while (cdr(p) != sc->NIL && newp > cdr(p))
2822 p = cdr(p);
2823 cdr(last) = cdr(p);
2824 cdr(p) = newp;
2825 }
2826 }
2827 return n;
2828 }
2829
2830 static INLINE pointer get_cell_x(scheme *sc, pointer a, pointer b) {
2831 if (sc->free_cell != sc->NIL) {
2832 pointer x = sc->free_cell;
2833 sc->free_cell = cdr(x);
2834 --sc->fcells;
2835 return (x);
2836 }
2837 return _get_cell (sc, a, b);
2838 }
2839
2840
2841 /* get new cell. parameter a, b is marked by gc. */
2842 static pointer _get_cell(scheme *sc, pointer a, pointer b) {
2843 pointer x;
2844
2845 if(sc->no_memory) {
2846 return sc->sink;
2847 }
2848
2849 if (sc->free_cell == sc->NIL) {
2850 const int min_to_be_recovered = sc->last_cell_seg*8;
2851 gc(sc,a, b);
2852 if (sc->fcells < min_to_be_recovered
2853 || sc->free_cell == sc->NIL) {
2854 /* if only a few recovered, get more to avoid fruitless gc's */
2855 if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) {
2856 sc->no_memory=1;
2857 return sc->sink;
2858 }
2859 }
2860 }
2861 x = sc->free_cell;
2862 sc->free_cell = cdr(x);
2863 --sc->fcells;
2864 return (x);
2865 }
2866
2867 /* make sure that there is a given number of cells free */
2868 static pointer reserve_cells(scheme *sc, int n) {
2869 if(sc->no_memory) {
2870 return sc->NIL;
2871 }
2872
2873 /* Are there enough cells available? */
2874 if (sc->fcells < n) {
2875 /* If not, try gc'ing some */
2876 gc(sc, sc->NIL, sc->NIL);
2877 if (sc->fcells < n) {
2878 /* If there still aren't, try getting more heap */
2879 if (!alloc_cellseg(sc,1)) {
2880 sc->no_memory=1;
2881 return sc->NIL;
2882 }
2883 }
2884 if (sc->fcells < n) {
2885 /* If all fail, report failure */
2886 sc->no_memory=1;
2887 return sc->NIL;
2888 }
2889 }
2890 return (sc->T);
2891 }
2892
2893 static pointer get_consecutive_cells(scheme *sc, int n) {
2894 pointer x;
2895
2896 if(sc->no_memory) { return sc->sink; }
2897
2898 /* Are there any cells available? */
2899 x=find_consecutive_cells(sc,n);
2900 if (x != sc->NIL) { return x; }
2901
2902 /* If not, try gc'ing some */
2903 gc(sc, sc->NIL, sc->NIL);
2904 x=find_consecutive_cells(sc,n);
2905 if (x != sc->NIL) { return x; }
2906
2907 /* If there still aren't, try getting more heap */
2908 if (!alloc_cellseg(sc,1))
2909 {
2910 sc->no_memory=1;
2911 return sc->sink;
2912 }
2913
2914 x=find_consecutive_cells(sc,n);
2915 if (x != sc->NIL) { return x; }
2916
2917 /* If all fail, report failure */
2918 sc->no_memory=1;
2919 return sc->sink;
2920 }
2921
2922 static int count_consecutive_cells(pointer x, int needed) {
2923 int n=1;
2924 while(cdr(x)==x+1) {
2925 x=cdr(x);
2926 n++;
2927 if(n>needed) return n;
2928 }
2929 return n;
2930 }
2931
2932 static pointer find_consecutive_cells(scheme *sc, int n) {
2933 pointer *pp;
2934 int cnt;
2935
2936 pp=&sc->free_cell;
2937 while(*pp!=sc->NIL) {
2938 cnt=count_consecutive_cells(*pp,n);
2939 if(cnt>=n) {
2940 pointer x=*pp;
2941 *pp=cdr(*pp+n-1);
2942 sc->fcells -= n;
2943 return x;
2944 }
2945 pp=&cdr(*pp+cnt-1);
2946 }
2947 return sc->NIL;
2948 }
2949
2950 /* To retain recent allocs before interpreter knows about them -
2951 Tehom */
2952
2953 static void push_recent_alloc(scheme *sc, pointer recent, pointer extra)
2954 {
2955 pointer holder = get_cell_x(sc, recent, extra);
2956 typeflag(holder) = T_PAIR | T_IMMUTABLE;
2957 car(holder) = recent;
2958 cdr(holder) = car(sc->sink);
2959 car(sc->sink) = holder;
2960 }
2961
2962
2963 static pointer get_cell(scheme *sc, pointer a, pointer b)
2964 {
2965 pointer cell = get_cell_x(sc, a, b);
2966 /* For right now, include "a" and "b" in "cell" so that gc doesn't
2967 think they are garbage. */
2968 /* Tentatively record it as a pair so gc understands it. */
2969 typeflag(cell) = T_PAIR;
2970 car(cell) = a;
2971 cdr(cell) = b;
2972 push_recent_alloc(sc, cell, sc->NIL);
2973 return cell;
2974 }
2975
2976 static pointer get_vector_object(scheme *sc, int len, pointer init)
2977 {
2978 pointer cells = get_consecutive_cells(sc,len/2+len%2+1);
2979 if(sc->no_memory) { return sc->sink; }
2980 /* Record it as a vector so that gc understands it. */
2981 typeflag(cells) = (T_VECTOR | T_ATOM);
2982 ivalue_unchecked(cells)=len;
2983 set_num_integer(cells);
2984 fill_vector(cells,init);
2985 push_recent_alloc(sc, cells, sc->NIL);
2986 return cells;
2987 }
2988
2989 static INLINE void ok_to_freely_gc(scheme *sc)
2990 {
2991 car(sc->sink) = sc->NIL;
2992 }
2993
2994
2995 #if defined TSGRIND
2996 static void check_cell_alloced(pointer p, int expect_alloced)
2997 {
2998 /* Can't use putstr(sc,str) because callers have no access to
2999 sc. */
3000 if(typeflag(p) & !expect_alloced)
3001 {
3002 fprintf(stderr,"Cell is already allocated!\n");
3003 }
3004 if(!(typeflag(p)) & expect_alloced)
3005 {
3006 fprintf(stderr,"Cell is not allocated!\n");
3007 }
3008
3009 }
3010 static void check_range_alloced(pointer p, int n, int expect_alloced)
3011 {
3012 int i;
3013 for(i = 0;i<n;i++)
3014 { (void)check_cell_alloced(p+i,expect_alloced); }
3015 }
3016
3017 #endif
3018
3019 /* Medium level cell allocation */
3020
3021 /* get new cons cell */
3022 pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
3023 pointer x = get_cell(sc,a, b);
3024
3025 typeflag(x) = T_PAIR;
3026 if(immutable) {
3027 setimmutable(x);
3028 }
3029 car(x) = a;
3030 cdr(x) = b;
3031 return (x);
3032 }
3033
3034 /* ========== oblist implementation ========== */
3035
3036 #ifndef USE_OBJECT_LIST
3037
3038 static int hash_fn(const char *key, int table_size);
3039
3040 static pointer oblist_initial_value(scheme *sc)
3041 {
3042 return mk_vector(sc, 461); /* probably should be bigger */
3043 }
3044
3045 /* returns the new symbol */
3046 static pointer oblist_add_by_name(scheme *sc, const char *name)
3047 {
3048 pointer x;
3049 int location;
3050
3051 x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
3052 typeflag(x) = T_SYMBOL;
3053 setimmutable(car(x));
3054
3055 location = hash_fn(name, ivalue_unchecked(sc->oblist));
3056 set_vector_elem(sc->oblist, location,
3057 immutable_cons(sc, x, vector_elem(sc->oblist, location)));
3058 return x;
3059 }
3060
3061 static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
3062 {
3063 int location;
3064 pointer x;
3065 char *s;
3066
3067 location = hash_fn(name, ivalue_unchecked(sc->oblist));
3068 for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) {
3069 s = symname(car(x));
3070 /* case-insensitive, per R5RS section 2. */
3071 if(stricmp(name, s) == 0) {
3072 return car(x);
3073 }
3074 }
3075 return sc->NIL;
3076 }
3077
3078 static pointer oblist_all_symbols(scheme *sc)
3079 {
3080 int i;
3081 pointer x;
3082 pointer ob_list = sc->NIL;
3083
3084 for (i = 0; i < ivalue_unchecked(sc->oblist); i++) {
3085 for (x = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) {
3086 ob_list = cons(sc, x, ob_list);
3087 }
3088 }
3089 return ob_list;
3090 }
3091
3092 #else
3093
3094 static pointer oblist_initial_value(scheme *sc)
3095 {
3096 return sc->NIL;
3097 }
3098
3099 static INLINE pointer oblist_find_by_name(scheme *sc, const char *name)
3100 {
3101 pointer x;
3102 char *s;
3103
3104 for (x = sc->oblist; x != sc->NIL; x = cdr(x)) {
3105 s = symname(car(x));
3106 /* case-insensitive, per R5RS section 2. */
3107 if(stricmp(name, s) == 0) {
3108 return car(x);
3109 }
3110 }
3111 return sc->NIL;
3112 }
3113
3114 /* returns the new symbol */
3115 static pointer oblist_add_by_name(scheme *sc, const char *name)
3116 {
3117 pointer x;
3118
3119 x = immutable_cons(sc, mk_string(sc, name), sc->NIL);
3120 typeflag(x) = T_SYMBOL;
3121 setimmutable(car(x));
3122 sc->oblist = immutable_cons(sc, x, sc->oblist);
3123 return x;
3124 }
3125 static pointer oblist_all_symbols(scheme *sc)
3126 {
3127 return sc->oblist;
3128 }
3129
3130 #endif
3131
3132 static pointer mk_port(scheme *sc, port *p) {
3133 pointer x = get_cell(sc, sc->NIL, sc->NIL);
3134
3135 typeflag(x) = T_PORT|T_ATOM;
3136 x->_object._port=p;
3137 return (x);
3138 }
3139
3140 pointer mk_foreign_func(scheme *sc, foreign_func f) {
3141 pointer x = get_cell(sc, sc->NIL, sc->NIL);
3142
3143 typeflag(x) = (T_FOREIGN | T_ATOM);
3144 x->_object._ff=f;
3145 return (x);
3146 }
3147
3148 INTERFACE pointer mk_character(scheme *sc, int c) {
3149 pointer x = get_cell(sc,sc->NIL, sc->NIL);
3150
3151 typeflag(x) = (T_CHARACTER | T_ATOM);
3152 ivalue_unchecked(x)= c;
3153 set_num_integer(x);
3154 return (x);
3155 }
3156
3157 /* get number atom (integer) */
3158 INTERFACE pointer mk_integer(scheme *sc, long num) {
3159 pointer x = get_cell(sc,sc->NIL, sc->NIL);
3160
3161 typeflag(x) = (T_NUMBER | T_ATOM);
3162 ivalue_unchecked(x)= num;
3163 set_num_integer(x);
3164 return (x);
3165 }
3166
3167 INTERFACE pointer mk_real(scheme *sc, double n) {
3168 pointer x = get_cell(sc,sc->NIL, sc->NIL);
3169
3170 typeflag(x) = (T_NUMBER | T_ATOM);
3171 rvalue_unchecked(x)= n;
3172 set_num_real(x);
3173 return (x);
3174 }
3175
3176 static pointer mk_number(scheme *sc, num n) {
3177 if(n.is_fixnum) {
3178 return mk_integer(sc,n.value.ivalue);
3179 } else {
3180 return mk_real(sc,n.value.rvalue);
3181 }
3182 }
3183
3184 /* allocate name to string area */
3185 static char *store_string(scheme *sc, int len_str, const char *str, char fill) {
3186 char *q;
3187
3188 q=(char*)sc->malloc(len_str+1);
3189 if(q==0) {
3190 sc->no_memory=1;
3191 return sc->strbuff;
3192 }
3193 if(str!=0) {
3194 snprintf(q, len_str+1, "%s", str);
3195 } else {
3196 memset(q, fill, len_str);
3197 q[len_str]=0;
3198 }
3199 return (q);
3200 }
3201
3202 /* get new string */
3203 INTERFACE pointer mk_string(scheme *sc, const char *str) {
3204 return mk_counted_string(sc,str,strlen(str));
3205 }
3206
3207 INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
3208 pointer x = get_cell(sc, sc->NIL, sc->NIL);
3209 typeflag(x) = (T_STRING | T_ATOM);
3210 strvalue(x) = store_string(sc,len,str,0);
3211 strlength(x) = len;
3212 return (x);
3213 }
3214
3215 INTERFACE pointer mk_empty_string(scheme *sc, int len, char fill) {
3216 pointer x = get_cell(sc, sc->NIL, sc->NIL);
3217 typeflag(x) = (T_STRING | T_ATOM);
3218 strvalue(x) = store_string(sc,len,0,fill);
3219 strlength(x) = len;
3220 return (x);
3221 }
3222
3223 INTERFACE static pointer mk_vector(scheme *sc, int len)
3224 { return get_vector_object(sc,len,sc->NIL); }
3225
3226 INTERFACE static void fill_vector(pointer vec, pointer obj) {
3227 int i;
3228 int num=ivalue(vec)/2+ivalue(vec)%2;
3229 for(i=0; i<num; i++) {
3230 typeflag(vec+1+i) = T_PAIR;
3231 setimmutable(vec+1+i);
3232 car(vec+1+i)=obj;
3233 cdr(vec+1+i)=obj;
3234 }
3235 }
3236
3237 INTERFACE static pointer vector_elem(pointer vec, int ielem) {
3238 int n=ielem/2;
3239 if(ielem%2==0) {
3240 return car(vec+1+n);
3241 } else {
3242 return cdr(vec+1+n);
3243 }
3244 }
3245
3246 INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
3247 int n=ielem/2;
3248 if(ielem%2==0) {
3249 return car(vec+1+n)=a;
3250 } else {
3251 return cdr(vec+1+n)=a;
3252 }
3253 }
3254
3255 /* get new symbol */
3256 INTERFACE pointer mk_symbol(scheme *sc, const char *name) {
3257 pointer x;
3258
3259 /* first check oblist */
3260 x = oblist_find_by_name(sc, name);
3261 if (x != sc->NIL) {
3262 return (x);
3263 } else {
3264 x = oblist_add_by_name(sc, name);
3265 return (x);
3266 }
3267 }
3268
3269 INTERFACE pointer gensym(scheme *sc) {
3270 pointer x;
3271 char name[40];
3272
3273 for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) {
3274 snprintf(name,40,"gensym-%ld",sc->gensym_cnt);
3275
3276 /* first check oblist */
3277 x = oblist_find_by_name(sc, name);
3278
3279 if (x != sc->NIL) {
3280 continue;
3281 } else {
3282 x = oblist_add_by_name(sc, name);
3283 return (x);
3284 }
3285 }
3286
3287 return sc->NIL;
3288 }
3289
3290 /* make symbol or number atom from string */
3291 static pointer mk_atom(scheme *sc, char *q) {
3292 char c, *p;
3293 int has_dec_point=0;
3294 int has_fp_exp = 0;
3295
3296 #if USE_COLON_HOOK
3297 if((p=strstr(q,"::"))!=0) {
3298 *p=0;
3299 return cons(sc, sc->COLON_HOOK,
3300 cons(sc,
3301 cons(sc,
3302 sc->QUOTE,
3303 cons(sc, mk_atom(sc,p+2), sc->NIL)),
3304 cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL)));
3305 }
3306 #endif
3307
3308 p = q;
3309 c = *p++;
3310 if ((c == '+') || (c == '-')) {
3311 c = *p++;
3312 if (c == '.') {
3313 has_dec_point=1;
3314 c = *p++;
3315 }
3316 if (!isdigit(c)) {
3317 return (mk_symbol(sc, strlwr(q)));
3318 }
3319 } else if (c == '.') {
3320 has_dec_point=1;
3321 c = *p++;
3322 if (!isdigit(c)) {
3323 return (mk_symbol(sc, strlwr(q)));
3324 }
3325 } else if (!isdigit(c)) {
3326 return (mk_symbol(sc, strlwr(q)));
3327 }
3328
3329 for ( ; (c = *p) != 0; ++p) {
3330 if (!isdigit(c)) {
3331 if(c=='.') {
3332 if(!has_dec_point) {
3333 has_dec_point=1;
3334 continue;
3335 }
3336 }
3337 else if ((c == 'e') || (c == 'E')) {
3338 if(!has_fp_exp) {
3339 has_dec_point = 1; /* decimal point illegal
3340 from now on */
3341 p++;
3342 if ((*p == '-') || (*p == '+') || isdigit(*p)) {
3343 continue;
3344 }
3345 }
3346 }
3347 return (mk_symbol(sc, strlwr(q)));
3348 }
3349 }
3350 if(has_dec_point) {
3351 return mk_real(sc,atof(q));
3352 }
3353 return (mk_integer(sc, atol(q)));
3354 }
3355
3356 /* make constant */
3357 static pointer mk_sharp_const(scheme *sc, char *name) {
3358 long x;
3359 char tmp[STRBUFFSIZE];
3360
3361 if (!strcmp(name, "t"))
3362 return (sc->T);
3363 else if (!strcmp(name, "f"))
3364 return (sc->F);
3365 else if (*name == 'o') {/* #o (octal) */
3366 snprintf(tmp, STRBUFFSIZE, "0%s", name+1);
3367 sscanf(tmp, "%lo", (long unsigned *)&x);
3368 return (mk_integer(sc, x));
3369 } else if (*name == 'd') { /* #d (decimal) */
3370 sscanf(name+1, "%ld", (long int *)&x);
3371 return (mk_integer(sc, x));
3372 } else if (*name == 'x') { /* #x (hex) */
3373 snprintf(tmp, STRBUFFSIZE, "0x%s", name+1);
3374 sscanf(tmp, "%lx", (long unsigned *)&x);
3375 return (mk_integer(sc, x));
3376 } else if (*name == 'b') { /* #b (binary) */
3377 x = binary_decode(name+1);
3378 return (mk_integer(sc, x));
3379 } else if (*name == '\\') { /* #\w (character) */
3380 int c=0;
3381 if(stricmp(name+1,"space")==0) {
3382 c=' ';
3383 } else if(stricmp(name+1,"newline")==0) {
3384 c='\n';
3385 } else if(stricmp(name+1,"return")==0) {
3386 c='\r';
3387 } else if(stricmp(name+1,"tab")==0) {
3388 c='\t';
3389 } else if(name[1]=='x' && name[2]!=0) {
3390 int c1=0;
3391 if(sscanf(name+2,"%x",(unsigned int *)&c1)==1 && c1 < UCHAR_MAX) {
3392 c=c1;
3393 } else {
3394 return sc->NIL;
3395 }
3396 #if USE_ASCII_NAMES
3397 } else if(is_ascii_name(name+1,&c)) {
3398 /* nothing */
3399 #endif
3400 } else if(name[2]==0) {
3401 c=name[1];
3402 } else {
3403 return sc->NIL;
3404 }
3405 return mk_character(sc,c);
3406 } else
3407 return (sc->NIL);
3408 }
3409
3410 /* ========== garbage collector ========== */
3411
3412 /*--
3413 * We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
3414 * sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm,
3415 * for marking.
3416 */
3417 static void mark(pointer a) {
3418 pointer t, q, p;
3419
3420 t = (pointer) 0;
3421 p = a;
3422 E2: setmark(p);
3423 if(is_vector(p)) {
3424 int i;
3425 int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2;
3426 for(i=0; i<num; i++) {
3427 /* Vector cells will be treated like ordinary cells */
3428 mark(p+1+i);
3429 }
3430 }
3431 if (is_atom(p))
3432 goto E6;
3433 /* E4: down car */
3434 q = car(p);
3435 if (q && !is_mark(q)) {
3436 setatom(p); /* a note that we have moved car */
3437 car(p) = t;
3438 t = p;
3439 p = q;
3440 goto E2;
3441 }
3442 E5: q = cdr(p); /* down cdr */
3443 if (q && !is_mark(q)) {
3444 cdr(p) = t;
3445 t = p;
3446 p = q;
3447 goto E2;
3448 }
3449 E6: /* up. Undo the link switching from steps E4 and E5. */
3450 if (!t)
3451 return;
3452 q = t;
3453 if (is_atom(q)) {
3454 clratom(q);
3455 t = car(q);
3456 car(q) = p;
3457 p = q;
3458 goto E5;
3459 } else {
3460 t = cdr(q);
3461 cdr(q) = p;
3462 p = q;
3463 goto E6;
3464 }
3465 }
3466
3467 /* garbage collection. parameter a, b is marked. */
3468 static void gc(scheme *sc, pointer a, pointer b) {
3469 pointer p;
3470 int i;
3471
3472 if(sc->gc_verbose) {
3473 putstr(sc, "gc...");
3474 }
3475
3476 /* mark system globals */
3477 mark(sc->oblist);
3478 mark(sc->global_env);
3479
3480 /* mark current registers */
3481 mark(sc->args);
3482 mark(sc->envir);
3483 mark(sc->code);
3484 dump_stack_mark(sc);
3485 mark(sc->value);
3486 mark(sc->inport);
3487 mark(sc->save_inport);
3488 mark(sc->outport);
3489 mark(sc->loadport);
3490
3491 /* Mark recent objects the interpreter doesn't know about yet. */
3492 mark(car(sc->sink));
3493 /* Mark any older stuff above nested C calls */
3494 mark(sc->c_nest);
3495
3496 /* mark variables a, b */
3497 mark(a);
3498 mark(b);
3499
3500 /* garbage collect */
3501 clrmark(sc->NIL);
3502 sc->fcells = 0;
3503 sc->free_cell = sc->NIL;
3504 /* free-list is kept sorted by address so as to maintain consecutive
3505 ranges, if possible, for use with vectors. Here we scan the cells
3506 (which are also kept sorted by address) downwards to build the
3507 free-list in sorted order.
3508 */
3509 for (i = sc->last_cell_seg; i >= 0; i--) {
3510 p = sc->cell_seg[i] + CELL_SEGSIZE;
3511 while (--p >= sc->cell_seg[i]) {
3512 if (is_mark(p)) {
3513 clrmark(p);
3514 } else {
3515 /* reclaim cell */
3516 if (typeflag(p) != 0) {
3517 finalize_cell(sc, p);
3518 typeflag(p) = 0;
3519 car(p) = sc->NIL;
3520 }
3521 ++sc->fcells;
3522 cdr(p) = sc->free_cell;
3523 sc->free_cell = p;
3524 }
3525 }
3526 }
3527
3528 if (sc->gc_verbose) {
3529 char msg[80];
3530 snprintf(msg,80,"done: %ld cells were recovered.\n", sc->fcells);
3531 putstr(sc,msg);
3532 }
3533 }
3534
3535 static void finalize_cell(scheme *sc, pointer a) {
3536 if(is_string(a)) {
3537 sc->free(strvalue(a));
3538 } else if(is_port(a)) {
3539 if(a->_object._port->kind&port_file
3540 && a->_object._port->rep.stdio.closeit) {
3541 port_close(sc,a,port_input|port_output);
3542 }
3543 sc->free(a->_object._port);
3544 }
3545 }
3546
3547 /* ========== Routines for Reading ========== */
3548
3549 static int file_push(scheme *sc, const char *fname) {
3550 FILE *fin = NULL;
3551
3552 if (sc->file_i == MAXFIL-1)
3553 return 0;
3554 fin=fopen(fname,"r");
3555 if(fin!=0) {
3556 sc->file_i++;
3557 sc->load_stack[sc->file_i].kind=port_file|port_input;
3558 sc->load_stack[sc->file_i].rep.stdio.file=fin;
3559 sc->load_stack[sc->file_i].rep.stdio.closeit=1;
3560 sc->nesting_stack[sc->file_i]=0;
3561 sc->loadport->_object._port=sc->load_stack+sc->file_i;
3562
3563 #if SHOW_ERROR_LINE
3564 sc->load_stack[sc->file_i].rep.stdio.curr_line = 0;
3565 if(fname)
3566 sc->load_stack[sc->file_i].rep.stdio.filename = store_string(sc, strlen(fname), fname, 0);
3567 #endif
3568 }
3569 return fin!=0;
3570 }
3571
3572 static void file_pop(scheme *sc) {
3573 if(sc->file_i != 0) {
3574 sc->nesting=sc->nesting_stack[sc->file_i];
3575 port_close(sc,sc->loadport,port_input);
3576 sc->file_i--;
3577 sc->loadport->_object._port=sc->load_stack+sc->file_i;
3578 }
3579 }
3580
3581 static int file_interactive(scheme *sc) {
3582 return sc->file_i==0 && sc->load_stack[0].rep.stdio.interactive /* sc->load_stack[0].rep.stdio.file==stdin */
3583 && sc->inport->_object._port->kind&port_file;
3584 }
3585
3586 static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
3587 FILE *f;
3588 char *rw;
3589 port *pt;
3590 if(prop==(port_input|port_output)) {
3591 rw="a+";
3592 } else if(prop==port_output) {
3593 rw="w";
3594 } else {
3595 rw="r";
3596 }
3597 f=fopen(fn,rw);
3598 if(f==0) {
3599 return 0;
3600 }
3601 pt=port_rep_from_file(sc,f,prop);
3602 pt->rep.stdio.closeit=1;
3603 pt->rep.stdio.interactive=0;
3604
3605 #if SHOW_ERROR_LINE
3606 if(fn)
3607 pt->rep.stdio.filename = store_string(sc, strlen(fn), fn, 0);
3608
3609 pt->rep.stdio.curr_line = 0;
3610 #endif
3611 return pt;
3612 }
3613
3614 static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
3615 port *pt;
3616 pt=port_rep_from_filename(sc,fn,prop);
3617 if(pt==0) {
3618 return sc->NIL;
3619 }
3620 return mk_port(sc,pt);
3621 }
3622
3623 static port *port_rep_from_file(scheme *sc, FILE *f, int prop)
3624 {
3625 port *pt;
3626
3627 pt = (port *)sc->malloc(sizeof *pt);
3628 if (pt == NULL) {
3629 return NULL;
3630 }
3631 pt->kind = port_file | prop;
3632 pt->rep.stdio.file = f;
3633 pt->rep.stdio.closeit = 0;
3634 pt->rep.stdio.interactive=sc->interactive_repl;
3635 return pt;
3636 }
3637
3638 static pointer port_from_file(scheme *sc, FILE *f, int prop) {
3639 port *pt;
3640 pt=port_rep_from_file(sc,f,prop);
3641 if(pt==0) {
3642 return sc->NIL;
3643 }
3644 return mk_port(sc,pt);
3645 }
3646
3647 static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
3648 port *pt;
3649 pt=(port*)sc->malloc(sizeof(port));
3650 if(pt==0) {
3651 return 0;
3652 }
3653 pt->kind=port_string|prop;
3654 pt->rep.string.start=start;
3655 pt->rep.string.curr=start;
3656 pt->rep.string.past_the_end=past_the_end;
3657 return pt;
3658 }
3659
3660 static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
3661 port *pt;
3662 pt=port_rep_from_string(sc,start,past_the_end,prop);
3663 if(pt==0) {
3664 return sc->NIL;
3665 }
3666 return mk_port(sc,pt);
3667 }
3668
3669 #define BLOCK_SIZE 256
3670
3671 static port *port_rep_from_scratch(scheme *sc) {
3672 port *pt;
3673 char *start;
3674 pt=(port*)sc->malloc(sizeof(port));
3675 if(pt==0) {
3676 return 0;
3677 }
3678 start=sc->malloc(BLOCK_SIZE);
3679 if(start==0) {
3680 return 0;
3681 }
3682 memset(start,' ',BLOCK_SIZE-1);
3683 start[BLOCK_SIZE-1]='\0';
3684 pt->kind=port_string|port_output|port_srfi6;
3685 pt->rep.string.start=start;
3686 pt->rep.string.curr=start;
3687 pt->rep.string.past_the_end=start+BLOCK_SIZE-1;
3688 return pt;
3689 }
3690
3691 static pointer port_from_scratch(scheme *sc) {
3692 port *pt;
3693 pt=port_rep_from_scratch(sc);
3694 if(pt==0) {
3695 return sc->NIL;
3696 }
3697 return mk_port(sc,pt);
3698 }
3699
3700 static void port_close(scheme *sc, pointer p, int flag) {
3701 port *pt=p->_object._port;
3702 pt->kind&=~flag;
3703 if((pt->kind & (port_input|port_output))==0) {
3704 if(pt->kind&port_file) {
3705
3706 #if SHOW_ERROR_LINE
3707 /* Cleanup is here so (close-*-port) functions could work too */
3708 pt->rep.stdio.curr_line = 0;
3709
3710 if(pt->rep.stdio.filename)
3711 sc->free(pt->rep.stdio.filename);
3712 #endif
3713
3714 fclose(pt->rep.stdio.file);
3715 }
3716 pt->kind=port_free;
3717 }
3718 }
3719
3720 /* get new character from input file */
3721 static int inchar(scheme *sc) {
3722 int c;
3723 port *pt;
3724
3725 pt = sc->inport->_object._port;
3726 if(pt->kind & port_saw_EOF)
3727 { return EOF; }
3728 c = basic_inchar(pt);
3729 if(c == EOF && sc->inport == sc->loadport) {
3730 /* Instead, set port_saw_EOF */
3731 pt->kind |= port_saw_EOF;
3732
3733 /* file_pop(sc); */
3734 return EOF;
3735 /* NOTREACHED */
3736 }
3737 return c;
3738 }
3739
3740 static int basic_inchar(port *pt) {
3741 if(pt->kind & port_file) {
3742 return fgetc(pt->rep.stdio.file);
3743 } else {
3744 if(*pt->rep.string.curr == 0 ||
3745 pt->rep.string.curr == pt->rep.string.past_the_end) {
3746 return EOF;
3747 } else {
3748 return *pt->rep.string.curr++;
3749 }
3750 }
3751 }
3752
3753 /* back character to input buffer */
3754 static void backchar(scheme *sc, int c) {
3755 port *pt;
3756 if(c==EOF) return;
3757 pt=sc->inport->_object._port;
3758 if(pt->kind&port_file) {
3759 ungetc(c,pt->rep.stdio.file);
3760 } else {
3761 if(pt->rep.string.curr!=pt->rep.string.start) {
3762 --pt->rep.string.curr;
3763 }
3764 }
3765 }
3766
3767 static int realloc_port_string(scheme *sc, port *p)
3768 {
3769 char *start=p->rep.string.start;
3770 size_t new_size=p->rep.string.past_the_end-start+1+BLOCK_SIZE;
3771 char *str=sc->malloc(new_size);
3772 if(str) {
3773 memset(str,' ',new_size-1);
3774 str[new_size-1]='\0';
3775 strcpy(str,start);
3776 p->rep.string.start=str;
3777 p->rep.string.past_the_end=str+new_size-1;
3778 p->rep.string.curr-=start-str;
3779 sc->free(start);
3780 return 1;
3781 } else {
3782 return 0;
3783 }
3784 }
3785
3786 INTERFACE void putstr(scheme *sc, const char *s) {
3787 port *pt=sc->outport->_object._port;
3788 if(pt->kind&port_file) {
3789 fputs(s,pt->rep.stdio.file);
3790 if( pt->rep.stdio.interactive )
3791 fflush( pt->rep.stdio.file );
3792 } else {
3793 for(;*s;s++) {
3794 if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
3795 *pt->rep.string.curr++=*s;
3796 } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
3797 *pt->rep.string.curr++=*s;
3798 }
3799 }
3800 }
3801 }
3802
3803 static void putchars(scheme *sc, const char *s, int len) {
3804 port *pt=sc->outport->_object._port;
3805 if(pt->kind&port_file) {
3806 fwrite(s,1,len,pt->rep.stdio.file);
3807 } else {
3808 for(;len;len--) {
3809 if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
3810 *pt->rep.string.curr++=*s++;
3811 } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
3812 *pt->rep.string.curr++=*s++;
3813 }
3814 }
3815 }
3816 }
3817
3818 INTERFACE void putcharacter(scheme *sc, int c) {
3819 port *pt=sc->outport->_object._port;
3820 if(pt->kind&port_file) {
3821 fputc(c,pt->rep.stdio.file);
3822 } else {
3823 if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
3824 *pt->rep.string.curr++=c;
3825 } else if(pt->kind&port_srfi6&&realloc_port_string(sc,pt)) {
3826 *pt->rep.string.curr++=c;
3827 }
3828 }
3829 }
3830
3831 /* read characters up to delimiter, but cater to character constants */
3832 static char *readstr_upto(scheme *sc, char *delim) {
3833 char *p = sc->strbuff;
3834
3835 while ((p - sc->strbuff < sizeof(sc->strbuff)) &&
3836 !is_one_of(delim, (*p++ = inchar(sc))));
3837
3838 if(p == sc->strbuff+2 && p[-2] == '\\') {
3839 *p=0;
3840 } else {
3841 backchar(sc,p[-1]);
3842 *--p = '\0';
3843 }
3844 return sc->strbuff;
3845 }
3846
3847 /* read string expression "xxx...xxx" */
3848 static pointer readstrexp(scheme *sc) {
3849 char *p = sc->strbuff;
3850 int c;
3851 int c1=0;
3852 enum { st_ok, st_bsl, st_x1, st_x2, st_oct1, st_oct2 } state=st_ok;
3853
3854 for (;;) {
3855 c=inchar(sc);
3856 if(c == EOF || p-sc->strbuff > sizeof(sc->strbuff)-1) {
3857 return sc->F;
3858 }
3859 switch(state) {
3860 case st_ok:
3861 switch(c) {
3862 case '\\':
3863 state=st_bsl;
3864 break;
3865 case '"':
3866 *p=0;
3867 return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
3868 default:
3869 *p++=c;
3870 break;
3871 }
3872 break;
3873 case st_bsl:
3874 switch(c) {
3875 case '0':
3876 case '1':
3877 case '2':
3878 case '3':
3879 case '4':
3880 case '5':
3881 case '6':
3882 case '7':
3883 state=st_oct1;
3884 c1=c-'0';
3885 break;
3886 case 'x':
3887 case 'X':
3888 state=st_x1;
3889 c1=0;
3890 break;
3891 case 'n':
3892 *p++='\n';
3893 state=st_ok;
3894 break;
3895 case 't':
3896 *p++='\t';
3897 state=st_ok;
3898 break;
3899 case 'r':
3900 *p++='\r';
3901 state=st_ok;
3902 break;
3903 case '"':
3904 *p++='"';
3905 state=st_ok;
3906 break;
3907 default:
3908 *p++=c;
3909 state=st_ok;
3910 break;
3911 }
3912 break;
3913 case st_x1:
3914 case st_x2:
3915 c=toupper(c);
3916 if(c>='0' && c<='F') {
3917 if(c<='9') {
3918 c1=(c1<<4)+c-'0';
3919 } else {
3920 c1=(c1<<4)+c-'A'+10;
3921 }
3922 if(state==st_x1) {
3923 state=st_x2;
3924 } else {
3925 *p++=c1;
3926 state=st_ok;
3927 }
3928 } else {
3929 return sc->F;
3930 }
3931 break;
3932 case st_oct1:
3933 case st_oct2:
3934 if (c < '0' || c > '7')
3935 {
3936 *p++=c1;
3937 backchar(sc, c);
3938 state=st_ok;
3939 }
3940 else
3941 {
3942 if (state==st_oct2 && c1 >= 32)
3943 return sc->F;
3944
3945 c1=(c1<<3)+(c-'0');
3946
3947 if (state == st_oct1)
3948 state=st_oct2;
3949 else
3950 {
3951 *p++=c1;
3952 state=st_ok;
3953 }
3954 }
3955 break;
3956
3957 }
3958 }
3959 }
3960
3961 /* check c is in chars */
3962 static INLINE int is_one_of(char *s, int c) {
3963 if(c==EOF) return 1;
3964 while (*s)
3965 if (*s++ == c)
3966 return (1);
3967 return (0);
3968 }
3969
3970 /* skip white characters */
3971 static INLINE int skipspace(scheme *sc) {
3972 int c = 0, curr_line = 0;
3973
3974 do {
3975 c=inchar(sc);
3976 #if SHOW_ERROR_LINE
3977 if(c=='\n')
3978 curr_line++;
3979 #endif
3980 } while (isspace(c));
3981
3982 /* record it */
3983 #if SHOW_ERROR_LINE
3984 if (sc->load_stack[sc->file_i].kind & port_file)
3985 sc->load_stack[sc->file_i].rep.stdio.curr_line += curr_line;
3986 #endif
3987
3988 if(c!=EOF) {
3989 backchar(sc,c);
3990 return 1;
3991 }
3992 else
3993 { return EOF; }
3994 }
3995
3996 /* get token */
3997 static int token(scheme *sc) {
3998 int c;
3999 c = skipspace(sc);
4000 if(c == EOF) { return (TOK_EOF); }
4001 switch (c=inchar(sc)) {
4002 case EOF:
4003 return (TOK_EOF);
4004 case '(':
4005 return (TOK_LPAREN);
4006 case ')':
4007 return (TOK_RPAREN);
4008 case '.':
4009 c=inchar(sc);
4010 if(is_one_of(" \n\t",c)) {
4011 return (TOK_DOT);
4012 } else {
4013 backchar(sc,c);
4014 backchar(sc,'.');
4015 return TOK_ATOM;
4016 }
4017 case '\'':
4018 return (TOK_QUOTE);
4019 case ';':
4020 while ((c=inchar(sc)) != '\n' && c!=EOF)
4021 ;
4022
4023 #if SHOW_ERROR_LINE
4024 if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file)
4025 sc->load_stack[sc->file_i].rep.stdio.curr_line++;
4026 #endif
4027
4028 if(c == EOF)
4029 { return (TOK_EOF); }
4030 else
4031 { return (token(sc));}
4032 case '"':
4033 return (TOK_DQUOTE);
4034 case BACKQUOTE:
4035 return (TOK_BQUOTE);
4036 case ',':
4037 if ((c=inchar(sc)) == '@') {
4038 return (TOK_ATMARK);
4039 } else {
4040 backchar(sc,c);
4041 return (TOK_COMMA);
4042 }
4043 case '#':
4044 c=inchar(sc);
4045 if (c == '(') {
4046 return (TOK_VEC);
4047 } else if(c == '!') {
4048 while ((c=inchar(sc)) != '\n' && c!=EOF)
4049 ;
4050
4051 #if SHOW_ERROR_LINE
4052 if(c == '\n' && sc->load_stack[sc->file_i].kind & port_file)
4053 sc->load_stack[sc->file_i].rep.stdio.curr_line++;
4054 #endif
4055
4056 if(c == EOF)
4057 { return (TOK_EOF); }
4058 else
4059 { return (token(sc));}
4060 } else {
4061 backchar(sc,c);
4062 if(is_one_of(" tfodxb\\",c)) {
4063 return TOK_SHARP_CONST;
4064 } else {
4065 return (TOK_SHARP);
4066 }
4067 }
4068 default:
4069 backchar(sc,c);
4070 return (TOK_ATOM);
4071 }
4072 }
4073
4074 /* ========== Routines for Printing ========== */
4075 #define ok_abbrev(x) (is_pair(x) && cdr(x) == sc->NIL)
4076
4077 static void printslashstring(scheme *sc, char *p, int len) {
4078 int i;
4079 unsigned char *s=(unsigned char*)p;
4080 putcharacter(sc,'"');
4081 for ( i=0; i<len; i++) {
4082 if(*s==0xff || *s=='"' || *s<' ' || *s=='\\') {
4083 putcharacter(sc,'\\');
4084 switch(*s) {
4085 case '"':
4086 putcharacter(sc,'"');
4087 break;
4088 case '\n':
4089 putcharacter(sc,'n');
4090 break;
4091 case '\t':
4092 putcharacter(sc,'t');
4093 break;
4094 case '\r':
4095 putcharacter(sc,'r');
4096 break;
4097 case '\\':
4098 putcharacter(sc,'\\');
4099 break;
4100 default: {
4101 int d=*s/16;
4102 putcharacter(sc,'x');
4103 if(d<10) {
4104 putcharacter(sc,d+'0');
4105 } else {
4106 putcharacter(sc,d-10+'A');
4107 }
4108 d=*s%16;
4109 if(d<10) {
4110 putcharacter(sc,d+'0');
4111 } else {
4112 putcharacter(sc,d-10+'A');
4113 }
4114 }
4115 }
4116 } else {
4117 putcharacter(sc,*s);
4118 }
4119 s++;
4120 }
4121 putcharacter(sc,'"');
4122 }
4123
4124
4125 /* print atoms */
4126 static void printatom(scheme *sc, pointer l, int f) {
4127 char *p;
4128 int len;
4129 atom2str(sc,l,f,&p,&len);
4130 putchars(sc,p,len);
4131 }
4132
4133
4134 /* Uses internal buffer unless string pointer is already available */
4135 static void atom2str(scheme *sc, pointer l, int f, char **pp, int *plen) {
4136 char *p;
4137
4138 if (l == sc->NIL) {
4139 p = "()";
4140 } else if (l == sc->T) {
4141 p = "#t";
4142 } else if (l == sc->F) {
4143 p = "#f";
4144 } else if (l == sc->EOF_OBJ) {
4145 p = "#<EOF>";
4146 } else if (is_port(l)) {
4147 p = sc->strbuff;
4148 snprintf(p, STRBUFFSIZE, "#<PORT>");
4149 } else if (is_number(l)) {
4150 p = sc->strbuff;
4151 if (f <= 1 || f == 10) /* f is the base for numbers if > 1 */ {
4152 if(num_is_integer(l)) {
4153 snprintf(p, STRBUFFSIZE, "%ld", ivalue_unchecked(l));
4154 } else {
4155 snprintf(p, STRBUFFSIZE, "%.10g", rvalue_unchecked(l));
4156 /* r5rs says there must be a '.' (unless 'e'?) */
4157 f = strcspn(p, ".e");
4158 if (p[f] == 0) {
4159 p[f] = '.'; /* not found, so add '.0' at the end */
4160 p[f+1] = '0';
4161 p[f+2] = 0;
4162 }
4163 }
4164 } else {
4165 long v = ivalue(l);
4166 if (f == 16) {
4167 if (v >= 0)
4168 snprintf(p, STRBUFFSIZE, "%lx", v);
4169 else
4170 snprintf(p, STRBUFFSIZE, "-%lx", -v);
4171 } else if (f == 8) {
4172 if (v >= 0)
4173 snprintf(p, STRBUFFSIZE, "%lo", v);
4174 else
4175 snprintf(p, STRBUFFSIZE, "-%lo", -v);
4176 } else if (f == 2) {
4177 unsigned long b = (v < 0) ? -v : v;
4178 p = &p[STRBUFFSIZE-1];
4179 *p = 0;
4180 do { *--p = (b&1) ? '1' : '0'; b >>= 1; } while (b != 0);
4181 if (v < 0) *--p = '-';
4182 }
4183 }
4184 } else if (is_string(l)) {
4185 if (!f) {
4186 p = strvalue(l);
4187 } else { /* Hack, uses the fact that printing is needed */
4188 *pp=sc->strbuff;
4189 *plen=0;
4190 printslashstring(sc, strvalue(l), strlength(l));
4191 return;
4192 }
4193 } else if (is_character(l)) {
4194 int c=charvalue(l);
4195 p = sc->strbuff;
4196 if (!f) {
4197 p[0]=c;
4198 p[1]=0;
4199 } else {
4200 switch(c) {
4201 case ' ':
4202 snprintf(p,STRBUFFSIZE,"#\\space"); break;
4203 case '\n':
4204 snprintf(p,STRBUFFSIZE,"#\\newline"); break;
4205 case '\r':
4206 snprintf(p,STRBUFFSIZE,"#\\return"); break;
4207 case '\t':
4208 snprintf(p,STRBUFFSIZE,"#\\tab"); break;
4209 default:
4210 #if USE_ASCII_NAMES
4211 if(c==127) {
4212 snprintf(p,STRBUFFSIZE, "#\\del");
4213 break;
4214 } else if(c<32) {
4215 snprintf(p, STRBUFFSIZE, "#\\%s", charnames[c]);
4216 break;
4217 }
4218 #else
4219 if(c<32) {
4220 snprintf(p,STRBUFFSIZE,"#\\x%x",c); break;
4221 break;
4222 }
4223 #endif
4224 snprintf(p,STRBUFFSIZE,"#\\%c",c); break;
4225 break;
4226 }
4227 }
4228 } else if (is_symbol(l)) {
4229 p = symname(l);
4230 } else if (is_proc(l)) {
4231 p = sc->strbuff;
4232 snprintf(p,STRBUFFSIZE,"#<%s PROCEDURE %ld>", procname(l),procnum(l));
4233 } else if (is_macro(l)) {
4234 p = "#<MACRO>";
4235 } else if (is_closure(l)) {
4236 p = "#<CLOSURE>";
4237 } else if (is_promise(l)) {
4238 p = "#<PROMISE>";
4239 } else if (is_foreign(l)) {
4240 p = sc->strbuff;
4241 snprintf(p,STRBUFFSIZE,"#<FOREIGN PROCEDURE %ld>", procnum(l));
4242 } else if (is_continuation(l)) {
4243 p = "#<CONTINUATION>";
4244 } else {
4245 p = "#<ERROR>";
4246 }
4247 *pp=p;
4248 *plen=strlen(p);
4249 }
4250 /* ========== Routines for Evaluation Cycle ========== */
4251
4252 /* make closure. c is code. e is environment */
4253 static pointer mk_closure(scheme *sc, pointer c, pointer e) {
4254 pointer x = get_cell(sc, c, e);
4255
4256 typeflag(x) = T_CLOSURE;
4257 car(x) = c;
4258 cdr(x) = e;
4259 return (x);
4260 }
4261
4262 /* make continuation. */
4263 static pointer mk_continuation(scheme *sc, pointer d) {
4264 pointer x = get_cell(sc, sc->NIL, d);
4265
4266 typeflag(x) = T_CONTINUATION;
4267 cont_dump(x) = d;
4268 return (x);
4269 }
4270
4271 static pointer list_star(scheme *sc, pointer d) {
4272 pointer p, q;
4273 if(cdr(d)==sc->NIL) {
4274 return car(d);
4275 }
4276 p=cons(sc,car(d),cdr(d));
4277 q=p;
4278 while(cdr(cdr(p))!=sc->NIL) {
4279 d=cons(sc,car(p),cdr(p));
4280 if(cdr(cdr(p))!=sc->NIL) {
4281 p=cdr(d);
4282 }
4283 }
4284 cdr(p)=car(cdr(p));
4285 return q;
4286 }
4287
4288 /* reverse list -- produce new list */
4289 static pointer reverse(scheme *sc, pointer a) {
4290 /* a must be checked by gc */
4291 pointer p = sc->NIL;
4292
4293 for ( ; is_pair(a); a = cdr(a)) {
4294 p = cons(sc, car(a), p);
4295 }
4296 return (p);
4297 }
4298
4299 /* reverse list --- in-place */
4300 static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
4301 pointer p = list, result = term, q;
4302
4303 while (p != sc->NIL) {
4304 q = cdr(p);
4305 cdr(p) = result;
4306 result = p;
4307 p = q;
4308 }
4309 return (result);
4310 }
4311
4312 /* append list -- produce new list (in reverse order) */
4313 static pointer revappend(scheme *sc, pointer a, pointer b) {
4314 pointer result = a;
4315 pointer p = b;
4316
4317 while (is_pair(p)) {
4318 result = cons(sc, car(p), result);
4319 p = cdr(p);
4320 }
4321
4322 if (p == sc->NIL) {
4323 return result;
4324 }
4325
4326 return sc->F; /* signal an error */
4327 }
4328
4329 /* equivalence of atoms */
4330 int eqv(pointer a, pointer b) {
4331 if (is_string(a)) {
4332 if (is_string(b))
4333 return (strvalue(a) == strvalue(b));
4334 else
4335 return (0);
4336 } else if (is_number(a)) {
4337 if (is_number(b)) {
4338 if (num_is_integer(a) == num_is_integer(b))
4339 return num_eq(nvalue(a),nvalue(b));
4340 }
4341 return (0);
4342 } else if (is_character(a)) {
4343 if (is_character(b))
4344 return charvalue(a)==charvalue(b);
4345 else
4346 return (0);
4347 } else if (is_port(a)) {
4348 if (is_port(b))
4349 return a==b;
4350 else
4351 return (0);
4352 } else if (is_proc(a)) {
4353 if (is_proc(b))
4354 return procnum(a)==procnum(b);
4355 else
4356 return (0);
4357 } else {
4358 return (a == b);
4359 }
4360 }
4361
4362 /* true or false value macro */
4363 /* () is #t in R5RS */
4364 #define is_true(p) ((p) != sc->F)
4365 #define is_false(p) ((p) == sc->F)
4366
4367 /* ========== Environment implementation ========== */
4368
4369 #if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST)
4370
4371 static int hash_fn(const char *key, int table_size)
4372 {
4373 unsigned int hashed = 0;
4374 const char *c;
4375 int bits_per_int = sizeof(unsigned int)*8;
4376
4377 for (c = key; *c; c++) {
4378 /* letters have about 5 bits in them */
4379 hashed = (hashed<<5) | (hashed>>(bits_per_int-5));
4380 hashed ^= *c;
4381 }
4382 return hashed % table_size;
4383 }
4384 #endif
4385
4386 #ifndef USE_ALIST_ENV
4387
4388 /*
4389 * In this implementation, each frame of the environment may be
4390 * a hash table: a vector of alists hashed by variable name.
4391 * In practice, we use a vector only for the initial frame;
4392 * subsequent frames are too small and transient for the lookup
4393 * speed to out-weigh the cost of making a new vector.
4394 */
4395
4396 static void new_frame_in_env(scheme *sc, pointer old_env)
4397 {
4398 pointer new_frame;
4399
4400 /* The interaction-environment has about 300 variables in it. */
4401 if (old_env == sc->NIL) {
4402 new_frame = mk_vector(sc, 461);
4403 } else {
4404 new_frame = sc->NIL;
4405 }
4406
4407 sc->envir = immutable_cons(sc, new_frame, old_env);
4408 setenvironment(sc->envir);
4409 }
4410
4411 static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
4412 pointer variable, pointer value)
4413 {
4414 pointer slot = immutable_cons(sc, variable, value);
4415
4416 if (is_vector(car(env))) {
4417 int location = hash_fn(symname(variable), ivalue_unchecked(car(env)));
4418
4419 set_vector_elem(car(env), location,
4420 immutable_cons(sc, slot, vector_elem(car(env), location)));
4421 } else {
4422 car(env) = immutable_cons(sc, slot, car(env));
4423 }
4424 }
4425
4426 static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
4427 {
4428 pointer x,y;
4429 int location;
4430
4431 for (x = env; x != sc->NIL; x = cdr(x)) {
4432 if (is_vector(car(x))) {
4433 location = hash_fn(symname(hdl), ivalue_unchecked(car(x)));
4434 y = vector_elem(car(x), location);
4435 } else {
4436 y = car(x);
4437 }
4438 for ( ; y != sc->NIL; y = cdr(y)) {
4439 if (caar(y) == hdl) {
4440 break;
4441 }
4442 }
4443 if (y != sc->NIL) {
4444 break;
4445 }
4446 if(!all) {
4447 return sc->NIL;
4448 }
4449 }
4450 if (x != sc->NIL) {
4451 return car(y);
4452 }
4453 return sc->NIL;
4454 }
4455
4456 #else /* USE_ALIST_ENV */
4457
4458 static INLINE void new_frame_in_env(scheme *sc, pointer old_env)
4459 {
4460 sc->envir = immutable_cons(sc, sc->NIL, old_env);
4461 setenvironment(sc->envir);
4462 }
4463
4464 static INLINE void new_slot_spec_in_env(scheme *sc, pointer env,
4465 pointer variable, pointer value)
4466 {
4467 car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env));
4468 }
4469
4470 static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all)
4471 {
4472 pointer x,y;
4473 for (x = env; x != sc->NIL; x = cdr(x)) {
4474 for (y = car(x); y != sc->NIL; y = cdr(y)) {
4475 if (caar(y) == hdl) {
4476 break;
4477 }
4478 }
4479 if (y != sc->NIL) {
4480 break;
4481 }
4482 if(!all) {
4483 return sc->NIL;
4484 }
4485 }
4486 if (x != sc->NIL) {
4487 return car(y);
4488 }
4489 return sc->NIL;
4490 }
4491
4492 #endif /* USE_ALIST_ENV else */
4493
4494 static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value)
4495 {
4496 new_slot_spec_in_env(sc, sc->envir, variable, value);
4497 }
4498
4499 static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value)
4500 {
4501 cdr(slot) = value;
4502 }
4503
4504 static INLINE pointer slot_value_in_env(pointer slot)
4505 {
4506 return cdr(slot);
4507 }
4508
4509 /* ========== Evaluation Cycle ========== */
4510
4511
4512 static pointer _Error_1(scheme *sc, const char *s, pointer a) {
4513 const char *str = s;
4514 #if USE_ERROR_HOOK
4515 pointer x;
4516 pointer hdl=sc->ERROR_HOOK;
4517 #endif
4518
4519 #if SHOW_ERROR_LINE
4520 char sbuf[STRBUFFSIZE];
4521
4522 /* make sure error is not in REPL */
4523 if (sc->load_stack[sc->file_i].kind & port_file &&
4524 sc->load_stack[sc->file_i].rep.stdio.file != stdin) {
4525 int ln = sc->load_stack[sc->file_i].rep.stdio.curr_line;
4526 const char *fname = sc->load_stack[sc->file_i].rep.stdio.filename;
4527
4528 /* should never happen */
4529 if(!fname) fname = "<unknown>";
4530
4531 /* we started from 0 */
4532 ln++;
4533 snprintf(sbuf, STRBUFFSIZE, "(%s : %i) %s", fname, ln, s);
4534
4535 str = (const char*)sbuf;
4536 }
4537 #endif
4538
4539 #if USE_ERROR_HOOK
4540 x=find_slot_in_env(sc,sc->envir,hdl,1);
4541 if (x != sc->NIL) {
4542 if(a!=0) {
4543 sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL);
4544 } else {
4545 sc->code = sc->NIL;
4546 }
4547 sc->code = cons(sc, mk_string(sc, str), sc->code);
4548 setimmutable(car(sc->code));
4549 sc->code = cons(sc, slot_value_in_env(x), sc->code);
4550 sc->op = (int)OP_EVAL;
4551 return sc->T;
4552 }
4553 #endif
4554
4555 if(a!=0) {
4556 sc->args = cons(sc, (a), sc->NIL);
4557 } else {
4558 sc->args = sc->NIL;
4559 }
4560 sc->args = cons(sc, mk_string(sc, str), sc->args);
4561 setimmutable(car(sc->args));
4562 sc->op = (int)OP_ERR0;
4563 return sc->T;
4564 }
4565 #define Error_1(sc,s, a) return _Error_1(sc,s,a)
4566 #define Error_0(sc,s) return _Error_1(sc,s,0)
4567
4568 /* Too small to turn into function */
4569 # define BEGIN do {
4570 # define END } while (0)
4571 #define s_goto(sc,a) BEGIN \
4572 sc->op = (int)(a); \
4573 return sc->T; END
4574
4575 #define s_return(sc,a) return _s_return(sc,a)
4576
4577 #ifndef USE_SCHEME_STACK
4578
4579 /* this structure holds all the interpreter's registers */
4580 struct dump_stack_frame {
4581 enum scheme_opcodes op;
4582 pointer args;
4583 pointer envir;
4584 pointer code;
4585 };
4586
4587 #define STACK_GROWTH 3
4588
4589 static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code)
4590 {
4591 int nframes = (int)sc->dump;
4592 struct dump_stack_frame *next_frame;
4593
4594 /* enough room for the next frame? */
4595 if (nframes >= sc->dump_size) {
4596 sc->dump_size += STACK_GROWTH;
4597 /* alas there is no sc->realloc */
4598 sc->dump_base = realloc(sc->dump_base,
4599 sizeof(struct dump_stack_frame) * sc->dump_size);
4600 }
4601 next_frame = (struct dump_stack_frame *)sc->dump_base + nframes;
4602 next_frame->op = op;
4603 next_frame->args = args;
4604 next_frame->envir = sc->envir;
4605 next_frame->code = code;
4606 sc->dump = (pointer)(nframes+1);
4607 }
4608
4609 static pointer _s_return(scheme *sc, pointer a)
4610 {
4611 int nframes = (int)sc->dump;
4612 struct dump_stack_frame *frame;
4613
4614 sc->value = (a);
4615 if (nframes <= 0) {
4616 return sc->NIL;
4617 }
4618 nframes--;
4619 frame = (struct dump_stack_frame *)sc->dump_base + nframes;
4620 sc->op = frame->op;
4621 sc->args = frame->args;
4622 sc->envir = frame->envir;
4623 sc->code = frame->code;
4624 sc->dump = (pointer)nframes;
4625 return sc->T;
4626 }
4627
4628 static INLINE void dump_stack_reset(scheme *sc)
4629 {
4630 /* in this implementation, sc->dump is the number of frames on the stack */
4631 sc->dump = (pointer)0;
4632 }
4633
4634 static INLINE void dump_stack_initialize(scheme *sc)
4635 {
4636 sc->dump_size = 0;
4637 sc->dump_base = NULL;
4638 dump_stack_reset(sc);
4639 }
4640
4641 static void dump_stack_free(scheme *sc)
4642 {
4643 free(sc->dump_base);
4644 sc->dump_base = NULL;
4645 sc->dump = (pointer)0;
4646 sc->dump_size = 0;
4647 }
4648
4649 static INLINE void dump_stack_mark(scheme *sc)
4650 {
4651 int nframes = (int)sc->dump;
4652 int i;
4653 for(i=0; i<nframes; i++) {
4654 struct dump_stack_frame *frame;
4655 frame = (struct dump_stack_frame *)sc->dump_base + i;
4656 mark(frame->args);
4657 mark(frame->envir);
4658 mark(frame->code);
4659 }
4660 }
4661
4662 #else
4663
4664 static INLINE void dump_stack_reset(scheme *sc)
4665 {
4666 sc->dump = sc->NIL;
4667 }
4668
4669 static INLINE void dump_stack_initialize(scheme *sc)
4670 {
4671 dump_stack_reset(sc);
4672 }
4673
4674 static void dump_stack_free(scheme *sc)
4675 {
4676 sc->dump = sc->NIL;
4677 }
4678
4679 static pointer _s_return(scheme *sc, pointer a) {
4680 sc->value = (a);
4681 if(sc->dump==sc->NIL) return sc->NIL;
4682 sc->op = ivalue(car(sc->dump));
4683 sc->args = cadr(sc->dump);
4684 sc->envir = caddr(sc->dump);
4685 sc->code = cadddr(sc->dump);
4686 sc->dump = cddddr(sc->dump);
4687 return sc->T;
4688 }
4689
4690 static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) {
4691 sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump));
4692 sc->dump = cons(sc, (args), sc->dump);
4693 sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump);
4694 }
4695
4696 static INLINE void dump_stack_mark(scheme *sc)
4697 {
4698 mark(sc->dump);
4699 }
4700 #endif
4701
4702 #define s_retbool(tf) s_return(sc,(tf) ? sc->T : sc->F)
4703
4704 static pointer opexe_0(scheme *sc, enum scheme_opcodes op) {
4705 pointer x, y;
4706
4707 switch (op) {
4708 case OP_LOAD: /* load */
4709 if(file_interactive(sc)) {
4710 fprintf(sc->outport->_object._port->rep.stdio.file,
4711 "Loading %s\n", strvalue(car(sc->args)));
4712 }
4713 if (!file_push(sc,strvalue(car(sc->args)))) {
4714 Error_1(sc,"unable to open", car(sc->args));
4715 }
4716 else
4717 {
4718 sc->args = mk_integer(sc,sc->file_i);
4719 s_goto(sc,OP_T0LVL);
4720 }
4721
4722 case OP_T0LVL: /* top level */
4723 /* If we reached the end of file, this loop is done. */
4724 if(sc->loadport->_object._port->kind & port_saw_EOF)
4725 {
4726 if(sc->file_i == 0)
4727 {
4728 sc->args=sc->NIL;
4729 s_goto(sc,OP_QUIT);
4730 }
4731 else
4732 {
4733 file_pop(sc);
4734 s_return(sc,sc->value);
4735 }
4736 /* NOTREACHED */
4737 }
4738
4739 /* If interactive, be nice to user. */
4740 if(file_interactive(sc))
4741 {
4742 sc->envir = sc->global_env;
4743 dump_stack_reset(sc);
4744 putstr(sc,"\n");
4745 putstr(sc,prompt);
4746 }
4747
4748 /* Set up another iteration of REPL */
4749 sc->nesting=0;
4750 sc->save_inport=sc->inport;
4751 sc->inport = sc->loadport;
4752 s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
4753 s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
4754 s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
4755 s_goto(sc,OP_READ_INTERNAL);
4756
4757 case OP_T1LVL: /* top level */
4758 sc->code = sc->value;
4759 sc->inport=sc->save_inport;
4760 s_goto(sc,OP_EVAL);
4761
4762 case OP_READ_INTERNAL: /* internal read */
4763 sc->tok = token(sc);
4764 if(sc->tok==TOK_EOF)
4765 { s_return(sc,sc->EOF_OBJ); }
4766 s_goto(sc,OP_RDSEXPR);
4767
4768 case OP_GENSYM:
4769 s_return(sc, gensym(sc));
4770
4771 case OP_VALUEPRINT: /* print evaluation result */
4772 /* OP_VALUEPRINT is always pushed, because when changing from
4773 non-interactive to interactive mode, it needs to be
4774 already on the stack */
4775 if(sc->tracing) {
4776 putstr(sc,"\nGives: ");
4777 }
4778 if(file_interactive(sc)) {
4779 sc->print_flag = 1;
4780 sc->args = sc->value;
4781 s_goto(sc,OP_P0LIST);
4782 } else {
4783 s_return(sc,sc->value);
4784 }
4785
4786 case OP_EVAL: /* main part of evaluation */
4787 #if USE_TRACING
4788 if(sc->tracing) {
4789 /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
4790 s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
4791 sc->args=sc->code;
4792 putstr(sc,"\nEval: ");
4793 s_goto(sc,OP_P0LIST);
4794 }
4795 /* fall through */
4796 case OP_REAL_EVAL:
4797 #endif
4798 if (is_symbol(sc->code)) { /* symbol */
4799 x=find_slot_in_env(sc,sc->envir,sc->code,1);
4800 if (x != sc->NIL) {
4801 s_return(sc,slot_value_in_env(x));
4802 } else {
4803 Error_1(sc,"eval: unbound variable:", sc->code);
4804 }
4805 } else if (is_pair(sc->code)) {
4806 if (is_syntax(x = car(sc->code))) { /* SYNTAX */
4807 sc->code = cdr(sc->code);
4808 s_goto(sc,syntaxnum(x));
4809 } else {/* first, eval top element and eval arguments */
4810 s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
4811 /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
4812 sc->code = car(sc->code);
4813 s_goto(sc,OP_EVAL);
4814 }
4815 } else {
4816 s_return(sc,sc->code);
4817 }
4818
4819 case OP_E0ARGS: /* eval arguments */
4820 if (is_macro(sc->value)) { /* macro expansion */
4821 s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
4822 sc->args = cons(sc,sc->code, sc->NIL);
4823 sc->code = sc->value;
4824 s_goto(sc,OP_APPLY);
4825 } else {
4826 sc->code = cdr(sc->code);
4827 s_goto(sc,OP_E1ARGS);
4828 }
4829
4830 case OP_E1ARGS: /* eval arguments */
4831 sc->args = cons(sc, sc->value, sc->args);
4832 if (is_pair(sc->code)) { /* continue */
4833 s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
4834 sc->code = car(sc->code);
4835 sc->args = sc->NIL;
4836 s_goto(sc,OP_EVAL);
4837 } else { /* end */
4838 sc->args = reverse_in_place(sc, sc->NIL, sc->args);
4839 sc->code = car(sc->args);
4840 sc->args = cdr(sc->args);
4841 s_goto(sc,OP_APPLY);
4842 }
4843
4844 #if USE_TRACING
4845 case OP_TRACING: {
4846 int tr=sc->tracing;
4847 sc->tracing=ivalue(car(sc->args));
4848 s_return(sc,mk_integer(sc,tr));
4849 }
4850 #endif
4851
4852 case OP_APPLY: /* apply 'code' to 'args' */
4853 #if USE_TRACING
4854 if(sc->tracing) {
4855 s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
4856 sc->print_flag = 1;
4857 /* sc->args=cons(sc,sc->code,sc->args);*/
4858 putstr(sc,"\nApply to: ");
4859 s_goto(sc,OP_P0LIST);
4860 }
4861 /* fall through */
4862 case OP_REAL_APPLY:
4863 #endif
4864 if (is_proc(sc->code)) {
4865 s_goto(sc,procnum(sc->code)); /* PROCEDURE */
4866 } else if (is_foreign(sc->code))
4867 {
4868 /* Keep nested calls from GC'ing the arglist */
4869 push_recent_alloc(sc,sc->args,sc->NIL);
4870 x=sc->code->_object._ff(sc,sc->args);
4871 s_return(sc,x);
4872 } else if (is_closure(sc->code) || is_macro(sc->code)
4873 || is_promise(sc->code)) { /* CLOSURE */
4874 /* Should not accept promise */
4875 /* make environment */
4876 new_frame_in_env(sc, closure_env(sc->code));
4877 for (x = car(closure_code(sc->code)), y = sc->args;
4878 is_pair(x); x = cdr(x), y = cdr(y)) {
4879 if (y == sc->NIL) {
4880 Error_0(sc,"not enough arguments");
4881 } else {
4882 new_slot_in_env(sc, car(x), car(y));
4883 }
4884 }
4885 if (x == sc->NIL) {
4886 /*--
4887 * if (y != sc->NIL) {
4888 * Error_0(sc,"too many arguments");
4889 * }
4890 */
4891 } else if (is_symbol(x))
4892 new_slot_in_env(sc, x, y);
4893 else {
4894 Error_1(sc,"syntax error in closure: not a symbol:", x);
4895 }
4896 sc->code = cdr(closure_code(sc->code));
4897 sc->args = sc->NIL;
4898 s_goto(sc,OP_BEGIN);
4899 } else if (is_continuation(sc->code)) { /* CONTINUATION */
4900 sc->dump = cont_dump(sc->code);
4901 s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
4902 } else {
4903 Error_0(sc,"illegal function");
4904 }
4905
4906 case OP_DOMACRO: /* do macro */
4907 sc->code = sc->value;
4908 s_goto(sc,OP_EVAL);
4909
4910 #if 1
4911 case OP_LAMBDA: /* lambda */
4912 /* If the hook is defined, apply it to sc->code, otherwise
4913 set sc->value fall thru */
4914 {
4915 pointer f=find_slot_in_env(sc,sc->envir,sc->COMPILE_HOOK,1);
4916 if(f==sc->NIL) {
4917 sc->value = sc->code;
4918 /* Fallthru */
4919 } else {
4920 s_save(sc,OP_LAMBDA1,sc->args,sc->code);
4921 sc->args=cons(sc,sc->code,sc->NIL);
4922 sc->code=slot_value_in_env(f);
4923 s_goto(sc,OP_APPLY);
4924 }
4925 }
4926
4927 case OP_LAMBDA1:
4928 s_return(sc,mk_closure(sc, sc->value, sc->envir));
4929
4930 #else
4931 case OP_LAMBDA: /* lambda */
4932 s_return(sc,mk_closure(sc, sc->code, sc->envir));
4933
4934 #endif
4935
4936 case OP_MKCLOSURE: /* make-closure */
4937 x=car(sc->args);
4938 if(car(x)==sc->LAMBDA) {
4939 x=cdr(x);
4940 }
4941 if(cdr(sc->args)==sc->NIL) {
4942 y=sc->envir;
4943 } else {
4944 y=cadr(sc->args);
4945 }
4946 s_return(sc,mk_closure(sc, x, y));
4947
4948 case OP_QUOTE: /* quote */
4949 s_return(sc,car(sc->code));
4950
4951 case OP_DEF0: /* define */
4952 if(is_immutable(car(sc->code)))
4953 Error_1(sc,"define: unable to alter immutable", car(sc->code));
4954
4955 if (is_pair(car(sc->code))) {
4956 x = caar(sc->code);
4957 sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
4958 } else {
4959 x = car(sc->code);
4960 sc->code = cadr(sc->code);
4961 }
4962 if (!is_symbol(x)) {
4963 Error_0(sc,"variable is not a symbol");
4964 }
4965 s_save(sc,OP_DEF1, sc->NIL, x);
4966 s_goto(sc,OP_EVAL);
4967
4968 case OP_DEF1: /* define */
4969 x=find_slot_in_env(sc,sc->envir,sc->code,0);
4970 if (x != sc->NIL) {
4971 set_slot_in_env(sc, x, sc->value);
4972 } else {
4973 new_slot_in_env(sc, sc->code, sc->value);
4974 }
4975 s_return(sc,sc->code);
4976
4977
4978 case OP_DEFP: /* defined? */
4979 x=sc->envir;
4980 if(cdr(sc->args)!=sc->NIL) {
4981 x=cadr(sc->args);
4982 }
4983 s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
4984
4985 case OP_SET0: /* set! */
4986 if(is_immutable(car(sc->code)))
4987 Error_1(sc,"set!: unable to alter immutable variable",car(sc->code));
4988 s_save(sc,OP_SET1, sc->NIL, car(sc->code));
4989 sc->code = cadr(sc->code);
4990 s_goto(sc,OP_EVAL);
4991
4992 case OP_SET1: /* set! */
4993 y=find_slot_in_env(sc,sc->envir,sc->code,1);
4994 if (y != sc->NIL) {
4995 set_slot_in_env(sc, y, sc->value);
4996 s_return(sc,sc->value);
4997 } else {
4998 Error_1(sc,"set!: unbound variable:", sc->code);
4999 }
5000
5001
5002 case OP_BEGIN: /* begin */
5003 if (!is_pair(sc->code)) {
5004 s_return(sc,sc->code);
5005 }
5006 if (cdr(sc->code) != sc->NIL) {
5007 s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
5008 }
5009 sc->code = car(sc->code);
5010 s_goto(sc,OP_EVAL);
5011
5012 case OP_IF0: /* if */
5013 s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
5014 sc->code = car(sc->code);
5015 s_goto(sc,OP_EVAL);
5016
5017 case OP_IF1: /* if */
5018 if (is_true(sc->value))
5019 sc->code = car(sc->code);
5020 else
5021 sc->code = cadr(sc->code); /* (if #f 1) ==> () because
5022 * car(sc->NIL) = sc->NIL */
5023 s_goto(sc,OP_EVAL);
5024
5025 case OP_LET0: /* let */
5026 sc->args = sc->NIL;
5027 sc->value = sc->code;
5028 sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
5029 s_goto(sc,OP_LET1);
5030
5031 case OP_LET1: /* let (calculate parameters) */
5032 sc->args = cons(sc, sc->value, sc->args);
5033 if (is_pair(sc->code)) { /* continue */
5034 if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) {
5035 Error_1(sc, "Bad syntax of binding spec in let :",
5036 car(sc->code));
5037 }
5038 s_save(sc,OP_LET1, sc->args, cdr(sc->code));
5039 sc->code = cadar(sc->code);
5040 sc->args = sc->NIL;
5041 s_goto(sc,OP_EVAL);
5042 } else { /* end */
5043 sc->args = reverse_in_place(sc, sc->NIL, sc->args);
5044 sc->code = car(sc->args);
5045 sc->args = cdr(sc->args);
5046 s_goto(sc,OP_LET2);
5047 }
5048
5049 case OP_LET2: /* let */
5050 new_frame_in_env(sc, sc->envir);
5051 for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
5052 y != sc->NIL; x = cdr(x), y = cdr(y)) {
5053 new_slot_in_env(sc, caar(x), car(y));
5054 }
5055 if (is_symbol(car(sc->code))) { /* named let */
5056 for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
5057 if (!is_pair(x))
5058 Error_1(sc, "Bad syntax of binding in let :", x);
5059 if (!is_list(sc, car(x)))
5060 Error_1(sc, "Bad syntax of binding in let :", car(x));
5061 sc->args = cons(sc, caar(x), sc->args);
5062 }
5063 x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir);
5064 new_slot_in_env(sc, car(sc->code), x);
5065 sc->code = cddr(sc->code);
5066 sc->args = sc->NIL;
5067 } else {
5068 sc->code = cdr(sc->code);
5069 sc->args = sc->NIL;
5070 }
5071 s_goto(sc,OP_BEGIN);
5072
5073 case OP_LET0AST: /* let* */
5074 if (car(sc->code) == sc->NIL) {
5075 new_frame_in_env(sc, sc->envir);
5076 sc->code = cdr(sc->code);
5077 s_goto(sc,OP_BEGIN);
5078 }
5079 if(!is_pair(car(sc->code)) || !is_pair(caar(sc->code)) || !is_pair(cdaar(sc->code))) {
5080 Error_1(sc,"Bad syntax of binding spec in let* :",car(sc->code));
5081 }
5082 s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
5083 sc->code = cadaar(sc->code);
5084 s_goto(sc,OP_EVAL);
5085
5086 case OP_LET1AST: /* let* (make new frame) */
5087 new_frame_in_env(sc, sc->envir);
5088 s_goto(sc,OP_LET2AST);
5089
5090 case OP_LET2AST: /* let* (calculate parameters) */
5091 new_slot_in_env(sc, caar(sc->code), sc->value);
5092 sc->code = cdr(sc->code);
5093 if (is_pair(sc->code)) { /* continue */
5094 s_save(sc,OP_LET2AST, sc->args, sc->code);
5095 sc->code = cadar(sc->code);
5096 sc->args = sc->NIL;
5097 s_goto(sc,OP_EVAL);
5098 } else { /* end */
5099 sc->code = sc->args;
5100 sc->args = sc->NIL;
5101 s_goto(sc,OP_BEGIN);
5102 }
5103 default:
5104 snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
5105 Error_0(sc,sc->strbuff);
5106 }
5107 return sc->T;
5108 }
5109
5110 static pointer opexe_1(scheme *sc, enum scheme_opcodes op) {
5111 pointer x, y;
5112
5113 switch (op) {
5114 case OP_LET0REC: /* letrec */
5115 new_frame_in_env(sc, sc->envir);
5116 sc->args = sc->NIL;
5117 sc->value = sc->code;
5118 sc->code = car(sc->code);
5119 s_goto(sc,OP_LET1REC);
5120
5121 case OP_LET1REC: /* letrec (calculate parameters) */
5122 sc->args = cons(sc, sc->value, sc->args);
5123 if (is_pair(sc->code)) { /* continue */
5124 if (!is_pair(car(sc->code)) || !is_pair(cdar(sc->code))) {
5125 Error_1(sc, "Bad syntax of binding spec in letrec :",
5126 car(sc->code));
5127 }
5128 s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
5129 sc->code = cadar(sc->code);
5130 sc->args = sc->NIL;
5131 s_goto(sc,OP_EVAL);
5132 } else { /* end */
5133 sc->args = reverse_in_place(sc, sc->NIL, sc->args);
5134 sc->code = car(sc->args);
5135 sc->args = cdr(sc->args);
5136 s_goto(sc,OP_LET2REC);
5137 }
5138
5139 case OP_LET2REC: /* letrec */
5140 for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
5141 new_slot_in_env(sc, caar(x), car(y));
5142 }
5143 sc->code = cdr(sc->code);
5144 sc->args = sc->NIL;
5145 s_goto(sc,OP_BEGIN);
5146
5147 case OP_COND0: /* cond */
5148 if (!is_pair(sc->code)) {
5149 Error_0(sc,"syntax error in cond");
5150 }
5151 s_save(sc,OP_COND1, sc->NIL, sc->code);
5152 sc->code = caar(sc->code);
5153 s_goto(sc,OP_EVAL);
5154
5155 case OP_COND1: /* cond */
5156 if (is_true(sc->value)) {
5157 if ((sc->code = cdar(sc->code)) == sc->NIL) {
5158 s_return(sc,sc->value);
5159 }
5160 if(car(sc->code)==sc->FEED_TO) {
5161 if(!is_pair(cdr(sc->code))) {
5162 Error_0(sc,"syntax error in cond");
5163 }
5164 x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
5165 sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
5166 s_goto(sc,OP_EVAL);
5167 }
5168 s_goto(sc,OP_BEGIN);
5169 } else {
5170 if ((sc->code = cdr(sc->code)) == sc->NIL) {
5171 s_return(sc,sc->NIL);
5172 } else {
5173 s_save(sc,OP_COND1, sc->NIL, sc->code);
5174 sc->code = caar(sc->code);
5175 s_goto(sc,OP_EVAL);
5176 }
5177 }
5178
5179 case OP_DELAY: /* delay */
5180 x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
5181 typeflag(x)=T_PROMISE;
5182 s_return(sc,x);
5183
5184 case OP_AND0: /* and */
5185 if (sc->code == sc->NIL) {
5186 s_return(sc,sc->T);
5187 }
5188 s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
5189 sc->code = car(sc->code);
5190 s_goto(sc,OP_EVAL);
5191
5192 case OP_AND1: /* and */
5193 if (is_false(sc->value)) {
5194 s_return(sc,sc->value);
5195 } else if (sc->code == sc->NIL) {
5196 s_return(sc,sc->value);
5197 } else {
5198 s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
5199 sc->code = car(sc->code);
5200 s_goto(sc,OP_EVAL);
5201 }
5202
5203 case OP_OR0: /* or */
5204 if (sc->code == sc->NIL) {
5205 s_return(sc,sc->F);
5206 }
5207 s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
5208 sc->code = car(sc->code);
5209 s_goto(sc,OP_EVAL);
5210
5211 case OP_OR1: /* or */
5212 if (is_true(sc->value)) {
5213 s_return(sc,sc->value);
5214 } else if (sc->code == sc->NIL) {
5215 s_return(sc,sc->value);
5216 } else {
5217 s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
5218 sc->code = car(sc->code);
5219 s_goto(sc,OP_EVAL);
5220 }
5221
5222 case OP_C0STREAM: /* cons-stream */
5223 s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
5224 sc->code = car(sc->code);
5225 s_goto(sc,OP_EVAL);
5226
5227 case OP_C1STREAM: /* cons-stream */
5228 sc->args = sc->value; /* save sc->value to register sc->args for gc */
5229 x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
5230 typeflag(x)=T_PROMISE;
5231 s_return(sc,cons(sc, sc->args, x));
5232
5233 case OP_MACRO0: /* macro */
5234 if (is_pair(car(sc->code))) {
5235 x = caar(sc->code);
5236 sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
5237 } else {
5238 x = car(sc->code);
5239 sc->code = cadr(sc->code);
5240 }
5241 if (!is_symbol(x)) {
5242 Error_0(sc,"variable is not a symbol");
5243 }
5244 s_save(sc,OP_MACRO1, sc->NIL, x);
5245 s_goto(sc,OP_EVAL);
5246
5247 case OP_MACRO1: /* macro */
5248 typeflag(sc->value) = T_MACRO;
5249 x = find_slot_in_env(sc, sc->envir, sc->code, 0);
5250 if (x != sc->NIL) {
5251 set_slot_in_env(sc, x, sc->value);
5252 } else {
5253 new_slot_in_env(sc, sc->code, sc->value);
5254 }
5255 s_return(sc,sc->code);
5256
5257 case OP_CASE0: /* case */
5258 s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
5259 sc->code = car(sc->code);
5260 s_goto(sc,OP_EVAL);
5261
5262 case OP_CASE1: /* case */
5263 for (x = sc->code; x != sc->NIL; x = cdr(x)) {
5264 if (!is_pair(y = caar(x))) {
5265 break;
5266 }
5267 for ( ; y != sc->NIL; y = cdr(y)) {
5268 if (eqv(car(y), sc->value)) {
5269 break;
5270 }
5271 }
5272 if (y != sc->NIL) {
5273 break;
5274 }
5275 }
5276 if (x != sc->NIL) {
5277 if (is_pair(caar(x))) {
5278 sc->code = cdar(x);
5279 s_goto(sc,OP_BEGIN);
5280 } else {/* else */
5281 s_save(sc,OP_CASE2, sc->NIL, cdar(x));
5282 sc->code = caar(x);
5283 s_goto(sc,OP_EVAL);
5284 }
5285 } else {
5286 s_return(sc,sc->NIL);
5287 }
5288
5289 case OP_CASE2: /* case */
5290 if (is_true(sc->value)) {
5291 s_goto(sc,OP_BEGIN);
5292 } else {
5293 s_return(sc,sc->NIL);
5294 }
5295
5296 case OP_PAPPLY: /* apply */
5297 sc->code = car(sc->args);
5298 sc->args = list_star(sc,cdr(sc->args));
5299 /*sc->args = cadr(sc->args);*/
5300 s_goto(sc,OP_APPLY);
5301
5302 case OP_PEVAL: /* eval */
5303 if(cdr(sc->args)!=sc->NIL) {
5304 sc->envir=cadr(sc->args);
5305 }
5306 sc->code = car(sc->args);
5307 s_goto(sc,OP_EVAL);
5308
5309 case OP_CONTINUATION: /* call-with-current-continuation */
5310 sc->code = car(sc->args);
5311 sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
5312 s_goto(sc,OP_APPLY);
5313
5314 default:
5315 snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
5316 Error_0(sc,sc->strbuff);
5317 }
5318 return sc->T;
5319 }
5320
5321 static pointer opexe_2(scheme *sc, enum scheme_opcodes op) {
5322 pointer x;
5323 num v;
5324 #if USE_MATH
5325 double dd;
5326 #endif
5327
5328 switch (op) {
5329 #if USE_MATH
5330 case OP_INEX2EX: /* inexact->exact */
5331 x=car(sc->args);
5332 if(num_is_integer(x)) {
5333 s_return(sc,x);
5334 } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
5335 s_return(sc,mk_integer(sc,ivalue(x)));
5336 } else {
5337 Error_1(sc,"inexact->exact: not integral:",x);
5338 }
5339
5340 case OP_EXP:
5341 x=car(sc->args);
5342 s_return(sc, mk_real(sc, exp(rvalue(x))));
5343
5344 case OP_LOG:
5345 x=car(sc->args);
5346 s_return(sc, mk_real(sc, log(rvalue(x))));
5347
5348 case OP_SIN:
5349 x=car(sc->args);
5350 s_return(sc, mk_real(sc, sin(rvalue(x))));
5351
5352 case OP_COS:
5353 x=car(sc->args);
5354 s_return(sc, mk_real(sc, cos(rvalue(x))));
5355
5356 case OP_TAN:
5357 x=car(sc->args);
5358 s_return(sc, mk_real(sc, tan(rvalue(x))));
5359
5360 case OP_ASIN:
5361 x=car(sc->args);
5362 s_return(sc, mk_real(sc, asin(rvalue(x))));
5363
5364 case OP_ACOS:
5365 x=car(sc->args);
5366 s_return(sc, mk_real(sc, acos(rvalue(x))));
5367
5368 case OP_ATAN:
5369 x=car(sc->args);
5370 if(cdr(sc->args)==sc->NIL) {
5371 s_return(sc, mk_real(sc, atan(rvalue(x))));
5372 } else {
5373 pointer y=cadr(sc->args);
5374 s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
5375 }
5376
5377 case OP_SQRT:
5378 x=car(sc->args);
5379 s_return(sc, mk_real(sc, sqrt(rvalue(x))));
5380
5381 case OP_EXPT: {
5382 double result;
5383 int real_result=1;
5384 pointer y=cadr(sc->args);
5385 x=car(sc->args);
5386 if (num_is_integer(x) && num_is_integer(y))
5387 real_result=0;
5388 /* This 'if' is an R5RS compatibility fix. */
5389 /* NOTE: Remove this 'if' fix for R6RS. */
5390 if (rvalue(x) == 0 && rvalue(y) < 0) {
5391 result = 0.0;
5392 } else {
5393 result = pow(rvalue(x),rvalue(y));
5394 }
5395 /* Before returning integer result make sure we can. */
5396 /* If the test fails, result is too big for integer. */
5397 if (!real_result)
5398 {
5399 long result_as_long = (long)result;
5400 if (result != (double)result_as_long)
5401 real_result = 1;
5402 }
5403 if (real_result) {
5404 s_return(sc, mk_real(sc, result));
5405 } else {
5406 s_return(sc, mk_integer(sc, result));
5407 }
5408 }
5409
5410 case OP_FLOOR:
5411 x=car(sc->args);
5412 s_return(sc, mk_real(sc, floor(rvalue(x))));
5413
5414 case OP_CEILING:
5415 x=car(sc->args);
5416 s_return(sc, mk_real(sc, ceil(rvalue(x))));
5417
5418 case OP_TRUNCATE : {
5419 double rvalue_of_x ;
5420 x=car(sc->args);
5421 rvalue_of_x = rvalue(x) ;
5422 if (rvalue_of_x > 0) {
5423 s_return(sc, mk_real(sc, floor(rvalue_of_x)));
5424 } else {
5425 s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
5426 }
5427 }
5428
5429 case OP_ROUND:
5430 x=car(sc->args);
5431 if (num_is_integer(x))
5432 s_return(sc, x);
5433 s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
5434 #endif
5435
5436 case OP_ADD: /* + */
5437 v=num_zero;
5438 for (x = sc->args; x != sc->NIL; x = cdr(x)) {
5439 v=num_add(v,nvalue(car(x)));
5440 }
5441 s_return(sc,mk_number(sc, v));
5442
5443 case OP_MUL: /* * */
5444 v=num_one;
5445 for (x = sc->args; x != sc->NIL; x = cdr(x)) {
5446 v=num_mul(v,nvalue(car(x)));
5447 }
5448 s_return(sc,mk_number(sc, v));
5449
5450 case OP_SUB: /* - */
5451 if(cdr(sc->args)==sc->NIL) {
5452 x=sc->args;
5453 v=num_zero;
5454 } else {
5455 x = cdr(sc->args);
5456 v = nvalue(car(sc->args));
5457 }
5458 for (; x != sc->NIL; x = cdr(x)) {
5459 v=num_sub(v,nvalue(car(x)));
5460 }
5461 s_return(sc,mk_number(sc, v));
5462
5463 case OP_DIV: /* / */
5464 if(cdr(sc->args)==sc->NIL) {
5465 x=sc->args;
5466 v=num_one;
5467 } else {
5468 x = cdr(sc->args);
5469 v = nvalue(car(sc->args));
5470 }
5471 for (; x != sc->NIL; x = cdr(x)) {
5472 if (!is_zero_double(rvalue(car(x))))
5473 v=num_div(v,nvalue(car(x)));
5474 else {
5475 Error_0(sc,"/: division by zero");
5476 }
5477 }
5478 s_return(sc,mk_number(sc, v));
5479
5480 case OP_INTDIV: /* quotient */
5481 if(cdr(sc->args)==sc->NIL) {
5482 x=sc->args;
5483 v=num_one;
5484 } else {
5485 x = cdr(sc->args);
5486 v = nvalue(car(sc->args));
5487 }
5488 for (; x != sc->NIL; x = cdr(x)) {
5489 if (ivalue(car(x)) != 0)
5490 v=num_intdiv(v,nvalue(car(x)));
5491 else {
5492 Error_0(sc,"quotient: division by zero");
5493 }
5494 }
5495 s_return(sc,mk_number(sc, v));
5496
5497 case OP_REM: /* remainder */
5498 v = nvalue(car(sc->args));
5499 if (ivalue(cadr(sc->args)) != 0)
5500 v=num_rem(v,nvalue(cadr(sc->args)));
5501 else {
5502 Error_0(sc,"remainder: division by zero");
5503 }
5504 s_return(sc,mk_number(sc, v));
5505
5506 case OP_MOD: /* modulo */
5507 v = nvalue(car(sc->args));
5508 if (ivalue(cadr(sc->args)) != 0)
5509 v=num_mod(v,nvalue(cadr(sc->args)));
5510 else {
5511 Error_0(sc,"modulo: division by zero");
5512 }
5513 s_return(sc,mk_number(sc, v));
5514
5515 case OP_CAR: /* car */
5516 s_return(sc,caar(sc->args));
5517
5518 case OP_CDR: /* cdr */
5519 s_return(sc,cdar(sc->args));
5520
5521 case OP_CONS: /* cons */
5522 cdr(sc->args) = cadr(sc->args);
5523 s_return(sc,sc->args);
5524
5525 case OP_SETCAR: /* set-car! */
5526 if(!is_immutable(car(sc->args))) {
5527 caar(sc->args) = cadr(sc->args);
5528 s_return(sc,car(sc->args));
5529 } else {
5530 Error_0(sc,"set-car!: unable to alter immutable pair");
5531 }
5532
5533 case OP_SETCDR: /* set-cdr! */
5534 if(!is_immutable(car(sc->args))) {
5535 cdar(sc->args) = cadr(sc->args);
5536 s_return(sc,car(sc->args));
5537 } else {
5538 Error_0(sc,"set-cdr!: unable to alter immutable pair");
5539 }
5540
5541 case OP_CHAR2INT: { /* char->integer */
5542 char c;
5543 c=(char)ivalue(car(sc->args));
5544 s_return(sc,mk_integer(sc,(unsigned char)c));
5545 }
5546
5547 case OP_INT2CHAR: { /* integer->char */
5548 unsigned char c;
5549 c=(unsigned char)ivalue(car(sc->args));
5550 s_return(sc,mk_character(sc,(char)c));
5551 }
5552
5553 case OP_CHARUPCASE: {
5554 unsigned char c;
5555 c=(unsigned char)ivalue(car(sc->args));
5556 c=toupper(c);
5557 s_return(sc,mk_character(sc,(char)c));
5558 }
5559
5560 case OP_CHARDNCASE: {
5561 unsigned char c;
5562 c=(unsigned char)ivalue(car(sc->args));
5563 c=tolower(c);
5564 s_return(sc,mk_character(sc,(char)c));
5565 }
5566
5567 case OP_STR2SYM: /* string->symbol */
5568 s_return(sc,mk_symbol(sc,strvalue(car(sc->args))));
5569
5570 case OP_STR2ATOM: /* string->atom */ {
5571 char *s=strvalue(car(sc->args));
5572 long pf = 0;
5573 if(cdr(sc->args)!=sc->NIL) {
5574 /* we know cadr(sc->args) is a natural number */
5575 /* see if it is 2, 8, 10, or 16, or error */
5576 pf = ivalue_unchecked(cadr(sc->args));
5577 if(pf == 16 || pf == 10 || pf == 8 || pf == 2) {
5578 /* base is OK */
5579 }
5580 else {
5581 pf = -1;
5582 }
5583 }
5584 if (pf < 0) {
5585 Error_1(sc, "string->atom: bad base:", cadr(sc->args));
5586 } else if(*s=='#') /* no use of base! */ {
5587 s_return(sc, mk_sharp_const(sc, s+1));
5588 } else {
5589 if (pf == 0 || pf == 10) {
5590 s_return(sc, mk_atom(sc, s));
5591 }
5592 else {
5593 char *ep;
5594 long iv = strtol(s,&ep,(int )pf);
5595 if (*ep == 0) {
5596 s_return(sc, mk_integer(sc, iv));
5597 }
5598 else {
5599 s_return(sc, sc->F);
5600 }
5601 }
5602 }
5603 }
5604
5605 case OP_SYM2STR: /* symbol->string */
5606 x=mk_string(sc,symname(car(sc->args)));
5607 setimmutable(x);
5608 s_return(sc,x);
5609
5610 case OP_ATOM2STR: /* atom->string */ {
5611 long pf = 0;
5612 x=car(sc->args);
5613 if(cdr(sc->args)!=sc->NIL) {
5614 /* we know cadr(sc->args) is a natural number */
5615 /* see if it is 2, 8, 10, or 16, or error */
5616 pf = ivalue_unchecked(cadr(sc->args));
5617 if(is_number(x) && (pf == 16 || pf == 10 || pf == 8 || pf == 2)) {
5618 /* base is OK */
5619 }
5620 else {
5621 pf = -1;
5622 }
5623 }
5624 if (pf < 0) {
5625 Error_1(sc, "atom->string: bad base:", cadr(sc->args));
5626 } else if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
5627 char *p;
5628 int len;
5629 atom2str(sc,x,(int )pf,&p,&len);
5630 s_return(sc,mk_counted_string(sc,p,len));
5631 } else {
5632 Error_1(sc, "atom->string: not an atom:", x);
5633 }
5634 }
5635
5636 case OP_MKSTRING: { /* make-string */
5637 int fill=' ';
5638 int len;
5639
5640 len=ivalue(car(sc->args));
5641
5642 if(cdr(sc->args)!=sc->NIL) {
5643 fill=charvalue(cadr(sc->args));
5644 }
5645 s_return(sc,mk_empty_string(sc,len,(char)fill));
5646 }
5647
5648 case OP_STRLEN: /* string-length */
5649 s_return(sc,mk_integer(sc,strlength(car(sc->args))));
5650
5651 case OP_STRREF: { /* string-ref */
5652 char *str;
5653 int index;
5654
5655 str=strvalue(car(sc->args));
5656
5657 index=ivalue(cadr(sc->args));
5658
5659 if(index>=strlength(car(sc->args))) {
5660 Error_1(sc,"string-ref: out of bounds:",cadr(sc->args));
5661 }
5662
5663 s_return(sc,mk_character(sc,((unsigned char*)str)[index]));
5664 }
5665
5666 case OP_STRSET: { /* string-set! */
5667 char *str;
5668 int index;
5669 int c;
5670
5671 if(is_immutable(car(sc->args))) {
5672 Error_1(sc,"string-set!: unable to alter immutable string:",car(sc->args));
5673 }
5674 str=strvalue(car(sc->args));
5675
5676 index=ivalue(cadr(sc->args));
5677 if(index>=strlength(car(sc->args))) {
5678 Error_1(sc,"string-set!: out of bounds:",cadr(sc->args));
5679 }
5680
5681 c=charvalue(caddr(sc->args));
5682
5683 str[index]=(char)c;
5684 s_return(sc,car(sc->args));
5685 }
5686
5687 case OP_STRAPPEND: { /* string-append */
5688 /* in 1.29 string-append was in Scheme in init.scm but was too slow */
5689 int len = 0;
5690 pointer newstr;
5691 char *pos;
5692
5693 /* compute needed length for new string */
5694 for (x = sc->args; x != sc->NIL; x = cdr(x)) {
5695 len += strlength(car(x));
5696 }
5697 newstr = mk_empty_string(sc, len, ' ');
5698 /* store the contents of the argument strings into the new string */
5699 for (pos = strvalue(newstr), x = sc->args; x != sc->NIL;
5700 pos += strlength(car(x)), x = cdr(x)) {
5701 memcpy(pos, strvalue(car(x)), strlength(car(x)));
5702 }
5703 s_return(sc, newstr);
5704 }
5705
5706 case OP_SUBSTR: { /* substring */
5707 char *str;
5708 int index0;
5709 int index1;
5710 int len;
5711
5712 str=strvalue(car(sc->args));
5713
5714 index0=ivalue(cadr(sc->args));
5715
5716 if(index0>strlength(car(sc->args))) {
5717 Error_1(sc,"substring: start out of bounds:",cadr(sc->args));
5718 }
5719
5720 if(cddr(sc->args)!=sc->NIL) {
5721 index1=ivalue(caddr(sc->args));
5722 if(index1>strlength(car(sc->args)) || index1<index0) {
5723 Error_1(sc,"substring: end out of bounds:",caddr(sc->args));
5724 }
5725 } else {
5726 index1=strlength(car(sc->args));
5727 }
5728
5729 len=index1-index0;
5730 x=mk_empty_string(sc,len,' ');
5731 memcpy(strvalue(x),str+index0,len);
5732 strvalue(x)[len]=0;
5733
5734 s_return(sc,x);
5735 }
5736
5737 case OP_VECTOR: { /* vector */
5738 int i;
5739 pointer vec;
5740 int len=list_length(sc,sc->args);
5741 if(len<0) {
5742 Error_1(sc,"vector: not a proper list:",sc->args);
5743 }
5744 vec=mk_vector(sc,len);
5745 if(sc->no_memory) { s_return(sc, sc->sink); }
5746 for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
5747 set_vector_elem(vec,i,car(x));
5748 }
5749 s_return(sc,vec);
5750 }
5751
5752 case OP_MKVECTOR: { /* make-vector */
5753 pointer fill=sc->NIL;
5754 int len;
5755 pointer vec;
5756
5757 len=ivalue(car(sc->args));
5758
5759 if(cdr(sc->args)!=sc->NIL) {
5760 fill=cadr(sc->args);
5761 }
5762 vec=mk_vector(sc,len);
5763 if(sc->no_memory) { s_return(sc, sc->sink); }
5764 if(fill!=sc->NIL) {
5765 fill_vector(vec,fill);
5766 }
5767 s_return(sc,vec);
5768 }
5769
5770 case OP_VECLEN: /* vector-length */
5771 s_return(sc,mk_integer(sc,ivalue(car(sc->args))));
5772
5773 case OP_VECREF: { /* vector-ref */
5774 int index;
5775
5776 index=ivalue(cadr(sc->args));
5777
5778 if(index>=ivalue(car(sc->args))) {
5779 Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args));
5780 }
5781
5782 s_return(sc,vector_elem(car(sc->args),index));
5783 }
5784
5785 case OP_VECSET: { /* vector-set! */
5786 int index;
5787
5788 if(is_immutable(car(sc->args))) {
5789 Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args));
5790 }
5791
5792 index=ivalue(cadr(sc->args));
5793 if(index>=ivalue(car(sc->args))) {
5794 Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args));
5795 }
5796
5797 set_vector_elem(car(sc->args),index,caddr(sc->args));
5798 s_return(sc,car(sc->args));
5799 }
5800
5801 default:
5802 snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
5803 Error_0(sc,sc->strbuff);
5804 }
5805 return sc->T;
5806 }
5807
5808 static int is_list(scheme *sc, pointer a)
5809 { return list_length(sc,a) >= 0; }
5810
5811 /* Result is:
5812 proper list: length
5813 circular list: -1
5814 not even a pair: -2
5815 dotted list: -2 minus length before dot
5816 */
5817 int list_length(scheme *sc, pointer a) {
5818 int i=0;
5819 pointer slow, fast;
5820
5821 slow = fast = a;
5822 while (1)
5823 {
5824 if (fast == sc->NIL)
5825 return i;
5826 if (!is_pair(fast))
5827 return -2 - i;
5828 fast = cdr(fast);
5829 ++i;
5830 if (fast == sc->NIL)
5831 return i;
5832 if (!is_pair(fast))
5833 return -2 - i;
5834 ++i;
5835 fast = cdr(fast);
5836
5837 /* Safe because we would have already returned if `fast'
5838 encountered a non-pair. */
5839 slow = cdr(slow);
5840 if (fast == slow)
5841 {
5842 /* the fast pointer has looped back around and caught up
5843 with the slow pointer, hence the structure is circular,
5844 not of finite length, and therefore not a list */
5845 return -1;
5846 }
5847 }
5848 }
5849
5850 static pointer opexe_3(scheme *sc, enum scheme_opcodes op) {
5851 pointer x;
5852 num v;
5853 int (*comp_func)(num,num)=0;
5854
5855 switch (op) {
5856 case OP_NOT: /* not */
5857 s_retbool(is_false(car(sc->args)));
5858 case OP_BOOLP: /* boolean? */
5859 s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
5860 case OP_EOFOBJP: /* boolean? */
5861 s_retbool(car(sc->args) == sc->EOF_OBJ);
5862 case OP_NULLP: /* null? */
5863 s_retbool(car(sc->args) == sc->NIL);
5864 case OP_NUMEQ: /* = */
5865 case OP_LESS: /* < */
5866 case OP_GRE: /* > */
5867 case OP_LEQ: /* <= */
5868 case OP_GEQ: /* >= */
5869 switch(op) {
5870 case OP_NUMEQ: comp_func=num_eq; break;
5871 case OP_LESS: comp_func=num_lt; break;
5872 case OP_GRE: comp_func=num_gt; break;
5873 case OP_LEQ: comp_func=num_le; break;
5874 case OP_GEQ: comp_func=num_ge; break;
5875 }
5876 x=sc->args;
5877 v=nvalue(car(x));
5878 x=cdr(x);
5879
5880 for (; x != sc->NIL; x = cdr(x)) {
5881 if(!comp_func(v,nvalue(car(x)))) {
5882 s_retbool(0);
5883 }
5884 v=nvalue(car(x));
5885 }
5886 s_retbool(1);
5887 case OP_SYMBOLP: /* symbol? */
5888 s_retbool(is_symbol(car(sc->args)));
5889 case OP_NUMBERP: /* number? */
5890 s_retbool(is_number(car(sc->args)));
5891 case OP_STRINGP: /* string? */
5892 s_retbool(is_string(car(sc->args)));
5893 case OP_INTEGERP: /* integer? */
5894 s_retbool(is_integer(car(sc->args)));
5895 case OP_REALP: /* real? */
5896 s_retbool(is_number(car(sc->args))); /* All numbers are real */
5897 case OP_CHARP: /* char? */
5898 s_retbool(is_character(car(sc->args)));
5899 #if USE_CHAR_CLASSIFIERS
5900 case OP_CHARAP: /* char-alphabetic? */
5901 s_retbool(Cisalpha(ivalue(car(sc->args))));
5902 case OP_CHARNP: /* char-numeric? */
5903 s_retbool(Cisdigit(ivalue(car(sc->args))));
5904 case OP_CHARWP: /* char-whitespace? */
5905 s_retbool(Cisspace(ivalue(car(sc->args))));
5906 case OP_CHARUP: /* char-upper-case? */
5907 s_retbool(Cisupper(ivalue(car(sc->args))));
5908 case OP_CHARLP: /* char-lower-case? */
5909 s_retbool(Cislower(ivalue(car(sc->args))));
5910 #endif
5911 case OP_PORTP: /* port? */
5912 s_retbool(is_port(car(sc->args)));
5913 case OP_INPORTP: /* input-port? */
5914 s_retbool(is_inport(car(sc->args)));
5915 case OP_OUTPORTP: /* output-port? */
5916 s_retbool(is_outport(car(sc->args)));
5917 case OP_PROCP: /* procedure? */
5918 /*--
5919 * continuation should be procedure by the example
5920 * (call-with-current-continuation procedure?) ==> #t
5921 * in R^3 report sec. 6.9
5922 */
5923 s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
5924 || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
5925 case OP_PAIRP: /* pair? */
5926 s_retbool(is_pair(car(sc->args)));
5927 case OP_LISTP: /* list? */
5928 s_retbool(list_length(sc,car(sc->args)) >= 0);
5929
5930 case OP_ENVP: /* environment? */
5931 s_retbool(is_environment(car(sc->args)));
5932 case OP_VECTORP: /* vector? */
5933 s_retbool(is_vector(car(sc->args)));
5934 case OP_EQ: /* eq? */
5935 s_retbool(car(sc->args) == cadr(sc->args));
5936 case OP_EQV: /* eqv? */
5937 s_retbool(eqv(car(sc->args), cadr(sc->args)));
5938 default:
5939 snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
5940 Error_0(sc,sc->strbuff);
5941 }
5942 return sc->T;
5943 }
5944
5945 static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
5946 pointer x, y;
5947
5948 switch (op) {
5949 case OP_FORCE: /* force */
5950 sc->code = car(sc->args);
5951 if (is_promise(sc->code)) {
5952 /* Should change type to closure here */
5953 s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
5954 sc->args = sc->NIL;
5955 s_goto(sc,OP_APPLY);
5956 } else {
5957 s_return(sc,sc->code);
5958 }
5959
5960 case OP_SAVE_FORCED: /* Save forced value replacing promise */
5961 memcpy(sc->code,sc->value,sizeof(struct cell));
5962 s_return(sc,sc->value);
5963
5964 case OP_WRITE: /* write */
5965 case OP_DISPLAY: /* display */
5966 case OP_WRITE_CHAR: /* write-char */
5967 if(is_pair(cdr(sc->args))) {
5968 if(cadr(sc->args)!=sc->outport) {
5969 x=cons(sc,sc->outport,sc->NIL);
5970 s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
5971 sc->outport=cadr(sc->args);
5972 }
5973 }
5974 sc->args = car(sc->args);
5975 if(op==OP_WRITE) {
5976 sc->print_flag = 1;
5977 } else {
5978 sc->print_flag = 0;
5979 }
5980 s_goto(sc,OP_P0LIST);
5981
5982 case OP_NEWLINE: /* newline */
5983 if(is_pair(sc->args)) {
5984 if(car(sc->args)!=sc->outport) {
5985 x=cons(sc,sc->outport,sc->NIL);
5986 s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
5987 sc->outport=car(sc->args);
5988 }
5989 }
5990 putstr(sc, "\n");
5991 s_return(sc,sc->T);
5992
5993 case OP_ERR0: /* error */
5994 sc->retcode=-1;
5995 if (!is_string(car(sc->args))) {
5996 sc->args=cons(sc,mk_string(sc," -- "),sc->args);
5997 setimmutable(car(sc->args));
5998 }
5999 putstr(sc, "Error: ");
6000 putstr(sc, strvalue(car(sc->args)));
6001 sc->args = cdr(sc->args);
6002 s_goto(sc,OP_ERR1);
6003
6004 case OP_ERR1: /* error */
6005 putstr(sc, " ");
6006 if (sc->args != sc->NIL) {
6007 s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
6008 sc->args = car(sc->args);
6009 sc->print_flag = 1;
6010 s_goto(sc,OP_P0LIST);
6011 } else {
6012 putstr(sc, "\n");
6013 if(sc->interactive_repl) {
6014 s_goto(sc,OP_T0LVL);
6015 } else {
6016 return sc->NIL;
6017 }
6018 }
6019
6020 case OP_REVERSE: /* reverse */
6021 s_return(sc,reverse(sc, car(sc->args)));
6022
6023 case OP_LIST_STAR: /* list* */
6024 s_return(sc,list_star(sc,sc->args));
6025
6026 case OP_APPEND: /* append */
6027 x = sc->NIL;
6028 y = sc->args;
6029 if (y == x) {
6030 s_return(sc, x);
6031 }
6032
6033 /* cdr() in the while condition is not a typo. If car() */
6034 /* is used (append '() 'a) will return the wrong result.*/
6035 while (cdr(y) != sc->NIL) {
6036 x = revappend(sc, x, car(y));
6037 y = cdr(y);
6038 if (x == sc->F) {
6039 Error_0(sc, "non-list argument to append");
6040 }
6041 }
6042
6043 s_return(sc, reverse_in_place(sc, car(y), x));
6044
6045 #if USE_PLIST
6046 case OP_PUT: /* put */
6047 if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
6048 Error_0(sc,"illegal use of put");
6049 }
6050 for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
6051 if (caar(x) == y) {
6052 break;
6053 }
6054 }
6055 if (x != sc->NIL)
6056 cdar(x) = caddr(sc->args);
6057 else
6058 symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)),
6059 symprop(car(sc->args)));
6060 s_return(sc,sc->T);
6061
6062 case OP_GET: /* get */
6063 if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
6064 Error_0(sc,"illegal use of get");
6065 }
6066 for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
6067 if (caar(x) == y) {
6068 break;
6069 }
6070 }
6071 if (x != sc->NIL) {
6072 s_return(sc,cdar(x));
6073 } else {
6074 s_return(sc,sc->NIL);
6075 }
6076 #endif /* USE_PLIST */
6077 case OP_QUIT: /* quit */
6078 if(is_pair(sc->args)) {
6079 sc->retcode=ivalue(car(sc->args));
6080 }
6081 return (sc->NIL);
6082
6083 case OP_GC: /* gc */
6084 gc(sc, sc->NIL, sc->NIL);
6085 s_return(sc,sc->T);
6086
6087 case OP_GCVERB: /* gc-verbose */
6088 { int was = sc->gc_verbose;
6089
6090 sc->gc_verbose = (car(sc->args) != sc->F);
6091 s_retbool(was);
6092 }
6093
6094 case OP_NEWSEGMENT: /* new-segment */
6095 if (!is_pair(sc->args) || !is_number(car(sc->args))) {
6096 Error_0(sc,"new-segment: argument must be a number");
6097 }
6098 alloc_cellseg(sc, (int) ivalue(car(sc->args)));
6099 s_return(sc,sc->T);
6100
6101 case OP_OBLIST: /* oblist */
6102 s_return(sc, oblist_all_symbols(sc));
6103
6104 case OP_CURR_INPORT: /* current-input-port */
6105 s_return(sc,sc->inport);
6106
6107 case OP_CURR_OUTPORT: /* current-output-port */
6108 s_return(sc,sc->outport);
6109
6110 case OP_OPEN_INFILE: /* open-input-file */
6111 case OP_OPEN_OUTFILE: /* open-output-file */
6112 case OP_OPEN_INOUTFILE: /* open-input-output-file */ {
6113 int prop=0;
6114 pointer p;
6115 switch(op) {
6116 case OP_OPEN_INFILE: prop=port_input; break;
6117 case OP_OPEN_OUTFILE: prop=port_output; break;
6118 case OP_OPEN_INOUTFILE: prop=port_input|port_output; break;
6119 }
6120 p=port_from_filename(sc,strvalue(car(sc->args)),prop);
6121 if(p==sc->NIL) {
6122 s_return(sc,sc->F);
6123 }
6124 s_return(sc,p);
6125 }
6126
6127 #if USE_STRING_PORTS
6128 case OP_OPEN_INSTRING: /* open-input-string */
6129 case OP_OPEN_INOUTSTRING: /* open-input-output-string */ {
6130 int prop=0;
6131 pointer p;
6132 switch(op) {
6133 case OP_OPEN_INSTRING: prop=port_input; break;
6134 case OP_OPEN_INOUTSTRING: prop=port_input|port_output; break;
6135 }
6136 p=port_from_string(sc, strvalue(car(sc->args)),
6137 strvalue(car(sc->args))+strlength(car(sc->args)), prop);
6138 if(p==sc->NIL) {
6139 s_return(sc,sc->F);
6140 }
6141 s_return(sc,p);
6142 }
6143 case OP_OPEN_OUTSTRING: /* open-output-string */ {
6144 pointer p;
6145 if(car(sc->args)==sc->NIL) {
6146 p=port_from_scratch(sc);
6147 if(p==sc->NIL) {
6148 s_return(sc,sc->F);
6149 }
6150 } else {
6151 p=port_from_string(sc, strvalue(car(sc->args)),
6152 strvalue(car(sc->args))+strlength(car(sc->args)),
6153 port_output);
6154 if(p==sc->NIL) {
6155 s_return(sc,sc->F);
6156 }
6157 }
6158 s_return(sc,p);
6159 }
6160 case OP_GET_OUTSTRING: /* get-output-string */ {
6161 port *p;
6162
6163 if ((p=car(sc->args)->_object._port)->kind&port_string) {
6164 off_t size;
6165 char *str;
6166
6167 size=p->rep.string.curr-p->rep.string.start+1;
6168 str=sc->malloc(size);
6169 if(str != NULL) {
6170 pointer s;
6171
6172 memcpy(str,p->rep.string.start,size-1);
6173 str[size-1]='\0';
6174 s=mk_string(sc,str);
6175 sc->free(str);
6176 s_return(sc,s);
6177 }
6178 }
6179 s_return(sc,sc->F);
6180 }
6181 #endif
6182
6183 case OP_CLOSE_INPORT: /* close-input-port */
6184 port_close(sc,car(sc->args),port_input);
6185 s_return(sc,sc->T);
6186
6187 case OP_CLOSE_OUTPORT: /* close-output-port */
6188 port_close(sc,car(sc->args),port_output);
6189 s_return(sc,sc->T);
6190
6191 case OP_INT_ENV: /* interaction-environment */
6192 s_return(sc,sc->global_env);
6193
6194 case OP_CURR_ENV: /* current-environment */
6195 s_return(sc,sc->envir);
6196
6197 }
6198 return sc->T;
6199 }
6200
6201 static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
6202 pointer x;
6203
6204 if(sc->nesting!=0) {
6205 int n=sc->nesting;
6206 sc->nesting=0;
6207 sc->retcode=-1;
6208 Error_1(sc,"unmatched parentheses:",mk_integer(sc,n));
6209 }
6210
6211 switch (op) {
6212 /* ========== reading part ========== */
6213 case OP_READ:
6214 if(!is_pair(sc->args)) {
6215 s_goto(sc,OP_READ_INTERNAL);
6216 }
6217 if(!is_inport(car(sc->args))) {
6218 Error_1(sc,"read: not an input port:",car(sc->args));
6219 }
6220 if(car(sc->args)==sc->inport) {
6221 s_goto(sc,OP_READ_INTERNAL);
6222 }
6223 x=sc->inport;
6224 sc->inport=car(sc->args);
6225 x=cons(sc,x,sc->NIL);
6226 s_save(sc,OP_SET_INPORT, x, sc->NIL);
6227 s_goto(sc,OP_READ_INTERNAL);
6228
6229 case OP_READ_CHAR: /* read-char */
6230 case OP_PEEK_CHAR: /* peek-char */ {
6231 int c;
6232 if(is_pair(sc->args)) {
6233 if(car(sc->args)!=sc->inport) {
6234 x=sc->inport;
6235 x=cons(sc,x,sc->NIL);
6236 s_save(sc,OP_SET_INPORT, x, sc->NIL);
6237 sc->inport=car(sc->args);
6238 }
6239 }
6240 c=inchar(sc);
6241 if(c==EOF) {
6242 s_return(sc,sc->EOF_OBJ);
6243 }
6244 if(sc->op==OP_PEEK_CHAR) {
6245 backchar(sc,c);
6246 }
6247 s_return(sc,mk_character(sc,c));
6248 }
6249
6250 case OP_CHAR_READY: /* char-ready? */ {
6251 pointer p=sc->inport;
6252 int res;
6253 if(is_pair(sc->args)) {
6254 p=car(sc->args);
6255 }
6256 res=p->_object._port->kind&port_string;
6257 s_retbool(res);
6258 }
6259
6260 case OP_SET_INPORT: /* set-input-port */
6261 sc->inport=car(sc->args);
6262 s_return(sc,sc->value);
6263
6264 case OP_SET_OUTPORT: /* set-output-port */
6265 sc->outport=car(sc->args);
6266 s_return(sc,sc->value);
6267
6268 case OP_RDSEXPR:
6269 switch (sc->tok) {
6270 case TOK_EOF:
6271 s_return(sc,sc->EOF_OBJ);
6272 /* NOTREACHED */
6273 /*
6274 * Commented out because we now skip comments in the scanner
6275 *
6276 case TOK_COMMENT: {
6277 int c;
6278 while ((c=inchar(sc)) != '\n' && c!=EOF)
6279 ;
6280 sc->tok = token(sc);
6281 s_goto(sc,OP_RDSEXPR);
6282 }
6283 */
6284 case TOK_VEC:
6285 s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
6286 /* fall through */
6287 case TOK_LPAREN:
6288 sc->tok = token(sc);
6289 if (sc->tok == TOK_RPAREN) {
6290 s_return(sc,sc->NIL);
6291 } else if (sc->tok == TOK_DOT) {
6292 Error_0(sc,"syntax error: illegal dot expression");
6293 } else {
6294 sc->nesting_stack[sc->file_i]++;
6295 s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
6296 s_goto(sc,OP_RDSEXPR);
6297 }
6298 case TOK_QUOTE:
6299 s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
6300 sc->tok = token(sc);
6301 s_goto(sc,OP_RDSEXPR);
6302 case TOK_BQUOTE:
6303 sc->tok = token(sc);
6304 if(sc->tok==TOK_VEC) {
6305 s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
6306 sc->tok=TOK_LPAREN;
6307 s_goto(sc,OP_RDSEXPR);
6308 } else {
6309 s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
6310 }
6311 s_goto(sc,OP_RDSEXPR);
6312 case TOK_COMMA:
6313 s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
6314 sc->tok = token(sc);
6315 s_goto(sc,OP_RDSEXPR);
6316 case TOK_ATMARK:
6317 s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
6318 sc->tok = token(sc);
6319 s_goto(sc,OP_RDSEXPR);
6320 case TOK_ATOM:
6321 s_return(sc,mk_atom(sc, readstr_upto(sc, DELIMITERS)));
6322 case TOK_DQUOTE:
6323 x=readstrexp(sc);
6324 if(x==sc->F) {
6325 Error_0(sc,"Error reading string");
6326 }
6327 setimmutable(x);
6328 s_return(sc,x);
6329 case TOK_SHARP: {
6330 pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
6331 if(f==sc->NIL) {
6332 Error_0(sc,"undefined sharp expression");
6333 } else {
6334 sc->code=cons(sc,slot_value_in_env(f),sc->NIL);
6335 s_goto(sc,OP_EVAL);
6336 }
6337 }
6338 case TOK_SHARP_CONST:
6339 if ((x = mk_sharp_const(sc, readstr_upto(sc, DELIMITERS))) == sc->NIL) {
6340 Error_0(sc,"undefined sharp expression");
6341 } else {
6342 s_return(sc,x);
6343 }
6344 default:
6345 Error_0(sc,"syntax error: illegal token");
6346 }
6347 break;
6348
6349 case OP_RDLIST: {
6350 sc->args = cons(sc, sc->value, sc->args);
6351 sc->tok = token(sc);
6352 /* We now skip comments in the scanner
6353 while (sc->tok == TOK_COMMENT) {
6354 int c;
6355 while ((c=inchar(sc)) != '\n' && c!=EOF)
6356 ;
6357 sc->tok = token(sc);
6358 }
6359 */
6360 if (sc->tok == TOK_EOF)
6361 { s_return(sc,sc->EOF_OBJ); }
6362 else if (sc->tok == TOK_RPAREN) {
6363 int c = inchar(sc);
6364 if (c != '\n')
6365 backchar(sc,c);
6366 #if SHOW_ERROR_LINE
6367 else if (sc->load_stack[sc->file_i].kind & port_file)
6368 sc->load_stack[sc->file_i].rep.stdio.curr_line++;
6369 #endif
6370 sc->nesting_stack[sc->file_i]--;
6371 s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
6372 } else if (sc->tok == TOK_DOT) {
6373 s_save(sc,OP_RDDOT, sc->args, sc->NIL);
6374 sc->tok = token(sc);
6375 s_goto(sc,OP_RDSEXPR);
6376 } else {
6377 s_save(sc,OP_RDLIST, sc->args, sc->NIL);;
6378 s_goto(sc,OP_RDSEXPR);
6379 }
6380 }
6381
6382 case OP_RDDOT:
6383 if (token(sc) != TOK_RPAREN) {
6384 Error_0(sc,"syntax error: illegal dot expression");
6385 } else {
6386 sc->nesting_stack[sc->file_i]--;
6387 s_return(sc,reverse_in_place(sc, sc->value, sc->args));
6388 }
6389
6390 case OP_RDQUOTE:
6391 s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)));
6392
6393 case OP_RDQQUOTE:
6394 s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL)));
6395
6396 case OP_RDQQUOTEVEC:
6397 s_return(sc,cons(sc, mk_symbol(sc,"apply"),
6398 cons(sc, mk_symbol(sc,"vector"),
6399 cons(sc,cons(sc, sc->QQUOTE,
6400 cons(sc,sc->value,sc->NIL)),
6401 sc->NIL))));
6402
6403 case OP_RDUNQUOTE:
6404 s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL)));
6405
6406 case OP_RDUQTSP:
6407 s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL)));
6408
6409 case OP_RDVEC:
6410 /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
6411 s_goto(sc,OP_EVAL); Cannot be quoted*/
6412 /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
6413 s_return(sc,x); Cannot be part of pairs*/
6414 /*sc->code=mk_proc(sc,OP_VECTOR);
6415 sc->args=sc->value;
6416 s_goto(sc,OP_APPLY);*/
6417 sc->args=sc->value;
6418 s_goto(sc,OP_VECTOR);
6419
6420 /* ========== printing part ========== */
6421 case OP_P0LIST:
6422 if(is_vector(sc->args)) {
6423 putstr(sc,"#(");
6424 sc->args=cons(sc,sc->args,mk_integer(sc,0));
6425 s_goto(sc,OP_PVECFROM);
6426 } else if(is_environment(sc->args)) {
6427 putstr(sc,"#<ENVIRONMENT>");
6428 s_return(sc,sc->T);
6429 } else if (!is_pair(sc->args)) {
6430 printatom(sc, sc->args, sc->print_flag);
6431 s_return(sc,sc->T);
6432 } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
6433 putstr(sc, "'");
6434 sc->args = cadr(sc->args);
6435 s_goto(sc,OP_P0LIST);
6436 } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
6437 putstr(sc, "`");
6438 sc->args = cadr(sc->args);
6439 s_goto(sc,OP_P0LIST);
6440 } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
6441 putstr(sc, ",");
6442 sc->args = cadr(sc->args);
6443 s_goto(sc,OP_P0LIST);
6444 } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
6445 putstr(sc, ",@");
6446 sc->args = cadr(sc->args);
6447 s_goto(sc,OP_P0LIST);
6448 } else {
6449 putstr(sc, "(");
6450 s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
6451 sc->args = car(sc->args);
6452 s_goto(sc,OP_P0LIST);
6453 }
6454
6455 case OP_P1LIST:
6456 if (is_pair(sc->args)) {
6457 s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
6458 putstr(sc, " ");
6459 sc->args = car(sc->args);
6460 s_goto(sc,OP_P0LIST);
6461 } else if(is_vector(sc->args)) {
6462 s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
6463 putstr(sc, " . ");
6464 s_goto(sc,OP_P0LIST);
6465 } else {
6466 if (sc->args != sc->NIL) {
6467 putstr(sc, " . ");
6468 printatom(sc, sc->args, sc->print_flag);
6469 }
6470 putstr(sc, ")");
6471 s_return(sc,sc->T);
6472 }
6473 case OP_PVECFROM: {
6474 int i=ivalue_unchecked(cdr(sc->args));
6475 pointer vec=car(sc->args);
6476 int len=ivalue_unchecked(vec);
6477 if(i==len) {
6478 putstr(sc,")");
6479 s_return(sc,sc->T);
6480 } else {
6481 pointer elem=vector_elem(vec,i);
6482 ivalue_unchecked(cdr(sc->args))=i+1;
6483 s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
6484 sc->args=elem;
6485 if (i > 0)
6486 putstr(sc," ");
6487 s_goto(sc,OP_P0LIST);
6488 }
6489 }
6490
6491 default:
6492 snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
6493 Error_0(sc,sc->strbuff);
6494
6495 }
6496 return sc->T;
6497 }
6498
6499 static pointer opexe_6(scheme *sc, enum scheme_opcodes op) {
6500 pointer x, y;
6501 long v;
6502
6503 switch (op) {
6504 case OP_LIST_LENGTH: /* length */ /* a.k */
6505 v=list_length(sc,car(sc->args));
6506 if(v<0) {
6507 Error_1(sc,"length: not a list:",car(sc->args));
6508 }
6509 s_return(sc,mk_integer(sc, v));
6510
6511 case OP_ASSQ: /* assq */ /* a.k */
6512 x = car(sc->args);
6513 for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
6514 if (!is_pair(car(y))) {
6515 Error_0(sc,"unable to handle non pair element");
6516 }
6517 if (x == caar(y))
6518 break;
6519 }
6520 if (is_pair(y)) {
6521 s_return(sc,car(y));
6522 } else {
6523 s_return(sc,sc->F);
6524 }
6525
6526
6527 case OP_GET_CLOSURE: /* get-closure-code */ /* a.k */
6528 sc->args = car(sc->args);
6529 if (sc->args == sc->NIL) {
6530 s_return(sc,sc->F);
6531 } else if (is_closure(sc->args)) {
6532 s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
6533 } else if (is_macro(sc->args)) {
6534 s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
6535 } else {
6536 s_return(sc,sc->F);
6537 }
6538 case OP_CLOSUREP: /* closure? */
6539 /*
6540 * Note, macro object is also a closure.
6541 * Therefore, (closure? <#MACRO>) ==> #t
6542 */
6543 s_retbool(is_closure(car(sc->args)));
6544 case OP_MACROP: /* macro? */
6545 s_retbool(is_macro(car(sc->args)));
6546 default:
6547 snprintf(sc->strbuff,STRBUFFSIZE,"%d: illegal operator", sc->op);
6548 Error_0(sc,sc->strbuff);
6549 }
6550 return sc->T; /* NOTREACHED */
6551 }
6552
6553 typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes);
6554
6555 typedef int (*test_predicate)(pointer);
6556 static int is_any(pointer p) { return 1;}
6557
6558 static int is_nonneg(pointer p) {
6559 return ivalue(p)>=0 && is_integer(p);
6560 }
6561
6562 /* Correspond carefully with following defines! */
6563 static struct {
6564 test_predicate fct;
6565 const char *kind;
6566 } tests[]={
6567 {0,0}, /* unused */
6568 {is_any, 0},
6569 {is_string, "string"},
6570 {is_symbol, "symbol"},
6571 {is_port, "port"},
6572 {is_inport,"input port"},
6573 {is_outport,"output port"},
6574 {is_environment, "environment"},
6575 {is_pair, "pair"},
6576 {0, "pair or '()"},
6577 {is_character, "character"},
6578 {is_vector, "vector"},
6579 {is_number, "number"},
6580 {is_integer, "integer"},
6581 {is_nonneg, "non-negative integer"}
6582 };
6583
6584 #define TST_NONE 0
6585 #define TST_ANY "\001"
6586 #define TST_STRING "\002"
6587 #define TST_SYMBOL "\003"
6588 #define TST_PORT "\004"
6589 #define TST_INPORT "\005"
6590 #define TST_OUTPORT "\006"
6591 #define TST_ENVIRONMENT "\007"
6592 #define TST_PAIR "\010"
6593 #define TST_LIST "\011"
6594 #define TST_CHAR "\012"
6595 #define TST_VECTOR "\013"
6596 #define TST_NUMBER "\014"
6597 #define TST_INTEGER "\015"
6598 #define TST_NATURAL "\016"
6599
6600 typedef struct {
6601 dispatch_func func;
6602 char *name;
6603 int min_arity;
6604 int max_arity;
6605 char *arg_tests_encoding;
6606 } op_code_info;
6607
6608 #define INF_ARG 0xffff
6609
6610 static op_code_info dispatch_table[]= {
6611 #define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E},
6612 #include "opdefines.h"
6613 { 0 }
6614 };
6615
6616 static const char *procname(pointer x) {
6617 int n=procnum(x);
6618 const char *name=dispatch_table[n].name;
6619 if(name==0) {
6620 name="ILLEGAL!";
6621 }
6622 return name;
6623 }
6624
6625 /* kernel of this interpreter */
6626 static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
6627 sc->op = op;
6628 for (;;) {
6629 op_code_info *pcd=dispatch_table+sc->op;
6630 if (pcd->name!=0) { /* if built-in function, check arguments */
6631 char msg[STRBUFFSIZE];
6632 int ok=1;
6633 int n=list_length(sc,sc->args);
6634
6635 /* Check number of arguments */
6636 if(n<pcd->min_arity) {
6637 ok=0;
6638 snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
6639 pcd->name,
6640 pcd->min_arity==pcd->max_arity?"":" at least",
6641 pcd->min_arity);
6642 }
6643 if(ok && n>pcd->max_arity) {
6644 ok=0;
6645 snprintf(msg, STRBUFFSIZE, "%s: needs%s %d argument(s)",
6646 pcd->name,
6647 pcd->min_arity==pcd->max_arity?"":" at most",
6648 pcd->max_arity);
6649 }
6650 if(ok) {
6651 if(pcd->arg_tests_encoding!=0) {
6652 int i=0;
6653 int j;
6654 const char *t=pcd->arg_tests_encoding;
6655 pointer arglist=sc->args;
6656 do {
6657 pointer arg=car(arglist);
6658 j=(int)t[0];
6659 if(j==TST_LIST[0]) {
6660 if(arg!=sc->NIL && !is_pair(arg)) break;
6661 } else {
6662 if(!tests[j].fct(arg)) break;
6663 }
6664
6665 if(t[1]!=0) {/* last test is replicated as necessary */
6666 t++;
6667 }
6668 arglist=cdr(arglist);
6669 i++;
6670 } while(i<n);
6671 if(i<n) {
6672 ok=0;
6673 snprintf(msg, STRBUFFSIZE, "%s: argument %d must be: %s",
6674 pcd->name,
6675 i+1,
6676 tests[j].kind);
6677 }
6678 }
6679 }
6680 if(!ok) {
6681 if(_Error_1(sc,msg,0)==sc->NIL) {
6682 return;
6683 }
6684 pcd=dispatch_table+sc->op;
6685 }
6686 }
6687 ok_to_freely_gc(sc);
6688 if (pcd->func(sc, (enum scheme_opcodes)sc->op) == sc->NIL) {
6689 return;
6690 }
6691 if(sc->no_memory) {
6692 fprintf(stderr,"No memory!\n");
6693 return;
6694 }
6695 }
6696 }
6697
6698 /* ========== Initialization of internal keywords ========== */
6699
6700 static void assign_syntax(scheme *sc, char *name) {
6701 pointer x;
6702
6703 x = oblist_add_by_name(sc, name);
6704 typeflag(x) |= T_SYNTAX;
6705 }
6706
6707 static void assign_proc(scheme *sc, enum scheme_opcodes op, char *name) {
6708 pointer x, y;
6709
6710 x = mk_symbol(sc, name);
6711 y = mk_proc(sc,op);
6712 new_slot_in_env(sc, x, y);
6713 }
6714
6715 static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
6716 pointer y;
6717
6718 y = get_cell(sc, sc->NIL, sc->NIL);
6719 typeflag(y) = (T_PROC | T_ATOM);
6720 ivalue_unchecked(y) = (long) op;
6721 set_num_integer(y);
6722 return y;
6723 }
6724
6725 /* Hard-coded for the given keywords. Remember to rewrite if more are added! */
6726 static int syntaxnum(pointer p) {
6727 const char *s=strvalue(car(p));
6728 switch(strlength(car(p))) {
6729 case 2:
6730 if(s[0]=='i') return OP_IF0; /* if */
6731 else return OP_OR0; /* or */
6732 case 3:
6733 if(s[0]=='a') return OP_AND0; /* and */
6734 else return OP_LET0; /* let */
6735 case 4:
6736 switch(s[3]) {
6737 case 'e': return OP_CASE0; /* case */
6738 case 'd': return OP_COND0; /* cond */
6739 case '*': return OP_LET0AST; /* let* */
6740 default: return OP_SET0; /* set! */
6741 }
6742 case 5:
6743 switch(s[2]) {
6744 case 'g': return OP_BEGIN; /* begin */
6745 case 'l': return OP_DELAY; /* delay */
6746 case 'c': return OP_MACRO0; /* macro */
6747 default: return OP_QUOTE; /* quote */
6748 }
6749 case 6:
6750 switch(s[2]) {
6751 case 'm': return OP_LAMBDA; /* lambda */
6752 case 'f': return OP_DEF0; /* define */
6753 default: return OP_LET0REC; /* letrec */
6754 }
6755 default:
6756 return OP_C0STREAM; /* cons-stream */
6757 }
6758 }
6759
6760 /* initialization of TinyScheme */
6761 #if USE_INTERFACE
6762 INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
6763 return cons(sc,a,b);
6764 }
6765 INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
6766 return immutable_cons(sc,a,b);
6767 }
6768
6769 static struct scheme_interface vtbl ={
6770 scheme_define,
6771 s_cons,
6772 s_immutable_cons,
6773 reserve_cells,
6774 mk_integer,
6775 mk_real,
6776 mk_symbol,
6777 gensym,
6778 mk_string,
6779 mk_counted_string,
6780 mk_character,
6781 mk_vector,
6782 mk_foreign_func,
6783 putstr,
6784 putcharacter,
6785
6786 is_string,
6787 string_value,
6788 is_number,
6789 nvalue,
6790 ivalue,
6791 rvalue,
6792 is_integer,
6793 is_real,
6794 is_character,
6795 charvalue,
6796 is_list,
6797 is_vector,
6798 list_length,
6799 ivalue,
6800 fill_vector,
6801 vector_elem,
6802 set_vector_elem,
6803 is_port,
6804 is_pair,
6805 pair_car,
6806 pair_cdr,
6807 set_car,
6808 set_cdr,
6809
6810 is_symbol,
6811 symname,
6812
6813 is_syntax,
6814 is_proc,
6815 is_foreign,
6816 syntaxname,
6817 is_closure,
6818 is_macro,
6819 closure_code,
6820 closure_env,
6821
6822 is_continuation,
6823 is_promise,
6824 is_environment,
6825 is_immutable,
6826 setimmutable,
6827
6828 scheme_load_file,
6829 scheme_load_string
6830 };
6831 #endif
6832
6833 scheme *scheme_init_new() {
6834 scheme *sc=(scheme*)malloc(sizeof(scheme));
6835 if(!scheme_init(sc)) {
6836 free(sc);
6837 return 0;
6838 } else {
6839 return sc;
6840 }
6841 }
6842
6843 scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
6844 scheme *sc=(scheme*)malloc(sizeof(scheme));
6845 if(!scheme_init_custom_alloc(sc,malloc,free)) {
6846 free(sc);
6847 return 0;
6848 } else {
6849 return sc;
6850 }
6851 }
6852
6853
6854 int scheme_init(scheme *sc) {
6855 return scheme_init_custom_alloc(sc,malloc,free);
6856 }
6857
6858 int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
6859 int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
6860 pointer x;
6861
6862 /* fix unitialized free under Mac OS X */
6863 memset( sc->load_stack, 0, sizeof(port) * MAXFIL );
6864
6865 num_zero.is_fixnum=1;
6866 num_zero.value.ivalue=0;
6867 num_one.is_fixnum=1;
6868 num_one.value.ivalue=1;
6869
6870 #if USE_INTERFACE
6871 sc->vptr=&vtbl;
6872 #endif
6873 sc->gensym_cnt=0;
6874 sc->malloc=malloc;
6875 sc->free=free;
6876 sc->last_cell_seg = -1;
6877 sc->sink = &sc->_sink;
6878 sc->NIL = &sc->_NIL;
6879 sc->T = &sc->_HASHT;
6880 sc->F = &sc->_HASHF;
6881 sc->EOF_OBJ=&sc->_EOF_OBJ;
6882 sc->free_cell = &sc->_NIL;
6883 sc->fcells = 0;
6884 sc->no_memory=0;
6885 sc->inport=sc->NIL;
6886 sc->outport=sc->NIL;
6887 sc->save_inport=sc->NIL;
6888 sc->loadport=sc->NIL;
6889 sc->nesting=0;
6890 sc->interactive_repl=0;
6891
6892 if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
6893 sc->no_memory=1;
6894 return 0;
6895 }
6896 sc->gc_verbose = 0;
6897 dump_stack_initialize(sc);
6898 sc->code = sc->NIL;
6899 sc->tracing=0;
6900
6901 /* init sc->NIL */
6902 typeflag(sc->NIL) = (T_ATOM | MARK);
6903 car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
6904 /* init T */
6905 typeflag(sc->T) = (T_ATOM | MARK);
6906 car(sc->T) = cdr(sc->T) = sc->T;
6907 /* init F */
6908 typeflag(sc->F) = (T_ATOM | MARK);
6909 car(sc->F) = cdr(sc->F) = sc->F;
6910 /* init sink */
6911 typeflag(sc->sink) = (T_PAIR | MARK);
6912 car(sc->sink) = sc->NIL;
6913 /* init c_nest */
6914 sc->c_nest = sc->NIL;
6915
6916 sc->oblist = oblist_initial_value(sc);
6917 /* init global_env */
6918 new_frame_in_env(sc, sc->NIL);
6919 sc->global_env = sc->envir;
6920 /* init else */
6921 x = mk_symbol(sc,"else");
6922 new_slot_in_env(sc, x, sc->T);
6923
6924 assign_syntax(sc, "lambda");
6925 assign_syntax(sc, "quote");
6926 assign_syntax(sc, "define");
6927 assign_syntax(sc, "if");
6928 assign_syntax(sc, "begin");
6929 assign_syntax(sc, "set!");
6930 assign_syntax(sc, "let");
6931 assign_syntax(sc, "let*");
6932 assign_syntax(sc, "letrec");
6933 assign_syntax(sc, "cond");
6934 assign_syntax(sc, "delay");
6935 assign_syntax(sc, "and");
6936 assign_syntax(sc, "or");
6937 assign_syntax(sc, "cons-stream");
6938 assign_syntax(sc, "macro");
6939 assign_syntax(sc, "case");
6940
6941 for(i=0; i<n; i++) {
6942 if(dispatch_table[i].name!=0) {
6943 assign_proc(sc, (enum scheme_opcodes)i, dispatch_table[i].name);
6944 }
6945 }
6946
6947 /* initialization of global pointers to special symbols */
6948 sc->LAMBDA = mk_symbol(sc, "lambda");
6949 sc->QUOTE = mk_symbol(sc, "quote");
6950 sc->QQUOTE = mk_symbol(sc, "quasiquote");
6951 sc->UNQUOTE = mk_symbol(sc, "unquote");
6952 sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
6953 sc->FEED_TO = mk_symbol(sc, "=>");
6954 sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
6955 sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
6956 sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
6957 sc->COMPILE_HOOK = mk_symbol(sc, "*compile-hook*");
6958
6959 return !sc->no_memory;
6960 }
6961
6962 void scheme_set_input_port_file(scheme *sc, FILE *fin) {
6963 sc->inport=port_from_file(sc,fin,port_input);
6964 }
6965
6966 void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
6967 sc->inport=port_from_string(sc,start,past_the_end,port_input);
6968 }
6969
6970 void scheme_set_output_port_file(scheme *sc, FILE *fout) {
6971 sc->outport=port_from_file(sc,fout,port_output);
6972 }
6973
6974 void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
6975 sc->outport=port_from_string(sc,start,past_the_end,port_output);
6976 }
6977
6978 void scheme_set_external_data(scheme *sc, void *p) {
6979 sc->ext_data=p;
6980 }
6981
6982 void scheme_deinit(scheme *sc) {
6983 int i;
6984
6985 #if SHOW_ERROR_LINE
6986 char *fname;
6987 #endif
6988
6989 sc->oblist=sc->NIL;
6990 sc->global_env=sc->NIL;
6991 dump_stack_free(sc);
6992 sc->envir=sc->NIL;
6993 sc->code=sc->NIL;
6994 sc->args=sc->NIL;
6995 sc->value=sc->NIL;
6996 if(is_port(sc->inport)) {
6997 typeflag(sc->inport) = T_ATOM;
6998 }
6999 sc->inport=sc->NIL;
7000 sc->outport=sc->NIL;
7001 if(is_port(sc->save_inport)) {
7002 typeflag(sc->save_inport) = T_ATOM;
7003 }
7004 sc->save_inport=sc->NIL;
7005 if(is_port(sc->loadport)) {
7006 typeflag(sc->loadport) = T_ATOM;
7007 }
7008 sc->loadport=sc->NIL;
7009 sc->gc_verbose=0;
7010 gc(sc,sc->NIL,sc->NIL);
7011
7012 for(i=0; i<=sc->last_cell_seg; i++) {
7013 sc->free(sc->alloc_seg[i]);
7014 }
7015
7016 #if SHOW_ERROR_LINE
7017 for(i=0; i<=sc->file_i; i++) {
7018 if (sc->load_stack[i].kind & port_file) {
7019 fname = sc->load_stack[i].rep.stdio.filename;
7020 if(fname)
7021 sc->free(fname);
7022 }
7023 }
7024 #endif
7025 }
7026
7027 void scheme_load_file(scheme *sc, FILE *fin)
7028 { scheme_load_named_file(sc,fin,0); }
7029
7030 void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename) {
7031 int interactive_repl = sc->interactive_repl && !filename;
7032 dump_stack_reset(sc);
7033 sc->envir = sc->global_env;
7034 sc->file_i=0;
7035 sc->load_stack[0].kind=port_input|port_file;
7036 sc->load_stack[0].rep.stdio.file=fin;
7037 sc->load_stack[0].rep.stdio.interactive=interactive_repl;
7038 sc->loadport=mk_port(sc,sc->load_stack);
7039 sc->retcode=0;
7040 if(interactive_repl) {
7041 sc->interactive_repl=interactive_repl;
7042 }
7043
7044 #if SHOW_ERROR_LINE
7045 sc->load_stack[0].rep.stdio.curr_line = 0;
7046 if(fin!=stdin && filename)
7047 sc->load_stack[0].rep.stdio.filename = store_string(sc, strlen(filename), filename, 0);
7048 #endif
7049
7050 sc->inport=sc->loadport;
7051 sc->args = mk_integer(sc,sc->file_i);
7052 Eval_Cycle(sc, OP_T0LVL);
7053 typeflag(sc->loadport)=T_ATOM;
7054 if(sc->retcode==0) {
7055 sc->retcode=sc->nesting!=0;
7056 }
7057 }
7058
7059 void scheme_load_string(scheme *sc, const char *cmd) {
7060 dump_stack_reset(sc);
7061 sc->envir = sc->global_env;
7062 sc->file_i=0;
7063 sc->load_stack[0].kind=port_input|port_string;
7064 sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */
7065 sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd);
7066 sc->load_stack[0].rep.string.curr=(char*)cmd;
7067 sc->loadport=mk_port(sc,sc->load_stack);
7068 sc->retcode=0;
7069 sc->interactive_repl=0;
7070 sc->inport=sc->loadport;
7071 sc->args = mk_integer(sc,sc->file_i);
7072 Eval_Cycle(sc, OP_T0LVL);
7073 typeflag(sc->loadport)=T_ATOM;
7074 if(sc->retcode==0) {
7075 sc->retcode=sc->nesting!=0;
7076 }
7077 }
7078
7079 void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
7080 pointer x;
7081
7082 x=find_slot_in_env(sc,envir,symbol,0);
7083 if (x != sc->NIL) {
7084 set_slot_in_env(sc, x, value);
7085 } else {
7086 new_slot_spec_in_env(sc, envir, symbol, value);
7087 }
7088 }
7089
7090 #if !STANDALONE
7091 void scheme_register_foreign_func(scheme * sc, scheme_registerable * sr)
7092 {
7093 scheme_define(sc,
7094 sc->global_env,
7095 mk_symbol(sc,sr->name),
7096 mk_foreign_func(sc, sr->f));
7097 }
7098
7099 void scheme_register_foreign_func_list(scheme * sc,
7100 scheme_registerable * list,
7101 int count)
7102 {
7103 int i;
7104 for(i = 0; i < count; i++)
7105 {
7106 scheme_register_foreign_func(sc, list + i);
7107 }
7108 }
7109
7110 pointer scheme_apply0(scheme *sc, const char *procname)
7111 { return scheme_eval(sc, cons(sc,mk_symbol(sc,procname),sc->NIL)); }
7112
7113 void save_from_C_call(scheme *sc)
7114 {
7115 pointer saved_data =
7116 cons(sc,
7117 car(sc->sink),
7118 cons(sc,
7119 sc->envir,
7120 sc->dump));
7121 /* Push */
7122 sc->c_nest = cons(sc, saved_data, sc->c_nest);
7123 /* Truncate the dump stack so TS will return here when done, not
7124 directly resume pre-C-call operations. */
7125 dump_stack_reset(sc);
7126 }
7127 void restore_from_C_call(scheme *sc)
7128 {
7129 car(sc->sink) = caar(sc->c_nest);
7130 sc->envir = cadar(sc->c_nest);
7131 sc->dump = cdr(cdar(sc->c_nest));
7132 /* Pop */
7133 sc->c_nest = cdr(sc->c_nest);
7134 }
7135
7136 /* "func" and "args" are assumed to be already eval'ed. */
7137 pointer scheme_call(scheme *sc, pointer func, pointer args)
7138 {
7139 int old_repl = sc->interactive_repl;
7140 sc->interactive_repl = 0;
7141 save_from_C_call(sc);
7142 sc->envir = sc->global_env;
7143 sc->args = args;
7144 sc->code = func;
7145 sc->retcode = 0;
7146 Eval_Cycle(sc, OP_APPLY);
7147 sc->interactive_repl = old_repl;
7148 restore_from_C_call(sc);
7149 return sc->value;
7150 }
7151
7152 pointer scheme_eval(scheme *sc, pointer obj)
7153 {
7154 int old_repl = sc->interactive_repl;
7155 sc->interactive_repl = 0;
7156 save_from_C_call(sc);
7157 sc->args = sc->NIL;
7158 sc->code = obj;
7159 sc->retcode = 0;
7160 Eval_Cycle(sc, OP_EVAL);
7161 sc->interactive_repl = old_repl;
7162 restore_from_C_call(sc);
7163 return sc->value;
7164 }
7165
7166
7167 #endif
7168
7169 /* ========== Main ========== */
7170
7171 #if STANDALONE
7172
7173 int main(int argc, char **argv) {
7174 scheme sc;
7175 FILE *fin;
7176 char *file_name=InitFile;
7177 int retcode;
7178 int isfile=1;
7179
7180 if(argc==1) {
7181 printf(banner);
7182 }
7183 if(argc==2 && strcmp(argv[1],"-?")==0) {
7184 printf("Usage: tinyscheme -?\n");
7185 printf("or: tinyscheme [<file1> <file2> ...]\n");
7186 printf("followed by\n");
7187 printf(" -1 <file> [<arg1> <arg2> ...]\n");
7188 printf(" -c <Scheme commands> [<arg1> <arg2> ...]\n");
7189 printf("assuming that the executable is named tinyscheme.\n");
7190 printf("Use - as filename for stdin.\n");
7191 return 1;
7192 }
7193 if(!scheme_init(&sc)) {
7194 fprintf(stderr,"Could not initialize!\n");
7195 return 2;
7196 }
7197 scheme_set_input_port_file(&sc, stdin);
7198 scheme_set_output_port_file(&sc, stdout);
7199 argv++;
7200 if(access(file_name,0)!=0) {
7201 char *p=getenv("TINYSCHEMEINIT");
7202 if(p!=0) {
7203 file_name=p;
7204 }
7205 }
7206 do {
7207 if(strcmp(file_name,"-")==0) {
7208 fin=stdin;
7209 } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
7210 pointer args=sc.NIL;
7211 isfile=file_name[1]=='1';
7212 file_name=*argv++;
7213 if(strcmp(file_name,"-")==0) {
7214 fin=stdin;
7215 } else if(isfile) {
7216 fin=fopen(file_name,"r");
7217 }
7218 for(;*argv;argv++) {
7219 pointer value=mk_string(&sc,*argv);
7220 args=cons(&sc,value,args);
7221 }
7222 args=reverse_in_place(&sc,sc.NIL,args);
7223 scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
7224
7225 } else {
7226 fin=fopen(file_name,"r");
7227 }
7228 if(isfile && fin==0) {
7229 fprintf(stderr,"Could not open file %s\n",file_name);
7230 } else {
7231 if(isfile) {
7232 scheme_load_named_file(&sc,fin,file_name);
7233 } else {
7234 scheme_load_string(&sc,file_name);
7235 }
7236 if(!isfile || fin!=stdin) {
7237 if(sc.retcode!=0) {
7238 fprintf(stderr,"Errors encountered reading %s\n",file_name);
7239 }
7240 if(isfile) {
7241 fclose(fin);
7242 }
7243 }
7244 }
7245 file_name=*argv++;
7246 } while(file_name!=0);
7247 if(argc==1) {
7248 scheme_load_named_file(&sc,stdin,0);
7249 }
7250 retcode=sc.retcode;
7251 scheme_deinit(&sc);
7252
7253 return retcode;
7254 }
7255
7256 #endif
-
+ FF0B30C650A38189BE4BB174A60143D1EA61061BC56838B49CBE63190CA0FCC15409E7CE7540B2A433EDE6BB1DFE97BAA901FDEA86D480224A36B69519E94171
bitcoin/src/shiva/scheme.h
(0 . 0)(1 . 253)
7261 /* SCHEME.H */
7262
7263 #ifndef _SCHEME_H
7264 #define _SCHEME_H
7265
7266 #include "scheme-knobs.h"
7267
7268 #define PACKAGE_VERSION "TRB"
7269
7270 #include <stdio.h>
7271
7272 #ifdef __cplusplus
7273 extern "C" {
7274 #endif
7275
7276 /*
7277 * Default values for #define'd symbols
7278 */
7279 #ifndef STANDALONE /* If used as standalone interpreter */
7280 # define STANDALONE 1
7281 #endif
7282
7283 #ifndef _MSC_VER
7284 # define USE_STRCASECMP 1
7285 # ifndef USE_STRLWR
7286 # define USE_STRLWR 1
7287 # endif
7288 # define SCHEME_EXPORT
7289 #else
7290 # define USE_STRCASECMP 0
7291 # define USE_STRLWR 0
7292 # ifdef _SCHEME_SOURCE
7293 # define SCHEME_EXPORT __declspec(dllexport)
7294 # else
7295 # define SCHEME_EXPORT __declspec(dllimport)
7296 # endif
7297 #endif
7298
7299 #if USE_NO_FEATURES
7300 # define USE_MATH 0
7301 # define USE_CHAR_CLASSIFIERS 0
7302 # define USE_ASCII_NAMES 0
7303 # define USE_STRING_PORTS 0
7304 # define USE_ERROR_HOOK 0
7305 # define USE_TRACING 0
7306 # define USE_COLON_HOOK 0
7307 # define USE_PLIST 0
7308 #endif
7309
7310 /*
7311 * Leave it defined if you want continuations, and also for the Sharp Zaurus.
7312 * Undefine it if you only care about faster speed and not strict Scheme compatibility.
7313 */
7314 #define USE_SCHEME_STACK
7315
7316 #ifndef USE_MATH /* If math support is needed */
7317 # define USE_MATH 1
7318 #endif
7319
7320 #ifndef USE_CHAR_CLASSIFIERS /* If char classifiers are needed */
7321 # define USE_CHAR_CLASSIFIERS 1
7322 #endif
7323
7324 #ifndef USE_ASCII_NAMES /* If extended escaped characters are needed */
7325 # define USE_ASCII_NAMES 1
7326 #endif
7327
7328 #ifndef USE_STRING_PORTS /* Enable string ports */
7329 # define USE_STRING_PORTS 1
7330 #endif
7331
7332 #ifndef USE_TRACING
7333 # define USE_TRACING 1
7334 #endif
7335
7336 #ifndef USE_PLIST
7337 # define USE_PLIST 0
7338 #endif
7339
7340 /* To force system errors through user-defined error handling (see *error-hook*) */
7341 #ifndef USE_ERROR_HOOK
7342 # define USE_ERROR_HOOK 1
7343 #endif
7344
7345 #ifndef USE_COLON_HOOK /* Enable qualified qualifier */
7346 # define USE_COLON_HOOK 1
7347 #endif
7348
7349 #ifndef USE_STRCASECMP /* stricmp for Unix */
7350 # define USE_STRCASECMP 0
7351 #endif
7352
7353 #ifndef USE_STRLWR
7354 # define USE_STRLWR 1
7355 #endif
7356
7357 #ifndef STDIO_ADDS_CR /* Define if DOS/Windows */
7358 # define STDIO_ADDS_CR 0
7359 #endif
7360
7361 #ifndef INLINE
7362 # define INLINE
7363 #endif
7364
7365 #ifndef USE_INTERFACE
7366 # define USE_INTERFACE 0
7367 #endif
7368
7369 #ifndef SHOW_ERROR_LINE /* Show error line in file */
7370 # define SHOW_ERROR_LINE 1
7371 #endif
7372
7373 typedef struct scheme scheme;
7374 typedef struct cell *pointer;
7375
7376 typedef void * (*func_alloc)(size_t);
7377 typedef void (*func_dealloc)(void *);
7378
7379 /* num, for generic arithmetic */
7380 typedef struct num {
7381 char is_fixnum;
7382 union {
7383 long ivalue;
7384 double rvalue;
7385 } value;
7386 } num;
7387
7388 SCHEME_EXPORT scheme *scheme_init_new();
7389 SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
7390 SCHEME_EXPORT int scheme_init(scheme *sc);
7391 SCHEME_EXPORT int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc);
7392 SCHEME_EXPORT void scheme_deinit(scheme *sc);
7393 void scheme_set_input_port_file(scheme *sc, FILE *fin);
7394 void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end);
7395 SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fin);
7396 void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end);
7397 SCHEME_EXPORT void scheme_load_file(scheme *sc, FILE *fin);
7398 SCHEME_EXPORT void scheme_load_named_file(scheme *sc, FILE *fin, const char *filename);
7399 SCHEME_EXPORT void scheme_load_string(scheme *sc, const char *cmd);
7400 SCHEME_EXPORT pointer scheme_apply0(scheme *sc, const char *procname);
7401 SCHEME_EXPORT pointer scheme_call(scheme *sc, pointer func, pointer args);
7402 SCHEME_EXPORT pointer scheme_eval(scheme *sc, pointer obj);
7403 void scheme_set_external_data(scheme *sc, void *p);
7404 SCHEME_EXPORT void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value);
7405
7406 typedef pointer (*foreign_func)(scheme *, pointer);
7407
7408 pointer _cons(scheme *sc, pointer a, pointer b, int immutable);
7409 pointer mk_integer(scheme *sc, long num);
7410 pointer mk_real(scheme *sc, double num);
7411 pointer mk_symbol(scheme *sc, const char *name);
7412 pointer gensym(scheme *sc);
7413 pointer mk_string(scheme *sc, const char *str);
7414 pointer mk_counted_string(scheme *sc, const char *str, int len);
7415 pointer mk_empty_string(scheme *sc, int len, char fill);
7416 pointer mk_character(scheme *sc, int c);
7417 pointer mk_foreign_func(scheme *sc, foreign_func f);
7418 void putstr(scheme *sc, const char *s);
7419 int list_length(scheme *sc, pointer a);
7420 int eqv(pointer a, pointer b);
7421
7422
7423 #if USE_INTERFACE
7424 struct scheme_interface {
7425 void (*scheme_define)(scheme *sc, pointer env, pointer symbol, pointer value);
7426 pointer (*cons)(scheme *sc, pointer a, pointer b);
7427 pointer (*immutable_cons)(scheme *sc, pointer a, pointer b);
7428 pointer (*reserve_cells)(scheme *sc, int n);
7429 pointer (*mk_integer)(scheme *sc, long num);
7430 pointer (*mk_real)(scheme *sc, double num);
7431 pointer (*mk_symbol)(scheme *sc, const char *name);
7432 pointer (*gensym)(scheme *sc);
7433 pointer (*mk_string)(scheme *sc, const char *str);
7434 pointer (*mk_counted_string)(scheme *sc, const char *str, int len);
7435 pointer (*mk_character)(scheme *sc, int c);
7436 pointer (*mk_vector)(scheme *sc, int len);
7437 pointer (*mk_foreign_func)(scheme *sc, foreign_func f);
7438 void (*putstr)(scheme *sc, const char *s);
7439 void (*putcharacter)(scheme *sc, int c);
7440
7441 int (*is_string)(pointer p);
7442 char *(*string_value)(pointer p);
7443 int (*is_number)(pointer p);
7444 num (*nvalue)(pointer p);
7445 long (*ivalue)(pointer p);
7446 double (*rvalue)(pointer p);
7447 int (*is_integer)(pointer p);
7448 int (*is_real)(pointer p);
7449 int (*is_character)(pointer p);
7450 long (*charvalue)(pointer p);
7451 int (*is_list)(scheme *sc, pointer p);
7452 int (*is_vector)(pointer p);
7453 int (*list_length)(scheme *sc, pointer vec);
7454 long (*vector_length)(pointer vec);
7455 void (*fill_vector)(pointer vec, pointer elem);
7456 pointer (*vector_elem)(pointer vec, int ielem);
7457 pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel);
7458 int (*is_port)(pointer p);
7459
7460 int (*is_pair)(pointer p);
7461 pointer (*pair_car)(pointer p);
7462 pointer (*pair_cdr)(pointer p);
7463 pointer (*set_car)(pointer p, pointer q);
7464 pointer (*set_cdr)(pointer p, pointer q);
7465
7466 int (*is_symbol)(pointer p);
7467 char *(*symname)(pointer p);
7468
7469 int (*is_syntax)(pointer p);
7470 int (*is_proc)(pointer p);
7471 int (*is_foreign)(pointer p);
7472 char *(*syntaxname)(pointer p);
7473 int (*is_closure)(pointer p);
7474 int (*is_macro)(pointer p);
7475 pointer (*closure_code)(pointer p);
7476 pointer (*closure_env)(pointer p);
7477
7478 int (*is_continuation)(pointer p);
7479 int (*is_promise)(pointer p);
7480 int (*is_environment)(pointer p);
7481 int (*is_immutable)(pointer p);
7482 void (*setimmutable)(pointer p);
7483 void (*load_file)(scheme *sc, FILE *fin);
7484 void (*load_string)(scheme *sc, const char *input);
7485 };
7486 #endif
7487
7488 #if !STANDALONE
7489 typedef struct scheme_registerable
7490 {
7491 foreign_func f;
7492 const char * name;
7493 }
7494 scheme_registerable;
7495
7496 void scheme_register_foreign_func_list(scheme * sc,
7497 scheme_registerable * list,
7498 int n);
7499
7500 #endif /* !STANDALONE */
7501
7502 #ifdef __cplusplus
7503 }
7504 #endif
7505
7506 #endif
7507
7508
7509 /*
7510 Local variables:
7511 c-file-style: "k&r"
7512 End:
7513 */
-
+ C9E5508D4522AEBF20480F5D58BFBBDF3118155CDCA7AAD2D2837D33AA5305CFA8A318DD2C8443FF5300C2BB8903466514D6051E070DA34B3F93B95EBAEADB06
bitcoin/src/shiva/scheme-knobs.h
(0 . 0)(1 . 9)
7518 #ifndef SCHEME_KNOBS_H
7519 #define SCHEME_KNOBS_H
7520
7521 #define STANDALONE 0
7522 #define USE_INTERFACE 1
7523 #define USE_MATH 1
7524 #define prompt "#>"
7525
7526 #endif
-
+ C74450E18AB91F7C226108E76075162D2DD9B111B10D42AF58FBFE5C2F18C71667E42CD865138DAA7339BACF158411642D62E742B208AA5133316B879081BB90
bitcoin/src/shiva/scheme-private.h
(0 . 0)(1 . 211)
7531 /* scheme-private.h */
7532
7533 #ifndef _SCHEME_PRIVATE_H
7534 #define _SCHEME_PRIVATE_H
7535
7536 #include "scheme.h"
7537 /*------------------ Ugly internals -----------------------------------*/
7538 /*------------------ Of interest only to FFI users --------------------*/
7539
7540 #ifdef __cplusplus
7541 extern "C" {
7542 #endif
7543
7544 enum scheme_port_kind {
7545 port_free=0,
7546 port_file=1,
7547 port_string=2,
7548 port_srfi6=4,
7549 port_input=16,
7550 port_output=32,
7551 port_saw_EOF=64
7552 };
7553
7554 typedef struct port {
7555 unsigned char kind;
7556 union {
7557 struct {
7558 FILE *file;
7559 int interactive;
7560 int closeit;
7561 #if SHOW_ERROR_LINE
7562 int curr_line;
7563 char *filename;
7564 #endif
7565 } stdio;
7566 struct {
7567 char *start;
7568 char *past_the_end;
7569 char *curr;
7570 } string;
7571 } rep;
7572 } port;
7573
7574 /* cell structure */
7575 struct cell {
7576 unsigned int _flag;
7577 union {
7578 struct {
7579 char *_svalue;
7580 int _length;
7581 } _string;
7582 num _number;
7583 port *_port;
7584 foreign_func _ff;
7585 struct {
7586 struct cell *_car;
7587 struct cell *_cdr;
7588 } _cons;
7589 } _object;
7590 };
7591
7592 struct scheme {
7593 /* arrays for segments */
7594 func_alloc malloc;
7595 func_dealloc free;
7596
7597 /* return code */
7598 int retcode;
7599 int tracing;
7600
7601
7602 #define CELL_SEGSIZE 5000 /* # of cells in one segment */
7603 #define CELL_NSEGMENT 10 /* # of segments for cells */
7604 char *alloc_seg[CELL_NSEGMENT];
7605 pointer cell_seg[CELL_NSEGMENT];
7606 int last_cell_seg;
7607
7608 /* We use 4 registers. */
7609 pointer args; /* register for arguments of function */
7610 pointer envir; /* stack register for current environment */
7611 pointer code; /* register for current code */
7612 pointer dump; /* stack register for next evaluation */
7613
7614 int interactive_repl; /* are we in an interactive REPL? */
7615
7616 struct cell _sink;
7617 pointer sink; /* when mem. alloc. fails */
7618 struct cell _NIL;
7619 pointer NIL; /* special cell representing empty cell */
7620 struct cell _HASHT;
7621 pointer T; /* special cell representing #t */
7622 struct cell _HASHF;
7623 pointer F; /* special cell representing #f */
7624 struct cell _EOF_OBJ;
7625 pointer EOF_OBJ; /* special cell representing end-of-file object */
7626 pointer oblist; /* pointer to symbol table */
7627 pointer global_env; /* pointer to global environment */
7628 pointer c_nest; /* stack for nested calls from C */
7629
7630 /* global pointers to special symbols */
7631 pointer LAMBDA; /* pointer to syntax lambda */
7632 pointer QUOTE; /* pointer to syntax quote */
7633
7634 pointer QQUOTE; /* pointer to symbol quasiquote */
7635 pointer UNQUOTE; /* pointer to symbol unquote */
7636 pointer UNQUOTESP; /* pointer to symbol unquote-splicing */
7637 pointer FEED_TO; /* => */
7638 pointer COLON_HOOK; /* *colon-hook* */
7639 pointer ERROR_HOOK; /* *error-hook* */
7640 pointer SHARP_HOOK; /* *sharp-hook* */
7641 pointer COMPILE_HOOK; /* *compile-hook* */
7642
7643 pointer free_cell; /* pointer to top of free cells */
7644 long fcells; /* # of free cells */
7645
7646 pointer inport;
7647 pointer outport;
7648 pointer save_inport;
7649 pointer loadport;
7650
7651 #define MAXFIL 64
7652 port load_stack[MAXFIL]; /* Stack of open files for port -1 (LOADing) */
7653 int nesting_stack[MAXFIL];
7654 int file_i;
7655 int nesting;
7656
7657 char gc_verbose; /* if gc_verbose is not zero, print gc status */
7658 char no_memory; /* Whether mem. alloc. has failed */
7659
7660 #define LINESIZE 1024
7661 char linebuff[LINESIZE];
7662 #define STRBUFFSIZE 256
7663 char strbuff[STRBUFFSIZE];
7664
7665 FILE *tmpfp;
7666 int tok;
7667 int print_flag;
7668 pointer value;
7669 int op;
7670
7671 void *ext_data; /* For the benefit of foreign functions */
7672 long gensym_cnt;
7673
7674 struct scheme_interface *vptr;
7675 void *dump_base; /* pointer to base of allocated dump stack */
7676 int dump_size; /* number of frames allocated for dump stack */
7677 };
7678
7679 /* operator code */
7680 enum scheme_opcodes {
7681 #define _OP_DEF(A,B,C,D,E,OP) OP,
7682 #include "opdefines.h"
7683 OP_MAXDEFINED
7684 };
7685
7686
7687 #define cons(sc,a,b) _cons(sc,a,b,0)
7688 #define immutable_cons(sc,a,b) _cons(sc,a,b,1)
7689
7690 int is_string(pointer p);
7691 char *string_value(pointer p);
7692 int is_number(pointer p);
7693 num nvalue(pointer p);
7694 long ivalue(pointer p);
7695 double rvalue(pointer p);
7696 int is_integer(pointer p);
7697 int is_real(pointer p);
7698 int is_character(pointer p);
7699 long charvalue(pointer p);
7700 int is_vector(pointer p);
7701
7702 int is_port(pointer p);
7703
7704 int is_pair(pointer p);
7705 pointer pair_car(pointer p);
7706 pointer pair_cdr(pointer p);
7707 pointer set_car(pointer p, pointer q);
7708 pointer set_cdr(pointer p, pointer q);
7709
7710 int is_symbol(pointer p);
7711 char *symname(pointer p);
7712 int hasprop(pointer p);
7713
7714 int is_syntax(pointer p);
7715 int is_proc(pointer p);
7716 int is_foreign(pointer p);
7717 char *syntaxname(pointer p);
7718 int is_closure(pointer p);
7719 #ifdef USE_MACRO
7720 int is_macro(pointer p);
7721 #endif
7722 pointer closure_code(pointer p);
7723 pointer closure_env(pointer p);
7724
7725 int is_continuation(pointer p);
7726 int is_promise(pointer p);
7727 int is_environment(pointer p);
7728 int is_immutable(pointer p);
7729 void setimmutable(pointer p);
7730
7731 #ifdef __cplusplus
7732 }
7733 #endif
7734
7735 #endif
7736
7737 /*
7738 Local variables:
7739 c-file-style: "k&r"
7740 End:
7741 */