tree checksum vpatch file split hunks
all signers: asciilifeform
antecedents:
press order: 
| asciilifeform_shiva_part_1_of_2 | asciilifeform | 
patch: 
(0 . 0)(1 . 2)
   5 *
   6 !.gitignore
-(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
-(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.
-(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.
-(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? */
-(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)
-(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 
-(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")
-(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
-(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
-(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 */
-(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
-(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 */