Home | History | Annotate | Line # | Download | only in lisp
      1 /*
      2  * Copyright (c) 2001 by The XFree86 Project, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     20  * SOFTWARE.
     21  *
     22  * Except as contained in this notice, the name of the XFree86 Project shall
     23  * not be used in advertising or otherwise to promote the sale, use or other
     24  * dealings in this Software without prior written authorization from the
     25  * XFree86 Project.
     26  *
     27  * Author: Paulo Csar Pereira de Andrade
     28  */
     29 
     30 /* $XFree86: xc/programs/xedit/lisp/lisp.c,v 1.87tsi Exp $ */
     31 
     32 #ifdef HAVE_CONFIG_H
     33 # include "config.h"
     34 #endif
     35 
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #ifdef sun
     39 #include <strings.h>
     40 #endif
     41 #include <ctype.h>
     42 #include <errno.h>
     43 #include <fcntl.h>
     44 #include <stdarg.h>
     45 #include <signal.h>
     46 #include <sys/wait.h>
     47 
     48 #ifndef X_NOT_POSIX
     49 #include <unistd.h>	/* for sysconf(), and getpagesize() */
     50 #endif
     51 
     52 #include "lisp/bytecode.h"
     53 
     54 #include "lisp/read.h"
     55 #include "lisp/format.h"
     56 #include "lisp/math.h"
     57 #include "lisp/hash.h"
     58 #include "lisp/package.h"
     59 #include "lisp/pathname.h"
     60 #include "lisp/regex.h"
     61 #include "lisp/require.h"
     62 #include "lisp/stream.h"
     63 #include "lisp/struct.h"
     64 #include "lisp/time.h"
     65 #include "lisp/write.h"
     66 #include <math.h>
     67 
     68 typedef struct {
     69     LispObj **objects;
     70     LispObj *freeobj;
     71     int nsegs;
     72     int nobjs;
     73     int nfree;
     74 } LispObjSeg;
     75 
     76 /*
     77  * Prototypes
     78  */
     79 static void Lisp__GC(LispObj*, LispObj*);
     80 static LispObj *Lisp__New(LispObj*, LispObj*);
     81 
     82 /* run a user function, to be called only by LispEval */
     83 static LispObj *LispRunFunMac(LispObj*, LispObj*, int, int);
     84 
     85 /* expands and executes a setf method, to be called only by Lisp_Setf */
     86 LispObj *LispRunSetf(LispArgList*, LispObj*, LispObj*, LispObj*);
     87 LispObj *LispRunSetfMacro(LispAtom*, LispObj*, LispObj*);
     88 
     89 /* increases storage size for environment */
     90 void LispMoreEnvironment(void);
     91 
     92 /* increases storage size for stack of builtin arguments */
     93 void LispMoreStack(void);
     94 
     95 /* increases storage size for global variables */
     96 void LispMoreGlobals(LispPackage*);
     97 
     98 #ifdef __GNUC__
     99 static INLINE LispObj *LispDoGetVar(LispObj*);
    100 #endif
    101 static INLINE void LispDoAddVar(LispObj*, LispObj*);
    102 
    103 /* Helper for importing symbol(s) functions,
    104  * Search for the specified object in the current package */
    105 static INLINE LispObj *LispGetVarPack(LispObj*);
    106 
    107 /* create environment for function call */
    108 static int LispMakeEnvironment(LispArgList*, LispObj*, LispObj*, int, int);
    109 
    110 	/* if not already in keyword package, move atom to keyword package */
    111 static LispObj *LispCheckKeyword(LispObj*);
    112 
    113 	/* builtin backquote parsing */
    114 static LispObj *LispEvalBackquoteObject(LispObj*, int, int);
    115 	/* used also by the bytecode compiler */
    116 LispObj *LispEvalBackquote(LispObj*, int);
    117 
    118 	/* create or change object property */
    119 void LispSetAtomObjectProperty(LispAtom*, LispObj*);
    120 	/* remove object property */
    121 static void LispRemAtomObjectProperty(LispAtom*);
    122 
    123 	/* allocates a new LispProperty for the given atom */
    124 static void LispAllocAtomProperty(LispAtom*);
    125 	/* Increment reference count of atom property */
    126 static void LispIncrementAtomReference(LispAtom*);
    127 	/* Decrement reference count of atom property */
    128 static void LispDecrementAtomReference(LispAtom*);
    129 	/* Removes all atom properties */
    130 static void LispRemAtomAllProperties(LispAtom*);
    131 
    132 static LispObj *LispAtomPropertyFunction(LispAtom*, LispObj*, int);
    133 
    134 static INLINE void LispCheckMemLevel(void);
    135 
    136 void LispAllocSeg(LispObjSeg*, int);
    137 static INLINE void LispMark(LispObj*);
    138 
    139 /* functions, macros, setf methods, and structure definitions */
    140 static INLINE void LispProt(LispObj*);
    141 
    142 static LispObj *LispCheckNeedProtect(LispObj*);
    143 
    144 static void LispSignalHandler(int);
    145 
    146 /*
    147  * Initialization
    148  */
    149 LispMac lisp__data;
    150 
    151 static LispObj lispunbound = {LispNil_t};
    152 LispObj *UNBOUND = &lispunbound;
    153 
    154 static volatile int lisp__disable_int;
    155 static volatile int lisp__interrupted;
    156 
    157 LispObj *Okey, *Orest, *Ooptional, *Oaux, *Olambda;
    158 
    159 Atom_id Snil, St;
    160 Atom_id Saux, Skey, Soptional, Srest;
    161 Atom_id Satom, Ssymbol, Sinteger, Scharacter, Sstring, Slist,
    162 	Scons, Svector, Sarray, Sstruct, Skeyword, Sfunction, Spathname,
    163 	Srational, Sfloat, Scomplex, Sopaque, Sdefault;
    164 
    165 LispObj *Oformat, *Kunspecific;
    166 LispObj *Oexpand_setf_method;
    167 
    168 static LispProperty noproperty;
    169 LispProperty *NOPROPERTY = &noproperty;
    170 static int segsize, minfree;
    171 int pagesize, gcpro;
    172 
    173 static LispObjSeg objseg = {NULL, NIL};
    174 static LispObjSeg atomseg = {NULL, NIL};
    175 
    176 int LispArgList_t;
    177 
    178 LispFile *Stdout, *Stdin, *Stderr;
    179 
    180 static LispBuiltin lispbuiltins[] = {
    181     {LispFunction, Lisp_Mul, "* &rest numbers"},
    182     {LispFunction, Lisp_Plus, "+ &rest numbers"},
    183     {LispFunction, Lisp_Minus, "- number &rest more-numbers"},
    184     {LispFunction, Lisp_Div, "/ number &rest more-numbers"},
    185     {LispFunction, Lisp_OnePlus, "1+ number"},
    186     {LispFunction, Lisp_OneMinus, "1- number"},
    187     {LispFunction, Lisp_Less, "< number &rest more-numbers"},
    188     {LispFunction, Lisp_LessEqual, "<= number &rest more-numbers"},
    189     {LispFunction, Lisp_Equal_, "= number &rest more-numbers"},
    190     {LispFunction, Lisp_Greater, "> number &rest more-numbers"},
    191     {LispFunction, Lisp_GreaterEqual, ">= number &rest more-numbers"},
    192     {LispFunction, Lisp_NotEqual, "/= number &rest more-numbers"},
    193     {LispFunction, Lisp_Max, "max number &rest more-numbers"},
    194     {LispFunction, Lisp_Min, "min number &rest more-numbers"},
    195     {LispFunction, Lisp_Abs, "abs number"},
    196     {LispFunction, Lisp_Acons, "acons key datum alist"},
    197     {LispFunction, Lisp_Adjoin, "adjoin item list &key key test test-not"},
    198     {LispFunction, Lisp_AlphaCharP, "alpha-char-p char"},
    199     {LispMacro, Lisp_And, "and &rest args", 1, 0, Com_And},
    200     {LispFunction, Lisp_Append, "append &rest lists"},
    201     {LispFunction, Lisp_Apply, "apply function arg &rest more-args", 1},
    202     {LispFunction, Lisp_Aref, "aref array &rest subscripts"},
    203     {LispFunction, Lisp_Assoc, "assoc item list &key test test-not key"},
    204     {LispFunction, Lisp_AssocIf, "assoc-if predicate list &key key"},
    205     {LispFunction, Lisp_AssocIfNot, "assoc-if-not predicate list &key key"},
    206     {LispFunction, Lisp_Atom, "atom object"},
    207     {LispMacro, Lisp_Block, "block name &rest body", 1, 0, Com_Block},
    208     {LispFunction, Lisp_BothCaseP, "both-case-p character"},
    209     {LispFunction, Lisp_Boundp, "boundp symbol"},
    210     {LispFunction, Lisp_Butlast, "butlast list &optional count"},
    211     {LispFunction, Lisp_Nbutlast, "nbutlast list &optional count"},
    212     {LispFunction, Lisp_Car, "car list", 0, 0, Com_C_r},
    213     {LispFunction, Lisp_Car, "first list", 0, 0, Com_C_r},
    214     {LispMacro, Lisp_Case, "case keyform &rest body"},
    215     {LispMacro, Lisp_Catch, "catch tag &rest body", 1},
    216     {LispFunction, Lisp_Cdr, "cdr list", 0, 0, Com_C_r},
    217     {LispFunction, Lisp_Cdr, "rest list", 0, 0, Com_C_r},
    218     {LispFunction, Lisp_Ceiling, "ceiling number &optional divisor", 1},
    219     {LispFunction, Lisp_Fceiling, "fceiling number &optional divisor", 1},
    220     {LispFunction, Lisp_Char, "char string index"},
    221     {LispFunction, Lisp_Char, "schar simple-string index"},
    222     {LispFunction, Lisp_CharLess, "char< character &rest more-characters"},
    223     {LispFunction, Lisp_CharLessEqual, "char<= character &rest more-characters"},
    224     {LispFunction, Lisp_CharEqual_, "char= character &rest more-characters"},
    225     {LispFunction, Lisp_CharGreater, "char> character &rest more-characters"},
    226     {LispFunction, Lisp_CharGreaterEqual, "char>= character &rest more-characters"},
    227     {LispFunction, Lisp_CharNotEqual_, "char/= character &rest more-characters"},
    228     {LispFunction, Lisp_CharLessp, "char-lessp character &rest more-characters"},
    229     {LispFunction, Lisp_CharNotGreaterp, "char-not-greaterp character &rest more-characters"},
    230     {LispFunction, Lisp_CharEqual, "char-equal character &rest more-characters"},
    231     {LispFunction, Lisp_CharGreaterp, "char-greaterp character &rest more-characters"},
    232     {LispFunction, Lisp_CharNotLessp, "char-not-lessp character &rest more-characters"},
    233     {LispFunction, Lisp_CharNotEqual, "char-not-equal character &rest more-characters"},
    234     {LispFunction, Lisp_CharDowncase, "char-downcase character"},
    235     {LispFunction, Lisp_CharInt, "char-code character"},
    236     {LispFunction, Lisp_CharInt, "char-int character"},
    237     {LispFunction, Lisp_CharUpcase, "char-upcase character"},
    238     {LispFunction, Lisp_Character, "character object"},
    239     {LispFunction, Lisp_Characterp, "characterp object"},
    240     {LispFunction, Lisp_Clrhash, "clrhash hash-table"},
    241     {LispFunction, Lisp_IntChar, "code-char integer"},
    242     {LispFunction, Lisp_Coerce, "coerce object result-type"},
    243     {LispFunction, Lisp_Compile, "compile name &optional definition", 1},
    244     {LispFunction, Lisp_Complex, "complex realpart &optional imagpart"},
    245     {LispMacro, Lisp_Cond, "cond &rest body", 0, 0, Com_Cond},
    246     {LispFunction, Lisp_Cons, "cons car cdr", 0, 0, Com_Cons},
    247     {LispFunction, Lisp_Consp, "consp object", 0, 0, Com_Consp},
    248     {LispFunction, Lisp_Constantp, "constantp form &optional environment"},
    249     {LispFunction, Lisp_Conjugate, "conjugate number"},
    250     {LispFunction, Lisp_Complexp, "complexp object"},
    251     {LispFunction, Lisp_CopyAlist, "copy-alist list"},
    252     {LispFunction, Lisp_CopyList, "copy-list list"},
    253     {LispFunction, Lisp_CopyTree, "copy-tree list"},
    254     {LispFunction, Lisp_Close, "close stream &key abort"},
    255     {LispFunction, Lisp_C_r, "caar list", 0, 0, Com_C_r},
    256     {LispFunction, Lisp_C_r, "cadr list", 0, 0, Com_C_r},
    257     {LispFunction, Lisp_C_r, "cdar list", 0, 0, Com_C_r},
    258     {LispFunction, Lisp_C_r, "cddr list", 0, 0, Com_C_r},
    259     {LispFunction, Lisp_C_r, "caaar list", 0, 0, Com_C_r},
    260     {LispFunction, Lisp_C_r, "caadr list", 0, 0, Com_C_r},
    261     {LispFunction, Lisp_C_r, "cadar list", 0, 0, Com_C_r},
    262     {LispFunction, Lisp_C_r, "caddr list", 0, 0, Com_C_r},
    263     {LispFunction, Lisp_C_r, "cdaar list", 0, 0, Com_C_r},
    264     {LispFunction, Lisp_C_r, "cdadr list", 0, 0, Com_C_r},
    265     {LispFunction, Lisp_C_r, "cddar list", 0, 0, Com_C_r},
    266     {LispFunction, Lisp_C_r, "cdddr list", 0, 0, Com_C_r},
    267     {LispFunction, Lisp_C_r, "caaaar list", 0, 0, Com_C_r},
    268     {LispFunction, Lisp_C_r, "caaadr list", 0, 0, Com_C_r},
    269     {LispFunction, Lisp_C_r, "caadar list", 0, 0, Com_C_r},
    270     {LispFunction, Lisp_C_r, "caaddr list", 0, 0, Com_C_r},
    271     {LispFunction, Lisp_C_r, "cadaar list", 0, 0, Com_C_r},
    272     {LispFunction, Lisp_C_r, "cadadr list", 0, 0, Com_C_r},
    273     {LispFunction, Lisp_C_r, "caddar list", 0, 0, Com_C_r},
    274     {LispFunction, Lisp_C_r, "cadddr list", 0, 0, Com_C_r},
    275     {LispFunction, Lisp_C_r, "cdaaar list", 0, 0, Com_C_r},
    276     {LispFunction, Lisp_C_r, "cdaadr list", 0, 0, Com_C_r},
    277     {LispFunction, Lisp_C_r, "cdadar list", 0, 0, Com_C_r},
    278     {LispFunction, Lisp_C_r, "cdaddr list", 0, 0, Com_C_r},
    279     {LispFunction, Lisp_C_r, "cddaar list", 0, 0, Com_C_r},
    280     {LispFunction, Lisp_C_r, "cddadr list", 0, 0, Com_C_r},
    281     {LispFunction, Lisp_C_r, "cdddar list", 0, 0, Com_C_r},
    282     {LispFunction, Lisp_C_r, "cddddr list", 0, 0, Com_C_r},
    283     {LispMacro, Lisp_Decf, "decf place &optional delta"},
    284     {LispMacro, Lisp_Defconstant, "defconstant name initial-value &optional documentation"},
    285     {LispMacro, Lisp_Defmacro, "defmacro name lambda-list &rest body"},
    286     {LispMacro, Lisp_Defstruct, "defstruct name &rest description"},
    287     {LispMacro, Lisp_Defun, "defun name lambda-list &rest body"},
    288     {LispMacro, Lisp_Defsetf, "defsetf function lambda-list &rest body"},
    289     {LispMacro, Lisp_Defparameter, "defparameter name initial-value &optional documentation"},
    290     {LispMacro, Lisp_Defvar, "defvar name &optional initial-value documentation"},
    291     {LispFunction, Lisp_Delete, "delete item sequence &key from-end test test-not start end count key"},
    292     {LispFunction, Lisp_DeleteDuplicates, "delete-duplicates sequence &key from-end test test-not start end key"},
    293     {LispFunction, Lisp_DeleteIf, "delete-if predicate sequence &key from-end start end count key"},
    294     {LispFunction, Lisp_DeleteIfNot, "delete-if-not predicate sequence &key from-end start end count key"},
    295     {LispFunction, Lisp_DeleteFile, "delete-file filename"},
    296     {LispFunction, Lisp_Denominator, "denominator rational"},
    297     {LispFunction, Lisp_DigitChar, "digit-char weight &optional radix"},
    298     {LispFunction, Lisp_DigitCharP, "digit-char-p character &optional radix"},
    299     {LispFunction, Lisp_Directory, "directory pathname &key all if-cannot-read"},
    300     {LispFunction, Lisp_DirectoryNamestring, "directory-namestring pathname"},
    301     {LispFunction, Lisp_Disassemble, "disassemble function"},
    302     {LispMacro, Lisp_Do, "do init test &rest body"},
    303     {LispMacro, Lisp_DoP, "do* init test &rest body"},
    304     {LispFunction, Lisp_Documentation, "documentation symbol type"},
    305     {LispMacro, Lisp_DoList, "dolist init &rest body", 0, 0, Com_Dolist},
    306     {LispMacro, Lisp_DoTimes, "dotimes init &rest body"},
    307     {LispMacro, Lisp_DoAllSymbols, "do-all-symbols init &rest body"},
    308     {LispMacro, Lisp_DoExternalSymbols, "do-external-symbols init &rest body"},
    309     {LispMacro, Lisp_DoSymbols, "do-symbols init &rest body"},
    310     {LispFunction, Lisp_Elt, "elt sequence index"},
    311     {LispFunction, Lisp_Endp, "endp object"},
    312     {LispFunction, Lisp_EnoughNamestring, "enough-namestring pathname &optional defaults"},
    313     {LispFunction, Lisp_Eq, "eq left right", 0, 0, Com_Eq},
    314     {LispFunction, Lisp_Eql, "eql left right", 0, 0, Com_Eq},
    315     {LispFunction, Lisp_Equal, "equal left right", 0, 0, Com_Eq},
    316     {LispFunction, Lisp_Equalp, "equalp left right", 0, 0, Com_Eq},
    317     {LispFunction, Lisp_Error, "error control-string &rest arguments"},
    318     {LispFunction, Lisp_Evenp, "evenp integer"},
    319     {LispFunction, Lisp_Export, "export symbols &optional package"},
    320     {LispFunction, Lisp_Eval, "eval form"},
    321     {LispFunction, Lisp_Every, "every predicate sequence &rest more-sequences"},
    322     {LispFunction, Lisp_Some, "some predicate sequence &rest more-sequences"},
    323     {LispFunction, Lisp_Notevery, "notevery predicate sequence &rest more-sequences"},
    324     {LispFunction, Lisp_Notany, "notany predicate sequence &rest more-sequences"},
    325     {LispFunction, Lisp_Fboundp, "fboundp symbol"},
    326     {LispFunction, Lisp_Find, "find item sequence &key from-end test test-not start end key"},
    327     {LispFunction, Lisp_FindIf, "find-if predicate sequence &key from-end start end key"},
    328     {LispFunction, Lisp_FindIfNot, "find-if-not predicate sequence &key from-end start end key"},
    329     {LispFunction, Lisp_FileNamestring, "file-namestring pathname"},
    330     {LispFunction, Lisp_Fill, "fill sequence item &key start end"},
    331     {LispFunction, Lisp_FindAllSymbols, "find-all-symbols string-or-symbol"},
    332     {LispFunction, Lisp_FindSymbol, "find-symbol string &optional package", 1},
    333     {LispFunction, Lisp_FindPackage, "find-package name"},
    334     {LispFunction, Lisp_Float, "float number &optional other"},
    335     {LispFunction, Lisp_Floatp, "floatp object"},
    336     {LispFunction, Lisp_Floor, "floor number &optional divisor", 1},
    337     {LispFunction, Lisp_Ffloor, "ffloor number &optional divisor", 1},
    338     {LispFunction, Lisp_Fmakunbound, "fmakunbound symbol"},
    339     {LispFunction, Lisp_Format, "format destination control-string &rest arguments"},
    340     {LispFunction, Lisp_FreshLine, "fresh-line &optional output-stream"},
    341     {LispFunction, Lisp_Funcall, "funcall function &rest arguments", 1},
    342     {LispFunction, Lisp_Functionp, "functionp object"},
    343     {LispFunction, Lisp_Gc, "gc &optional car cdr"},
    344     {LispFunction, Lisp_Gcd, "gcd &rest integers"},
    345     {LispFunction, Lisp_Gensym, "gensym &optional arg"},
    346     {LispFunction, Lisp_Get, "get symbol indicator &optional default"},
    347     {LispFunction, Lisp_Gethash, "gethash key hash-table &optional default", 1},
    348     {LispMacro, Lisp_Go, "go tag", 0, 0, Com_Go},
    349     {LispFunction, Lisp_GraphicCharP, "graphic-char-p char"},
    350     {LispFunction, Lisp_HashTableP, "hash-table-p object"},
    351     {LispFunction, Lisp_HashTableCount, "hash-table-count hash-table"},
    352     {LispFunction, Lisp_HashTableRehashSize, "hash-table-rehash-size hash-table"},
    353     {LispFunction, Lisp_HashTableRehashThreshold, "hash-table-rehash-threshold hash-table"},
    354     {LispFunction, Lisp_HashTableSize, "hash-table-size hash-table"},
    355     {LispFunction, Lisp_HashTableTest, "hash-table-test hash-table"},
    356     {LispFunction, Lisp_HostNamestring, "host-namestring pathname"},
    357     {LispMacro, Lisp_If, "if test then &optional else", 0, 0, Com_If},
    358     {LispMacro, Lisp_IgnoreErrors, "ignore-errors &rest body", 1},
    359     {LispFunction, Lisp_Imagpart, "imagpart number"},
    360     {LispMacro, Lisp_InPackage, "in-package name"},
    361     {LispMacro, Lisp_Incf, "incf place &optional delta"},
    362     {LispFunction, Lisp_Import, "import symbols &optional package"},
    363     {LispFunction, Lisp_InputStreamP, "input-stream-p stream"},
    364     {LispFunction, Lisp_IntChar, "int-char integer"},
    365     {LispFunction, Lisp_Integerp, "integerp object"},
    366     {LispFunction, Lisp_Intern, "intern string &optional package", 1},
    367     {LispFunction, Lisp_Intersection, "intersection list1 list2 &key test test-not key"},
    368     {LispFunction, Lisp_Nintersection, "nintersection list1 list2 &key test test-not key"},
    369     {LispFunction, Lisp_Isqrt, "isqrt natural"},
    370     {LispFunction, Lisp_Keywordp, "keywordp object"},
    371     {LispFunction, Lisp_Last, "last list &optional count", 0, 0, Com_Last},
    372     {LispMacro, Lisp_Lambda, "lambda lambda-list &rest body"},
    373     {LispFunction, Lisp_Lcm, "lcm &rest integers"},
    374     {LispFunction, Lisp_Length, "length sequence", 0, 0, Com_Length},
    375     {LispMacro, Lisp_Let, "let init &rest body", 1, 0, Com_Let},
    376     {LispMacro, Lisp_LetP, "let* init &rest body", 1, 0, Com_Letx},
    377     {LispFunction, Lisp_ListP, "list* object &rest more-objects"},
    378     {LispFunction, Lisp_ListAllPackages, "list-all-packages"},
    379     {LispFunction, Lisp_List, "list &rest args"},
    380     {LispFunction, Lisp_ListLength, "list-length list"},
    381     {LispFunction, Lisp_Listp, "listp object", 0, 0, Com_Listp},
    382     {LispFunction, Lisp_Listen, "listen &optional input-stream"},
    383     {LispFunction, Lisp_Load, "load filename &key verbose print if-does-not-exist"},
    384     {LispFunction, Lisp_Logand, "logand &rest integers"},
    385     {LispFunction, Lisp_Logeqv, "logeqv &rest integers"},
    386     {LispFunction, Lisp_Logior, "logior &rest integers"},
    387     {LispFunction, Lisp_Lognot, "lognot integer"},
    388     {LispFunction, Lisp_Logxor, "logxor &rest integers"},
    389     {LispMacro, Lisp_Loop, "loop &rest body", 0, 0, Com_Loop},
    390     {LispFunction, Lisp_LowerCaseP, "lower-case-p character"},
    391     {LispFunction, Lisp_MakeArray, "make-array dimensions &key element-type initial-element initial-contents adjustable fill-pointer displaced-to displaced-index-offset"},
    392     {LispFunction, Lisp_MakeHashTable, "make-hash-table &key test size rehash-size rehash-threshold initial-contents"},
    393     {LispFunction, Lisp_MakeList, "make-list size &key initial-element"},
    394     {LispFunction, Lisp_MakePackage, "make-package package-name &key nicknames use"},
    395     {LispFunction, Lisp_MakePathname, "make-pathname &key host device directory name type version defaults"},
    396     {LispFunction, Lisp_MakeString, "make-string size &key initial-element element-type"},
    397     {LispFunction, Lisp_MakeSymbol, "make-symbol name"},
    398     {LispFunction, Lisp_MakeStringInputStream, "make-string-input-stream string &optional start end"},
    399     {LispFunction, Lisp_MakeStringOutputStream, "make-string-output-stream &key element-type"},
    400     {LispFunction, Lisp_GetOutputStreamString, "get-output-stream-string string-output-stream"},
    401     {LispFunction, Lisp_Makunbound, "makunbound symbol"},
    402     {LispFunction, Lisp_Mapc, "mapc function list &rest more-lists"},
    403     {LispFunction, Lisp_Mapcar, "mapcar function list &rest more-lists"},
    404     {LispFunction, Lisp_Mapcan, "mapcan function list &rest more-lists"},
    405     {LispFunction, Lisp_Maphash, "maphash function hash-table"},
    406     {LispFunction, Lisp_Mapl, "mapl function list &rest more-lists"},
    407     {LispFunction, Lisp_Maplist, "maplist function list &rest more-lists"},
    408     {LispFunction, Lisp_Mapcon, "mapcon function list &rest more-lists"},
    409     {LispFunction, Lisp_Member, "member item list &key test test-not key"},
    410     {LispFunction, Lisp_MemberIf, "member-if predicate list &key key"},
    411     {LispFunction, Lisp_MemberIfNot, "member-if-not predicate list &key key"},
    412     {LispFunction, Lisp_Minusp, "minusp number"},
    413     {LispFunction, Lisp_Mod, "mod number divisor"},
    414     {LispMacro, Lisp_MultipleValueBind, "multiple-value-bind symbols values &rest body"},
    415     {LispMacro, Lisp_MultipleValueCall, "multiple-value-call function &rest form", 1},
    416     {LispMacro, Lisp_MultipleValueProg1, "multiple-value-prog1 first-form &rest form", 1},
    417     {LispMacro, Lisp_MultipleValueList, "multiple-value-list form"},
    418     {LispMacro, Lisp_MultipleValueSetq, "multiple-value-setq symbols form"},
    419     {LispFunction, Lisp_Nconc, "nconc &rest lists"},
    420     {LispFunction, Lisp_Nreverse, "nreverse sequence"},
    421     {LispFunction, Lisp_NsetDifference, "nset-difference list1 list2 &key test test-not key"},
    422     {LispFunction, Lisp_Nsubstitute, "nsubstitute newitem olditem sequence &key from-end test test-not start end count key"},
    423     {LispFunction, Lisp_NsubstituteIf, "nsubstitute-if newitem test sequence &key from-end start end count key"},
    424     {LispFunction, Lisp_NsubstituteIfNot, "nsubstitute-if-not newitem test sequence &key from-end start end count key"},
    425     {LispFunction, Lisp_Nth, "nth index list"},
    426     {LispFunction, Lisp_Nthcdr, "nthcdr index list", 0, 0, Com_Nthcdr},
    427     {LispMacro, Lisp_NthValue, "nth-value index form"},
    428     {LispFunction, Lisp_Numerator, "numerator rational"},
    429     {LispFunction, Lisp_Namestring, "namestring pathname"},
    430     {LispFunction, Lisp_Null, "not arg", 0, 0, Com_Null},
    431     {LispFunction, Lisp_Null, "null list", 0, 0, Com_Null},
    432     {LispFunction, Lisp_Numberp, "numberp object", 0, 0, Com_Numberp},
    433     {LispFunction, Lisp_Oddp, "oddp integer"},
    434     {LispFunction, Lisp_Open, "open filename &key direction element-type if-exists if-does-not-exist external-format"},
    435     {LispFunction, Lisp_OpenStreamP, "open-stream-p stream"},
    436     {LispMacro, Lisp_Or, "or &rest args", 1, 0, Com_Or},
    437     {LispFunction, Lisp_OutputStreamP, "output-stream-p stream"},
    438     {LispFunction, Lisp_Packagep, "packagep object"},
    439     {LispFunction, Lisp_PackageName, "package-name package"},
    440     {LispFunction, Lisp_PackageNicknames, "package-nicknames package"},
    441     {LispFunction, Lisp_PackageUseList, "package-use-list package"},
    442     {LispFunction, Lisp_PackageUsedByList, "package-used-by-list package"},
    443     {LispFunction, Lisp_Pairlis, "pairlis key data &optional alist"},
    444     {LispFunction, Lisp_ParseInteger, "parse-integer string &key start end radix junk-allowed", 1},
    445     {LispFunction, Lisp_ParseNamestring, "parse-namestring object &optional host defaults &key start end junk-allowed", 1},
    446     {LispFunction, Lisp_PathnameHost, "pathname-host pathname"},
    447     {LispFunction, Lisp_PathnameDevice, "pathname-device pathname"},
    448     {LispFunction, Lisp_PathnameDirectory, "pathname-directory pathname"},
    449     {LispFunction, Lisp_PathnameName, "pathname-name pathname"},
    450     {LispFunction, Lisp_PathnameType, "pathname-type pathname"},
    451     {LispFunction, Lisp_PathnameVersion, "pathname-version pathname"},
    452     {LispFunction, Lisp_Pathnamep, "pathnamep object"},
    453     {LispFunction, Lisp_Plusp, "plusp number"},
    454     {LispMacro, Lisp_Pop, "pop place"},
    455     {LispFunction, Lisp_Position, "position item sequence &key from-end test test-not start end key"},
    456     {LispFunction, Lisp_PositionIf, "position-if predicate sequence &key from-end start end key"},
    457     {LispFunction, Lisp_PositionIfNot, "position-if-not predicate sequence &key from-end start end key"},
    458     {LispFunction, Lisp_Prin1, "prin1 object &optional output-stream"},
    459     {LispFunction, Lisp_Princ, "princ object &optional output-stream"},
    460     {LispFunction, Lisp_Print, "print object &optional output-stream"},
    461     {LispFunction, Lisp_ProbeFile, "probe-file pathname"},
    462     {LispFunction, Lisp_Proclaim, "proclaim declaration"},
    463     {LispMacro, Lisp_Prog1, "prog1 first &rest body"},
    464     {LispMacro, Lisp_Prog2, "prog2 first second &rest body"},
    465     {LispMacro, Lisp_Progn, "progn &rest body", 1, 0, Com_Progn},
    466     {LispMacro, Lisp_Progv, "progv symbols values &rest body", 1},
    467     {LispFunction, Lisp_Provide, "provide module"},
    468     {LispMacro, Lisp_Push, "push item place"},
    469     {LispMacro, Lisp_Pushnew, "pushnew item place &key key test test-not"},
    470     {LispFunction, Lisp_Quit, "quit &optional status"},
    471     {LispMacro, Lisp_Quote, "quote object"},
    472     {LispFunction, Lisp_Rational, "rational number"},
    473     {LispFunction, Lisp_Rationalp, "rationalp object"},
    474     {LispFunction, Lisp_Read, "read &optional input-stream eof-error-p eof-value recursive-p"},
    475     {LispFunction, Lisp_ReadChar, "read-char &optional input-stream eof-error-p eof-value recursive-p"},
    476     {LispFunction, Lisp_ReadCharNoHang, "read-char-no-hang &optional input-stream eof-error-p eof-value recursive-p"},
    477     {LispFunction, Lisp_ReadLine, "read-line &optional input-stream eof-error-p eof-value recursive-p", 1},
    478     {LispFunction, Lisp_Realpart, "realpart number"},
    479     {LispFunction, Lisp_Replace, "replace sequence1 sequence2 &key start1 end1 start2 end2"},
    480     {LispFunction, Lisp_ReadFromString, "read-from-string string &optional eof-error-p eof-value &key start end preserve-whitespace", 1},
    481     {LispFunction, Lisp_Require, "require module &optional pathname"},
    482     {LispFunction, Lisp_Rem, "rem number divisor"},
    483     {LispFunction, Lisp_Remhash, "remhash key hash-table"},
    484     {LispFunction, Lisp_Remove, "remove item sequence &key from-end test test-not start end count key"},
    485     {LispFunction, Lisp_RemoveDuplicates, "remove-duplicates sequence &key from-end test test-not start end key"},
    486     {LispFunction, Lisp_RemoveIf, "remove-if predicate sequence &key from-end start end count key"},
    487     {LispFunction, Lisp_RemoveIfNot, "remove-if-not predicate sequence &key from-end start end count key"},
    488     {LispFunction, Lisp_Remprop, "remprop symbol indicator"},
    489     {LispFunction, Lisp_RenameFile, "rename-file filename new-name", 1},
    490     {LispMacro, Lisp_Return, "return &optional result", 1, 0, Com_Return},
    491     {LispMacro, Lisp_ReturnFrom, "return-from name &optional result", 1, 0, Com_ReturnFrom},
    492     {LispFunction, Lisp_Reverse, "reverse sequence"},
    493     {LispFunction, Lisp_Round, "round number &optional divisor", 1},
    494     {LispFunction, Lisp_Fround, "fround number &optional divisor", 1},
    495     {LispFunction, Lisp_Rplaca, "rplaca place value", 0, 0, Com_Rplac_},
    496     {LispFunction, Lisp_Rplacd, "rplacd place value", 0, 0, Com_Rplac_},
    497     {LispFunction, Lisp_Search, "search sequence1 sequence2 &key from-end test test-not key start1 start2 end1 end2"},
    498     {LispFunction, Lisp_Set, "set symbol value"},
    499     {LispFunction, Lisp_SetDifference, "set-difference list1 list2 &key test test-not key"},
    500     {LispFunction, Lisp_SetExclusiveOr, "set-exclusive-or list1 list2 &key test test-not key"},
    501     {LispFunction, Lisp_NsetExclusiveOr, "nset-exclusive-or list1 list2 &key test test-not key"},
    502     {LispMacro, Lisp_Setf, "setf &rest form"},
    503     {LispMacro, Lisp_Psetf, "psetf &rest form"},
    504     {LispMacro, Lisp_SetQ, "setq &rest form", 0, 0, Com_Setq},
    505     {LispMacro, Lisp_Psetq, "psetq &rest form"},
    506     {LispFunction, Lisp_Sleep, "sleep seconds"},
    507     {LispFunction, Lisp_Sort, "sort sequence predicate &key key"},
    508     {LispFunction, Lisp_Sqrt, "sqrt number"},
    509     {LispFunction, Lisp_Elt, "svref sequence index"},
    510     {LispFunction, Lisp_Sort, "stable-sort sequence predicate &key key"},
    511     {LispFunction, Lisp_Streamp, "streamp object"},
    512     {LispFunction, Lisp_String, "string object"},
    513     {LispFunction, Lisp_Stringp, "stringp object"},
    514     {LispFunction, Lisp_StringEqual_, "string= string1 string2 &key start1 end1 start2 end2"},
    515     {LispFunction, Lisp_StringLess, "string< string1 string2 &key start1 end1 start2 end2"},
    516     {LispFunction, Lisp_StringGreater, "string> string1 string2 &key start1 end1 start2 end2"},
    517     {LispFunction, Lisp_StringLessEqual, "string<= string1 string2 &key start1 end1 start2 end2"},
    518     {LispFunction, Lisp_StringGreaterEqual, "string>= string1 string2 &key start1 end1 start2 end2"},
    519     {LispFunction, Lisp_StringNotEqual_, "string/= string1 string2 &key start1 end1 start2 end2"},
    520     {LispFunction, Lisp_StringConcat, "string-concat &rest strings"},
    521     {LispFunction, Lisp_StringEqual, "string-equal string1 string2 &key start1 end1 start2 end2"},
    522     {LispFunction, Lisp_StringGreaterp, "string-greaterp string1 string2 &key start1 end1 start2 end2"},
    523     {LispFunction, Lisp_StringNotEqual, "string-not-equal string1 string2 &key start1 end1 start2 end2"},
    524     {LispFunction, Lisp_StringNotGreaterp, "string-not-greaterp string1 string2 &key start1 end1 start2 end2"},
    525     {LispFunction, Lisp_StringNotLessp, "string-not-lessp string1 string2 &key start1 end1 start2 end2"},
    526     {LispFunction, Lisp_StringLessp, "string-lessp string1 string2 &key start1 end1 start2 end2"},
    527     {LispFunction, Lisp_StringTrim, "string-trim character-bag string"},
    528     {LispFunction, Lisp_StringLeftTrim, "string-left-trim character-bag string"},
    529     {LispFunction, Lisp_StringRightTrim, "string-right-trim character-bag string"},
    530     {LispFunction, Lisp_StringUpcase, "string-upcase string &key start end"},
    531     {LispFunction, Lisp_NstringUpcase, "nstring-upcase string &key start end"},
    532     {LispFunction, Lisp_StringDowncase, "string-downcase string &key start end"},
    533     {LispFunction, Lisp_NstringDowncase, "nstring-downcase string &key start end"},
    534     {LispFunction, Lisp_StringCapitalize, "string-capitalize string &key start end"},
    535     {LispFunction, Lisp_NstringCapitalize, "nstring-capitalize string &key start end"},
    536     {LispFunction, Lisp_Subseq, "subseq sequence start &optional end"},
    537     {LispFunction, Lisp_Subsetp, "subsetp list1 list2 &key test test-not key"},
    538     {LispFunction, Lisp_Substitute, "substitute newitem olditem sequence &key from-end test test-not start end count key"},
    539     {LispFunction, Lisp_SubstituteIf, "substitute-if newitem test sequence &key from-end start end count key"},
    540     {LispFunction, Lisp_SubstituteIfNot, "substitute-if-not newitem test sequence &key from-end start end count key"},
    541     {LispFunction, Lisp_SymbolFunction, "symbol-function symbol"},
    542     {LispFunction, Lisp_SymbolName, "symbol-name symbol"},
    543     {LispFunction, Lisp_Symbolp, "symbolp object"},
    544     {LispFunction, Lisp_SymbolPlist, "symbol-plist symbol"},
    545     {LispFunction, Lisp_SymbolPackage, "symbol-package symbol"},
    546     {LispFunction, Lisp_SymbolValue, "symbol-value symbol"},
    547     {LispMacro, Lisp_Tagbody, "tagbody &rest body", 0, 0, Com_Tagbody},
    548     {LispFunction, Lisp_Terpri, "terpri &optional output-stream"},
    549     {LispFunction, Lisp_Typep, "typep object type"},
    550     {LispMacro, Lisp_The, "the value-type form"},
    551     {LispMacro, Lisp_Throw, "throw tag result", 1},
    552     {LispMacro, Lisp_Time, "time form"},
    553     {LispFunction, Lisp_Truename, "truename pathname"},
    554     {LispFunction, Lisp_TreeEqual, "tree-equal tree-1 tree-2 &key test test-not"},
    555     {LispFunction, Lisp_Truncate, "truncate number &optional divisor", 1},
    556     {LispFunction, Lisp_Ftruncate, "ftruncate number &optional divisor", 1},
    557     {LispFunction, Lisp_Unexport, "unexport symbols &optional package"},
    558     {LispFunction, Lisp_Union, "union list1 list2 &key test test-not key"},
    559     {LispFunction, Lisp_Nunion, "nunion list1 list2 &key test test-not key"},
    560     {LispMacro, Lisp_Unless, "unless test &rest body", 1, 0, Com_Unless},
    561     {LispFunction, Lisp_UserHomedirPathname, "user-homedir-pathname &optional host"},
    562     {LispMacro, Lisp_UnwindProtect, "unwind-protect protect &rest cleanup"},
    563     {LispFunction, Lisp_UpperCaseP, "upper-case-p character"},
    564     {LispFunction, Lisp_Values, "values &rest objects", 1},
    565     {LispFunction, Lisp_ValuesList, "values-list list", 1},
    566     {LispFunction, Lisp_Vector, "vector &rest objects"},
    567     {LispMacro, Lisp_When, "when test &rest body", 1, 0, Com_When},
    568     {LispFunction, Lisp_Write, " write object &key case circle escape length level lines pretty readably right-margin stream"},
    569     {LispFunction, Lisp_WriteChar, "write-char string &optional output-stream"},
    570     {LispFunction, Lisp_WriteLine, "write-line string &optional output-stream &key start end"},
    571     {LispFunction, Lisp_WriteString, "write-string string &optional output-stream &key start end"},
    572     {LispFunction, Lisp_XeditCharStore, "lisp::char-store string index value", 0, 1},
    573     {LispFunction, Lisp_XeditEltStore, "lisp::elt-store sequence index value", 0, 1},
    574     {LispFunction, Lisp_XeditMakeStruct, "lisp::make-struct atom &rest init", 0, 1},
    575     {LispFunction, Lisp_XeditPut, " lisp::put symbol indicator value", 0, 1},
    576     {LispFunction, Lisp_XeditPuthash, "lisp::puthash key hash-table value", 0, 1},
    577     {LispFunction, Lisp_XeditSetSymbolPlist, "lisp::set-symbol-plist symbol list", 0, 1},
    578     {LispFunction, Lisp_XeditStructAccess, "lisp::struct-access atom struct", 0, 1},
    579     {LispFunction, Lisp_XeditStructType, "lisp::struct-type atom struct", 0, 1},
    580     {LispFunction, Lisp_XeditStructStore, "lisp::struct-store atom struct value", 0, 1},
    581     {LispFunction, Lisp_XeditVectorStore, "lisp::vector-store array &rest values", 0, 1},
    582     {LispFunction, Lisp_XeditDocumentationStore, "lisp::documentation-store symbol type string", 0, 1},
    583     {LispFunction, Lisp_Zerop, "zerop number"},
    584 };
    585 
    586 static LispBuiltin extbuiltins[] = {
    587     {LispFunction, Lisp_Getenv, "getenv name"},
    588     {LispFunction, Lisp_MakePipe, "make-pipe command-line &key direction element-type external-format"},
    589     {LispFunction, Lisp_PipeBroken, "pipe-broken pipe-stream"},
    590     {LispFunction, Lisp_PipeErrorStream, "pipe-error-stream pipe-stream"},
    591     {LispFunction, Lisp_PipeInputDescriptor, "pipe-input-descriptor pipe-stream"},
    592     {LispFunction, Lisp_PipeErrorDescriptor, "pipe-error-descriptor pipe-stream"},
    593     {LispFunction, Lisp_Recomp, "re-comp pattern &key nospec icase nosub newline"},
    594     {LispFunction, Lisp_Reexec, "re-exec regex string &key count start end notbol noteol"},
    595     {LispFunction, Lisp_Rep, "re-p object"},
    596     {LispFunction, Lisp_Setenv, "setenv name value &optional overwrite"},
    597     {LispFunction, Lisp_Unsetenv, "unsetenv name"},
    598     {LispFunction, Lisp_NstringTrim, "nstring-trim character-bag string"},
    599     {LispFunction, Lisp_NstringLeftTrim, "nstring-left-trim character-bag string"},
    600     {LispFunction, Lisp_NstringRightTrim, "nstring-right-trim character-bag string"},
    601     {LispMacro, Lisp_Until, "until test &rest body", 0, 0, Com_Until},
    602     {LispMacro, Lisp_While, "while test &rest body", 0, 0, Com_While},
    603 };
    604 
    605 /* byte code function argument list for functions that don't change it's
    606  * &REST argument list. */
    607 extern LispObj x_cons[8];
    608 
    609 /*
    610  * Implementation
    611  */
    612 static int
    613 LispGetPageSize(void)
    614 {
    615     static int pagesize = -1;
    616 
    617     if (pagesize != -1)
    618 	return pagesize;
    619 
    620     /* Try each supported method in the preferred order */
    621 
    622 #if defined(_SC_PAGESIZE) || defined(HAVE_DECL__SC_PAGESIZE)
    623     pagesize = sysconf(_SC_PAGESIZE);
    624 #endif
    625 
    626 #ifdef _SC_PAGE_SIZE
    627     if (pagesize == -1)
    628 	pagesize = sysconf(_SC_PAGE_SIZE);
    629 #endif
    630 
    631 #ifdef HAVE_GETPAGESIZE
    632     if (pagesize == -1)
    633 	pagesize = getpagesize();
    634 #endif
    635 
    636 #ifdef PAGE_SIZE
    637     if (pagesize == -1)
    638 	pagesize = PAGE_SIZE;
    639 #endif
    640 
    641     if (pagesize < sizeof(LispObj) * 16)
    642 	pagesize = sizeof(LispObj) * 16;	/* need a reasonable sane size */
    643 
    644     return pagesize;
    645 }
    646 
    647 void
    648 LispDestroy(const char *fmt, ...)
    649 {
    650     static char Error[] = "*** ";
    651 
    652     if (!lisp__data.destroyed) {
    653 	char string[128];
    654 	va_list ap;
    655 
    656 	va_start(ap, fmt);
    657 	vsnprintf(string, sizeof(string), fmt, ap);
    658 	va_end(ap);
    659 
    660 	if (!lisp__data.ignore_errors) {
    661 	    if (Stderr->column)
    662 		LispFputc(Stderr, '\n');
    663 	    LispFputs(Stderr, Error);
    664 	    LispFputs(Stderr, string);
    665 	    LispFputc(Stderr, '\n');
    666 	    LispFflush(Stderr);
    667 	}
    668 	else
    669 	    lisp__data.error_condition = STRING(string);
    670 
    671 #ifdef DEBUGGER
    672 	if (lisp__data.debugging) {
    673 	    LispDebugger(LispDebugCallWatch, NIL, NIL);
    674 	    LispDebugger(LispDebugCallFatal, NIL, NIL);
    675 	}
    676 #endif
    677 
    678 	lisp__data.destroyed = 1;
    679 	LispBlockUnwind(NULL);
    680 	if (lisp__data.errexit)
    681 	    exit(1);
    682     }
    683 
    684 #ifdef DEBUGGER
    685     if (lisp__data.debugging) {
    686 	/* when stack variables could be changed, this must be also changed! */
    687 	lisp__data.debug_level = -1;
    688 	lisp__data.debug = LispDebugUnspec;
    689     }
    690 #endif
    691 
    692     while (lisp__data.mem.level) {
    693 	--lisp__data.mem.level;
    694 	if (lisp__data.mem.mem[lisp__data.mem.level])
    695 	    free(lisp__data.mem.mem[lisp__data.mem.level]);
    696     }
    697     lisp__data.mem.index = 0;
    698 
    699     /* If the package was changed and an error happened */
    700     if (lisp__data.savepackage != NULL)
    701         PACKAGE = lisp__data.savepackage;
    702     lisp__data.pack = lisp__data.savepack;
    703 
    704     LispTopLevel();
    705 
    706     if (!lisp__data.running) {
    707 	static const char *Fatal = "*** Fatal: nowhere to longjmp.\n";
    708 
    709 	LispFputs(Stderr, Fatal);
    710 	LispFflush(Stderr);
    711 	abort();
    712     }
    713 
    714     siglongjmp(lisp__data.jmp, 1);
    715 }
    716 
    717 void
    718 LispContinuable(const char *fmt, ...)
    719 {
    720     va_list ap;
    721     char string[128];
    722     static const char *Error = "*** Error: ";
    723 
    724     if (Stderr->column)
    725 	LispFputc(Stderr, '\n');
    726     LispFputs(Stderr, Error);
    727     va_start(ap, fmt);
    728     vsnprintf(string, sizeof(string), fmt, ap);
    729     va_end(ap);
    730     LispFputs(Stderr, string);
    731     LispFputc(Stderr, '\n');
    732     LispFputs(Stderr, "Type 'continue' if you want to proceed: ");
    733     LispFflush(Stderr);
    734 
    735     /* NOTE: does not check if stdin is a tty */
    736     if (LispFgets(Stdin, string, sizeof(string)) &&
    737 	strcmp(string, "continue\n") == 0)
    738 	return;
    739 
    740     LispDestroy("aborted on continuable error");
    741 }
    742 
    743 void
    744 LispMessage(const char *fmt, ...)
    745 {
    746     va_list ap;
    747     char string[128];
    748 
    749     if (Stderr->column)
    750 	LispFputc(Stderr, '\n');
    751     va_start(ap, fmt);
    752     vsnprintf(string, sizeof(string), fmt, ap);
    753     va_end(ap);
    754     LispFputs(Stderr, string);
    755     LispFputc(Stderr, '\n');
    756     LispFflush(Stderr);
    757 }
    758 
    759 void
    760 LispWarning(const char *fmt, ...)
    761 {
    762     va_list ap;
    763     char string[128];
    764     static const char *Warning = "*** Warning: ";
    765 
    766     if (Stderr->column)
    767 	LispFputc(Stderr, '\n');
    768     LispFputs(Stderr, Warning);
    769     va_start(ap, fmt);
    770     vsnprintf(string, sizeof(string), fmt, ap);
    771     va_end(ap);
    772     LispFputs(Stderr, string);
    773     LispFputc(Stderr, '\n');
    774     LispFflush(Stderr);
    775 }
    776 
    777 void
    778 LispTopLevel(void)
    779 {
    780     int count;
    781 
    782     COD = NIL;
    783 #ifdef DEBUGGER
    784     if (lisp__data.debugging) {
    785 	DBG = NIL;
    786 	if (lisp__data.debug == LispDebugFinish)
    787 	    lisp__data.debug = LispDebugUnspec;
    788 	lisp__data.debug_level = -1;
    789 	lisp__data.debug_step = 0;
    790     }
    791 #endif
    792     gcpro = 0;
    793     lisp__data.block.block_level = 0;
    794     if (lisp__data.block.block_size) {
    795 	while (lisp__data.block.block_size)
    796 	    free(lisp__data.block.block[--lisp__data.block.block_size]);
    797 	free(lisp__data.block.block);
    798 	lisp__data.block.block = NULL;
    799     }
    800 
    801     lisp__data.destroyed = lisp__data.ignore_errors = 0;
    802 
    803     if (CONSP(lisp__data.input_list)) {
    804 	LispUngetInfo **info, *unget = lisp__data.unget[0];
    805 
    806 	while (CONSP(lisp__data.input_list))
    807 	    lisp__data.input_list = CDR(lisp__data.input_list);
    808 	SINPUT = lisp__data.input_list;
    809 	while (lisp__data.nunget > 1)
    810 	    free(lisp__data.unget[--lisp__data.nunget]);
    811 	if ((info = realloc(lisp__data.unget, sizeof(LispUngetInfo*))) != NULL)
    812 	    lisp__data.unget = info;
    813 	lisp__data.unget[0] = unget;
    814 	lisp__data.iunget = 0;
    815 	lisp__data.eof = 0;
    816     }
    817 
    818     for (count = 0; lisp__data.mem.level;) {
    819 	--lisp__data.mem.level;
    820 	if (lisp__data.mem.mem[lisp__data.mem.level]) {
    821 	    ++count;
    822 #if 0
    823 	    printf("LEAK: %p\n", lisp__data.mem.mem[lisp__data.mem.level]);
    824 #endif
    825 	}
    826     }
    827     lisp__data.mem.index = 0;
    828     if (count)
    829 	LispWarning("%d raw memory pointer(s) left. Probably a leak.", count);
    830 
    831     lisp__data.stack.base = lisp__data.stack.length =
    832 	lisp__data.env.lex = lisp__data.env.length = lisp__data.env.head = 0;
    833     RETURN_COUNT = 0;
    834     lisp__data.protect.length = 0;
    835 
    836     lisp__data.savepackage = PACKAGE;
    837     lisp__data.savepack = lisp__data.pack;
    838 
    839     lisp__disable_int = lisp__interrupted = 0;
    840 }
    841 
    842 void
    843 LispGC(LispObj *car, LispObj *cdr)
    844 {
    845     Lisp__GC(car, cdr);
    846 }
    847 
    848 static void
    849 Lisp__GC(LispObj *car, LispObj *cdr)
    850 {
    851     register LispObj *entry, *last, *freeobj, **pentry, **eentry;
    852     register int nfree;
    853     unsigned i, j;
    854     LispAtom *atom;
    855     struct timeval start, end;
    856 #ifdef DEBUG
    857     long sec, msec;
    858     int count = objseg.nfree;
    859 #else
    860     long msec;
    861 #endif
    862 
    863     if (gcpro)
    864 	return;
    865 
    866     DISABLE_INTERRUPTS();
    867 
    868     nfree = 0;
    869     freeobj = NIL;
    870 
    871     ++lisp__data.gc.count;
    872 
    873 #ifdef DEBUG
    874     gettimeofday(&start, NULL);
    875 #else
    876     if (lisp__data.gc.timebits)
    877 	gettimeofday(&start, NULL);
    878 #endif
    879 
    880     /*  Need to measure timings again to check if it is not better/faster
    881      * to just mark these fields as any other data, as the interface was
    882      * changed to properly handle circular lists in the function body itself.
    883      */
    884     if (lisp__data.gc.immutablebits) {
    885 	for (j = 0; j < objseg.nsegs; j++) {
    886 	    for (entry = objseg.objects[j], last = entry + segsize;
    887 		 entry < last; entry++)
    888 		entry->prot = 0;
    889 	}
    890     }
    891 
    892     /* Protect all packages */
    893     for (entry = PACK; CONSP(entry); entry = CDR(entry)) {
    894 	LispObj *package = CAR(entry);
    895 	LispPackage *pack = package->data.package.package;
    896 
    897 	/* Protect cons cell */
    898 	entry->mark = 1;
    899 
    900 	/* Protect the package cell */
    901 	package->mark = 1;
    902 
    903 	/* Protect package name */
    904 	package->data.package.name->mark = 1;
    905 
    906 	/* Protect package nicknames */
    907 	LispMark(package->data.package.nicknames);
    908 
    909 	/* Protect global symbols */
    910 	for (pentry = pack->glb.pairs, eentry = pentry + pack->glb.length;
    911 	    pentry < eentry; pentry++)
    912 	    LispMark((*pentry)->data.atom->property->value);
    913 
    914 	/* Traverse atom list, protecting properties, and function/structure
    915 	 * definitions if lisp__data.gc.immutablebits set */
    916 	for (atom = (LispAtom *)hash_iter_first(pack->atoms);
    917 	     atom;
    918 	     atom = (LispAtom *)hash_iter_next(pack->atoms)) {
    919 	    if (atom->property != NOPROPERTY) {
    920 		if (atom->a_property)
    921 		    LispMark(atom->property->properties);
    922 		if (lisp__data.gc.immutablebits) {
    923 		    if (atom->a_function || atom->a_compiled)
    924 			LispProt(atom->property->fun.function);
    925 		    if (atom->a_defsetf)
    926 			LispProt(atom->property->setf);
    927 		    if (atom->a_defstruct)
    928 			LispProt(atom->property->structure.definition);
    929 		}
    930 	    }
    931 	}
    932     }
    933 
    934     /* protect environment */
    935     for (pentry = lisp__data.env.values,
    936 	 eentry = pentry + lisp__data.env.length;
    937 	 pentry < eentry; pentry++)
    938 	LispMark(*pentry);
    939 
    940     /* protect multiple return values */
    941     for (pentry = lisp__data.returns.values,
    942 	 eentry = pentry + lisp__data.returns.count;
    943 	 pentry < eentry; pentry++)
    944 	LispMark(*pentry);
    945 
    946     /* protect stack of arguments to builtin functions */
    947     for (pentry = lisp__data.stack.values,
    948 	 eentry = pentry + lisp__data.stack.length;
    949 	 pentry < eentry; pentry++)
    950 	LispMark(*pentry);
    951 
    952     /* protect temporary data used by builtin functions */
    953     for (pentry = lisp__data.protect.objects,
    954 	 eentry = pentry + lisp__data.protect.length;
    955 	 pentry < eentry; pentry++)
    956 	LispMark(*pentry);
    957 
    958     for (i = 0; i < sizeof(x_cons) / sizeof(x_cons[0]); i++)
    959 	x_cons[i].mark = 0;
    960 
    961     LispMark(COD);
    962 #ifdef DEBUGGER
    963     LispMark(DBG);
    964     LispMark(BRK);
    965 #endif
    966     LispMark(PRO);
    967     LispMark(lisp__data.input_list);
    968     LispMark(lisp__data.output_list);
    969     LispMark(car);
    970     LispMark(cdr);
    971 
    972     for (j = 0; j < objseg.nsegs; j++) {
    973 	for (entry = objseg.objects[j], last = entry + segsize;
    974 	     entry < last; entry++) {
    975 	    if (entry->prot)
    976 		continue;
    977 	    else if (entry->mark)
    978 		entry->mark = 0;
    979 	    else {
    980 		switch (XOBJECT_TYPE(entry)) {
    981 		    case LispString_t:
    982 			free(THESTR(entry));
    983 			entry->type = LispCons_t;
    984 			break;
    985 		    case LispStream_t:
    986 			switch (entry->data.stream.type) {
    987 			    case LispStreamString:
    988 				free(SSTREAMP(entry)->string);
    989 				free(SSTREAMP(entry));
    990 				break;
    991 			    case LispStreamFile:
    992 				if (FSTREAMP(entry))
    993 				    LispFclose(FSTREAMP(entry));
    994 				break;
    995 			    case LispStreamPipe:
    996 				/* XXX may need special handling if child hangs */
    997 				if (PSTREAMP(entry)) {
    998 				    if (IPSTREAMP(entry))
    999 					LispFclose(IPSTREAMP(entry));
   1000 				    if (OPSTREAMP(entry))
   1001 					LispFclose(OPSTREAMP(entry));
   1002 				    /* don't bother with error stream, will also
   1003 				     * freed in this GC call, maybe just out
   1004 				     * of order */
   1005 				    if (PIDPSTREAMP(entry) > 0) {
   1006 					kill(PIDPSTREAMP(entry), SIGTERM);
   1007 					waitpid(PIDPSTREAMP(entry), NULL, 0);
   1008 				    }
   1009 				    free(PSTREAMP(entry));
   1010 				}
   1011 				break;
   1012 			    default:
   1013 				break;
   1014 			}
   1015 			entry->type = LispCons_t;
   1016 			break;
   1017 		    case LispBignum_t:
   1018 			mpi_clear(entry->data.mp.integer);
   1019 			free(entry->data.mp.integer);
   1020 			entry->type = LispCons_t;
   1021 			break;
   1022 		    case LispBigratio_t:
   1023 			mpr_clear(entry->data.mp.ratio);
   1024 			free(entry->data.mp.ratio);
   1025 			entry->type = LispCons_t;
   1026 			break;
   1027 		    case LispLambda_t:
   1028 			if (!SYMBOLP(entry->data.lambda.name))
   1029 			    LispFreeArgList((LispArgList*)
   1030 				entry->data.lambda.name->data.opaque.data);
   1031 			entry->type = LispCons_t;
   1032 			break;
   1033 		    case LispRegex_t:
   1034 			refree(entry->data.regex.regex);
   1035 			free(entry->data.regex.regex);
   1036 			entry->type = LispCons_t;
   1037 			break;
   1038 		    case LispBytecode_t:
   1039 			free(entry->data.bytecode.bytecode->code);
   1040 			free(entry->data.bytecode.bytecode);
   1041 			entry->type = LispCons_t;
   1042 			break;
   1043 		    case LispHashTable_t:
   1044 			LispFreeHashTable(entry->data.hash.table);
   1045 			entry->type = LispCons_t;
   1046 			break;
   1047 		    case LispCons_t:
   1048 			break;
   1049 		    default:
   1050 			entry->type = LispCons_t;
   1051 			break;
   1052 		}
   1053 		CDR(entry) = freeobj;
   1054 		freeobj = entry;
   1055 		++nfree;
   1056 	    }
   1057 	}
   1058     }
   1059 
   1060     objseg.nfree = nfree;
   1061     objseg.freeobj = freeobj;
   1062 
   1063     lisp__data.gc.immutablebits = 0;
   1064 
   1065 #ifdef DEBUG
   1066     gettimeofday(&end, NULL);
   1067     sec = end.tv_sec - start.tv_sec;
   1068     msec = end.tv_usec - start.tv_usec;
   1069     if (msec < 0) {
   1070 	--sec;
   1071 	msec += 1000000;
   1072     }
   1073     LispMessage("gc: "
   1074 		"%ld sec, %ld msec, "
   1075 		"%d recovered, %d free, %d protected, %d total",
   1076 		sec, msec,
   1077 		objseg.nfree - count, objseg.nfree,
   1078 		objseg.nobjs - objseg.nfree, objseg.nobjs);
   1079 #else
   1080     if (lisp__data.gc.timebits) {
   1081 	gettimeofday(&end, NULL);
   1082 	if ((msec = end.tv_usec - start.tv_usec) < 0)
   1083 	    msec += 1000000;
   1084 	lisp__data.gc.gctime += msec;
   1085     }
   1086 #endif
   1087 
   1088     ENABLE_INTERRUPTS();
   1089 }
   1090 
   1091 static INLINE void
   1092 LispCheckMemLevel(void)
   1093 {
   1094     int i;
   1095 
   1096     /* Check for a free slot before the end. */
   1097     for (i = lisp__data.mem.index; i < lisp__data.mem.level; i++)
   1098 	if (lisp__data.mem.mem[i] == NULL) {
   1099 	    lisp__data.mem.index = i;
   1100 	    return;
   1101 	}
   1102 
   1103     /* Check for a free slot in the beginning */
   1104     for (i = 0; i < lisp__data.mem.index; i++)
   1105 	if (lisp__data.mem.mem[i] == NULL) {
   1106 	    lisp__data.mem.index = i;
   1107 	    return;
   1108 	}
   1109 
   1110     lisp__data.mem.index = lisp__data.mem.level;
   1111     ++lisp__data.mem.level;
   1112     if (lisp__data.mem.index < lisp__data.mem.space)
   1113 	/* There is free space to store pointer. */
   1114 	return;
   1115     else {
   1116 	void **ptr = (void**)realloc(lisp__data.mem.mem,
   1117 				     (lisp__data.mem.space + 16) *
   1118 				     sizeof(void*));
   1119 
   1120 	if (ptr == NULL)
   1121 	    LispDestroy("out of memory");
   1122 	lisp__data.mem.mem = ptr;
   1123 	lisp__data.mem.space += 16;
   1124     }
   1125 }
   1126 
   1127 void
   1128 LispMused(void *pointer)
   1129 {
   1130     int i;
   1131 
   1132     DISABLE_INTERRUPTS();
   1133     for (i = lisp__data.mem.index; i >= 0; i--)
   1134 	if (lisp__data.mem.mem[i] == pointer) {
   1135 	    lisp__data.mem.mem[i] = NULL;
   1136 	    lisp__data.mem.index = i;
   1137 	    goto mused_done;
   1138 	}
   1139 
   1140     for (i = lisp__data.mem.level - 1; i > lisp__data.mem.index; i--)
   1141 	if (lisp__data.mem.mem[i] == pointer) {
   1142 	    lisp__data.mem.mem[i] = NULL;
   1143 	    lisp__data.mem.index = i;
   1144 	    break;
   1145 	}
   1146 
   1147 mused_done:
   1148     ENABLE_INTERRUPTS();
   1149 }
   1150 
   1151 void *
   1152 LispMalloc(size_t size)
   1153 {
   1154     void *pointer;
   1155 
   1156     DISABLE_INTERRUPTS();
   1157     LispCheckMemLevel();
   1158     if ((pointer = malloc(size)) == NULL)
   1159 	LispDestroy("out of memory, couldn't allocate %lu bytes",
   1160 		    (unsigned long)size);
   1161 
   1162     lisp__data.mem.mem[lisp__data.mem.index] = pointer;
   1163     ENABLE_INTERRUPTS();
   1164 
   1165     return (pointer);
   1166 }
   1167 
   1168 void *
   1169 LispCalloc(size_t nmemb, size_t size)
   1170 {
   1171     void *pointer;
   1172 
   1173     DISABLE_INTERRUPTS();
   1174     LispCheckMemLevel();
   1175     if ((pointer = calloc(nmemb, size)) == NULL)
   1176 	LispDestroy("out of memory, couldn't allocate %lu bytes",
   1177 		    (unsigned long)size);
   1178 
   1179     lisp__data.mem.mem[lisp__data.mem.index] = pointer;
   1180     ENABLE_INTERRUPTS();
   1181 
   1182     return (pointer);
   1183 }
   1184 
   1185 void *
   1186 LispRealloc(void *pointer, size_t size)
   1187 {
   1188     void *ptr;
   1189     int i;
   1190 
   1191     DISABLE_INTERRUPTS();
   1192     if (pointer != NULL) {
   1193 	for (i = lisp__data.mem.index; i >= 0; i--)
   1194 	    if (lisp__data.mem.mem[i] == pointer)
   1195 		goto index_found;
   1196 
   1197 	for (i = lisp__data.mem.index + 1; i < lisp__data.mem.level; i++)
   1198 	    if (lisp__data.mem.mem[i] == pointer)
   1199 		goto index_found;
   1200 
   1201     }
   1202     LispCheckMemLevel();
   1203     i = lisp__data.mem.index;
   1204 
   1205 index_found:
   1206     if ((ptr = realloc(pointer, size)) == NULL)
   1207 	LispDestroy("out of memory, couldn't realloc");
   1208 
   1209     lisp__data.mem.mem[i] = ptr;
   1210     ENABLE_INTERRUPTS();
   1211 
   1212     return (ptr);
   1213 }
   1214 
   1215 char *
   1216 LispStrdup(const char *str)
   1217 {
   1218     char *ptr = LispMalloc(strlen(str) + 1);
   1219 
   1220     strcpy(ptr, str);
   1221 
   1222     return (ptr);
   1223 }
   1224 
   1225 void
   1226 LispFree(void *pointer)
   1227 {
   1228     int i;
   1229 
   1230     DISABLE_INTERRUPTS();
   1231     for (i = lisp__data.mem.index; i >= 0; i--)
   1232 	if (lisp__data.mem.mem[i] == pointer) {
   1233 	    lisp__data.mem.mem[i] = NULL;
   1234 	    lisp__data.mem.index = i;
   1235 	    goto free_done;
   1236 	}
   1237 
   1238     for (i = lisp__data.mem.level - 1; i > lisp__data.mem.index; i--)
   1239 	if (lisp__data.mem.mem[i] == pointer) {
   1240 	    lisp__data.mem.mem[i] = NULL;
   1241 	    lisp__data.mem.index = i;
   1242 	    break;
   1243 	}
   1244 
   1245 free_done:
   1246     free(pointer);
   1247     ENABLE_INTERRUPTS();
   1248 }
   1249 
   1250 LispObj *
   1251 LispSetVariable(LispObj *var, LispObj *val, const char *fname, int eval)
   1252 {
   1253     if (!SYMBOLP(var))
   1254 	LispDestroy("%s: %s is not a symbol", fname, STROBJ(var));
   1255     if (eval)
   1256 	val = EVAL(val);
   1257 
   1258     return (LispSetVar(var, val));
   1259 }
   1260 
   1261 int
   1262 LispRegisterOpaqueType(const char *desc)
   1263 {
   1264     int length;
   1265     LispOpaque *opaque;
   1266 
   1267     length = strlen(desc);
   1268     opaque = (LispOpaque *)hash_check(lisp__data.opqs, desc, length);
   1269 
   1270     if (opaque == NULL) {
   1271 	opaque = (LispOpaque*)LispMalloc(sizeof(LispOpaque));
   1272 	opaque->desc = (hash_key*)LispCalloc(1, sizeof(hash_key));
   1273 	opaque->desc->value = LispStrdup(desc);
   1274 	opaque->desc->length = length;
   1275 	hash_put(lisp__data.opqs, (hash_entry *)opaque);
   1276 	LispMused(opaque->desc->value);
   1277 	LispMused(opaque->desc);
   1278 	LispMused(opaque);
   1279 	opaque->type = ++lisp__data.opaque;
   1280     }
   1281 
   1282     return (opaque->type);
   1283 }
   1284 
   1285 char *
   1286 LispIntToOpaqueType(int type)
   1287 {
   1288     LispOpaque *opaque;
   1289 
   1290     if (type) {
   1291 	for (opaque = (LispOpaque *)hash_iter_first(lisp__data.opqs);
   1292 	     opaque;
   1293 	     opaque = (LispOpaque *)hash_iter_next(lisp__data.opqs)) {
   1294 	    if (opaque->type == type)
   1295 		return (opaque->desc->value);
   1296 	}
   1297 	LispDestroy("Opaque type %d not registered", type);
   1298     }
   1299 
   1300     return (Snil->value);
   1301 }
   1302 
   1303 hash_key *
   1304 LispGetAtomKey(const char *string, int perm)
   1305 {
   1306     int length;
   1307     hash_entry *entry;
   1308 
   1309     length = strlen(string);
   1310     entry = hash_check(lisp__data.strings, string, length);
   1311     if (entry == NULL) {
   1312 	entry = LispCalloc(1, sizeof(hash_entry));
   1313 	entry->key = LispCalloc(1, sizeof(hash_key));
   1314 	if (perm)
   1315 	    entry->key->value = (char *) string;
   1316 	else
   1317 	    entry->key->value = LispStrdup(string);
   1318 	entry->key->length = length;
   1319 
   1320 	hash_put(lisp__data.strings, entry);
   1321 	if (!perm)
   1322 	    LispMused(entry->key->value);
   1323 	LispMused(entry->key);
   1324 	LispMused(entry);
   1325     }
   1326 
   1327     return (entry->key);
   1328 }
   1329 
   1330 LispAtom *
   1331 LispDoGetAtom(const char *str, int perm)
   1332 {
   1333     int length;
   1334     LispAtom *atom;
   1335 
   1336     length = strlen(str);
   1337     atom = (LispAtom *)hash_check(lisp__data.pack->atoms, str, length);
   1338 
   1339     if (atom == NULL) {
   1340 	atom = (LispAtom*)LispCalloc(1, sizeof(LispAtom));
   1341 	atom->key = LispGetAtomKey(str, perm);
   1342 	hash_put(lisp__data.pack->atoms, (hash_entry *)atom);
   1343 	atom->property = NOPROPERTY;
   1344 	LispMused(atom);
   1345     }
   1346 
   1347     return (atom);
   1348 }
   1349 
   1350 static void
   1351 LispAllocAtomProperty(LispAtom *atom)
   1352 {
   1353     LispProperty *property;
   1354 
   1355     if (atom->property != NOPROPERTY)
   1356 	LispDestroy("internal error at ALLOC-ATOM-PROPERTY");
   1357 
   1358     property = LispCalloc(1, sizeof(LispProperty));
   1359     LispMused(property);
   1360     atom->property = property;
   1361     property->package = lisp__data.pack;
   1362     if (atom->package == NULL)
   1363 	atom->package = PACKAGE;
   1364 
   1365     LispIncrementAtomReference(atom);
   1366 }
   1367 
   1368 static void
   1369 LispIncrementAtomReference(LispAtom *atom)
   1370 {
   1371     if (atom->property != NOPROPERTY)
   1372 	/* if atom->property is NOPROPERTY, this is an unbound symbol */
   1373 	++atom->property->refcount;
   1374 }
   1375 
   1376 /* Assumes atom property is not NOPROPERTY */
   1377 static void
   1378 LispDecrementAtomReference(LispAtom *atom)
   1379 {
   1380     if (atom->property == NOPROPERTY)
   1381 	/* if atom->property is NOPROPERTY, this is an unbound symbol */
   1382 	return;
   1383 
   1384     if (atom->property->refcount <= 0)
   1385 	LispDestroy("internal error at DECREMENT-ATOM-REFERENCE");
   1386 
   1387     --atom->property->refcount;
   1388 
   1389     if (atom->property->refcount == 0) {
   1390 	LispRemAtomAllProperties(atom);
   1391 	free(atom->property);
   1392 	atom->property = NOPROPERTY;
   1393     }
   1394 }
   1395 
   1396 static void
   1397 LispRemAtomAllProperties(LispAtom *atom)
   1398 {
   1399     if (atom->property != NOPROPERTY) {
   1400 	if (atom->a_object)
   1401 	    LispRemAtomObjectProperty(atom);
   1402 	if (atom->a_function) {
   1403 	    lisp__data.gc.immutablebits = 1;
   1404 	    LispRemAtomFunctionProperty(atom);
   1405 	}
   1406 	else if (atom->a_compiled) {
   1407 	    lisp__data.gc.immutablebits = 1;
   1408 	    LispRemAtomCompiledProperty(atom);
   1409 	}
   1410 	else if (atom->a_builtin) {
   1411 	    lisp__data.gc.immutablebits = 1;
   1412 	    LispRemAtomBuiltinProperty(atom);
   1413 	}
   1414 	if (atom->a_defsetf) {
   1415 	    lisp__data.gc.immutablebits = 1;
   1416 	    LispRemAtomSetfProperty(atom);
   1417 	}
   1418 	if (atom->a_defstruct) {
   1419 	    lisp__data.gc.immutablebits = 1;
   1420 	    LispRemAtomStructProperty(atom);
   1421 	}
   1422     }
   1423 }
   1424 
   1425 void
   1426 LispSetAtomObjectProperty(LispAtom *atom, LispObj *object)
   1427 {
   1428     if (atom->property == NOPROPERTY)
   1429 	LispAllocAtomProperty(atom);
   1430     else if (atom->watch) {
   1431 	if (atom->object == lisp__data.package) {
   1432 	    if (!PACKAGEP(object))
   1433 		LispDestroy("Symbol %s must be a package, not %s",
   1434 			    ATOMID(lisp__data.package)->value, STROBJ(object));
   1435 	    lisp__data.pack = object->data.package.package;
   1436 	}
   1437     }
   1438 
   1439     atom->a_object = 1;
   1440     SETVALUE(atom, object);
   1441 }
   1442 
   1443 static void
   1444 LispRemAtomObjectProperty(LispAtom *atom)
   1445 {
   1446     if (atom->a_object) {
   1447 	atom->a_object = 0;
   1448 	atom->property->value = NULL;
   1449     }
   1450 }
   1451 
   1452 void
   1453 LispSetAtomCompiledProperty(LispAtom *atom, LispObj *bytecode)
   1454 {
   1455     if (atom->property == NOPROPERTY)
   1456 	LispAllocAtomProperty(atom);
   1457 
   1458     lisp__data.gc.immutablebits = 1;
   1459     if (atom->a_builtin) {
   1460 	atom->a_builtin = 0;
   1461 	LispFreeArgList(atom->property->alist);
   1462     }
   1463     else
   1464 	atom->a_function = 0;
   1465     atom->a_compiled = 1;
   1466     atom->property->fun.function = bytecode;
   1467 }
   1468 
   1469 void
   1470 LispRemAtomCompiledProperty(LispAtom *atom)
   1471 {
   1472     if (atom->a_compiled) {
   1473 	lisp__data.gc.immutablebits = 1;
   1474 	atom->property->fun.function = NULL;
   1475 	atom->a_compiled = 0;
   1476 	LispFreeArgList(atom->property->alist);
   1477 	atom->property->alist = NULL;
   1478     }
   1479 }
   1480 
   1481 void
   1482 LispSetAtomFunctionProperty(LispAtom *atom, LispObj *function,
   1483 			    LispArgList *alist)
   1484 {
   1485     if (atom->property == NOPROPERTY)
   1486 	LispAllocAtomProperty(atom);
   1487 
   1488     lisp__data.gc.immutablebits = 1;
   1489     if (atom->a_function == 0 && atom->a_builtin == 0 && atom->a_compiled == 0)
   1490 	atom->a_function = 1;
   1491     else {
   1492 	if (atom->a_builtin) {
   1493 	    atom->a_builtin = 0;
   1494 	    LispFreeArgList(atom->property->alist);
   1495 	}
   1496 	else
   1497 	    atom->a_compiled = 0;
   1498 	atom->a_function = 1;
   1499     }
   1500 
   1501     atom->property->fun.function = function;
   1502     atom->property->alist = alist;
   1503 }
   1504 
   1505 void
   1506 LispRemAtomFunctionProperty(LispAtom *atom)
   1507 {
   1508     if (atom->a_function) {
   1509 	lisp__data.gc.immutablebits = 1;
   1510 	atom->property->fun.function = NULL;
   1511 	atom->a_function = 0;
   1512 	LispFreeArgList(atom->property->alist);
   1513 	atom->property->alist = NULL;
   1514     }
   1515 }
   1516 
   1517 void
   1518 LispSetAtomBuiltinProperty(LispAtom *atom, LispBuiltin *builtin,
   1519 			   LispArgList *alist)
   1520 {
   1521     if (atom->property == NOPROPERTY)
   1522 	LispAllocAtomProperty(atom);
   1523 
   1524     lisp__data.gc.immutablebits = 1;
   1525     if (atom->a_builtin == 0 && atom->a_function == 0)
   1526 	atom->a_builtin = 1;
   1527     else {
   1528 	if (atom->a_function) {
   1529 	    atom->a_function = 0;
   1530 	    LispFreeArgList(atom->property->alist);
   1531 	}
   1532     }
   1533 
   1534     atom->property->fun.builtin = builtin;
   1535     atom->property->alist = alist;
   1536 }
   1537 
   1538 void
   1539 LispRemAtomBuiltinProperty(LispAtom *atom)
   1540 {
   1541     if (atom->a_builtin) {
   1542 	lisp__data.gc.immutablebits = 1;
   1543 	atom->property->fun.function = NULL;
   1544 	atom->a_builtin = 0;
   1545 	LispFreeArgList(atom->property->alist);
   1546 	atom->property->alist = NULL;
   1547     }
   1548 }
   1549 
   1550 void
   1551 LispSetAtomSetfProperty(LispAtom *atom, LispObj *setf, LispArgList *alist)
   1552 {
   1553     if (atom->property == NOPROPERTY)
   1554 	LispAllocAtomProperty(atom);
   1555 
   1556     lisp__data.gc.immutablebits = 1;
   1557     if (atom->a_defsetf)
   1558 	LispFreeArgList(atom->property->salist);
   1559 
   1560     atom->a_defsetf = 1;
   1561     atom->property->setf = setf;
   1562     atom->property->salist = alist;
   1563 }
   1564 
   1565 void
   1566 LispRemAtomSetfProperty(LispAtom *atom)
   1567 {
   1568     if (atom->a_defsetf) {
   1569 	lisp__data.gc.immutablebits = 1;
   1570 	atom->property->setf = NULL;
   1571 	atom->a_defsetf = 0;
   1572 	LispFreeArgList(atom->property->salist);
   1573 	atom->property->salist = NULL;
   1574     }
   1575 }
   1576 
   1577 void
   1578 LispSetAtomStructProperty(LispAtom *atom, LispObj *def, int fun)
   1579 {
   1580     if (fun > 0xff)
   1581 	/* Not suported by the bytecode compiler... */
   1582 	LispDestroy("SET-ATOM-STRUCT-PROPERTY: "
   1583 		    "more than 256 fields not supported");
   1584 
   1585     if (atom->property == NOPROPERTY)
   1586 	LispAllocAtomProperty(atom);
   1587 
   1588     lisp__data.gc.immutablebits = 1;
   1589     atom->a_defstruct = 1;
   1590     atom->property->structure.definition = def;
   1591     atom->property->structure.function = fun;
   1592 }
   1593 
   1594 void
   1595 LispRemAtomStructProperty(LispAtom *atom)
   1596 {
   1597     if (atom->a_defstruct) {
   1598 	lisp__data.gc.immutablebits = 1;
   1599 	atom->property->structure.definition = NULL;
   1600 	atom->a_defstruct = 0;
   1601     }
   1602 }
   1603 
   1604 LispAtom *
   1605 LispGetAtom(const char *str)
   1606 {
   1607     return (LispDoGetAtom(str, 0));
   1608 }
   1609 
   1610 LispAtom *
   1611 LispGetPermAtom(const char *str)
   1612 {
   1613     return (LispDoGetAtom(str, 1));
   1614 }
   1615 
   1616 #define GET_PROPERTY	0
   1617 #define ADD_PROPERTY	1
   1618 #define REM_PROPERTY	2
   1619 static LispObj *
   1620 LispAtomPropertyFunction(LispAtom *atom, LispObj *key, int function)
   1621 {
   1622     LispObj *list = NIL, *result = NIL;
   1623 
   1624     if (function == ADD_PROPERTY) {
   1625 	if (atom->property == NOPROPERTY)
   1626 	    LispAllocAtomProperty(atom);
   1627 	if (atom->property->properties == NULL) {
   1628 	    atom->a_property = 1;
   1629 	    atom->property->properties = NIL;
   1630 	}
   1631     }
   1632 
   1633     if (atom->a_property) {
   1634 	LispObj *base;
   1635 
   1636 	for (base = list = atom->property->properties;
   1637 	     CONSP(list);
   1638 	     list = CDR(list)) {
   1639 	    if (key == CAR(list)) {
   1640 		result = CDR(list);
   1641 		break;
   1642 	    }
   1643 	    base = list;
   1644 	    list = CDR(list);
   1645 	    if (!CONSP(list))
   1646 		LispDestroy("%s: %s has an odd property list length",
   1647 			    STROBJ(atom->object),
   1648 			    function == REM_PROPERTY ? "REMPROP" : "GET");
   1649 	}
   1650 	if (CONSP(list) && function == REM_PROPERTY) {
   1651 	    if (!CONSP(CDR(list)))
   1652 		LispDestroy("REMPROP: %s has an odd property list length",
   1653 			    STROBJ(atom->object));
   1654 	    if (base == list)
   1655 		atom->property->properties = CDDR(list);
   1656 	    else
   1657 		RPLACD(CDR(base), CDDR(list));
   1658 	}
   1659     }
   1660 
   1661     if (!CONSP(list)) {
   1662 	if (function == ADD_PROPERTY) {
   1663 	    atom->property->properties =
   1664 		CONS(key, CONS(NIL, atom->property->properties));
   1665 	    result = CDR(atom->property->properties);
   1666 	}
   1667     }
   1668     else if (function == REM_PROPERTY)
   1669 	result = T;
   1670 
   1671     return (result);
   1672 }
   1673 
   1674 LispObj *
   1675 LispGetAtomProperty(LispAtom *atom, LispObj *key)
   1676 {
   1677     return (LispAtomPropertyFunction(atom, key, GET_PROPERTY));
   1678 }
   1679 
   1680 LispObj *
   1681 LispPutAtomProperty(LispAtom *atom, LispObj *key, LispObj *value)
   1682 {
   1683     LispObj *result = LispAtomPropertyFunction(atom, key, ADD_PROPERTY);
   1684 
   1685     RPLACA(result, value);
   1686 
   1687     return (result);
   1688 }
   1689 
   1690 LispObj *
   1691 LispRemAtomProperty(LispAtom *atom, LispObj *key)
   1692 {
   1693     return (LispAtomPropertyFunction(atom, key, REM_PROPERTY));
   1694 }
   1695 
   1696 LispObj *
   1697 LispReplaceAtomPropertyList(LispAtom *atom, LispObj *list)
   1698 {
   1699     if (atom->property == NOPROPERTY)
   1700 	LispAllocAtomProperty(atom);
   1701     if (atom->property->properties == NULL)
   1702 	atom->a_property = 1;
   1703     atom->property->properties = list;
   1704 
   1705     return (list);
   1706 }
   1707 #undef GET_PROPERTY
   1708 #undef ADD_PROPERTY
   1709 #undef REM_PROPERTY
   1710 
   1711 
   1712 /* Used to make sure that when defining a function like:
   1713  *	(defun my-function (... &key key1 key2 key3 ...)
   1714  * key1, key2, and key3 will be in the keyword package
   1715  */
   1716 static LispObj *
   1717 LispCheckKeyword(LispObj *keyword)
   1718 {
   1719     if (KEYWORDP(keyword))
   1720 	return (keyword);
   1721 
   1722     return (KEYWORD(ATOMID(keyword)->value));
   1723 }
   1724 
   1725 void
   1726 LispUseArgList(LispArgList *alist)
   1727 {
   1728     if (alist->normals.num_symbols)
   1729 	LispMused(alist->normals.symbols);
   1730     if (alist->optionals.num_symbols) {
   1731 	LispMused(alist->optionals.symbols);
   1732 	LispMused(alist->optionals.defaults);
   1733 	LispMused(alist->optionals.sforms);
   1734     }
   1735     if (alist->keys.num_symbols) {
   1736 	LispMused(alist->keys.symbols);
   1737 	LispMused(alist->keys.defaults);
   1738 	LispMused(alist->keys.sforms);
   1739 	LispMused(alist->keys.keys);
   1740     }
   1741     if (alist->auxs.num_symbols) {
   1742 	LispMused(alist->auxs.symbols);
   1743 	LispMused(alist->auxs.initials);
   1744     }
   1745     LispMused(alist);
   1746 }
   1747 
   1748 void
   1749 LispFreeArgList(LispArgList *alist)
   1750 {
   1751     if (alist->normals.num_symbols)
   1752 	LispFree(alist->normals.symbols);
   1753     if (alist->optionals.num_symbols) {
   1754 	LispFree(alist->optionals.symbols);
   1755 	LispFree(alist->optionals.defaults);
   1756 	LispFree(alist->optionals.sforms);
   1757     }
   1758     if (alist->keys.num_symbols) {
   1759 	LispFree(alist->keys.symbols);
   1760 	LispFree(alist->keys.defaults);
   1761 	LispFree(alist->keys.sforms);
   1762 	LispFree(alist->keys.keys);
   1763     }
   1764     if (alist->auxs.num_symbols) {
   1765 	LispFree(alist->auxs.symbols);
   1766 	LispFree(alist->auxs.initials);
   1767     }
   1768     LispFree(alist);
   1769 }
   1770 
   1771 static LispObj *
   1772 LispCheckNeedProtect(LispObj *object)
   1773 {
   1774     if (object) {
   1775 	switch (OBJECT_TYPE(object)) {
   1776 	    case LispNil_t:
   1777 	    case LispAtom_t:
   1778 	    case LispFunction_t:
   1779 	    case LispFixnum_t:
   1780 	    case LispSChar_t:
   1781 		return (NULL);
   1782 	    default:
   1783 		return (object);
   1784 	}
   1785     }
   1786     return (NULL);
   1787 }
   1788 
   1789 LispObj *
   1790 LispListProtectedArguments(LispArgList *alist)
   1791 {
   1792     int i;
   1793     GC_ENTER();
   1794     LispObj *arguments, *cons, *obj, *prev;
   1795 
   1796     arguments = cons = prev = NIL;
   1797     for (i = 0; i < alist->optionals.num_symbols; i++) {
   1798 	if ((obj = LispCheckNeedProtect(alist->optionals.defaults[i])) != NULL) {
   1799 	    if (arguments == NIL) {
   1800 		arguments = cons = prev = CONS(obj, NIL);
   1801 		GC_PROTECT(arguments);
   1802 	    }
   1803 	    else {
   1804 		RPLACD(cons, CONS(obj, NIL));
   1805 		prev = cons;
   1806 		cons = CDR(cons);
   1807 	    }
   1808 	}
   1809     }
   1810     for (i = 0; i < alist->keys.num_symbols; i++) {
   1811 	if ((obj = LispCheckNeedProtect(alist->keys.defaults[i])) != NULL) {
   1812 	    if (arguments == NIL) {
   1813 		arguments = cons = prev = CONS(obj, NIL);
   1814 		GC_PROTECT(arguments);
   1815 	    }
   1816 	    else {
   1817 		RPLACD(cons, CONS(obj, NIL));
   1818 		prev = cons;
   1819 		cons = CDR(cons);
   1820 	    }
   1821 	}
   1822     }
   1823     for (i = 0; i < alist->auxs.num_symbols; i++) {
   1824 	if ((obj = LispCheckNeedProtect(alist->auxs.initials[i])) != NULL) {
   1825 	    if (arguments == NIL) {
   1826 		arguments = cons = prev = CONS(obj, NIL);
   1827 		GC_PROTECT(arguments);
   1828 	    }
   1829 	    else {
   1830 		RPLACD(cons, CONS(obj, NIL));
   1831 		prev = cons;
   1832 		cons = CDR(cons);
   1833 	    }
   1834 	}
   1835     }
   1836     GC_LEAVE();
   1837 
   1838     /* Don't add a NIL cell at the end, to save some space */
   1839     if (arguments != NIL) {
   1840 	if (arguments == cons)
   1841 	    arguments = CAR(cons);
   1842 	else
   1843 	    CDR(prev) = CAR(cons);
   1844     }
   1845 
   1846     return (arguments);
   1847 }
   1848 
   1849 LispArgList *
   1850 LispCheckArguments(LispFunType type, LispObj *list, const char *name, int builtin)
   1851 {
   1852     static const char *types[4] = {"LAMBDA-LIST", "FUNCTION", "MACRO", "SETF-METHOD"};
   1853     static const char *fnames[4] = {"LAMBDA", "DEFUN", "DEFMACRO", "DEFSETF"};
   1854 #define IKEY		0
   1855 #define IOPTIONAL	1
   1856 #define IREST		2
   1857 #define IAUX		3
   1858     static const char *keys[4] = {"&KEY", "&OPTIONAL", "&REST", "&AUX"};
   1859     int rest, optional, key, aux, count;
   1860     LispArgList *alist;
   1861     LispObj *spec, *sform, *defval, *default_value;
   1862     char description[8], *desc;
   1863 
   1864 /* If LispRealloc fails, the previous memory will be released
   1865  * in LispTopLevel, unless LispMused was called on the pointer */
   1866 #define REALLOC_OBJECTS(pointer, count)		\
   1867     pointer = LispRealloc(pointer, (count) * sizeof(LispObj*))
   1868 
   1869     alist = LispCalloc(1, sizeof(LispArgList));
   1870     if (!CONSP(list)) {
   1871 	if (list != NIL)
   1872 	    LispDestroy("%s %s: %s cannot be a %s argument list",
   1873 			fnames[type], name, STROBJ(list), types[type]);
   1874 	alist->description = GETATOMID("")->value;
   1875 
   1876 	return (alist);
   1877     }
   1878 
   1879     default_value = builtin ? UNSPEC : NIL;
   1880 
   1881     description[0] = '\0';
   1882     desc = description;
   1883     rest = optional = key = aux = 0;
   1884     for (; CONSP(list); list = CDR(list)) {
   1885 	spec = CAR(list);
   1886 
   1887 	if (CONSP(spec)) {
   1888 	    if (builtin)
   1889 		LispDestroy("builtin function argument cannot have default value");
   1890 	    if (aux) {
   1891 		if (!SYMBOLP(CAR(spec)) ||
   1892 		    (CDR(spec) != NIL && CDDR(spec) != NIL))
   1893 		    LispDestroy("%s %s: bad &AUX argument %s",
   1894 				fnames[type], name, STROBJ(spec));
   1895 		defval = CDR(spec) != NIL ? CADR(spec) : NIL;
   1896 		count = alist->auxs.num_symbols;
   1897 		REALLOC_OBJECTS(alist->auxs.symbols, count + 1);
   1898 		REALLOC_OBJECTS(alist->auxs.initials, count + 1);
   1899 		alist->auxs.symbols[count] = CAR(spec);
   1900 		alist->auxs.initials[count] = defval;
   1901 		++alist->auxs.num_symbols;
   1902 		if (count == 0)
   1903 		    *desc++ = 'a';
   1904 		++alist->num_arguments;
   1905 	    }
   1906 	    else if (rest)
   1907 		LispDestroy("%s %s: syntax error parsing %s",
   1908 			    fnames[type], name, keys[IREST]);
   1909 	    else if (key) {
   1910 		LispObj *akey = CAR(spec);
   1911 
   1912 		defval = default_value;
   1913 		sform = NULL;
   1914 		if (CONSP(akey)) {
   1915 		    /* check for special case, as in:
   1916 		     *	(defun a (&key ((key name) 'default-value)) name)
   1917 		     *	(a 'key 'test)	=> TEST
   1918 		     *	(a)		=> DEFAULT-VALUE
   1919 		     */
   1920 		    if (!SYMBOLP(CAR(akey)) || !CONSP(CDR(akey)) ||
   1921 			!SYMBOLP(CADR(akey)) || CDDR(akey) != NIL ||
   1922 			(CDR(spec) != NIL && CDDR(spec) != NIL))
   1923 			LispDestroy("%s %s: bad special &KEY %s",
   1924 				    fnames[type], name, STROBJ(spec));
   1925 		    if (CDR(spec) != NIL)
   1926 			defval = CADR(spec);
   1927 		    spec = CADR(akey);
   1928 		    akey = CAR(akey);
   1929 		}
   1930 		else {
   1931 		    akey = NULL;
   1932 
   1933 		    if (!SYMBOLP(CAR(spec)))
   1934 			LispDestroy("%s %s: %s cannot be a %s argument name",
   1935 				    fnames[type], name,
   1936 				    STROBJ(CAR(spec)), types[type]);
   1937 		    /* check if default value provided, and optionally a `svar' */
   1938 		    else if (CDR(spec) != NIL && (!CONSP(CDR(spec)) ||
   1939 			      (CDDR(spec) != NIL &&
   1940 			       (!SYMBOLP(CAR(CDDR(spec))) ||
   1941 				CDR(CDDR(spec)) != NIL))))
   1942 			LispDestroy("%s %s: bad argument specification %s",
   1943 				    fnames[type], name, STROBJ(spec));
   1944 		    if (CONSP(CDR(spec))) {
   1945 			defval = CADR(spec);
   1946 			if (CONSP(CDDR(spec)))
   1947 			    sform = CAR(CDDR(spec));
   1948 		    }
   1949 		    /* Add to keyword package, and set the keyword in the
   1950 		     * argument list, so that a function argument keyword
   1951 		     * will reference the same object, and make comparison
   1952 		     * simpler. */
   1953 		    spec = LispCheckKeyword(CAR(spec));
   1954 		}
   1955 
   1956 		count = alist->keys.num_symbols;
   1957 		REALLOC_OBJECTS(alist->keys.keys, count + 1);
   1958 		REALLOC_OBJECTS(alist->keys.defaults, count + 1);
   1959 		REALLOC_OBJECTS(alist->keys.sforms, count + 1);
   1960 		REALLOC_OBJECTS(alist->keys.symbols, count + 1);
   1961 		alist->keys.symbols[count] = spec;
   1962 		alist->keys.defaults[count] = defval;
   1963 		alist->keys.sforms[count] = sform;
   1964 		alist->keys.keys[count] = akey;
   1965 		++alist->keys.num_symbols;
   1966 		if (count == 0)
   1967 		    *desc++ = 'k';
   1968 		alist->num_arguments += 1 + (sform != NULL);
   1969 	    }
   1970 	    else if (optional) {
   1971 		defval = default_value;
   1972 		sform = NULL;
   1973 
   1974 		if (!SYMBOLP(CAR(spec)))
   1975 		    LispDestroy("%s %s: %s cannot be a %s argument name",
   1976 				fnames[type], name,
   1977 				STROBJ(CAR(spec)), types[type]);
   1978 		/* check if default value provided, and optionally a `svar' */
   1979 		else if (CDR(spec) != NIL && (!CONSP(CDR(spec)) ||
   1980 			  (CDDR(spec) != NIL &&
   1981 			   (!SYMBOLP(CAR(CDDR(spec))) ||
   1982 			    CDR(CDDR(spec)) != NIL))))
   1983 		    LispDestroy("%s %s: bad argument specification %s",
   1984 				fnames[type], name, STROBJ(spec));
   1985 		if (CONSP(CDR(spec))) {
   1986 		    defval = CADR(spec);
   1987 		    if (CONSP(CDDR(spec)))
   1988 			sform = CAR(CDDR(spec));
   1989 		}
   1990 		spec = CAR(spec);
   1991 
   1992 		count = alist->optionals.num_symbols;
   1993 		REALLOC_OBJECTS(alist->optionals.symbols, count + 1);
   1994 		REALLOC_OBJECTS(alist->optionals.defaults, count + 1);
   1995 		REALLOC_OBJECTS(alist->optionals.sforms, count + 1);
   1996 		alist->optionals.symbols[count] = spec;
   1997 		alist->optionals.defaults[count] = defval;
   1998 		alist->optionals.sforms[count] = sform;
   1999 		++alist->optionals.num_symbols;
   2000 		if (count == 0)
   2001 		    *desc++ = 'o';
   2002 		alist->num_arguments += 1 + (sform != NULL);
   2003 	    }
   2004 
   2005 	    /* Normal arguments cannot have default value */
   2006 	    else
   2007 		LispDestroy("%s %s: syntax error parsing %s",
   2008 			    fnames[type], name, STROBJ(spec));
   2009 	}
   2010 
   2011 	/* spec must be an atom, excluding keywords */
   2012 	else if (!SYMBOLP(spec) || KEYWORDP(spec))
   2013 	    LispDestroy("%s %s: %s cannot be a %s argument",
   2014 			fnames[type], name, STROBJ(spec), types[type]);
   2015 	else {
   2016 	    Atom_id atom = ATOMID(spec);
   2017 
   2018 	    if (atom->value[0] == '&') {
   2019 		if (atom == Srest) {
   2020 		    if (rest || aux || CDR(list) == NIL || !SYMBOLP(CADR(list))
   2021 			/* only &aux allowed after &rest */
   2022 			|| (CDDR(list) != NIL && !SYMBOLP(CAR(CDDR(list))) &&
   2023 			    ATOMID(CAR(CDDR(list))) != Saux))
   2024 			LispDestroy("%s %s: syntax error parsing %s",
   2025 				    fnames[type], name, ATOMID(spec)->value);
   2026 		    if (key)
   2027 			LispDestroy("%s %s: %s not allowed after %s",
   2028 				    fnames[type], name, keys[IREST], keys[IKEY]);
   2029 		    rest = 1;
   2030 		    continue;
   2031 		}
   2032 
   2033 		else if (atom == Skey) {
   2034 		    if (rest || aux)
   2035 			LispDestroy("%s %s: %s not allowed after %s",
   2036 				    fnames[type], name, ATOMID(spec)->value,
   2037 				    rest ? keys[IREST] : keys[IAUX]);
   2038 		    key = 1;
   2039 		    continue;
   2040 		}
   2041 
   2042 		else if (atom == Soptional) {
   2043 		    if (rest || optional || aux || key)
   2044 			LispDestroy("%s %s: %s not allowed after %s",
   2045 				    fnames[type], name, ATOMID(spec)->value,
   2046 				    rest ? keys[IREST] :
   2047 					optional ?
   2048 					keys[IOPTIONAL] :
   2049 					    aux ? keys[IAUX] : keys[IKEY]);
   2050 		    optional = 1;
   2051 		    continue;
   2052 		}
   2053 
   2054 		else if (atom == Saux) {
   2055 		    /* &AUX must be the last keyword parameter */
   2056 		    if (aux)
   2057 			LispDestroy("%s %s: syntax error parsing %s",
   2058 				    fnames[type], name, ATOMID(spec)->value);
   2059 		    else if (builtin)
   2060 			LispDestroy("builtin function cannot have &AUX arguments");
   2061 		    aux = 1;
   2062 		    continue;
   2063 		}
   2064 
   2065 		/* Untill more lambda-list keywords supported, don't allow
   2066 		 * argument names starting with the '&' character */
   2067 		else
   2068 		    LispDestroy("%s %s: %s not allowed/implemented",
   2069 				fnames[type], name, ATOMID(spec)->value);
   2070 	    }
   2071 
   2072 	    /* Add argument to alist */
   2073 	    if (aux) {
   2074 		count = alist->auxs.num_symbols;
   2075 		REALLOC_OBJECTS(alist->auxs.symbols, count + 1);
   2076 		REALLOC_OBJECTS(alist->auxs.initials, count + 1);
   2077 		alist->auxs.symbols[count] = spec;
   2078 		alist->auxs.initials[count] = default_value;
   2079 		++alist->auxs.num_symbols;
   2080 		if (count == 0)
   2081 		    *desc++ = 'a';
   2082 		++alist->num_arguments;
   2083 	    }
   2084 	    else if (rest) {
   2085 		alist->rest = spec;
   2086 		*desc++ = 'r';
   2087 		++alist->num_arguments;
   2088 	    }
   2089 	    else if (key) {
   2090 		/* Add to keyword package, and set the keyword in the
   2091 		 * argument list, so that a function argument keyword
   2092 		 * will reference the same object, and make comparison
   2093 		 * simpler. */
   2094 		spec = LispCheckKeyword(spec);
   2095 		count = alist->keys.num_symbols;
   2096 		REALLOC_OBJECTS(alist->keys.keys, count + 1);
   2097 		REALLOC_OBJECTS(alist->keys.defaults, count + 1);
   2098 		REALLOC_OBJECTS(alist->keys.sforms, count + 1);
   2099 		REALLOC_OBJECTS(alist->keys.symbols, count + 1);
   2100 		alist->keys.symbols[count] = spec;
   2101 		alist->keys.defaults[count] = default_value;
   2102 		alist->keys.sforms[count] = NULL;
   2103 		alist->keys.keys[count] = NULL;
   2104 		++alist->keys.num_symbols;
   2105 		if (count == 0)
   2106 		    *desc++ = 'k';
   2107 		++alist->num_arguments;
   2108 	    }
   2109 	    else if (optional) {
   2110 		count = alist->optionals.num_symbols;
   2111 		REALLOC_OBJECTS(alist->optionals.symbols, count + 1);
   2112 		REALLOC_OBJECTS(alist->optionals.defaults, count + 1);
   2113 		REALLOC_OBJECTS(alist->optionals.sforms, count + 1);
   2114 		alist->optionals.symbols[count] = spec;
   2115 		alist->optionals.defaults[count] = default_value;
   2116 		alist->optionals.sforms[count] = NULL;
   2117 		++alist->optionals.num_symbols;
   2118 		if (count == 0)
   2119 		    *desc++ = 'o';
   2120 		++alist->num_arguments;
   2121 	    }
   2122 	    else {
   2123 		count = alist->normals.num_symbols;
   2124 		REALLOC_OBJECTS(alist->normals.symbols, count + 1);
   2125 		alist->normals.symbols[count] = spec;
   2126 		++alist->normals.num_symbols;
   2127 		if (count == 0)
   2128 		    *desc++ = '.';
   2129 		++alist->num_arguments;
   2130 	    }
   2131 	}
   2132     }
   2133 
   2134     /* Check for dotted argument list */
   2135     if (list != NIL)
   2136 	LispDestroy("%s %s: %s cannot end %s arguments",
   2137 		    fnames[type], name, STROBJ(list), types[type]);
   2138 
   2139     *desc = '\0';
   2140     alist->description = LispGetAtomKey(description, 0)->value;
   2141 
   2142     return (alist);
   2143 }
   2144 
   2145 void
   2146 LispAddBuiltinFunction(LispBuiltin *builtin)
   2147 {
   2148     static LispObj stream;
   2149     static LispString string;
   2150     static int first = 1;
   2151     LispObj *name, *obj, *list, *cons, *code;
   2152     LispAtom *atom;
   2153     LispArgList *alist;
   2154     int length = lisp__data.protect.length;
   2155 
   2156     if (first) {
   2157 	stream.type = LispStream_t;
   2158 	stream.data.stream.source.string = &string;
   2159 	stream.data.stream.pathname = NIL;
   2160 	stream.data.stream.type = LispStreamString;
   2161 	stream.data.stream.readable = 1;
   2162 	stream.data.stream.writable = 0;
   2163 	string.output = 0;
   2164 	first = 0;
   2165     }
   2166     string.string = builtin->declaration;
   2167     string.length = strlen(builtin->declaration);
   2168     string.input = 0;
   2169 
   2170     code = COD;
   2171     LispPushInput(&stream);
   2172     name = LispRead();
   2173     list = cons = CONS(name, NIL);
   2174     if (length + 1 >= lisp__data.protect.space)
   2175 	LispMoreProtects();
   2176     lisp__data.protect.objects[lisp__data.protect.length++] = list;
   2177     while ((obj = LispRead()) != NULL) {
   2178 	RPLACD(cons, CONS(obj, NIL));
   2179 	cons = CDR(cons);
   2180     }
   2181     LispPopInput(&stream);
   2182 
   2183     atom = name->data.atom;
   2184     alist = LispCheckArguments(builtin->type, CDR(list), atom->key->value, 1);
   2185     builtin->symbol = CAR(list);
   2186     LispSetAtomBuiltinProperty(atom, builtin, alist);
   2187     LispUseArgList(alist);
   2188 
   2189     /* Make function a extern symbol, unless told to not do so */
   2190     if (!builtin->internal)
   2191 	LispExportSymbol(name);
   2192 
   2193     lisp__data.protect.length = length;
   2194     COD = code;			/* LispRead protect data in COD */
   2195 }
   2196 
   2197 void
   2198 LispAllocSeg(LispObjSeg *seg, int cellcount)
   2199 {
   2200     unsigned int i;
   2201     LispObj **list, *obj;
   2202 
   2203     DISABLE_INTERRUPTS();
   2204     while (seg->nfree < cellcount) {
   2205 	if ((obj = (LispObj*)calloc(1, sizeof(LispObj) * segsize)) == NULL) {
   2206 	    ENABLE_INTERRUPTS();
   2207 	    LispDestroy("out of memory");
   2208 	}
   2209 	if ((list = (LispObj**)realloc(seg->objects,
   2210 	    sizeof(LispObj*) * (seg->nsegs + 1))) == NULL) {
   2211 	    free(obj);
   2212 	    ENABLE_INTERRUPTS();
   2213 	    LispDestroy("out of memory");
   2214 	}
   2215 	seg->objects = list;
   2216 	seg->objects[seg->nsegs] = obj;
   2217 
   2218 	seg->nfree += segsize;
   2219 	seg->nobjs += segsize;
   2220 	for (i = 1; i < segsize; i++, obj++) {
   2221 	    /* Objects of type cons are the most used, save some time
   2222 	     * by not setting it's type in LispNewCons. */
   2223 	    obj->type = LispCons_t;
   2224 	    CDR(obj) = obj + 1;
   2225 	}
   2226 	obj->type = LispCons_t;
   2227 	CDR(obj) = seg->freeobj;
   2228 	seg->freeobj = seg->objects[seg->nsegs];
   2229 	++seg->nsegs;
   2230     }
   2231 #ifdef DEBUG
   2232     LispMessage("gc: %d cell(s) allocated at %d segment(s)",
   2233 		seg->nobjs, seg->nsegs);
   2234 #endif
   2235     ENABLE_INTERRUPTS();
   2236 }
   2237 
   2238 static INLINE void
   2239 LispMark(register LispObj *object)
   2240 {
   2241 mark_again:
   2242     switch (OBJECT_TYPE(object)) {
   2243 	case LispNil_t:
   2244 	case LispAtom_t:
   2245 	case LispFixnum_t:
   2246 	case LispSChar_t:
   2247 	case LispFunction_t:
   2248 	    return;
   2249 	case LispLambda_t:
   2250 	    if (OPAQUEP(object->data.lambda.name))
   2251 		object->data.lambda.name->mark = 1;
   2252 	    object->mark = 1;
   2253 	    LispMark(object->data.lambda.data);
   2254 	    object = object->data.lambda.code;
   2255 	    goto mark_cons;
   2256 	case LispQuote_t:
   2257 	case LispBackquote_t:
   2258 	case LispFunctionQuote_t:
   2259 	    object->mark = 1;
   2260 	    object = object->data.quote;
   2261 	    goto mark_again;
   2262 	case LispPathname_t:
   2263 	    object->mark = 1;
   2264 	    object = object->data.pathname;
   2265 	    goto mark_again;
   2266 	case LispComma_t:
   2267 	    object->mark = 1;
   2268 	    object = object->data.comma.eval;
   2269 	    goto mark_again;
   2270 	case LispComplex_t:
   2271 	    if (POINTERP(object->data.complex.real))
   2272 		object->data.complex.real->mark = 1;
   2273 	    if (POINTERP(object->data.complex.imag))
   2274 		object->data.complex.imag->mark = 1;
   2275 	    break;
   2276 	case LispCons_t:
   2277 mark_cons:
   2278 	    for (; CONSP(object) && !object->mark; object = CDR(object)) {
   2279 		object->mark = 1;
   2280 		switch (OBJECT_TYPE(CAR(object))) {
   2281 		    case LispNil_t:
   2282 		    case LispAtom_t:
   2283 		    case LispFixnum_t:
   2284 		    case LispSChar_t:
   2285 		    case LispPackage_t:		/* protected in gc */
   2286 			break;
   2287 		    case LispInteger_t:
   2288 		    case LispDFloat_t:
   2289 		    case LispString_t:
   2290 		    case LispRatio_t:
   2291 		    case LispOpaque_t:
   2292 		    case LispBignum_t:
   2293 		    case LispBigratio_t:
   2294 			CAR(object)->mark = 1;
   2295 			break;
   2296 		    default:
   2297 			LispMark(CAR(object));
   2298 			break;
   2299 		}
   2300 	    }
   2301 	    if (POINTERP(object) && !object->mark)
   2302 		goto mark_again;
   2303 	    return;
   2304 	case LispArray_t:
   2305 	    LispMark(object->data.array.list);
   2306 	    object->mark = 1;
   2307 	    object = object->data.array.dim;
   2308 	    goto mark_cons;
   2309 	case LispStruct_t:
   2310 	    object->mark = 1;
   2311 	    object = object->data.struc.fields;
   2312 	    goto mark_cons;
   2313 	case LispStream_t:
   2314 mark_stream:
   2315 	    LispMark(object->data.stream.pathname);
   2316 	    if (object->data.stream.type == LispStreamPipe) {
   2317 		object->mark = 1;
   2318 		object = object->data.stream.source.program->errorp;
   2319 		goto mark_stream;
   2320 	    }
   2321 	    break;
   2322 	case LispRegex_t:
   2323 	    object->data.regex.pattern->mark = 1;
   2324 	    break;
   2325 	case LispBytecode_t:
   2326 	    object->mark = 1;
   2327 	    object = object->data.bytecode.code;
   2328 	    goto mark_again;
   2329 	case LispHashTable_t: {
   2330 	    unsigned long i;
   2331 	    LispHashEntry *entry = object->data.hash.table->entries,
   2332 			  *last = entry + object->data.hash.table->num_entries;
   2333 
   2334 	    if (object->mark)
   2335 		return;
   2336 	    object->mark = 1;
   2337 	    for (; entry < last; entry++) {
   2338 		for (i = 0; i < entry->count; i++) {
   2339 		    switch (OBJECT_TYPE(entry->keys[i])) {
   2340 			case LispNil_t:
   2341 			case LispAtom_t:
   2342 			case LispFixnum_t:
   2343 			case LispSChar_t:
   2344 			case LispFunction_t:
   2345 			case LispPackage_t:
   2346 			    break;
   2347 			case LispInteger_t:
   2348 			case LispDFloat_t:
   2349 			case LispString_t:
   2350 			case LispRatio_t:
   2351 			case LispOpaque_t:
   2352 			case LispBignum_t:
   2353 			case LispBigratio_t:
   2354 			    entry->keys[i]->mark = 1;
   2355 			    break;
   2356 			default:
   2357 			    LispMark(entry->keys[i]);
   2358 			    break;
   2359 		    }
   2360 		    switch (OBJECT_TYPE(entry->values[i])) {
   2361 			case LispNil_t:
   2362 			case LispAtom_t:
   2363 			case LispFixnum_t:
   2364 			case LispSChar_t:
   2365 			case LispFunction_t:
   2366 			case LispPackage_t:
   2367 			    break;
   2368 			case LispInteger_t:
   2369 			case LispDFloat_t:
   2370 			case LispString_t:
   2371 			case LispRatio_t:
   2372 			case LispOpaque_t:
   2373 			case LispBignum_t:
   2374 			case LispBigratio_t:
   2375 			    entry->values[i]->mark = 1;
   2376 			    break;
   2377 			default:
   2378 			    LispMark(entry->values[i]);
   2379 			    break;
   2380 		    }
   2381 		}
   2382 	    }
   2383 	}   return;
   2384 	default:
   2385 	    break;
   2386     }
   2387     object->mark = 1;
   2388 }
   2389 
   2390 static INLINE void
   2391 LispProt(register LispObj *object)
   2392 {
   2393 prot_again:
   2394     switch (OBJECT_TYPE(object)) {
   2395 	case LispNil_t:
   2396 	case LispAtom_t:
   2397 	case LispFixnum_t:
   2398 	case LispSChar_t:
   2399 	case LispFunction_t:
   2400 	    return;
   2401 	case LispLambda_t:
   2402 	    if (OPAQUEP(object->data.lambda.name))
   2403 		object->data.lambda.name->prot = 1;
   2404 	    object->prot = 1;
   2405 	    LispProt(object->data.lambda.data);
   2406 	    object = object->data.lambda.code;
   2407 	    goto prot_cons;
   2408 	case LispQuote_t:
   2409 	case LispBackquote_t:
   2410 	case LispFunctionQuote_t:
   2411 	    object->prot = 1;
   2412 	    object = object->data.quote;
   2413 	    goto prot_again;
   2414 	case LispPathname_t:
   2415 	    object->prot = 1;
   2416 	    object = object->data.pathname;
   2417 	    goto prot_again;
   2418 	case LispComma_t:
   2419 	    object->prot = 1;
   2420 	    object = object->data.comma.eval;
   2421 	    goto prot_again;
   2422 	case LispComplex_t:
   2423 	    if (POINTERP(object->data.complex.real))
   2424 		object->data.complex.real->prot = 1;
   2425 	    if (POINTERP(object->data.complex.imag))
   2426 		object->data.complex.imag->prot = 1;
   2427 	    break;
   2428 	case LispCons_t:
   2429 prot_cons:
   2430 	    for (; CONSP(object) && !object->prot; object = CDR(object)) {
   2431 		object->prot = 1;
   2432 		switch (OBJECT_TYPE(CAR(object))) {
   2433 		    case LispNil_t:
   2434 		    case LispAtom_t:
   2435 		    case LispFixnum_t:
   2436 		    case LispSChar_t:
   2437 		    case LispFunction_t:
   2438 		    case LispPackage_t:		/* protected in gc */
   2439 			break;
   2440 		    case LispInteger_t:
   2441 		    case LispDFloat_t:
   2442 		    case LispString_t:
   2443 		    case LispRatio_t:
   2444 		    case LispOpaque_t:
   2445 		    case LispBignum_t:
   2446 		    case LispBigratio_t:
   2447 			CAR(object)->prot = 1;
   2448 			break;
   2449 		    default:
   2450 			LispProt(CAR(object));
   2451 			break;
   2452 		}
   2453 	    }
   2454 	    if (POINTERP(object) && !object->prot)
   2455 		goto prot_again;
   2456 	    return;
   2457 	case LispArray_t:
   2458 	    LispProt(object->data.array.list);
   2459 	    object->prot = 1;
   2460 	    object = object->data.array.dim;
   2461 	    goto prot_cons;
   2462 	case LispStruct_t:
   2463 	    object->prot = 1;
   2464 	    object = object->data.struc.fields;
   2465 	    goto prot_cons;
   2466 	case LispStream_t:
   2467 prot_stream:
   2468 	    LispProt(object->data.stream.pathname);
   2469 	    if (object->data.stream.type == LispStreamPipe) {
   2470 		object->prot = 1;
   2471 		object = object->data.stream.source.program->errorp;
   2472 		goto prot_stream;
   2473 	    }
   2474 	    break;
   2475 	case LispRegex_t:
   2476 	    object->data.regex.pattern->prot = 1;
   2477 	    break;
   2478 	case LispBytecode_t:
   2479 	    object->prot = 1;
   2480 	    object = object->data.bytecode.code;
   2481 	    goto prot_again;
   2482 	case LispHashTable_t: {
   2483 	    unsigned long i;
   2484 	    LispHashEntry *entry = object->data.hash.table->entries,
   2485 			  *last = entry + object->data.hash.table->num_entries;
   2486 
   2487 	    if (object->prot)
   2488 		return;
   2489 	    object->prot = 1;
   2490 	    for (; entry < last; entry++) {
   2491 		for (i = 0; i < entry->count; i++) {
   2492 		    switch (OBJECT_TYPE(entry->keys[i])) {
   2493 			case LispNil_t:
   2494 			case LispAtom_t:
   2495 			case LispFixnum_t:
   2496 			case LispSChar_t:
   2497 			case LispFunction_t:
   2498 			case LispPackage_t:
   2499 			    break;
   2500 			case LispInteger_t:
   2501 			case LispDFloat_t:
   2502 			case LispString_t:
   2503 			case LispRatio_t:
   2504 			case LispOpaque_t:
   2505 			case LispBignum_t:
   2506 			case LispBigratio_t:
   2507 			    entry->keys[i]->prot = 1;
   2508 			    break;
   2509 			default:
   2510 			    LispProt(entry->keys[i]);
   2511 			    break;
   2512 		    }
   2513 		    switch (OBJECT_TYPE(entry->values[i])) {
   2514 			case LispNil_t:
   2515 			case LispAtom_t:
   2516 			case LispFixnum_t:
   2517 			case LispSChar_t:
   2518 			case LispFunction_t:
   2519 			case LispPackage_t:
   2520 			    break;
   2521 			case LispInteger_t:
   2522 			case LispDFloat_t:
   2523 			case LispString_t:
   2524 			case LispRatio_t:
   2525 			case LispOpaque_t:
   2526 			case LispBignum_t:
   2527 			case LispBigratio_t:
   2528 			    entry->values[i]->prot = 1;
   2529 			    break;
   2530 			default:
   2531 			    LispProt(entry->values[i]);
   2532 			    break;
   2533 		    }
   2534 		}
   2535 	    }
   2536 	}   return;
   2537 	default:
   2538 	    break;
   2539     }
   2540     object->prot = 1;
   2541 }
   2542 
   2543 void
   2544 LispProtect(LispObj *key, LispObj *list)
   2545 {
   2546     PRO = CONS(CONS(key, list), PRO);
   2547 }
   2548 
   2549 void
   2550 LispUProtect(LispObj *key, LispObj *list)
   2551 {
   2552     LispObj *prev, *obj;
   2553 
   2554     for (prev = obj = PRO; obj != NIL; prev = obj, obj = CDR(obj))
   2555 	if (CAR(CAR(obj)) == key && CDR(CAR(obj)) == list) {
   2556 	    if (obj == PRO)
   2557 		PRO = CDR(PRO);
   2558 	    else
   2559 		CDR(prev) = CDR(obj);
   2560 	    return;
   2561 	}
   2562 
   2563     LispDestroy("no match for %s, at UPROTECT", STROBJ(key));
   2564 }
   2565 
   2566 static LispObj *
   2567 Lisp__New(LispObj *car, LispObj *cdr)
   2568 {
   2569     int cellcount;
   2570     LispObj *obj;
   2571 
   2572     Lisp__GC(car, cdr);
   2573 #if 0
   2574     lisp__data.gc.average = (objseg.nfree + lisp__data.gc.average) >> 1;
   2575     if (lisp__data.gc.average < minfree) {
   2576 	if (lisp__data.gc.expandbits < 6)
   2577 	    ++lisp__data.gc.expandbits;
   2578     }
   2579     else if (lisp__data.gc.expandbits)
   2580 	--lisp__data.gc.expandbits;
   2581     /* For 32 bit computers, where sizeof(LispObj) == 16,
   2582      * minfree is set to 1024, and expandbits limited to 6,
   2583      * the maximum extra memory requested here should be 1Mb
   2584      */
   2585     cellcount = minfree << lisp__data.gc.expandbits;
   2586 #else
   2587     /* Try to keep at least 3 times more free cells than the de number
   2588      * of used cells in the freelist, to amenize the cost of the gc time,
   2589      * in the, currently, very simple gc strategy code. */
   2590     cellcount = (objseg.nobjs - objseg.nfree) * 3;
   2591     cellcount = cellcount + (minfree - (cellcount % minfree));
   2592 #endif
   2593 
   2594     if (objseg.freeobj == NIL || objseg.nfree < cellcount)
   2595 	LispAllocSeg(&objseg, cellcount);
   2596 
   2597     obj = objseg.freeobj;
   2598     objseg.freeobj = CDR(obj);
   2599     --objseg.nfree;
   2600 
   2601     return (obj);
   2602 }
   2603 
   2604 LispObj *
   2605 LispNew(LispObj *car, LispObj *cdr)
   2606 {
   2607     LispObj *obj = objseg.freeobj;
   2608 
   2609     if (obj == NIL)
   2610 	obj = Lisp__New(car, cdr);
   2611     else {
   2612 	objseg.freeobj = CDR(obj);
   2613 	--objseg.nfree;
   2614     }
   2615 
   2616     return (obj);
   2617 }
   2618 
   2619 LispObj *
   2620 LispNewAtom(const char *str, int intern)
   2621 {
   2622     LispObj *object;
   2623     LispAtom *atom = LispDoGetAtom(str, 0);
   2624 
   2625     if (atom->object) {
   2626 	if (intern && atom->package == NULL)
   2627 	    atom->package = PACKAGE;
   2628 
   2629 	return (atom->object);
   2630     }
   2631 
   2632     if (atomseg.freeobj == NIL)
   2633 	LispAllocSeg(&atomseg, pagesize);
   2634     object = atomseg.freeobj;
   2635     atomseg.freeobj = CDR(object);
   2636     --atomseg.nfree;
   2637 
   2638     object->type = LispAtom_t;
   2639     object->data.atom = atom;
   2640     atom->object = object;
   2641     if (intern)
   2642 	atom->package = PACKAGE;
   2643 
   2644     return (object);
   2645 }
   2646 
   2647 LispObj *
   2648 LispNewStaticAtom(const char *str)
   2649 {
   2650     LispObj *object;
   2651     LispAtom *atom = LispDoGetAtom(str, 1);
   2652 
   2653     object = LispNewSymbol(atom);
   2654 
   2655     return (object);
   2656 }
   2657 
   2658 LispObj *
   2659 LispNewSymbol(LispAtom *atom)
   2660 {
   2661     if (atom->object) {
   2662 	if (atom->package == NULL)
   2663 	    atom->package = PACKAGE;
   2664 
   2665 	return (atom->object);
   2666     }
   2667     else {
   2668 	LispObj *symbol;
   2669 
   2670 	if (atomseg.freeobj == NIL)
   2671 	    LispAllocSeg(&atomseg, pagesize);
   2672 	symbol = atomseg.freeobj;
   2673 	atomseg.freeobj = CDR(symbol);
   2674 	--atomseg.nfree;
   2675 
   2676 	symbol->type = LispAtom_t;
   2677 	symbol->data.atom = atom;
   2678 	atom->object = symbol;
   2679 	atom->package = PACKAGE;
   2680 
   2681 	return (symbol);
   2682     }
   2683 }
   2684 
   2685 /* function representation is created on demand and never released,
   2686  * even if the function is undefined and never defined again */
   2687 LispObj *
   2688 LispNewFunction(LispObj *symbol)
   2689 {
   2690     LispObj *function;
   2691 
   2692     if (symbol->data.atom->function)
   2693 	return (symbol->data.atom->function);
   2694 
   2695     if (symbol->data.atom->package == NULL)
   2696 	symbol->data.atom->package = PACKAGE;
   2697 
   2698     if (atomseg.freeobj == NIL)
   2699 	LispAllocSeg(&atomseg, pagesize);
   2700     function = atomseg.freeobj;
   2701     atomseg.freeobj = CDR(function);
   2702     --atomseg.nfree;
   2703 
   2704     function->type = LispFunction_t;
   2705     function->data.atom = symbol->data.atom;
   2706     symbol->data.atom->function = function;
   2707 
   2708     return (function);
   2709 }
   2710 
   2711 /* symbol name representation is created on demand and never released */
   2712 LispObj *
   2713 LispSymbolName(LispObj *symbol)
   2714 {
   2715     LispObj *name;
   2716     LispAtom *atom = symbol->data.atom;
   2717 
   2718     if (atom->name)
   2719 	return (atom->name);
   2720 
   2721     if (atomseg.freeobj == NIL)
   2722 	LispAllocSeg(&atomseg, pagesize);
   2723     name = atomseg.freeobj;
   2724     atomseg.freeobj = CDR(name);
   2725     --atomseg.nfree;
   2726 
   2727     name->type = LispString_t;
   2728     THESTR(name) = atom->key->value;
   2729     STRLEN(name) = atom->key->length;
   2730     name->data.string.writable = 0;
   2731     atom->name = name;
   2732 
   2733     return (name);
   2734 }
   2735 
   2736 LispObj *
   2737 LispNewFunctionQuote(LispObj *object)
   2738 {
   2739     LispObj *quote = LispNew(object, NIL);
   2740 
   2741     quote->type = LispFunctionQuote_t;
   2742     quote->data.quote = object;
   2743 
   2744     return (quote);
   2745 }
   2746 
   2747 LispObj *
   2748 LispNewDFloat(double value)
   2749 {
   2750     LispObj *dfloat = objseg.freeobj;
   2751 
   2752     if (dfloat == NIL)
   2753 	dfloat = Lisp__New(NIL, NIL);
   2754     else {
   2755 	objseg.freeobj = CDR(dfloat);
   2756 	--objseg.nfree;
   2757     }
   2758     dfloat->type = LispDFloat_t;
   2759     dfloat->data.dfloat = value;
   2760 
   2761     return (dfloat);
   2762 }
   2763 
   2764 LispObj *
   2765 LispNewString(const char *str, long length)
   2766 {
   2767     char *cstring = LispMalloc(length + 1);
   2768     memcpy(cstring, str, length);
   2769     cstring[length] = '\0';
   2770     return LispNewStringAlloced(cstring, length);
   2771 }
   2772 
   2773 LispObj *
   2774 LispNewStringAlloced(char *cstring, long length)
   2775 {
   2776     LispObj *string = objseg.freeobj;
   2777 
   2778     if (string == NIL)
   2779 	string = Lisp__New(NIL, NIL);
   2780     else {
   2781 	objseg.freeobj = CDR(string);
   2782 	--objseg.nfree;
   2783     }
   2784     LispMused(cstring);
   2785     string->type = LispString_t;
   2786     THESTR(string) = cstring;
   2787     STRLEN(string) = length;
   2788     string->data.string.writable = 1;
   2789 
   2790     return (string);
   2791 }
   2792 
   2793 LispObj *
   2794 LispNewComplex(LispObj *realpart, LispObj *imagpart)
   2795 {
   2796     LispObj *complexp = objseg.freeobj;
   2797 
   2798     if (complexp == NIL)
   2799 	complexp = Lisp__New(realpart, imagpart);
   2800     else {
   2801 	objseg.freeobj = CDR(complexp);
   2802 	--objseg.nfree;
   2803     }
   2804     complexp->type = LispComplex_t;
   2805     complexp->data.complex.real = realpart;
   2806     complexp->data.complex.imag = imagpart;
   2807 
   2808     return (complexp);
   2809 }
   2810 
   2811 LispObj *
   2812 LispNewInteger(long integer)
   2813 {
   2814     if (integer > MOST_POSITIVE_FIXNUM || integer < MOST_NEGATIVE_FIXNUM) {
   2815 	LispObj *object = objseg.freeobj;
   2816 
   2817 	if (object == NIL)
   2818 	    object = Lisp__New(NIL, NIL);
   2819 	else {
   2820 	    objseg.freeobj = CDR(object);
   2821 	    --objseg.nfree;
   2822 	}
   2823 	object->type = LispInteger_t;
   2824 	object->data.integer = integer;
   2825 
   2826 	return (object);
   2827     }
   2828     return (FIXNUM(integer));
   2829 }
   2830 
   2831 LispObj *
   2832 LispNewRatio(long num, long den)
   2833 {
   2834     LispObj *ratio = objseg.freeobj;
   2835 
   2836     if (ratio == NIL)
   2837 	ratio = Lisp__New(NIL, NIL);
   2838     else {
   2839 	objseg.freeobj = CDR(ratio);
   2840 	--objseg.nfree;
   2841     }
   2842     ratio->type = LispRatio_t;
   2843     ratio->data.ratio.numerator = num;
   2844     ratio->data.ratio.denominator = den;
   2845 
   2846     return (ratio);
   2847 }
   2848 
   2849 LispObj *
   2850 LispNewVector(LispObj *objects)
   2851 {
   2852     GC_ENTER();
   2853     long count;
   2854     LispObj *array, *dimension;
   2855 
   2856     for (count = 0, array = objects; CONSP(array); count++, array = CDR(array))
   2857 	;
   2858 
   2859     GC_PROTECT(objects);
   2860     dimension = CONS(FIXNUM(count), NIL);
   2861     array = LispNew(objects, dimension);
   2862     array->type = LispArray_t;
   2863     array->data.array.list = objects;
   2864     array->data.array.dim = dimension;
   2865     array->data.array.rank = 1;
   2866     array->data.array.type = LispNil_t;
   2867     array->data.array.zero = count == 0;
   2868     GC_LEAVE();
   2869 
   2870     return (array);
   2871 }
   2872 
   2873 LispObj *
   2874 LispNewQuote(LispObj *object)
   2875 {
   2876     LispObj *quote = LispNew(object, NIL);
   2877 
   2878     quote->type = LispQuote_t;
   2879     quote->data.quote = object;
   2880 
   2881     return (quote);
   2882 }
   2883 
   2884 LispObj *
   2885 LispNewBackquote(LispObj *object)
   2886 {
   2887     LispObj *backquote = LispNew(object, NIL);
   2888 
   2889     backquote->type = LispBackquote_t;
   2890     backquote->data.quote = object;
   2891 
   2892     return (backquote);
   2893 }
   2894 
   2895 LispObj *
   2896 LispNewComma(LispObj *object, int atlist)
   2897 {
   2898     LispObj *comma = LispNew(object, NIL);
   2899 
   2900     comma->type = LispComma_t;
   2901     comma->data.comma.eval = object;
   2902     comma->data.comma.atlist = atlist;
   2903 
   2904     return (comma);
   2905 }
   2906 
   2907 LispObj *
   2908 LispNewCons(LispObj *car, LispObj *cdr)
   2909 {
   2910     LispObj *cons = objseg.freeobj;
   2911 
   2912     if (cons == NIL)
   2913 	cons = Lisp__New(car, cdr);
   2914     else {
   2915 	objseg.freeobj = CDR(cons);
   2916 	--objseg.nfree;
   2917     }
   2918     CAR(cons) = car;
   2919     CDR(cons) = cdr;
   2920 
   2921     return (cons);
   2922 }
   2923 
   2924 LispObj *
   2925 LispNewLambda(LispObj *name, LispObj *code, LispObj *data, LispFunType type)
   2926 {
   2927     LispObj *fun = LispNew(data, code);
   2928 
   2929     fun->type = LispLambda_t;
   2930     fun->funtype = type;
   2931     fun->data.lambda.name = name;
   2932     fun->data.lambda.code = code;
   2933     fun->data.lambda.data = data;
   2934 
   2935     return (fun);
   2936 }
   2937 
   2938 LispObj *
   2939 LispNewStruct(LispObj *fields, LispObj *def)
   2940 {
   2941     LispObj *struc = LispNew(fields, def);
   2942 
   2943     struc->type = LispStruct_t;
   2944     struc->data.struc.fields = fields;
   2945     struc->data.struc.def = def;
   2946 
   2947     return (struc);
   2948 }
   2949 
   2950 LispObj *
   2951 LispNewOpaque(void *data, int type)
   2952 {
   2953     LispObj *opaque = LispNew(NIL, NIL);
   2954 
   2955     opaque->type = LispOpaque_t;
   2956     opaque->data.opaque.data = data;
   2957     opaque->data.opaque.type = type;
   2958 
   2959     return (opaque);
   2960 }
   2961 
   2962 /* string argument must be static, or allocated */
   2963 LispObj *
   2964 LispNewKeyword(const char *string)
   2965 {
   2966     LispObj *keyword;
   2967 
   2968     if (PACKAGE != lisp__data.keyword) {
   2969 	LispObj *savepackage;
   2970 	LispPackage *savepack;
   2971 
   2972 	/* Save package environment */
   2973 	savepackage = PACKAGE;
   2974 	savepack = lisp__data.pack;
   2975 
   2976 	/* Change package environment */
   2977 	PACKAGE = lisp__data.keyword;
   2978 	lisp__data.pack = lisp__data.key;
   2979 
   2980 	/* Create symbol in keyword package */
   2981 	keyword = LispNewStaticAtom(string);
   2982 
   2983 	/* Restore package environment */
   2984 	PACKAGE = savepackage;
   2985 	lisp__data.pack = savepack;
   2986     }
   2987     else
   2988 	/* Just create symbol in keyword package */
   2989 	keyword = LispNewStaticAtom(string);
   2990 
   2991     /* Export keyword symbol */
   2992     LispExportSymbol(keyword);
   2993 
   2994     /* All keywords are constants */
   2995     keyword->data.atom->constant = 1;
   2996 
   2997     /* XXX maybe should bound the keyword to itself, but that would
   2998      * require allocating a LispProperty structure for every keyword */
   2999 
   3000     return (keyword);
   3001 }
   3002 
   3003 LispObj *
   3004 LispNewPathname(LispObj *obj)
   3005 {
   3006     LispObj *path = LispNew(obj, NIL);
   3007 
   3008     path->type = LispPathname_t;
   3009     path->data.pathname = obj;
   3010 
   3011     return (path);
   3012 }
   3013 
   3014 LispObj *
   3015 LispNewStringStream(const char *string, int flags, long length)
   3016 {
   3017     char *newstring = LispMalloc(length + 1);
   3018     memcpy(newstring, string, length);
   3019     newstring[length] = '\0';
   3020 
   3021     return LispNewStringStreamAlloced(newstring, flags, length);
   3022 }
   3023 
   3024 LispObj *
   3025 LispNewStringStreamAlloced(char *string, int flags, long length)
   3026 {
   3027     LispObj *stream = LispNew(NIL, NIL);
   3028 
   3029     SSTREAMP(stream) = LispCalloc(1, sizeof(LispString));
   3030     SSTREAMP(stream)->string = string;
   3031 
   3032     stream->type = LispStream_t;
   3033 
   3034     SSTREAMP(stream)->length = length;
   3035     LispMused(SSTREAMP(stream));
   3036     LispMused(SSTREAMP(stream)->string);
   3037     stream->data.stream.type = LispStreamString;
   3038     stream->data.stream.readable = (flags & STREAM_READ) != 0;
   3039     stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
   3040     SSTREAMP(stream)->space = length + 1;
   3041 
   3042     stream->data.stream.pathname = NIL;
   3043 
   3044     return (stream);
   3045 }
   3046 
   3047 LispObj *
   3048 LispNewFileStream(LispFile *file, LispObj *path, int flags)
   3049 {
   3050     LispObj *stream = LispNew(NIL, NIL);
   3051 
   3052     stream->type = LispStream_t;
   3053     FSTREAMP(stream) = file;
   3054     stream->data.stream.pathname = path;
   3055     stream->data.stream.type = LispStreamFile;
   3056     stream->data.stream.readable = (flags & STREAM_READ) != 0;
   3057     stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
   3058 
   3059     return (stream);
   3060 }
   3061 
   3062 LispObj *
   3063 LispNewPipeStream(LispPipe *program, LispObj *path, int flags)
   3064 {
   3065     LispObj *stream = LispNew(NIL, NIL);
   3066 
   3067     stream->type = LispStream_t;
   3068     PSTREAMP(stream) = program;
   3069     stream->data.stream.pathname = path;
   3070     stream->data.stream.type = LispStreamPipe;
   3071     stream->data.stream.readable = (flags & STREAM_READ) != 0;
   3072     stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
   3073 
   3074     return (stream);
   3075 }
   3076 
   3077 LispObj *
   3078 LispNewStandardStream(LispFile *file, LispObj *description, int flags)
   3079 {
   3080     LispObj *stream = LispNew(NIL, NIL);
   3081 
   3082     stream->type = LispStream_t;
   3083     FSTREAMP(stream) = file;
   3084     stream->data.stream.pathname = description;
   3085     stream->data.stream.type = LispStreamStandard;
   3086     stream->data.stream.readable = (flags & STREAM_READ) != 0;
   3087     stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
   3088 
   3089     return (stream);
   3090 }
   3091 
   3092 LispObj *
   3093 LispNewBignum(mpi *bignum)
   3094 {
   3095     LispObj *integer = LispNew(NIL, NIL);
   3096 
   3097     integer->type = LispBignum_t;
   3098     integer->data.mp.integer = bignum;
   3099     LispMused(bignum->digs);
   3100     LispMused(bignum);
   3101 
   3102     return (integer);
   3103 }
   3104 
   3105 LispObj *
   3106 LispNewBigratio(mpr *bigratio)
   3107 {
   3108     LispObj *ratio = LispNew(NIL, NIL);
   3109 
   3110     ratio->type = LispBigratio_t;
   3111     ratio->data.mp.ratio = bigratio;
   3112     LispMused(mpr_num(bigratio)->digs);
   3113     LispMused(mpr_den(bigratio)->digs);
   3114     LispMused(bigratio);
   3115 
   3116     return (ratio);
   3117 }
   3118 
   3119 /* name must be of type LispString_t */
   3120 LispObj *
   3121 LispNewPackage(LispObj *name, LispObj *nicknames)
   3122 {
   3123     LispObj *package = LispNew(name, nicknames);
   3124     LispPackage *pack = LispCalloc(1, sizeof(LispPackage));
   3125 
   3126     package->type = LispPackage_t;
   3127     package->data.package.name = name;
   3128     package->data.package.nicknames = nicknames;
   3129     package->data.package.package = pack;
   3130 
   3131     package->data.package.package->atoms = hash_new(STRTBLSZ, NULL);
   3132 
   3133     LispMused(pack);
   3134 
   3135     return (package);
   3136 }
   3137 
   3138 LispObj *
   3139 LispSymbolFunction(LispObj *symbol)
   3140 {
   3141     LispAtom *atom = symbol->data.atom;
   3142 
   3143     if ((atom->a_builtin &&
   3144 	 atom->property->fun.builtin->type == LispFunction) ||
   3145 	(atom->a_function &&
   3146 	 atom->property->fun.function->funtype == LispFunction) ||
   3147 	(atom->a_defstruct &&
   3148 	 atom->property->structure.function != STRUCT_NAME) ||
   3149 	/* XXX currently bytecode is only generated for functions */
   3150 	atom->a_compiled)
   3151 	symbol = FUNCTION(symbol);
   3152     else
   3153 	LispDestroy("SYMBOL-FUNCTION: %s is not a function", STROBJ(symbol));
   3154 
   3155     return (symbol);
   3156 }
   3157 
   3158 
   3159 static INLINE LispObj *
   3160 LispGetVarPack(LispObj *symbol)
   3161 {
   3162     LispAtom *atom;
   3163 
   3164     atom = (LispAtom *)hash_get(lisp__data.pack->atoms,
   3165 				 symbol->data.atom->key);
   3166 
   3167     return (atom ? atom->object : NULL);
   3168 }
   3169 
   3170 /* package must be of type LispPackage_t */
   3171 void
   3172 LispUsePackage(LispObj *package)
   3173 {
   3174     LispAtom *atom;
   3175     LispPackage *pack;
   3176     LispObj **pentry, **eentry;
   3177 
   3178     /* Already using its own symbols... */
   3179     if (package == PACKAGE)
   3180 	return;
   3181 
   3182     /* Check if package not already in use-package list */
   3183     for (pentry = lisp__data.pack->use.pairs,
   3184 	 eentry = pentry + lisp__data.pack->use.length;
   3185 	 pentry < eentry; pentry++)
   3186 	if (*pentry == package)
   3187 	return;
   3188 
   3189     /* Remember this package is in the use-package list */
   3190     if (lisp__data.pack->use.length + 1 >= lisp__data.pack->use.space) {
   3191 	LispObj **pairs = realloc(lisp__data.pack->use.pairs,
   3192 				  (lisp__data.pack->use.space + 1) *
   3193 				  sizeof(LispObj*));
   3194 
   3195 	if (pairs == NULL)
   3196 	    LispDestroy("out of memory");
   3197 
   3198 	lisp__data.pack->use.pairs = pairs;
   3199 	++lisp__data.pack->use.space;
   3200     }
   3201     lisp__data.pack->use.pairs[lisp__data.pack->use.length++] = package;
   3202 
   3203     /* Import all extern symbols from package */
   3204     pack = package->data.package.package;
   3205 
   3206     /* Traverse atom list, searching for extern symbols */
   3207     for (atom = (LispAtom *)hash_iter_first(pack->atoms);
   3208 	 atom;
   3209 	 atom = (LispAtom *)hash_iter_next(pack->atoms)) {
   3210 	if (atom->ext)
   3211 	    LispImportSymbol(atom->object);
   3212     }
   3213 }
   3214 
   3215 /* symbol must be of type LispAtom_t */
   3216 void
   3217 LispImportSymbol(LispObj *symbol)
   3218 {
   3219     int increment;
   3220     LispAtom *atom;
   3221     LispObj *current;
   3222 
   3223     current = LispGetVarPack(symbol);
   3224     if (current == NULL || current->data.atom->property == NOPROPERTY) {
   3225 	/* No conflicts */
   3226 
   3227 	if (symbol->data.atom->a_object) {
   3228 	    /* If it is a bounded variable */
   3229 	    if (lisp__data.pack->glb.length + 1 >= lisp__data.pack->glb.space)
   3230 		LispMoreGlobals(lisp__data.pack);
   3231 	    lisp__data.pack->glb.pairs[lisp__data.pack->glb.length++] = symbol;
   3232 	}
   3233 
   3234 	/* Create copy of atom in current package */
   3235 	atom = LispDoGetAtom(ATOMID(symbol)->value, 0);
   3236 	/*   Need to create a copy because if anything new is atached to the
   3237 	 * property, the current package is the owner, not the previous one. */
   3238 
   3239 	/* And reference the same properties */
   3240 	atom->property = symbol->data.atom->property;
   3241 
   3242 	increment = 1;
   3243     }
   3244     else if (current->data.atom->property != symbol->data.atom->property) {
   3245 	/* Symbol already exists in the current package,
   3246 	 * but does not reference the same variable */
   3247 	LispContinuable("Symbol %s already defined in package %s. Redefine?",
   3248 			ATOMID(symbol)->value, THESTR(PACKAGE->data.package.name));
   3249 
   3250 	atom = current->data.atom;
   3251 
   3252 	/* Continued from error, redefine variable */
   3253 	LispDecrementAtomReference(atom);
   3254 	atom->property = symbol->data.atom->property;
   3255 
   3256 	atom->a_object = atom->a_function = atom->a_builtin =
   3257 	    atom->a_property = atom->a_defsetf = atom->a_defstruct = 0;
   3258 
   3259 	increment = 1;
   3260     }
   3261     else {
   3262 	/* Symbol is already available in the current package, just update */
   3263 	atom = current->data.atom;
   3264 
   3265 	increment = 0;
   3266     }
   3267 
   3268     /* If importing an important system variable */
   3269     atom->watch = symbol->data.atom->watch;
   3270 
   3271     /* Update constant flag */
   3272     atom->constant = symbol->data.atom->constant;
   3273 
   3274     /* Set home-package and unique-atom associated with symbol */
   3275     atom->package = symbol->data.atom->package;
   3276     atom->object = symbol->data.atom->object;
   3277 
   3278     if (symbol->data.atom->a_object)
   3279 	atom->a_object = 1;
   3280     if (symbol->data.atom->a_function)
   3281 	atom->a_function = 1;
   3282     else if (symbol->data.atom->a_builtin)
   3283 	atom->a_builtin = 1;
   3284     else if (symbol->data.atom->a_compiled)
   3285 	atom->a_compiled = 1;
   3286     if (symbol->data.atom->a_property)
   3287 	atom->a_property = 1;
   3288     if (symbol->data.atom->a_defsetf)
   3289 	atom->a_defsetf = 1;
   3290     if (symbol->data.atom->a_defstruct)
   3291 	atom->a_defstruct = 1;
   3292 
   3293     if (increment)
   3294 	/* Increase reference count, more than one package using the symbol */
   3295 	LispIncrementAtomReference(symbol->data.atom);
   3296 }
   3297 
   3298 /* symbol must be of type LispAtom_t */
   3299 void
   3300 LispExportSymbol(LispObj *symbol)
   3301 {
   3302     /* This does not automatically export symbols to another package using
   3303      * the symbols of the current package */
   3304     symbol->data.atom->ext = 1;
   3305 }
   3306 
   3307 #ifdef __GNUC__
   3308 LispObj *
   3309 LispGetVar(LispObj *atom)
   3310 {
   3311     return (LispDoGetVar(atom));
   3312 }
   3313 
   3314 static INLINE LispObj *
   3315 LispDoGetVar(LispObj *atom)
   3316 #else
   3317 #define LispDoGetVar LispGetVar
   3318 LispObj *
   3319 LispGetVar(LispObj *atom)
   3320 #endif
   3321 {
   3322     LispAtom *name;
   3323     int i, base, offset;
   3324     Atom_id id;
   3325 
   3326     name = atom->data.atom;
   3327     if (name->constant && name->package == lisp__data.keyword)
   3328 	return (atom);
   3329 
   3330     /* XXX offset should be stored elsewhere, it is unique, like the string
   3331      * pointer. Unless a multi-thread interface is implemented (where
   3332      * multiple stacks would be required, the offset value should be
   3333      * stored with the string, so that a few cpu cicles could be saved
   3334      * by initializing the value to -1, and only searching for the symbol
   3335      * binding if it is not -1, and if no binding is found, because the
   3336      * lexical scope was left, reset offset to -1. */
   3337     offset = name->offset;
   3338     id = name->key;
   3339     base = lisp__data.env.lex;
   3340     i = lisp__data.env.head - 1;
   3341 
   3342     if (offset <= i && (offset >= base || name->dyn) &&
   3343 	lisp__data.env.names[offset] == id)
   3344 	return (lisp__data.env.values[offset]);
   3345 
   3346     for (; i >= base; i--)
   3347 	if (lisp__data.env.names[i] == id) {
   3348 	    name->offset = i;
   3349 
   3350 	    return (lisp__data.env.values[i]);
   3351 	}
   3352 
   3353     if (name->dyn) {
   3354 	/* Keep searching as maybe a rebound dynamic variable */
   3355 	for (; i >= 0; i--)
   3356 	    if (lisp__data.env.names[i] == id) {
   3357 		name->offset = i;
   3358 
   3359 	    return (lisp__data.env.values[i]);
   3360 	}
   3361 
   3362 	if (name->a_object) {
   3363 	    /* Check for a symbol defined as special, but not yet bound. */
   3364 	    if (name->property->value == UNBOUND)
   3365 		return (NULL);
   3366 
   3367 	    return (name->property->value);
   3368 	}
   3369     }
   3370 
   3371     return (name->a_object ? name->property->value : NULL);
   3372 }
   3373 
   3374 #ifdef DEBUGGER
   3375 /* Same code as LispDoGetVar, but returns the address of the pointer to
   3376  * the object value. Used only by the debugger */
   3377 void *
   3378 LispGetVarAddr(LispObj *atom)
   3379 {
   3380     LispAtom *name;
   3381     int i, base;
   3382     Atom_id id;
   3383 
   3384     name = atom->data.atom;
   3385     if (name->constant && name->package == lisp__data.keyword)
   3386 	return (&atom);
   3387 
   3388     id = name->string;
   3389 
   3390     i = lisp__data.env.head - 1;
   3391     for (base = lisp__data.env.lex; i >= base; i--)
   3392 	if (lisp__data.env.names[i] == id)
   3393 	    return (&(lisp__data.env.values[i]));
   3394 
   3395     if (name->dyn) {
   3396 	for (; i >= 0; i--)
   3397 	    if (lisp__data.env.names[i] == id)
   3398 		return (&(lisp__data.env.values[i]));
   3399 
   3400 	if (name->a_object) {
   3401 	    /* Check for a symbol defined as special, but not yet bound */
   3402 	    if (name->property->value == UNBOUND)
   3403 		return (NULL);
   3404 
   3405 	    return (&(name->property->value));
   3406 	}
   3407     }
   3408 
   3409     return (name->a_object ? &(name->property->value) : NULL);
   3410 }
   3411 #endif
   3412 
   3413 /* Only removes global variables. To be called by makunbound
   3414  * Local variables are unbounded once their block is closed anyway.
   3415  */
   3416 void
   3417 LispUnsetVar(LispObj *atom)
   3418 {
   3419     LispAtom *name = atom->data.atom;
   3420 
   3421     if (name->package) {
   3422 	int i;
   3423 	LispPackage *pack = name->package->data.package.package;
   3424 
   3425 	for (i = pack->glb.length - 1; i > 0; i--)
   3426 	    if (pack->glb.pairs[i] == atom) {
   3427 		LispRemAtomObjectProperty(name);
   3428 		--pack->glb.length;
   3429 		if (i < pack->glb.length)
   3430 		    memmove(pack->glb.pairs + i, pack->glb.pairs + i + 1,
   3431 			    sizeof(LispObj*) * (pack->glb.length - i));
   3432 
   3433 		/* unset hint about dynamically binded variable */
   3434 		if (name->dyn)
   3435 		    name->dyn = 0;
   3436 		break;
   3437 	    }
   3438     }
   3439 }
   3440 
   3441 LispObj *
   3442 LispAddVar(LispObj *atom, LispObj *obj)
   3443 {
   3444     if (lisp__data.env.length >= lisp__data.env.space)
   3445 	LispMoreEnvironment();
   3446 
   3447     LispDoAddVar(atom, obj);
   3448 
   3449     return (obj);
   3450 }
   3451 
   3452 static INLINE void
   3453 LispDoAddVar(LispObj *symbol, LispObj *value)
   3454 {
   3455     LispAtom *atom = symbol->data.atom;
   3456 
   3457     atom->offset = lisp__data.env.length;
   3458     lisp__data.env.values[lisp__data.env.length] = value;
   3459     lisp__data.env.names[lisp__data.env.length++] = atom->key;
   3460 }
   3461 
   3462 LispObj *
   3463 LispSetVar(LispObj *atom, LispObj *obj)
   3464 {
   3465     LispPackage *pack;
   3466     LispAtom *name;
   3467     int i, base, offset;
   3468     Atom_id id;
   3469 
   3470     name = atom->data.atom;
   3471     offset = name->offset;
   3472     id = name->key;
   3473     base = lisp__data.env.lex;
   3474     i = lisp__data.env.head - 1;
   3475 
   3476     if (offset <= i && (offset >= base || name->dyn) &&
   3477 	lisp__data.env.names[offset] == id)
   3478 	return (lisp__data.env.values[offset] = obj);
   3479 
   3480     for (; i >= base; i--)
   3481 	if (lisp__data.env.names[i] == id) {
   3482 	    name->offset = i;
   3483 
   3484 	    return (lisp__data.env.values[i] = obj);
   3485 	}
   3486 
   3487     if (name->dyn) {
   3488 	for (; i >= 0; i--)
   3489 	    if (lisp__data.env.names[i] == id)
   3490 		return (lisp__data.env.values[i] = obj);
   3491 
   3492 	if (name->watch) {
   3493 	    LispSetAtomObjectProperty(name, obj);
   3494 
   3495 	    return (obj);
   3496 	}
   3497 
   3498 	return (SETVALUE(name, obj));
   3499     }
   3500 
   3501     if (name->a_object) {
   3502 	if (name->watch) {
   3503 	    LispSetAtomObjectProperty(name, obj);
   3504 
   3505 	    return (obj);
   3506 	}
   3507 
   3508 	return (SETVALUE(name, obj));
   3509     }
   3510 
   3511     LispSetAtomObjectProperty(name, obj);
   3512 
   3513     pack = name->package->data.package.package;
   3514     if (pack->glb.length >= pack->glb.space)
   3515 	LispMoreGlobals(pack);
   3516 
   3517     pack->glb.pairs[pack->glb.length++] = atom;
   3518 
   3519     return (obj);
   3520 }
   3521 
   3522 void
   3523 LispProclaimSpecial(LispObj *atom, LispObj *value, LispObj *doc)
   3524 {
   3525     int i = 0, dyn, glb;
   3526     LispAtom *name;
   3527     LispPackage *pack;
   3528 
   3529     glb = 0;
   3530     name = atom->data.atom;
   3531     pack = name->package->data.package.package;
   3532     dyn = name->dyn;
   3533 
   3534     if (!dyn) {
   3535 	/* Note: don't check if a local variable already is using the symbol */
   3536 	for (i = pack->glb.length - 1; i >= 0; i--)
   3537 	    if (pack->glb.pairs[i] == atom) {
   3538 		glb = 1;
   3539 		break;
   3540 	    }
   3541     }
   3542 
   3543     if (dyn) {
   3544 	if (name->property->value == UNBOUND && value)
   3545 	    /* if variable was just made special, but not bounded */
   3546 	    LispSetAtomObjectProperty(name, value);
   3547     }
   3548     else if (glb)
   3549 	/* Already a global variable, but not marked as special.
   3550 	 * Set hint about dynamically binded variable. */
   3551 	name->dyn = 1;
   3552     else {
   3553 	/* create new special variable */
   3554 	LispSetAtomObjectProperty(name, value ? value : UNBOUND);
   3555 
   3556 	if (pack->glb.length >= pack->glb.space)
   3557 	    LispMoreGlobals(pack);
   3558 
   3559 	pack->glb.pairs[pack->glb.length] = atom;
   3560 	++pack->glb.length;
   3561 	/* set hint about possibly dynamically binded variable */
   3562 	name->dyn = 1;
   3563     }
   3564 
   3565     if (doc != NIL)
   3566 	LispAddDocumentation(atom, doc, LispDocVariable);
   3567 }
   3568 
   3569 void
   3570 LispDefconstant(LispObj *atom, LispObj *value, LispObj *doc)
   3571 {
   3572     int i;
   3573     LispAtom *name = atom->data.atom;
   3574     LispPackage *pack = name->package->data.package.package;
   3575 
   3576     /* Unset hint about dynamically binded variable, if set. */
   3577     name->dyn = 0;
   3578 
   3579     /* Check if variable is bounded as a global variable */
   3580     for (i = pack->glb.length - 1; i >= 0; i--)
   3581 	if (pack->glb.pairs[i] == atom)
   3582 	    break;
   3583 
   3584     if (i < 0) {
   3585 	/* Not a global variable */
   3586 	if (pack->glb.length >= pack->glb.space)
   3587 	    LispMoreGlobals(pack);
   3588 
   3589 	pack->glb.pairs[pack->glb.length] = atom;
   3590 	++pack->glb.length;
   3591     }
   3592 
   3593     /* If already a constant variable */
   3594     if (name->constant && name->a_object && name->property->value != value)
   3595 	LispWarning("constant %s is being redefined", STROBJ(atom));
   3596     else
   3597 	name->constant = 1;
   3598 
   3599     /* Set constant value */
   3600     LispSetAtomObjectProperty(name, value);
   3601 
   3602     if (doc != NIL)
   3603 	LispAddDocumentation(atom, doc, LispDocVariable);
   3604 }
   3605 
   3606 void
   3607 LispAddDocumentation(LispObj *symbol, LispObj *documentation, LispDocType_t type)
   3608 {
   3609     int length;
   3610     char *string;
   3611     LispAtom *atom;
   3612     LispObj *object;
   3613 
   3614     if (!SYMBOLP(symbol) || !STRINGP(documentation))
   3615 	LispDestroy("DOCUMENTATION: invalid argument");
   3616 
   3617     atom = symbol->data.atom;
   3618     if (atom->documentation[type])
   3619 	LispRemDocumentation(symbol, type);
   3620 
   3621     /* allocate documentation in atomseg */
   3622     if (atomseg.freeobj == NIL)
   3623 	LispAllocSeg(&atomseg, pagesize);
   3624     length = STRLEN(documentation);
   3625     string = LispMalloc(length);
   3626     memcpy(string, THESTR(documentation), length);
   3627     string[length] = '\0';
   3628     object = atomseg.freeobj;
   3629     atomseg.freeobj = CDR(object);
   3630     --atomseg.nfree;
   3631 
   3632     object->type = LispString_t;
   3633     THESTR(object) = string;
   3634     STRLEN(object) = length;
   3635     object->data.string.writable = 0;
   3636     atom->documentation[type] = object;
   3637     LispMused(string);
   3638 }
   3639 
   3640 void
   3641 LispRemDocumentation(LispObj *symbol, LispDocType_t type)
   3642 {
   3643     LispAtom *atom;
   3644 
   3645     if (!SYMBOLP(symbol))
   3646 	LispDestroy("DOCUMENTATION: invalid argument");
   3647 
   3648     atom = symbol->data.atom;
   3649     if (atom->documentation[type]) {
   3650 	/* reclaim object to atomseg */
   3651 	free(THESTR(atom->documentation[type]));
   3652 	CDR(atom->documentation[type]) = atomseg.freeobj;
   3653 	atomseg.freeobj = atom->documentation[type];
   3654 	atom->documentation[type] = NULL;
   3655 	++atomseg.nfree;
   3656     }
   3657 }
   3658 
   3659 LispObj *
   3660 LispGetDocumentation(LispObj *symbol, LispDocType_t type)
   3661 {
   3662     LispAtom *atom;
   3663 
   3664     if (!SYMBOLP(symbol))
   3665 	LispDestroy("DOCUMENTATION: invalid argument");
   3666 
   3667     atom = symbol->data.atom;
   3668 
   3669     return (atom->documentation[type] ? atom->documentation[type] : NIL);
   3670 }
   3671 
   3672 LispObj *
   3673 LispReverse(LispObj *list)
   3674 {
   3675     LispObj *tmp, *res = NIL;
   3676 
   3677     while (list != NIL) {
   3678 	tmp = CDR(list);
   3679 	CDR(list) = res;
   3680 	res = list;
   3681 	list = tmp;
   3682     }
   3683 
   3684     return (res);
   3685 }
   3686 
   3687 LispBlock *
   3688 LispBeginBlock(LispObj *tag, LispBlockType type)
   3689 {
   3690     LispBlock *block;
   3691     unsigned blevel = lisp__data.block.block_level + 1;
   3692 
   3693     if (blevel > lisp__data.block.block_size) {
   3694 	LispBlock **blk;
   3695 
   3696 	if (blevel > MAX_STACK_DEPTH)
   3697 	    LispDestroy("stack overflow");
   3698 
   3699 	DISABLE_INTERRUPTS();
   3700 	blk = realloc(lisp__data.block.block, sizeof(LispBlock*) * (blevel + 1));
   3701 
   3702 	block = NULL;
   3703 	if (blk == NULL || (block = malloc(sizeof(LispBlock))) == NULL) {
   3704 	    ENABLE_INTERRUPTS();
   3705 	    LispDestroy("out of memory");
   3706 	}
   3707 	lisp__data.block.block = blk;
   3708 	lisp__data.block.block[lisp__data.block.block_size] = block;
   3709 	lisp__data.block.block_size = blevel;
   3710 	ENABLE_INTERRUPTS();
   3711     }
   3712     block = lisp__data.block.block[lisp__data.block.block_level];
   3713     if (type == LispBlockCatch && !CONSTANTP(tag)) {
   3714 	tag = EVAL(tag);
   3715 	lisp__data.protect.objects[lisp__data.protect.length++] = tag;
   3716     }
   3717     block->type = type;
   3718     block->tag = tag;
   3719     block->stack = lisp__data.stack.length;
   3720     block->protect = lisp__data.protect.length;
   3721     block->block_level = lisp__data.block.block_level;
   3722 
   3723     lisp__data.block.block_level = blevel;
   3724 
   3725 #ifdef DEBUGGER
   3726     if (lisp__data.debugging) {
   3727 	block->debug_level = lisp__data.debug_level;
   3728 	block->debug_step = lisp__data.debug_step;
   3729     }
   3730 #endif
   3731 
   3732     return (block);
   3733 }
   3734 
   3735 void
   3736 LispEndBlock(LispBlock *block)
   3737 {
   3738     lisp__data.protect.length = block->protect;
   3739     lisp__data.block.block_level = block->block_level;
   3740 
   3741 #ifdef DEBUGGER
   3742     if (lisp__data.debugging) {
   3743 	if (lisp__data.debug_level >= block->debug_level) {
   3744 	    while (lisp__data.debug_level > block->debug_level) {
   3745 		DBG = CDR(DBG);
   3746 		--lisp__data.debug_level;
   3747 	    }
   3748 	}
   3749 	lisp__data.debug_step = block->debug_step;
   3750     }
   3751 #endif
   3752 }
   3753 
   3754 void
   3755 LispBlockUnwind(LispBlock *block)
   3756 {
   3757     LispBlock *unwind;
   3758     int blevel = lisp__data.block.block_level;
   3759 
   3760     while (blevel > 0) {
   3761 	unwind = lisp__data.block.block[--blevel];
   3762 	if (unwind->type == LispBlockProtect) {
   3763 	    BLOCKJUMP(unwind);
   3764 	}
   3765 	if (unwind == block)
   3766 	    /* jump above unwind block */
   3767 	    break;
   3768     }
   3769 }
   3770 
   3771 static LispObj *
   3772 LispEvalBackquoteObject(LispObj *argument, int list, int quote)
   3773 {
   3774     LispObj *result = argument, *object;
   3775 
   3776     if (!POINTERP(argument))
   3777 	return (argument);
   3778 
   3779     else if (XCOMMAP(argument)) {
   3780 	/* argument may need to be evaluated */
   3781 
   3782 	int atlist;
   3783 
   3784 	if (!list && argument->data.comma.atlist)
   3785 	    /* cannot append, not in a list */
   3786 	    LispDestroy("EVAL: ,@ only allowed on lists");
   3787 
   3788 	--quote;
   3789 	if (quote < 0)
   3790 	    LispDestroy("EVAL: comma outside of backquote");
   3791 
   3792 	result = object = argument->data.comma.eval;
   3793 	atlist = COMMAP(object) && object->data.comma.atlist;
   3794 
   3795 	if (POINTERP(result) && (XCOMMAP(result) || XBACKQUOTEP(result)))
   3796 	    /* nested commas, reduce 1 level, or backquote,
   3797 	     * don't call LispEval or quote argument will be reset */
   3798 	    result = LispEvalBackquoteObject(object, 0, quote);
   3799 
   3800 	else if (quote == 0)
   3801 	   /* just evaluate it */
   3802 	    result = EVAL(result);
   3803 
   3804 	if (quote != 0)
   3805 	    result = result == object ? argument : COMMA(result, atlist);
   3806     }
   3807 
   3808     else if (XBACKQUOTEP(argument)) {
   3809 	object = argument->data.quote;
   3810 
   3811 	result = LispEvalBackquote(object, quote + 1);
   3812 	if (quote)
   3813 	    result = result == object ? argument : BACKQUOTE(result);
   3814     }
   3815 
   3816     else if (XQUOTEP(argument) && POINTERP(argument->data.quote) &&
   3817 	     (XCOMMAP(argument->data.quote) ||
   3818 	      XBACKQUOTEP(argument->data.quote) ||
   3819 	      XCONSP(argument->data.quote))) {
   3820 	/* ensures `',sym to be the same as `(quote ,sym) */
   3821 	object = argument->data.quote;
   3822 
   3823 	result = LispEvalBackquote(argument->data.quote, quote);
   3824 	result = result == object ? argument : QUOTE(result);
   3825     }
   3826 
   3827     return (result);
   3828 }
   3829 
   3830 LispObj *
   3831 LispEvalBackquote(LispObj *argument, int quote)
   3832 {
   3833     int protect;
   3834     LispObj *result, *object, *cons, *cdr;
   3835 
   3836     if (!CONSP(argument))
   3837 	return (LispEvalBackquoteObject(argument, 0, quote));
   3838 
   3839     result = cdr = NIL;
   3840     protect = lisp__data.protect.length;
   3841 
   3842     /* always generate a new list for the result, even if nothing
   3843      * is evaluated. It is not expected to use backqoutes when
   3844      * not required. */
   3845 
   3846     /* reserve a GC protected slot for the result */
   3847     if (protect + 1 >= lisp__data.protect.space)
   3848 	LispMoreProtects();
   3849     lisp__data.protect.objects[lisp__data.protect.length++] = NIL;
   3850 
   3851     for (cons = argument; ; cons = CDR(cons)) {
   3852 	/* if false, last argument, and if cons is not NIL, a dotted list */
   3853 	int list = CONSP(cons), insert;
   3854 
   3855 	if (list)
   3856 	    object = CAR(cons);
   3857 	else
   3858 	    object = cons;
   3859 
   3860 	if (COMMAP(object))
   3861 	    /* need to insert list elements in result, not just cons it? */
   3862 	    insert = object->data.comma.atlist;
   3863 	else
   3864 	    insert = 0;
   3865 
   3866 	/* evaluate object, if required */
   3867 	if (CONSP(object))
   3868 	    object = LispEvalBackquote(object, quote);
   3869 	else
   3870 	    object = LispEvalBackquoteObject(object, insert, quote);
   3871 
   3872 	if (result == NIL) {
   3873 	    /* if starting result list */
   3874 	    if (!insert) {
   3875 		if (list)
   3876 		    result = cdr = CONS(object, NIL);
   3877 		else
   3878 		    result = cdr = object;
   3879 		/* gc protect result */
   3880 		lisp__data.protect.objects[protect] = result;
   3881 	    }
   3882 	    else {
   3883 		if (!CONSP(object)) {
   3884 		    result = cdr = object;
   3885 		    /* gc protect result */
   3886 		    lisp__data.protect.objects[protect] = result;
   3887 		}
   3888 		else {
   3889 		    result = cdr = CONS(CAR(object), NIL);
   3890 		    /* gc protect result */
   3891 		    lisp__data.protect.objects[protect] = result;
   3892 
   3893 		    /* add remaining elements to result */
   3894 		    for (object = CDR(object);
   3895 			 CONSP(object);
   3896 			 object = CDR(object)) {
   3897 			RPLACD(cdr, CONS(CAR(object), NIL));
   3898 			cdr = CDR(cdr);
   3899 		    }
   3900 		    if (object != NIL) {
   3901 			/* object was a dotted list */
   3902 			RPLACD(cdr, object);
   3903 			cdr = CDR(cdr);
   3904 		    }
   3905 		}
   3906 	    }
   3907 	}
   3908 	else {
   3909 	    if (!CONSP(cdr))
   3910 		LispDestroy("EVAL: cannot append to %s", STROBJ(cdr));
   3911 
   3912 	    if (!insert) {
   3913 		if (list) {
   3914 		    RPLACD(cdr, CONS(object, NIL));
   3915 		    cdr = CDR(cdr);
   3916 		}
   3917 		else {
   3918 		    RPLACD(cdr, object);
   3919 		    cdr = object;
   3920 		}
   3921 	    }
   3922 	    else {
   3923 		if (!CONSP(object)) {
   3924 		    RPLACD(cdr, object);
   3925 		    /* if object is NIL, it is a empty list appended, not
   3926 		     * creating a dotted list. */
   3927 		    if (object != NIL)
   3928 			cdr = object;
   3929 		}
   3930 		else {
   3931 		    for (; CONSP(object); object = CDR(object)) {
   3932 			RPLACD(cdr, CONS(CAR(object), NIL));
   3933 			cdr = CDR(cdr);
   3934 		    }
   3935 		    if (object != NIL) {
   3936 			/* object was a dotted list */
   3937 			RPLACD(cdr, object);
   3938 			cdr = CDR(cdr);
   3939 		    }
   3940 		}
   3941 	    }
   3942 	}
   3943 
   3944 	/* if last argument list element processed */
   3945 	if (!list)
   3946 	    break;
   3947     }
   3948 
   3949     lisp__data.protect.length = protect;
   3950 
   3951     return (result);
   3952 }
   3953 
   3954 void
   3955 LispMoreEnvironment(void)
   3956 {
   3957     Atom_id *names;
   3958     LispObj **values;
   3959 
   3960     DISABLE_INTERRUPTS();
   3961     names = realloc(lisp__data.env.names,
   3962 		    (lisp__data.env.space + 256) * sizeof(Atom_id));
   3963     if (names != NULL) {
   3964 	values = realloc(lisp__data.env.values,
   3965 			 (lisp__data.env.space + 256) * sizeof(LispObj*));
   3966 	if (values != NULL) {
   3967 	    lisp__data.env.names = names;
   3968 	    lisp__data.env.values = values;
   3969 	    lisp__data.env.space += 256;
   3970 	    ENABLE_INTERRUPTS();
   3971 	    return;
   3972 	}
   3973 	else
   3974 	    free(names);
   3975     }
   3976     ENABLE_INTERRUPTS();
   3977     LispDestroy("out of memory");
   3978 }
   3979 
   3980 void
   3981 LispMoreStack(void)
   3982 {
   3983     LispObj **values;
   3984 
   3985     DISABLE_INTERRUPTS();
   3986     values = realloc(lisp__data.stack.values,
   3987 		     (lisp__data.stack.space + 256) * sizeof(LispObj*));
   3988     if (values == NULL) {
   3989 	ENABLE_INTERRUPTS();
   3990 	LispDestroy("out of memory");
   3991     }
   3992     lisp__data.stack.values = values;
   3993     lisp__data.stack.space += 256;
   3994     ENABLE_INTERRUPTS();
   3995 }
   3996 
   3997 void
   3998 LispMoreGlobals(LispPackage *pack)
   3999 {
   4000     LispObj **pairs;
   4001 
   4002     DISABLE_INTERRUPTS();
   4003     pairs = realloc(pack->glb.pairs,
   4004 		    (pack->glb.space + 256) * sizeof(LispObj*));
   4005     if (pairs == NULL) {
   4006 	ENABLE_INTERRUPTS();
   4007 	LispDestroy("out of memory");
   4008     }
   4009     pack->glb.pairs = pairs;
   4010     pack->glb.space += 256;
   4011     ENABLE_INTERRUPTS();
   4012 }
   4013 
   4014 void
   4015 LispMoreProtects(void)
   4016 {
   4017     LispObj **objects;
   4018 
   4019     DISABLE_INTERRUPTS();
   4020     objects = realloc(lisp__data.protect.objects,
   4021 		      (lisp__data.protect.space + 256) * sizeof(LispObj*));
   4022     if (objects == NULL) {
   4023 	ENABLE_INTERRUPTS();
   4024 	LispDestroy("out of memory");
   4025     }
   4026     lisp__data.protect.objects = objects;
   4027     lisp__data.protect.space += 256;
   4028     ENABLE_INTERRUPTS();
   4029 }
   4030 
   4031 static int
   4032 LispMakeEnvironment(LispArgList *alist, LispObj *values,
   4033 		    LispObj *name, int eval, int builtin)
   4034 {
   4035     char *desc;
   4036     int i, count, base;
   4037     LispObj **symbols, **defaults, **sforms;
   4038 
   4039 #define BUILTIN_ARGUMENT(value)				\
   4040     lisp__data.stack.values[lisp__data.stack.length++] = value
   4041 
   4042 /* If the index value is from register variables, this
   4043  * can save some cpu time. Useful for normal arguments
   4044  * that are the most common, and thus the ones that
   4045  * consume more time in LispMakeEnvironment. */
   4046 #define BUILTIN_NO_EVAL_ARGUMENT(index, value)		\
   4047     lisp__data.stack.values[index] = value
   4048 
   4049 #define NORMAL_ARGUMENT(symbol, value)			\
   4050     LispDoAddVar(symbol, value)
   4051 
   4052     if (builtin) {
   4053 	base = lisp__data.stack.length;
   4054 	if (base + alist->num_arguments > lisp__data.stack.space) {
   4055 	    do
   4056 		LispMoreStack();
   4057 	    while (base + alist->num_arguments > lisp__data.stack.space);
   4058 	}
   4059     }
   4060     else {
   4061 	base = lisp__data.env.length;
   4062 	if (base + alist->num_arguments > lisp__data.env.space) {
   4063 	    do
   4064 		LispMoreEnvironment();
   4065 	    while (base + alist->num_arguments > lisp__data.env.space);
   4066 	}
   4067     }
   4068 
   4069     desc = alist->description;
   4070     switch (*desc++) {
   4071 	case '.':
   4072 	    goto normal_label;
   4073 	case 'o':
   4074 	    goto optional_label;
   4075 	case 'k':
   4076 	    goto key_label;
   4077 	case 'r':
   4078 	    goto rest_label;
   4079 	case 'a':
   4080 	    goto aux_label;
   4081 	default:
   4082 	    goto done_label;
   4083     }
   4084 
   4085 
   4086     /* Code below is done in several almost identical loops, to avoid
   4087      * checking the value of the arguments eval and builtin too much times */
   4088 
   4089 
   4090     /* Normal arguments */
   4091 normal_label:
   4092     i = 0;
   4093     count = alist->normals.num_symbols;
   4094     if (builtin) {
   4095 	if (eval) {
   4096 	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
   4097 		BUILTIN_ARGUMENT(EVAL(CAR(values)));
   4098 	    }
   4099 	}
   4100 	else {
   4101 	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
   4102 		BUILTIN_NO_EVAL_ARGUMENT(base + i, CAR(values));
   4103 	    }
   4104 	    /* macro BUILTIN_NO_EVAL_ARGUMENT does not update
   4105 	     * lisp__data.stack.length, as there is no risk of GC while
   4106 	     * adding the arguments. */
   4107 	    lisp__data.stack.length += i;
   4108 	}
   4109     }
   4110     else {
   4111 	symbols = alist->normals.symbols;
   4112 	if (eval) {
   4113 	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
   4114 		NORMAL_ARGUMENT(symbols[i], EVAL(CAR(values)));
   4115 	    }
   4116 	}
   4117 	else {
   4118 	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
   4119 		NORMAL_ARGUMENT(symbols[i], CAR(values));
   4120 	    }
   4121 	}
   4122     }
   4123     if (i < count)
   4124 	LispDestroy("%s: too few arguments", STROBJ(name));
   4125 
   4126     switch (*desc++) {
   4127 	case 'o':
   4128 	    goto optional_label;
   4129 	case 'k':
   4130 	    goto key_label;
   4131 	case 'r':
   4132 	    goto rest_label;
   4133 	case 'a':
   4134 	    goto aux_label;
   4135 	default:
   4136 	    goto done_label;
   4137     }
   4138 
   4139     /* &OPTIONAL */
   4140 optional_label:
   4141     i = 0;
   4142     count = alist->optionals.num_symbols;
   4143     defaults = alist->optionals.defaults;
   4144     sforms = alist->optionals.sforms;
   4145     if (builtin) {
   4146 	if (eval) {
   4147 	    for (; i < count && CONSP(values); i++, values = CDR(values))
   4148 		BUILTIN_ARGUMENT(EVAL(CAR(values)));
   4149 	    for (; i < count; i++)
   4150 		BUILTIN_ARGUMENT(UNSPEC);
   4151 	}
   4152 	else {
   4153 	    for (; i < count && CONSP(values); i++, values = CDR(values))
   4154 		BUILTIN_ARGUMENT(CAR(values));
   4155 	    for (; i < count; i++)
   4156 		BUILTIN_ARGUMENT(UNSPEC);
   4157 	}
   4158     }
   4159     else {
   4160 	symbols = alist->optionals.symbols;
   4161 	if (eval) {
   4162 	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
   4163 		NORMAL_ARGUMENT(symbols[i], EVAL(CAR(values)));
   4164 		if (sforms[i]) {
   4165 		    NORMAL_ARGUMENT(sforms[i], T);
   4166 		}
   4167 	    }
   4168 	}
   4169 	else {
   4170 	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
   4171 		NORMAL_ARGUMENT(symbols[i], CAR(values));
   4172 		if (sforms[i]) {
   4173 		    NORMAL_ARGUMENT(sforms[i], T);
   4174 		}
   4175 	    }
   4176 	}
   4177 
   4178 	/* default arguments are evaluated for macros */
   4179 	for (; i < count; i++) {
   4180 	    if (!CONSTANTP(defaults[i])) {
   4181 		int head = lisp__data.env.head;
   4182 		int lex = lisp__data.env.lex;
   4183 
   4184 		lisp__data.env.lex = base;
   4185 		lisp__data.env.head = lisp__data.env.length;
   4186 		NORMAL_ARGUMENT(symbols[i], EVAL(defaults[i]));
   4187 		lisp__data.env.head = head;
   4188 		lisp__data.env.lex = lex;
   4189 	    }
   4190 	    else {
   4191 		NORMAL_ARGUMENT(symbols[i], defaults[i]);
   4192 	    }
   4193 	    if (sforms[i]) {
   4194 		NORMAL_ARGUMENT(sforms[i], NIL);
   4195 	    }
   4196 	}
   4197     }
   4198     switch (*desc++) {
   4199 	case 'k':
   4200 	    goto key_label;
   4201 	case 'r':
   4202 	    goto rest_label;
   4203 	case 'a':
   4204 	    goto aux_label;
   4205 	default:
   4206 	    goto done_label;
   4207     }
   4208 
   4209     /* &KEY */
   4210 key_label:
   4211     {
   4212 	int argc, nused;
   4213 	LispObj *val, *karg, **keys;
   4214 
   4215 	/* Count number of remaining arguments */
   4216 	for (karg = values, argc = 0; CONSP(karg); karg = CDR(karg), argc++) {
   4217 	    karg = CDR(karg);
   4218 	    if (!CONSP(karg))
   4219 		LispDestroy("%s: &KEY needs arguments as pairs",
   4220 			    STROBJ(name));
   4221 	}
   4222 
   4223 
   4224 	/* OPTIMIZATION:
   4225 	 * Builtin functions require that the keyword be in the keyword package.
   4226 	 * User functions don't need the arguments being pushed in the stack
   4227 	 * in the declared order (bytecode expects it...).
   4228 	 * XXX Error checking should be done elsewhere, code may be looping
   4229 	 * and doing error check here may consume too much cpu time.
   4230 	 * XXX Would also be good to already have the arguments specified in
   4231 	 * the correct order.
   4232 	 */
   4233 
   4234 
   4235 	nused = 0;
   4236 	val = NIL;
   4237 	count = alist->keys.num_symbols;
   4238 	symbols = alist->keys.symbols;
   4239 	defaults = alist->keys.defaults;
   4240 	sforms = alist->keys.sforms;
   4241 	if (builtin) {
   4242 
   4243 	    /* Arguments must be created in the declared order */
   4244 	    i = 0;
   4245 	    if (eval) {
   4246 		for (; i < count; i++) {
   4247 		    for (karg = values; CONSP(karg); karg = CDDR(karg)) {
   4248 			/* This is only true if both point to the
   4249 			 * same symbol in the keyword package. */
   4250 			if (symbols[i] == CAR(karg)) {
   4251 			    if (karg == values)
   4252 				values = CDDR(values);
   4253 			    ++nused;
   4254 			    BUILTIN_ARGUMENT(EVAL(CADR(karg)));
   4255 			    goto keyword_builtin_eval_used_label;
   4256 			}
   4257 		    }
   4258 		    BUILTIN_ARGUMENT(UNSPEC);
   4259 keyword_builtin_eval_used_label:;
   4260 		}
   4261 	    }
   4262 	    else {
   4263 		for (; i < count; i++) {
   4264 		    for (karg = values; CONSP(karg); karg = CDDR(karg)) {
   4265 			if (symbols[i] == CAR(karg)) {
   4266 			    if (karg == values)
   4267 				values = CDDR(values);
   4268 			    ++nused;
   4269 			    BUILTIN_ARGUMENT(CADR(karg));
   4270 			    goto keyword_builtin_used_label;
   4271 			}
   4272 		    }
   4273 		    BUILTIN_ARGUMENT(UNSPEC);
   4274 keyword_builtin_used_label:;
   4275 		}
   4276 	    }
   4277 
   4278 	    if (argc != nused) {
   4279 		/* Argument(s) may be incorrectly specified, or specified
   4280 		 * twice (what is not an error). */
   4281 		for (karg = values; CONSP(karg); karg = CDDR(karg)) {
   4282 		    val = CAR(karg);
   4283 		    if (KEYWORDP(val)) {
   4284 			for (i = 0; i < count; i++)
   4285 			    if (symbols[i] == val)
   4286 				break;
   4287 		    }
   4288 		    else
   4289 			/* Just make the error test true */
   4290 			i = count;
   4291 
   4292 		    if (i == count)
   4293 			goto invalid_keyword_label;
   4294 		}
   4295 	    }
   4296 	}
   4297 
   4298 #if 0
   4299 	else {
   4300 	    /* The base offset of the atom in the stack, to check for
   4301 	     * keywords specified twice. */
   4302 	    LispObj *symbol;
   4303 	    int offset = lisp__data.env.length;
   4304 
   4305 	    keys = alist->keys.keys;
   4306 	    for (karg = values; CONSP(karg); karg = CDDR(karg)) {
   4307 		symbol = CAR(karg);
   4308 		if (SYMBOLP(symbol)) {
   4309 		    /* Must be a keyword, but even if it is a keyword, may
   4310 		     * be a typo, so assume it is correct. If it is not
   4311 		     * in the argument list, it is an error. */
   4312 		    for (i = 0; i < count; i++) {
   4313 			if (!keys[i] && symbols[i] == symbol) {
   4314 			    LispAtom *atom = symbol->data.atom;
   4315 
   4316 			    /* Symbol found in the argument list. */
   4317 			    if (atom->offset >= offset &&
   4318 				atom->offset < offset + nused &&
   4319 				lisp__data.env.names[atom->offset] ==
   4320 				atom->string)
   4321 				/* Specified more than once... */
   4322 				goto keyword_duplicated_label;
   4323 			    break;
   4324 			}
   4325 		    }
   4326 		}
   4327 		else {
   4328 		    Atom_id id;
   4329 
   4330 		    if (!QUOTEP(symbol) || !SYMBOLP(val = symbol->data.quote)) {
   4331 			/* Bad argument. */
   4332 			val = symbol;
   4333 			goto invalid_keyword_label;
   4334 		    }
   4335 
   4336 		    id = ATOMID(val);
   4337 		    for (i = 0; i < count; i++) {
   4338 			if (keys[i] && ATOMID(keys[i]) == id) {
   4339 			    LispAtom *atom = val->data.atom;
   4340 
   4341 			    /* Symbol found in the argument list. */
   4342 			    if (atom->offset >= offset &&
   4343 				atom->offset < offset + nused &&
   4344 				lisp__data.env.names[atom->offset] ==
   4345 				atom->string)
   4346 				/* Specified more than once... */
   4347 				goto keyword_duplicated_label;
   4348 			    break;
   4349 			}
   4350 		    }
   4351 		}
   4352 		if (i == count) {
   4353 		    /* Argument specification not found. */
   4354 		    val = symbol;
   4355 		    goto invalid_keyword_label;
   4356 		}
   4357 		++nused;
   4358 		if (eval) {
   4359 		    NORMAL_ARGUMENT(symbols[i], EVAL(CADR(karg)));
   4360 		}
   4361 		else {
   4362 		    NORMAL_ARGUMENT(symbols[i], CADR(karg));
   4363 		}
   4364 		if (sforms[i]) {
   4365 		    NORMAL_ARGUMENT(sforms[i], T);
   4366 		}
   4367 keyword_duplicated_label:;
   4368 	    }
   4369 
   4370 	    /* Add variables that were not specified in the function call. */
   4371 	    if (nused < count) {
   4372 		int j;
   4373 
   4374 		for (i = 0; i < count; i++) {
   4375 		    Atom_id id = ATOMID(symbols[i]);
   4376 
   4377 		    for (j = offset + nused - 1; j >= offset; j--) {
   4378 			if (lisp__data.env.names[j] == id)
   4379 			    break;
   4380 		    }
   4381 
   4382 		    if (j < offset) {
   4383 			/* Argument not specified. Use default value */
   4384 
   4385 			/* default arguments are evaluated for macros */
   4386 			if (!CONSTANTP(defaults[i])) {
   4387 			    int head = lisp__data.env.head;
   4388 			    int lex = lisp__data.env.lex;
   4389 
   4390 			    lisp__data.env.lex = base;
   4391 			    lisp__data.env.head = lisp__data.env.length;
   4392 			    NORMAL_ARGUMENT(symbols[i], EVAL(defaults[i]));
   4393 			    lisp__data.env.head = head;
   4394 			    lisp__data.env.lex = lex;
   4395 			}
   4396 			else {
   4397 			    NORMAL_ARGUMENT(symbols[i], defaults[i]);
   4398 			}
   4399 			if (sforms[i]) {
   4400 			    NORMAL_ARGUMENT(sforms[i], NIL);
   4401 			}
   4402 		    }
   4403 		}
   4404 	    }
   4405 	}
   4406 #else
   4407 	else {
   4408 	    int varset;
   4409 
   4410 	    sforms = alist->keys.sforms;
   4411 	    keys = alist->keys.keys;
   4412 
   4413 	    /* Add variables */
   4414 	    for (i = 0; i < alist->keys.num_symbols; i++) {
   4415 		val = defaults[i];
   4416 		varset = 0;
   4417 		if (keys[i]) {
   4418 		    Atom_id atom = ATOMID(keys[i]);
   4419 
   4420 		    /* Special keyword specification, need to compare ATOMID
   4421 		     * and keyword specification must be a quoted object */
   4422 		    for (karg = values; CONSP(karg); karg = CDR(karg)) {
   4423 			val = CAR(karg);
   4424 		 	if (QUOTEP(val) && atom == ATOMID(val->data.quote)) {
   4425 			    val = CADR(karg);
   4426 			    varset = 1;
   4427 			    ++nused;
   4428 			    break;
   4429 			}
   4430 			karg = CDR(karg);
   4431 		    }
   4432 		}
   4433 
   4434 		else {
   4435 		    /* Normal keyword specification, can compare object pointers,
   4436 		     * as they point to the same object in the keyword package */
   4437 		    for (karg = values; CONSP(karg); karg = CDR(karg)) {
   4438 			/* Don't check if argument is a valid keyword or
   4439 			 * special quoted keyword */
   4440 			if (symbols[i] == CAR(karg)) {
   4441 			    val = CADR(karg);
   4442 			    varset = 1;
   4443 			    ++nused;
   4444 			    break;
   4445 			}
   4446 			karg = CDR(karg);
   4447 		    }
   4448 		}
   4449 
   4450 		/* Add the variable to environment */
   4451 		if (varset) {
   4452 		    NORMAL_ARGUMENT(symbols[i], eval ? EVAL(val) : val);
   4453 		    if (sforms[i]) {
   4454 			NORMAL_ARGUMENT(sforms[i], T);
   4455 		    }
   4456 		}
   4457 		else {
   4458 		    /* default arguments are evaluated for macros */
   4459 		    if (!CONSTANTP(val)) {
   4460 			int head = lisp__data.env.head;
   4461 			int lex = lisp__data.env.lex;
   4462 
   4463 			lisp__data.env.lex = base;
   4464 			lisp__data.env.head = lisp__data.env.length;
   4465 			NORMAL_ARGUMENT(symbols[i], EVAL(val));
   4466 			lisp__data.env.head = head;
   4467 			lisp__data.env.lex = lex;
   4468 		    }
   4469 		    else {
   4470 			NORMAL_ARGUMENT(symbols[i], val);
   4471 		    }
   4472 		    if (sforms[i]) {
   4473 			NORMAL_ARGUMENT(sforms[i], NIL);
   4474 		    }
   4475 		}
   4476 	    }
   4477 
   4478 	    if (argc != nused) {
   4479 		/* Argument(s) may be incorrectly specified, or specified
   4480 		 * twice (what is not an error). */
   4481 		for (karg = values; CONSP(karg); karg = CDDR(karg)) {
   4482 		    val = CAR(karg);
   4483 		    if (KEYWORDP(val)) {
   4484 			for (i = 0; i < count; i++)
   4485 			    if (symbols[i] == val)
   4486 				break;
   4487 		    }
   4488 		    else if (QUOTEP(val) && SYMBOLP(val->data.quote)) {
   4489 			Atom_id atom = ATOMID(val->data.quote);
   4490 
   4491 			for (i = 0; i < count; i++)
   4492 			    if (ATOMID(keys[i]) == atom)
   4493 				break;
   4494 		    }
   4495 		    else
   4496 			/* Just make the error test true */
   4497 			i = count;
   4498 
   4499 		    if (i == count)
   4500 			goto invalid_keyword_label;
   4501 		}
   4502 	    }
   4503 	}
   4504 #endif
   4505 	goto check_aux_label;
   4506 
   4507 invalid_keyword_label:
   4508 	{
   4509 	    /* If not in argument specification list... */
   4510 	    char function_name[36];
   4511 
   4512 	    strcpy(function_name, STROBJ(name));
   4513 	    LispDestroy("%s: %s is an invalid keyword",
   4514 			function_name, STROBJ(val));
   4515 	}
   4516     }
   4517 
   4518 check_aux_label:
   4519     if (*desc == 'a') {
   4520 	/* &KEY uses all remaining arguments */
   4521 	values = NIL;
   4522 	goto aux_label;
   4523     }
   4524     goto finished_label;
   4525 
   4526     /* &REST */
   4527 rest_label:
   4528     if (!CONSP(values)) {
   4529 	if (builtin) {
   4530 	    BUILTIN_ARGUMENT(values);
   4531 	}
   4532 	else {
   4533 	    NORMAL_ARGUMENT(alist->rest, values);
   4534 	}
   4535 	values = NIL;
   4536     }
   4537     /* always allocate a new list, don't know if it will be retained */
   4538     else if (eval) {
   4539 	LispObj *cons;
   4540 
   4541 	cons = CONS(EVAL(CAR(values)), NIL);
   4542 	if (builtin) {
   4543 	    BUILTIN_ARGUMENT(cons);
   4544 	}
   4545 	else {
   4546 	    NORMAL_ARGUMENT(alist->rest, cons);
   4547 	}
   4548 	values = CDR(values);
   4549 	for (; CONSP(values); values = CDR(values)) {
   4550 	    RPLACD(cons, CONS(EVAL(CAR(values)), NIL));
   4551 	    cons = CDR(cons);
   4552 	}
   4553     }
   4554     else {
   4555 	LispObj *cons;
   4556 
   4557 	cons = CONS(CAR(values), NIL);
   4558 	if (builtin) {
   4559 	    BUILTIN_ARGUMENT(cons);
   4560 	}
   4561 	else {
   4562 	    NORMAL_ARGUMENT(alist->rest, cons);
   4563 	}
   4564 	values = CDR(values);
   4565 	for (; CONSP(values); values = CDR(values)) {
   4566 	    RPLACD(cons, CONS(CAR(values), NIL));
   4567 	    cons = CDR(cons);
   4568 	}
   4569     }
   4570     if (*desc != 'a')
   4571 	goto finished_label;
   4572 
   4573     /* &AUX */
   4574 aux_label:
   4575     i = 0;
   4576     count = alist->auxs.num_symbols;
   4577     defaults = alist->auxs.initials;
   4578     symbols = alist->auxs.symbols;
   4579     {
   4580 	int lex = lisp__data.env.lex;
   4581 
   4582 	lisp__data.env.lex = base;
   4583 	lisp__data.env.head = lisp__data.env.length;
   4584 	for (; i < count; i++) {
   4585 	    NORMAL_ARGUMENT(symbols[i], EVAL(defaults[i]));
   4586 	    ++lisp__data.env.head;
   4587 	}
   4588 	lisp__data.env.lex = lex;
   4589     }
   4590 
   4591 done_label:
   4592     if (CONSP(values))
   4593 	LispDestroy("%s: too many arguments", STROBJ(name));
   4594 
   4595 finished_label:
   4596     if (builtin)
   4597 	lisp__data.stack.base = base;
   4598     else {
   4599 	lisp__data.env.head = lisp__data.env.length;
   4600     }
   4601 #undef BULTIN_ARGUMENT
   4602 #undef NORMAL_ARGUMENT
   4603 #undef BUILTIN_NO_EVAL_ARGUMENT
   4604 
   4605     return (base);
   4606 }
   4607 
   4608 LispObj *
   4609 LispFuncall(LispObj *function, LispObj *arguments, int eval)
   4610 {
   4611     LispAtom *atom;
   4612     LispArgList *alist;
   4613     LispBuiltin *builtin;
   4614     LispObj *lambda, *result;
   4615     int macro, base;
   4616 
   4617 #ifdef DEBUGGER
   4618     if (lisp__data.debugging)
   4619 	LispDebugger(LispDebugCallBegin, function, arguments);
   4620 #endif
   4621 
   4622     switch (OBJECT_TYPE(function)) {
   4623 	case LispFunction_t:
   4624 	    function = function->data.atom->object;
   4625 	case LispAtom_t:
   4626 	    atom = function->data.atom;
   4627 	    if (atom->a_builtin) {
   4628 		builtin = atom->property->fun.builtin;
   4629 
   4630 		if (eval)
   4631 		    eval = builtin->type != LispMacro;
   4632 		base = LispMakeEnvironment(atom->property->alist,
   4633 					   arguments, function, eval, 1);
   4634 		if (builtin->multiple_values) {
   4635 		    RETURN_COUNT = 0;
   4636 		    result = builtin->function(builtin);
   4637 		}
   4638 		else {
   4639 		    result = builtin->function(builtin);
   4640 		    RETURN_COUNT = 0;
   4641 		}
   4642 		lisp__data.stack.base = lisp__data.stack.length = base;
   4643 	    }
   4644 	    else if (atom->a_compiled) {
   4645 		int lex = lisp__data.env.lex;
   4646 		lambda = atom->property->fun.function;
   4647 		alist = atom->property->alist;
   4648 
   4649 		base = LispMakeEnvironment(alist, arguments, function, eval, 0);
   4650 		lisp__data.env.lex = base;
   4651 		result = LispExecuteBytecode(lambda);
   4652 		lisp__data.env.lex = lex;
   4653 		lisp__data.env.head = lisp__data.env.length = base;
   4654 	    }
   4655 	    else if (atom->a_function) {
   4656 		lambda = atom->property->fun.function;
   4657 		macro = lambda->funtype == LispMacro;
   4658 		alist = atom->property->alist;
   4659 
   4660 		lambda = lambda->data.lambda.code;
   4661 		if (eval)
   4662 		    eval = !macro;
   4663 		base = LispMakeEnvironment(alist, arguments, function, eval, 0);
   4664 		result = LispRunFunMac(function, lambda, macro, base);
   4665 	    }
   4666 	    else if (atom->a_defstruct &&
   4667 		     atom->property->structure.function != STRUCT_NAME) {
   4668 		LispObj cons;
   4669 
   4670 		if (atom->property->structure.function == STRUCT_CONSTRUCTOR)
   4671 		    atom = Omake_struct->data.atom;
   4672 		else if (atom->property->structure.function == STRUCT_CHECK)
   4673 		    atom = Ostruct_type->data.atom;
   4674 		else
   4675 		    atom = Ostruct_access->data.atom;
   4676 		builtin = atom->property->fun.builtin;
   4677 
   4678 		cons.type = LispCons_t;
   4679 		cons.data.cons.cdr = arguments;
   4680 		if (eval) {
   4681 		    LispObj quote;
   4682 
   4683 		    quote.type = LispQuote_t;
   4684 		    quote.data.quote = function;
   4685 		    cons.data.cons.car = &quote;
   4686 		    base = LispMakeEnvironment(atom->property->alist,
   4687 					       &cons, function, 1, 1);
   4688 		}
   4689 		else {
   4690 		    cons.data.cons.car = function;
   4691 		    base = LispMakeEnvironment(atom->property->alist,
   4692 					       &cons, function, 0, 1);
   4693 		}
   4694 		result = builtin->function(builtin);
   4695 		RETURN_COUNT = 0;
   4696 		lisp__data.stack.length = base;
   4697 	    }
   4698 	    else {
   4699 		LispDestroy("EVAL: the function %s is not defined",
   4700 			    STROBJ(function));
   4701 		/*NOTREACHED*/
   4702 		result = NIL;
   4703 	    }
   4704 	    break;
   4705 	case LispLambda_t:
   4706 	    lambda = function->data.lambda.code;
   4707 	    alist = (LispArgList*)function->data.lambda.name->data.opaque.data;
   4708 	    base = LispMakeEnvironment(alist, arguments, function, eval, 0);
   4709 	    result = LispRunFunMac(function, lambda, 0, base);
   4710 	    break;
   4711 	case LispCons_t:
   4712 	    if (CAR(function) == Olambda) {
   4713 		function = EVAL(function);
   4714 		if (LAMBDAP(function)) {
   4715 		    GC_ENTER();
   4716 
   4717 		    GC_PROTECT(function);
   4718 		    lambda = function->data.lambda.code;
   4719 		    alist = (LispArgList*)function->data.lambda.name->data.opaque.data;
   4720 		    base = LispMakeEnvironment(alist, arguments, NIL, eval, 0);
   4721 		    result = LispRunFunMac(NIL, lambda, 0, base);
   4722 		    GC_LEAVE();
   4723 		    break;
   4724 		}
   4725 	    }
   4726 	default:
   4727 	    LispDestroy("EVAL: %s is invalid as a function",
   4728 			STROBJ(function));
   4729 	    /*NOTREACHED*/
   4730 	    result = NIL;
   4731 	    break;
   4732     }
   4733 
   4734 #ifdef DEBUGGER
   4735     if (lisp__data.debugging)
   4736 	LispDebugger(LispDebugCallEnd, function, result);
   4737 #endif
   4738 
   4739     return (result);
   4740 }
   4741 
   4742 LispObj *
   4743 LispEval(LispObj *object)
   4744 {
   4745     LispObj *result;
   4746 
   4747     switch (OBJECT_TYPE(object)) {
   4748 	case LispAtom_t:
   4749 	    if ((result = LispDoGetVar(object)) == NULL)
   4750 		LispDestroy("EVAL: the variable %s is unbound", STROBJ(object));
   4751 	    break;
   4752 	case LispCons_t:
   4753 	    result = LispFuncall(CAR(object), CDR(object), 1);
   4754 	    break;
   4755 	case LispQuote_t:
   4756 	    result = object->data.quote;
   4757 	    break;
   4758 	case LispFunctionQuote_t:
   4759 	    result = object->data.quote;
   4760 	    if (SYMBOLP(result))
   4761 		result = LispSymbolFunction(result);
   4762 	    else if (CONSP(result) && CAR(result) == Olambda)
   4763 		result = EVAL(result);
   4764 	    else
   4765 		LispDestroy("FUNCTION: %s is not a function", STROBJ(result));
   4766 	    break;
   4767 	case LispBackquote_t:
   4768 	    result = LispEvalBackquote(object->data.quote, 1);
   4769 	    break;
   4770 	case LispComma_t:
   4771 	    LispDestroy("EVAL: comma outside of backquote");
   4772 	default:
   4773 	    result = object;
   4774 	    break;
   4775     }
   4776 
   4777     return (result);
   4778 }
   4779 
   4780 LispObj *
   4781 LispApply1(LispObj *function, LispObj *argument)
   4782 {
   4783     LispObj arguments;
   4784 
   4785     arguments.type = LispCons_t;
   4786     arguments.data.cons.car = argument;
   4787     arguments.data.cons.cdr = NIL;
   4788 
   4789     return (LispFuncall(function, &arguments, 0));
   4790 }
   4791 
   4792 LispObj *
   4793 LispApply2(LispObj *function, LispObj *argument1, LispObj *argument2)
   4794 {
   4795     LispObj arguments, cdr;
   4796 
   4797     arguments.type = cdr.type = LispCons_t;
   4798     arguments.data.cons.car = argument1;
   4799     arguments.data.cons.cdr = &cdr;
   4800     cdr.data.cons.car = argument2;
   4801     cdr.data.cons.cdr = NIL;
   4802 
   4803     return (LispFuncall(function, &arguments, 0));
   4804 }
   4805 
   4806 LispObj *
   4807 LispApply3(LispObj *function, LispObj *arg1, LispObj *arg2, LispObj *arg3)
   4808 {
   4809     LispObj arguments, car, cdr;
   4810 
   4811     arguments.type = car.type = cdr.type = LispCons_t;
   4812     arguments.data.cons.car = arg1;
   4813     arguments.data.cons.cdr = &car;
   4814     car.data.cons.car = arg2;
   4815     car.data.cons.cdr = &cdr;
   4816     cdr.data.cons.car = arg3;
   4817     cdr.data.cons.cdr = NIL;
   4818 
   4819     return (LispFuncall(function, &arguments, 0));
   4820 }
   4821 
   4822 static LispObj *
   4823 LispRunFunMac(LispObj *name, LispObj *code, int macro, int base)
   4824 {
   4825     LispObj *result = NIL;
   4826 
   4827     if (!macro) {
   4828 	int lex = lisp__data.env.lex;
   4829 	int did_jump = 1;
   4830 	LispBlock *block;
   4831 
   4832 	block = LispBeginBlock(name, LispBlockClosure);
   4833 	lisp__data.env.lex = base;
   4834 	if (setjmp(block->jmp) == 0) {
   4835 	    for (; CONSP(code); code = CDR(code))
   4836 		result = EVAL(CAR(code));
   4837 	    did_jump = 0;
   4838 	}
   4839 	LispEndBlock(block);
   4840 	if (did_jump)
   4841 	    result = lisp__data.block.block_ret;
   4842 	lisp__data.env.lex = lex;
   4843 	lisp__data.env.head = lisp__data.env.length = base;
   4844     }
   4845     else {
   4846 	GC_ENTER();
   4847 
   4848 	for (; CONSP(code); code = CDR(code))
   4849 	    result = EVAL(CAR(code));
   4850 	/* FIXME this does not work if macro has &aux variables,
   4851 	 * but there are several other missing features, like
   4852 	 * destructuring and more lambda list keywords still missing.
   4853 	 * TODO later.
   4854 	 */
   4855 	lisp__data.env.head = lisp__data.env.length = base;
   4856 
   4857 	GC_PROTECT(result);
   4858 	result = EVAL(result);
   4859 	GC_LEAVE();
   4860     }
   4861 
   4862     return (result);
   4863 }
   4864 
   4865 LispObj *
   4866 LispRunSetf(LispArgList *alist, LispObj *setf, LispObj *place, LispObj *value)
   4867 {
   4868     GC_ENTER();
   4869     LispObj *store, *code, *expression, *result, quote;
   4870     int base;
   4871 
   4872     code = setf->data.lambda.code;
   4873     store = setf->data.lambda.data;
   4874 
   4875     quote.type = LispQuote_t;
   4876     quote.data.quote = value;
   4877     LispDoAddVar(CAR(store), &quote);
   4878     ++lisp__data.env.head;
   4879     base = LispMakeEnvironment(alist, place, Oexpand_setf_method, 0, 0);
   4880 
   4881     /* build expansion macro */
   4882     expression = NIL;
   4883     for (; CONSP(code); code = CDR(code))
   4884 	expression = EVAL(CAR(code));
   4885 
   4886     /* Minus 1 to pop the added variable */
   4887     lisp__data.env.head = lisp__data.env.length = base - 1;
   4888 
   4889     /* protect expansion, and executes it */
   4890     GC_PROTECT(expression);
   4891     result = EVAL(expression);
   4892     GC_LEAVE();
   4893 
   4894     return (result);
   4895 }
   4896 
   4897 LispObj *
   4898 LispRunSetfMacro(LispAtom *atom, LispObj *arguments, LispObj *value)
   4899 {
   4900     int base;
   4901     GC_ENTER();
   4902     LispObj *place, *body, *result, quote;
   4903 
   4904     place = NIL;
   4905     base = LispMakeEnvironment(atom->property->alist,
   4906 			       arguments, atom->object, 0, 0);
   4907     body = atom->property->fun.function->data.lambda.code;
   4908 
   4909     /* expand macro body */
   4910     for (; CONSP(body); body = CDR(body))
   4911 	place = EVAL(CAR(body));
   4912 
   4913     /* protect expansion */
   4914     GC_PROTECT(place);
   4915 
   4916     /* restore environment */
   4917     lisp__data.env.head = lisp__data.env.length = base;
   4918 
   4919     /* value is already evaluated */
   4920     quote.type = LispQuote_t;
   4921     quote.data.quote = value;
   4922 
   4923     /* call setf again */
   4924     result = APPLY2(Osetf, place, &quote);
   4925 
   4926     GC_LEAVE();
   4927 
   4928     return (result);
   4929 }
   4930 
   4931 char *
   4932 LispStrObj(LispObj *object)
   4933 {
   4934     static int first = 1;
   4935     static char buffer[34];
   4936     static LispObj stream;
   4937     static LispString string;
   4938 
   4939     if (first) {
   4940 	stream.type = LispStream_t;
   4941 	stream.data.stream.source.string = &string;
   4942 	stream.data.stream.pathname = NIL;
   4943 	stream.data.stream.type = LispStreamString;
   4944 	stream.data.stream.readable = 0;
   4945 	stream.data.stream.writable = 1;
   4946 
   4947 	string.string = buffer;
   4948 	string.fixed = 1;
   4949 	string.space = sizeof(buffer) - 1;
   4950 	first = 0;
   4951     }
   4952 
   4953     string.length = string.output = 0;
   4954 
   4955     LispWriteObject(&stream, object);
   4956 
   4957     /* make sure string is nul terminated */
   4958     string.string[string.length] = '\0';
   4959     if (string.length >= 32) {
   4960 	if (buffer[0] == '(')
   4961 	    strcpy(buffer + 27, "...)");
   4962 	else
   4963 	    strcpy(buffer + 28, "...");
   4964     }
   4965 
   4966     return (buffer);
   4967 }
   4968 
   4969 void
   4970 LispPrint(LispObj *object, LispObj *stream, int newline)
   4971 {
   4972     if (stream != NIL && !STREAMP(stream)) {
   4973 	LispDestroy("PRINT: %s is not a stream", STROBJ(stream));
   4974     }
   4975     if (newline && LispGetColumn(stream))
   4976 	LispWriteChar(stream, '\n');
   4977     LispWriteObject(stream, object);
   4978     if (stream == NIL || (stream->data.stream.type == LispStreamStandard &&
   4979 	stream->data.stream.source.file == Stdout))
   4980 	LispFflush(Stdout);
   4981 }
   4982 
   4983 void
   4984 LispUpdateResults(LispObj *cod, LispObj *res)
   4985 {
   4986     LispSetVar(RUN[2], LispGetVar(RUN[1]));
   4987     LispSetVar(RUN[1], LispGetVar(RUN[0]));
   4988     LispSetVar(RUN[0], cod);
   4989 
   4990     LispSetVar(RES[2], LispGetVar(RES[1]));
   4991     LispSetVar(RES[1], LispGetVar(RES[0]));
   4992     LispSetVar(RES[0], res);
   4993 }
   4994 
   4995 void
   4996 LispSignalHandler(int signum)
   4997 {
   4998     LispSignal(signum);
   4999 }
   5000 
   5001 void
   5002 LispSignal(int signum)
   5003 {
   5004     const char *errstr;
   5005     char buffer[32];
   5006 
   5007     if (lisp__disable_int) {
   5008 	lisp__interrupted = signum;
   5009 	return;
   5010     }
   5011     switch (signum) {
   5012 	case SIGINT:
   5013 	    errstr = "interrupted";
   5014 	    break;
   5015 	case SIGFPE:
   5016 	    errstr = "floating point exception";
   5017 	    break;
   5018 	default:
   5019 	    sprintf(buffer, "signal %d received", signum);
   5020 	    errstr = buffer;
   5021 	    break;
   5022     }
   5023     LispDestroy("%s", errstr);
   5024 }
   5025 
   5026 void
   5027 LispDisableInterrupts(void)
   5028 {
   5029     ++lisp__disable_int;
   5030 }
   5031 
   5032 void
   5033 LispEnableInterrupts(void)
   5034 {
   5035     --lisp__disable_int;
   5036     if (lisp__disable_int <= 0 && lisp__interrupted)
   5037 	LispSignal(lisp__interrupted);
   5038 }
   5039 
   5040 void
   5041 LispMachine(void)
   5042 {
   5043     LispObj *cod, *obj;
   5044 
   5045     lisp__data.sigint = signal(SIGINT, LispSignalHandler);
   5046     lisp__data.sigfpe = signal(SIGFPE, LispSignalHandler);
   5047 
   5048     /*CONSTCOND*/
   5049     while (1) {
   5050 	if (sigsetjmp(lisp__data.jmp, 1) == 0) {
   5051 	    lisp__data.running = 1;
   5052 	    if (lisp__data.interactive && lisp__data.prompt) {
   5053 		LispFputs(Stdout, lisp__data.prompt);
   5054 		LispFflush(Stdout);
   5055 	    }
   5056 	    if ((cod = LispRead()) != NULL) {
   5057 		obj = EVAL(cod);
   5058 		if (lisp__data.interactive) {
   5059 		    if (RETURN_COUNT >= 0)
   5060 			LispPrint(obj, NIL, 1);
   5061 		    if (RETURN_COUNT > 0) {
   5062 			int i;
   5063 
   5064 			for (i = 0; i < RETURN_COUNT; i++)
   5065 			    LispPrint(RETURN(i), NIL, 1);
   5066 		    }
   5067 		    LispUpdateResults(cod, obj);
   5068 		    if (LispGetColumn(NIL))
   5069 			LispWriteChar(NIL, '\n');
   5070 		}
   5071 	    }
   5072 	    LispTopLevel();
   5073 	}
   5074 	if (lisp__data.eof)
   5075 	    break;
   5076     }
   5077 
   5078     signal(SIGINT, lisp__data.sigint);
   5079     signal(SIGFPE, lisp__data.sigfpe);
   5080 
   5081     lisp__data.running = 0;
   5082 }
   5083 
   5084 void *
   5085 LispExecute(char *str)
   5086 {
   5087     static LispObj stream;
   5088     static LispString string;
   5089     static int first = 1;
   5090 
   5091     int running = lisp__data.running;
   5092     LispObj *result, *cod, *obj, **presult = &result;
   5093 
   5094     if (str == NULL || *str == '\0')
   5095 	return (NIL);
   5096 
   5097     *presult = NIL;
   5098 
   5099     if (first) {
   5100 	stream.type = LispStream_t;
   5101 	stream.data.stream.source.string = &string;
   5102 	stream.data.stream.pathname = NIL;
   5103 	stream.data.stream.type = LispStreamString;
   5104 	stream.data.stream.readable = 1;
   5105 	stream.data.stream.writable = 0;
   5106 	string.output = 0;
   5107 	first = 0;
   5108     }
   5109     string.string = str;
   5110     string.length = strlen(str);
   5111     string.input = 0;
   5112 
   5113     LispPushInput(&stream);
   5114     if (!running) {
   5115 	lisp__data.running = 1;
   5116 	if (sigsetjmp(lisp__data.jmp, 1) != 0)
   5117 	    return (NULL);
   5118     }
   5119 
   5120     cod = COD;
   5121     /*CONSTCOND*/
   5122     while (1) {
   5123 	if ((obj = LispRead()) != NULL) {
   5124 	    result = EVAL(obj);
   5125 	    COD = cod;
   5126 	}
   5127 	if (lisp__data.eof)
   5128 	    break;
   5129     }
   5130     LispPopInput(&stream);
   5131 
   5132     lisp__data.running = running;
   5133 
   5134     return (result);
   5135 }
   5136 
   5137 void
   5138 LispBegin(void)
   5139 {
   5140     int i;
   5141     LispAtom *atom;
   5142     char results[4];
   5143     LispObj *object, *path, *ext;
   5144 
   5145     pagesize = LispGetPageSize();
   5146     segsize = pagesize / sizeof(LispObj);
   5147 
   5148     lisp__data.strings = hash_new(STRTBLSZ, NULL);
   5149     lisp__data.opqs = hash_new(STRTBLSZ, NULL);
   5150 
   5151     /* Initialize memory management */
   5152     lisp__data.mem.mem = (void**)calloc(lisp__data.mem.space = 16,
   5153 					sizeof(void*));
   5154     lisp__data.mem.index = lisp__data.mem.level = 0;
   5155 
   5156     /* Allow LispGetVar to check ATOMID() of unbound symbols */
   5157     UNBOUND->data.atom = (LispAtom*)LispCalloc(1, sizeof(LispAtom));
   5158     LispMused(UNBOUND->data.atom);
   5159     noproperty.value = UNBOUND;
   5160 
   5161     if (Stdin == NULL)
   5162 	Stdin = LispFdopen(0, FILE_READ);
   5163     if (Stdout == NULL)
   5164 	Stdout = LispFdopen(1, FILE_WRITE | FILE_BUFFERED);
   5165     if (Stderr == NULL)
   5166 	Stderr = LispFdopen(2, FILE_WRITE);
   5167 
   5168     /* minimum number of free cells after GC
   5169      * if sizeof(LispObj) == 16, than a minfree of 1024 would try to keep
   5170      * at least 16Kb of free cells.
   5171      */
   5172     minfree = 1024;
   5173 
   5174     MOD = COD = PRO = NIL;
   5175 #ifdef DEBUGGER
   5176     DBG = BRK = NIL;
   5177 #endif
   5178 
   5179     /* allocate initial object cells */
   5180     LispAllocSeg(&objseg, minfree);
   5181     LispAllocSeg(&atomseg, pagesize);
   5182     lisp__data.gc.average = segsize;
   5183 
   5184     /* Don't allow gc in initialization */
   5185     GCDisable();
   5186 
   5187     /* Initialize package system, the current package is LISP. Order of
   5188      * initialization is very important here */
   5189     lisp__data.lisp = LispNewPackage(STRING("LISP"),
   5190 				     CONS(STRING("COMMON-LISP"), NIL));
   5191 
   5192     /* Make LISP package the current one */
   5193     lisp__data.pack = lisp__data.savepack =
   5194 	lisp__data.lisp->data.package.package;
   5195 
   5196     /* Allocate space in LISP package */
   5197     LispMoreGlobals(lisp__data.pack);
   5198 
   5199     /* Allocate  space for multiple value return values */
   5200     lisp__data.returns.values = malloc(MULTIPLE_VALUES_LIMIT *
   5201 				       (sizeof(LispObj*)));
   5202 
   5203     /*  Create the first atom, do it "by hand" because macro "PACKAGE"
   5204      * cannot yet be used. */
   5205     atom = LispGetPermAtom("*PACKAGE*");
   5206     lisp__data.package = atomseg.freeobj;
   5207     atomseg.freeobj = CDR(atomseg.freeobj);
   5208     --atomseg.nfree;
   5209     lisp__data.package->type = LispAtom_t;
   5210     lisp__data.package->data.atom = atom;
   5211     atom->object = lisp__data.package;
   5212     atom->package = lisp__data.lisp;
   5213 
   5214     /* Set package list, to be used by (gc) and (list-all-packages) */
   5215     PACK = CONS(lisp__data.lisp, NIL);
   5216 
   5217     /* Make *PACKAGE* a special variable */
   5218     LispProclaimSpecial(lisp__data.package, lisp__data.lisp, NIL);
   5219 
   5220 	/* Value of macro "PACKAGE" is now properly available */
   5221 
   5222     /* Changing *PACKAGE* is like calling (in-package) */
   5223     lisp__data.package->data.atom->watch = 1;
   5224 
   5225     /* And available to other packages */
   5226     LispExportSymbol(lisp__data.package);
   5227 
   5228     /* Initialize stacks */
   5229     LispMoreEnvironment();
   5230     LispMoreStack();
   5231 
   5232     /* Create the KEYWORD package */
   5233     Skeyword = GETATOMID("KEYWORD");
   5234     object = LispNewPackage(STRING(Skeyword->value),
   5235 			    CONS(STRING(""), NIL));
   5236 
   5237     /* Update list of packages */
   5238     PACK = CONS(object, PACK);
   5239 
   5240     /* Allow easy access to the keyword package */
   5241     lisp__data.keyword = object;
   5242     lisp__data.key = object->data.package.package;
   5243 
   5244     /* Initialize some static important symbols */
   5245     Olambda		= STATIC_ATOM("LAMBDA");
   5246     LispExportSymbol(Olambda);
   5247     Okey		= STATIC_ATOM("&KEY");
   5248     LispExportSymbol(Okey);
   5249     Orest		= STATIC_ATOM("&REST");
   5250     LispExportSymbol(Orest);
   5251     Ooptional		= STATIC_ATOM("&OPTIONAL");
   5252     LispExportSymbol(Ooptional);
   5253     Oaux		= STATIC_ATOM("&AUX");
   5254     LispExportSymbol(Oaux);
   5255     Kunspecific		= KEYWORD("UNSPECIFIC");
   5256     Oformat		= STATIC_ATOM("FORMAT");
   5257     Oexpand_setf_method	= STATIC_ATOM("EXPAND-SETF-METHOD");
   5258 
   5259     Omake_struct	= STATIC_ATOM("MAKE-STRUCT");
   5260     Ostruct_access	= STATIC_ATOM("STRUCT-ACCESS");
   5261     Ostruct_store	= STATIC_ATOM("STRUCT-STORE");
   5262     Ostruct_type	= STATIC_ATOM("STRUCT-TYPE");
   5263     Smake_struct	= ATOMID(Omake_struct);
   5264     Sstruct_access	= ATOMID(Ostruct_access);
   5265     Sstruct_store	= ATOMID(Ostruct_store);
   5266     Sstruct_type	= ATOMID(Ostruct_type);
   5267 
   5268     /* Initialize some static atom ids */
   5269     Snil		= GETATOMID("NIL");
   5270     St			= GETATOMID("T");
   5271     Saux		= ATOMID(Oaux);
   5272     Skey		= ATOMID(Okey);
   5273     Soptional		= ATOMID(Ooptional);
   5274     Srest		= ATOMID(Orest);
   5275     Sand		= GETATOMID("AND");
   5276     Sor			= GETATOMID("OR");
   5277     Snot		= GETATOMID("NOT");
   5278     Satom		= GETATOMID("ATOM");
   5279     Ssymbol		= GETATOMID("SYMBOL");
   5280     Sinteger		= GETATOMID("INTEGER");
   5281     Scharacter		= GETATOMID("CHARACTER");
   5282     Sstring		= GETATOMID("STRING");
   5283     Slist		= GETATOMID("LIST");
   5284     Scons		= GETATOMID("CONS");
   5285     Svector		= GETATOMID("VECTOR");
   5286     Sarray		= GETATOMID("ARRAY");
   5287     Sstruct		= GETATOMID("STRUCT");
   5288     Sfunction		= GETATOMID("FUNCTION");
   5289     Spathname		= GETATOMID("PATHNAME");
   5290     Srational		= GETATOMID("RATIONAL");
   5291     Sfloat		= GETATOMID("FLOAT");
   5292     Scomplex		= GETATOMID("COMPLEX");
   5293     Sopaque		= GETATOMID("OPAQUE");
   5294     Sdefault		= GETATOMID("DEFAULT");
   5295 
   5296     LispArgList_t	= LispRegisterOpaqueType("LispArgList*");
   5297 
   5298     lisp__data.unget = malloc(sizeof(LispUngetInfo*));
   5299     lisp__data.unget[0] = calloc(1, sizeof(LispUngetInfo));
   5300     lisp__data.nunget = 1;
   5301 
   5302     lisp__data.standard_input = ATOM2("*STANDARD-INPUT*");
   5303     SINPUT = STANDARDSTREAM(Stdin, lisp__data.standard_input, STREAM_READ);
   5304     lisp__data.interactive = 1;
   5305     LispProclaimSpecial(lisp__data.standard_input,
   5306 			lisp__data.input_list = SINPUT, NIL);
   5307     LispExportSymbol(lisp__data.standard_input);
   5308 
   5309     lisp__data.standard_output = ATOM2("*STANDARD-OUTPUT*");
   5310     SOUTPUT = STANDARDSTREAM(Stdout, lisp__data.standard_output, STREAM_WRITE);
   5311     LispProclaimSpecial(lisp__data.standard_output,
   5312 			lisp__data.output_list = SOUTPUT, NIL);
   5313     LispExportSymbol(lisp__data.standard_output);
   5314 
   5315     object = ATOM2("*STANDARD-ERROR*");
   5316     lisp__data.error_stream = STANDARDSTREAM(Stderr, object, STREAM_WRITE);
   5317     LispProclaimSpecial(object, lisp__data.error_stream, NIL);
   5318     LispExportSymbol(object);
   5319 
   5320     lisp__data.modules = ATOM2("*MODULES*");
   5321     LispProclaimSpecial(lisp__data.modules, MOD, NIL);
   5322     LispExportSymbol(lisp__data.modules);
   5323 
   5324     object = CONS(KEYWORD("UNIX"), CONS(KEYWORD("XEDIT"), NIL));
   5325     lisp__data.features = ATOM2("*FEATURES*");
   5326     LispProclaimSpecial(lisp__data.features, object, NIL);
   5327     LispExportSymbol(lisp__data.features);
   5328 
   5329     object = ATOM2("MULTIPLE-VALUES-LIMIT");
   5330     LispDefconstant(object, FIXNUM(MULTIPLE_VALUES_LIMIT + 1), NIL);
   5331     LispExportSymbol(object);
   5332 
   5333     /* Reenable gc */
   5334     GCEnable();
   5335 
   5336     LispBytecodeInit();
   5337     LispPackageInit();
   5338     LispCoreInit();
   5339     LispMathInit();
   5340     LispPathnameInit();
   5341     LispStreamInit();
   5342     LispRegexInit();
   5343     LispWriteInit();
   5344 
   5345     lisp__data.prompt = isatty(0) ? "> " : NULL;
   5346 
   5347     lisp__data.errexit = !lisp__data.interactive;
   5348 
   5349     if (lisp__data.interactive) {
   5350 	/* add +, ++, +++, *, **, and *** */
   5351 	for (i = 0; i < 3; i++) {
   5352 	    results[i] = '+';
   5353 	    results[i + 1] = '\0';
   5354 	    RUN[i] = ATOM(results);
   5355 	    LispSetVar(RUN[i], NIL);
   5356 	    LispExportSymbol(RUN[i]);
   5357 	}
   5358 	for (i = 0; i < 3; i++) {
   5359 	    results[i] = '*';
   5360 	    results[i + 1] = '\0';
   5361 	    RES[i] = ATOM(results);
   5362 	    LispSetVar(RES[i], NIL);
   5363 	    LispExportSymbol(RES[i]);
   5364 	}
   5365     }
   5366     else
   5367 	RUN[0] = RUN[1] = RUN[2] = RES[0] = RES[1] = RES[2] = NIL;
   5368 
   5369     /* Add LISP builtin functions */
   5370     for (i = 0; i < sizeof(lispbuiltins) / sizeof(lispbuiltins[0]); i++)
   5371 	LispAddBuiltinFunction(&lispbuiltins[i]);
   5372 
   5373     EXECUTE("(require \"lisp\")");
   5374 
   5375     object = ATOM2("*DEFAULT-PATHNAME-DEFAULTS*");
   5376 #ifdef LISPDIR
   5377     {
   5378 	int length;
   5379 	const char *pathname = LISPDIR;
   5380 
   5381 	length = strlen(pathname);
   5382 	if (length && pathname[length - 1] != '/') {
   5383 	    char *fixed_pathname = LispMalloc(length + 2);
   5384 
   5385 	    strcpy(fixed_pathname, LISPDIR);
   5386 	    strcpy(fixed_pathname + length, "/");
   5387 	    path = LSTRING2(fixed_pathname, length + 1);
   5388 	}
   5389 	else
   5390 	    path = LSTRING(pathname, length);
   5391     }
   5392 #else
   5393     path = STRING("");
   5394 #endif
   5395     GCDisable();
   5396     LispProclaimSpecial(object, APPLY1(Oparse_namestring, path), NIL);
   5397     LispExportSymbol(object);
   5398     GCEnable();
   5399 
   5400     /* Create and make EXT the current package */
   5401     PACKAGE = ext = LispNewPackage(STRING("EXT"), NIL);
   5402     lisp__data.pack = lisp__data.savepack = PACKAGE->data.package.package;
   5403 
   5404     /* Update list of packages */
   5405     PACK = CONS(ext, PACK);
   5406 
   5407     /* Import LISP external symbols in EXT package */
   5408     LispUsePackage(lisp__data.lisp);
   5409 
   5410     /* Add EXT non standard builtin functions */
   5411     for (i = 0; i < sizeof(extbuiltins) / sizeof(extbuiltins[0]); i++)
   5412 	LispAddBuiltinFunction(&extbuiltins[i]);
   5413 
   5414     /* Create and make USER the current package */
   5415     GCDisable();
   5416     PACKAGE = LispNewPackage(STRING("USER"),
   5417 			     CONS(STRING("COMMON-LISP-USER"), NIL));
   5418     GCEnable();
   5419     lisp__data.pack = lisp__data.savepack = PACKAGE->data.package.package;
   5420 
   5421     /* Update list of packages */
   5422     PACK = CONS(PACKAGE, PACK);
   5423 
   5424     /* USER package inherits all LISP external symbols */
   5425     LispUsePackage(lisp__data.lisp);
   5426     /* And all EXT external symbols */
   5427     LispUsePackage(ext);
   5428 
   5429     LispTopLevel();
   5430 }
   5431 
   5432 void
   5433 LispEnd(void)
   5434 {
   5435     /* XXX needs to free all used memory, not just close file descriptors */
   5436 }
   5437 
   5438 void
   5439 LispSetPrompt(const char *prompt)
   5440 {
   5441     lisp__data.prompt = prompt;
   5442 }
   5443 
   5444 void
   5445 LispSetInteractive(int interactive)
   5446 {
   5447     lisp__data.interactive = !!interactive;
   5448 }
   5449 
   5450 void
   5451 LispSetExitOnError(int errexit)
   5452 {
   5453     lisp__data.errexit = !!errexit;
   5454 }
   5455 
   5456 void
   5457 LispDebug(int enable)
   5458 {
   5459     lisp__data.debugging = !!enable;
   5460 
   5461 #ifdef DEBUGGER
   5462     /* assumes we are at the toplevel */
   5463     DBG = BRK = NIL;
   5464     lisp__data.debug_level = -1;
   5465     lisp__data.debug_step = 0;
   5466 #endif
   5467 }
   5468