15dfecf96Smrg/*
25dfecf96Smrg * Copyright (c) 2001 by The XFree86 Project, Inc.
35dfecf96Smrg *
45dfecf96Smrg * Permission is hereby granted, free of charge, to any person obtaining a
55dfecf96Smrg * copy of this software and associated documentation files (the "Software"),
65dfecf96Smrg * to deal in the Software without restriction, including without limitation
75dfecf96Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
85dfecf96Smrg * and/or sell copies of the Software, and to permit persons to whom the
95dfecf96Smrg * Software is furnished to do so, subject to the following conditions:
105dfecf96Smrg *
115dfecf96Smrg * The above copyright notice and this permission notice shall be included in
125dfecf96Smrg * all copies or substantial portions of the Software.
135dfecf96Smrg *
145dfecf96Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
155dfecf96Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
165dfecf96Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
175dfecf96Smrg * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
185dfecf96Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
195dfecf96Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
205dfecf96Smrg * SOFTWARE.
215dfecf96Smrg *
225dfecf96Smrg * Except as contained in this notice, the name of the XFree86 Project shall
235dfecf96Smrg * not be used in advertising or otherwise to promote the sale, use or other
245dfecf96Smrg * dealings in this Software without prior written authorization from the
255dfecf96Smrg * XFree86 Project.
265dfecf96Smrg *
275dfecf96Smrg * Author: Paulo César Pereira de Andrade
285dfecf96Smrg */
295dfecf96Smrg
305dfecf96Smrg/* $XFree86: xc/programs/xedit/lisp/lisp.c,v 1.87tsi Exp $ */
315dfecf96Smrg
32f765521fSmrg#ifdef HAVE_CONFIG_H
33f765521fSmrg# include "config.h"
34f765521fSmrg#endif
35f765521fSmrg
365dfecf96Smrg#include <stdlib.h>
375dfecf96Smrg#include <string.h>
385dfecf96Smrg#ifdef sun
395dfecf96Smrg#include <strings.h>
405dfecf96Smrg#endif
415dfecf96Smrg#include <ctype.h>
425dfecf96Smrg#include <errno.h>
435dfecf96Smrg#include <fcntl.h>
445dfecf96Smrg#include <stdarg.h>
455dfecf96Smrg#include <signal.h>
465dfecf96Smrg#include <sys/wait.h>
475dfecf96Smrg
485dfecf96Smrg#ifndef X_NOT_POSIX
495dfecf96Smrg#include <unistd.h>	/* for sysconf(), and getpagesize() */
505dfecf96Smrg#endif
515dfecf96Smrg
525dfecf96Smrg#include "lisp/bytecode.h"
535dfecf96Smrg
545dfecf96Smrg#include "lisp/read.h"
555dfecf96Smrg#include "lisp/format.h"
565dfecf96Smrg#include "lisp/math.h"
575dfecf96Smrg#include "lisp/hash.h"
585dfecf96Smrg#include "lisp/package.h"
595dfecf96Smrg#include "lisp/pathname.h"
605dfecf96Smrg#include "lisp/regex.h"
615dfecf96Smrg#include "lisp/require.h"
625dfecf96Smrg#include "lisp/stream.h"
635dfecf96Smrg#include "lisp/struct.h"
645dfecf96Smrg#include "lisp/time.h"
655dfecf96Smrg#include "lisp/write.h"
665dfecf96Smrg#include <math.h>
675dfecf96Smrg
685dfecf96Smrgtypedef struct {
695dfecf96Smrg    LispObj **objects;
705dfecf96Smrg    LispObj *freeobj;
715dfecf96Smrg    int nsegs;
725dfecf96Smrg    int nobjs;
735dfecf96Smrg    int nfree;
745dfecf96Smrg} LispObjSeg;
755dfecf96Smrg
765dfecf96Smrg/*
775dfecf96Smrg * Prototypes
785dfecf96Smrg */
795dfecf96Smrgstatic void Lisp__GC(LispObj*, LispObj*);
805dfecf96Smrgstatic LispObj *Lisp__New(LispObj*, LispObj*);
815dfecf96Smrg
825dfecf96Smrg/* run a user function, to be called only by LispEval */
835dfecf96Smrgstatic LispObj *LispRunFunMac(LispObj*, LispObj*, int, int);
845dfecf96Smrg
855dfecf96Smrg/* expands and executes a setf method, to be called only by Lisp_Setf */
865dfecf96SmrgLispObj *LispRunSetf(LispArgList*, LispObj*, LispObj*, LispObj*);
875dfecf96SmrgLispObj *LispRunSetfMacro(LispAtom*, LispObj*, LispObj*);
885dfecf96Smrg
895dfecf96Smrg/* increases storage size for environment */
905dfecf96Smrgvoid LispMoreEnvironment(void);
915dfecf96Smrg
925dfecf96Smrg/* increases storage size for stack of builtin arguments */
935dfecf96Smrgvoid LispMoreStack(void);
945dfecf96Smrg
955dfecf96Smrg/* increases storage size for global variables */
965dfecf96Smrgvoid LispMoreGlobals(LispPackage*);
975dfecf96Smrg
985dfecf96Smrg#ifdef __GNUC__
995dfecf96Smrgstatic INLINE LispObj *LispDoGetVar(LispObj*);
1005dfecf96Smrg#endif
1015dfecf96Smrgstatic INLINE void LispDoAddVar(LispObj*, LispObj*);
1025dfecf96Smrg
1035dfecf96Smrg/* Helper for importing symbol(s) functions,
1045dfecf96Smrg * Search for the specified object in the current package */
1055dfecf96Smrgstatic INLINE LispObj *LispGetVarPack(LispObj*);
1065dfecf96Smrg
1075dfecf96Smrg/* create environment for function call */
1085dfecf96Smrgstatic int LispMakeEnvironment(LispArgList*, LispObj*, LispObj*, int, int);
1095dfecf96Smrg
1105dfecf96Smrg	/* if not already in keyword package, move atom to keyword package */
1115dfecf96Smrgstatic LispObj *LispCheckKeyword(LispObj*);
1125dfecf96Smrg
1135dfecf96Smrg	/* builtin backquote parsing */
1145dfecf96Smrgstatic LispObj *LispEvalBackquoteObject(LispObj*, int, int);
1155dfecf96Smrg	/* used also by the bytecode compiler */
1165dfecf96SmrgLispObj *LispEvalBackquote(LispObj*, int);
1175dfecf96Smrg
1185dfecf96Smrg	/* create or change object property */
1195dfecf96Smrgvoid LispSetAtomObjectProperty(LispAtom*, LispObj*);
1205dfecf96Smrg	/* remove object property */
1215dfecf96Smrgstatic void LispRemAtomObjectProperty(LispAtom*);
1225dfecf96Smrg
1235dfecf96Smrg	/* allocates a new LispProperty for the given atom */
1245dfecf96Smrgstatic void LispAllocAtomProperty(LispAtom*);
1255dfecf96Smrg	/* Increment reference count of atom property */
1265dfecf96Smrgstatic void LispIncrementAtomReference(LispAtom*);
1275dfecf96Smrg	/* Decrement reference count of atom property */
1285dfecf96Smrgstatic void LispDecrementAtomReference(LispAtom*);
1295dfecf96Smrg	/* Removes all atom properties */
1305dfecf96Smrgstatic void LispRemAtomAllProperties(LispAtom*);
1315dfecf96Smrg
1325dfecf96Smrgstatic LispObj *LispAtomPropertyFunction(LispAtom*, LispObj*, int);
1335dfecf96Smrg
1345dfecf96Smrgstatic INLINE void LispCheckMemLevel(void);
1355dfecf96Smrg
1365dfecf96Smrgvoid LispAllocSeg(LispObjSeg*, int);
1375dfecf96Smrgstatic INLINE void LispMark(LispObj*);
1385dfecf96Smrg
1395dfecf96Smrg/* functions, macros, setf methods, and structure definitions */
1405dfecf96Smrgstatic INLINE void LispProt(LispObj*);
1415dfecf96Smrg
1425dfecf96Smrgstatic LispObj *LispCheckNeedProtect(LispObj*);
1435dfecf96Smrg
144f765521fSmrgstatic void LispSignalHandler(int);
1455dfecf96Smrg
1465dfecf96Smrg/*
1475dfecf96Smrg * Initialization
1485dfecf96Smrg */
1495dfecf96SmrgLispMac lisp__data;
1505dfecf96Smrg
1515dfecf96Smrgstatic LispObj lispunbound = {LispNil_t};
1525dfecf96SmrgLispObj *UNBOUND = &lispunbound;
1535dfecf96Smrg
1545dfecf96Smrgstatic volatile int lisp__disable_int;
1555dfecf96Smrgstatic volatile int lisp__interrupted;
1565dfecf96Smrg
1575dfecf96SmrgLispObj *Okey, *Orest, *Ooptional, *Oaux, *Olambda;
1585dfecf96Smrg
1595dfecf96SmrgAtom_id Snil, St;
1605dfecf96SmrgAtom_id Saux, Skey, Soptional, Srest;
1615dfecf96SmrgAtom_id Satom, Ssymbol, Sinteger, Scharacter, Sstring, Slist,
1625dfecf96Smrg	Scons, Svector, Sarray, Sstruct, Skeyword, Sfunction, Spathname,
1635dfecf96Smrg	Srational, Sfloat, Scomplex, Sopaque, Sdefault;
1645dfecf96Smrg
1655dfecf96SmrgLispObj *Oformat, *Kunspecific;
1665dfecf96SmrgLispObj *Oexpand_setf_method;
1675dfecf96Smrg
1685dfecf96Smrgstatic LispProperty noproperty;
1695dfecf96SmrgLispProperty *NOPROPERTY = &noproperty;
1705dfecf96Smrgstatic int segsize, minfree;
1715dfecf96Smrgint pagesize, gcpro;
1725dfecf96Smrg
1735dfecf96Smrgstatic LispObjSeg objseg = {NULL, NIL};
1745dfecf96Smrgstatic LispObjSeg atomseg = {NULL, NIL};
1755dfecf96Smrg
1765dfecf96Smrgint LispArgList_t;
1775dfecf96Smrg
1785dfecf96SmrgLispFile *Stdout, *Stdin, *Stderr;
1795dfecf96Smrg
1805dfecf96Smrgstatic LispBuiltin lispbuiltins[] = {
1815dfecf96Smrg    {LispFunction, Lisp_Mul, "* &rest numbers"},
1825dfecf96Smrg    {LispFunction, Lisp_Plus, "+ &rest numbers"},
1835dfecf96Smrg    {LispFunction, Lisp_Minus, "- number &rest more-numbers"},
1845dfecf96Smrg    {LispFunction, Lisp_Div, "/ number &rest more-numbers"},
1855dfecf96Smrg    {LispFunction, Lisp_OnePlus, "1+ number"},
1865dfecf96Smrg    {LispFunction, Lisp_OneMinus, "1- number"},
1875dfecf96Smrg    {LispFunction, Lisp_Less, "< number &rest more-numbers"},
1885dfecf96Smrg    {LispFunction, Lisp_LessEqual, "<= number &rest more-numbers"},
1895dfecf96Smrg    {LispFunction, Lisp_Equal_, "= number &rest more-numbers"},
1905dfecf96Smrg    {LispFunction, Lisp_Greater, "> number &rest more-numbers"},
1915dfecf96Smrg    {LispFunction, Lisp_GreaterEqual, ">= number &rest more-numbers"},
1925dfecf96Smrg    {LispFunction, Lisp_NotEqual, "/= number &rest more-numbers"},
1935dfecf96Smrg    {LispFunction, Lisp_Max, "max number &rest more-numbers"},
1945dfecf96Smrg    {LispFunction, Lisp_Min, "min number &rest more-numbers"},
1955dfecf96Smrg    {LispFunction, Lisp_Abs, "abs number"},
1965dfecf96Smrg    {LispFunction, Lisp_Acons, "acons key datum alist"},
1975dfecf96Smrg    {LispFunction, Lisp_Adjoin, "adjoin item list &key key test test-not"},
1985dfecf96Smrg    {LispFunction, Lisp_AlphaCharP, "alpha-char-p char"},
1995dfecf96Smrg    {LispMacro, Lisp_And, "and &rest args", 1, 0, Com_And},
2005dfecf96Smrg    {LispFunction, Lisp_Append, "append &rest lists"},
2015dfecf96Smrg    {LispFunction, Lisp_Apply, "apply function arg &rest more-args", 1},
2025dfecf96Smrg    {LispFunction, Lisp_Aref, "aref array &rest subscripts"},
2035dfecf96Smrg    {LispFunction, Lisp_Assoc, "assoc item list &key test test-not key"},
2045dfecf96Smrg    {LispFunction, Lisp_AssocIf, "assoc-if predicate list &key key"},
2055dfecf96Smrg    {LispFunction, Lisp_AssocIfNot, "assoc-if-not predicate list &key key"},
2065dfecf96Smrg    {LispFunction, Lisp_Atom, "atom object"},
2075dfecf96Smrg    {LispMacro, Lisp_Block, "block name &rest body", 1, 0, Com_Block},
2085dfecf96Smrg    {LispFunction, Lisp_BothCaseP, "both-case-p character"},
2095dfecf96Smrg    {LispFunction, Lisp_Boundp, "boundp symbol"},
2105dfecf96Smrg    {LispFunction, Lisp_Butlast, "butlast list &optional count"},
2115dfecf96Smrg    {LispFunction, Lisp_Nbutlast, "nbutlast list &optional count"},
2125dfecf96Smrg    {LispFunction, Lisp_Car, "car list", 0, 0, Com_C_r},
2135dfecf96Smrg    {LispFunction, Lisp_Car, "first list", 0, 0, Com_C_r},
2145dfecf96Smrg    {LispMacro, Lisp_Case, "case keyform &rest body"},
2155dfecf96Smrg    {LispMacro, Lisp_Catch, "catch tag &rest body", 1},
2165dfecf96Smrg    {LispFunction, Lisp_Cdr, "cdr list", 0, 0, Com_C_r},
2175dfecf96Smrg    {LispFunction, Lisp_Cdr, "rest list", 0, 0, Com_C_r},
2185dfecf96Smrg    {LispFunction, Lisp_Ceiling, "ceiling number &optional divisor", 1},
2195dfecf96Smrg    {LispFunction, Lisp_Fceiling, "fceiling number &optional divisor", 1},
2205dfecf96Smrg    {LispFunction, Lisp_Char, "char string index"},
2215dfecf96Smrg    {LispFunction, Lisp_Char, "schar simple-string index"},
2225dfecf96Smrg    {LispFunction, Lisp_CharLess, "char< character &rest more-characters"},
2235dfecf96Smrg    {LispFunction, Lisp_CharLessEqual, "char<= character &rest more-characters"},
2245dfecf96Smrg    {LispFunction, Lisp_CharEqual_, "char= character &rest more-characters"},
2255dfecf96Smrg    {LispFunction, Lisp_CharGreater, "char> character &rest more-characters"},
2265dfecf96Smrg    {LispFunction, Lisp_CharGreaterEqual, "char>= character &rest more-characters"},
2275dfecf96Smrg    {LispFunction, Lisp_CharNotEqual_, "char/= character &rest more-characters"},
2285dfecf96Smrg    {LispFunction, Lisp_CharLessp, "char-lessp character &rest more-characters"},
2295dfecf96Smrg    {LispFunction, Lisp_CharNotGreaterp, "char-not-greaterp character &rest more-characters"},
2305dfecf96Smrg    {LispFunction, Lisp_CharEqual, "char-equal character &rest more-characters"},
2315dfecf96Smrg    {LispFunction, Lisp_CharGreaterp, "char-greaterp character &rest more-characters"},
2325dfecf96Smrg    {LispFunction, Lisp_CharNotLessp, "char-not-lessp character &rest more-characters"},
2335dfecf96Smrg    {LispFunction, Lisp_CharNotEqual, "char-not-equal character &rest more-characters"},
2345dfecf96Smrg    {LispFunction, Lisp_CharDowncase, "char-downcase character"},
2355dfecf96Smrg    {LispFunction, Lisp_CharInt, "char-code character"},
2365dfecf96Smrg    {LispFunction, Lisp_CharInt, "char-int character"},
2375dfecf96Smrg    {LispFunction, Lisp_CharUpcase, "char-upcase character"},
2385dfecf96Smrg    {LispFunction, Lisp_Character, "character object"},
2395dfecf96Smrg    {LispFunction, Lisp_Characterp, "characterp object"},
2405dfecf96Smrg    {LispFunction, Lisp_Clrhash, "clrhash hash-table"},
2415dfecf96Smrg    {LispFunction, Lisp_IntChar, "code-char integer"},
2425dfecf96Smrg    {LispFunction, Lisp_Coerce, "coerce object result-type"},
2435dfecf96Smrg    {LispFunction, Lisp_Compile, "compile name &optional definition", 1},
2445dfecf96Smrg    {LispFunction, Lisp_Complex, "complex realpart &optional imagpart"},
2455dfecf96Smrg    {LispMacro, Lisp_Cond, "cond &rest body", 0, 0, Com_Cond},
2465dfecf96Smrg    {LispFunction, Lisp_Cons, "cons car cdr", 0, 0, Com_Cons},
2475dfecf96Smrg    {LispFunction, Lisp_Consp, "consp object", 0, 0, Com_Consp},
2485dfecf96Smrg    {LispFunction, Lisp_Constantp, "constantp form &optional environment"},
2495dfecf96Smrg    {LispFunction, Lisp_Conjugate, "conjugate number"},
2505dfecf96Smrg    {LispFunction, Lisp_Complexp, "complexp object"},
2515dfecf96Smrg    {LispFunction, Lisp_CopyAlist, "copy-alist list"},
2525dfecf96Smrg    {LispFunction, Lisp_CopyList, "copy-list list"},
2535dfecf96Smrg    {LispFunction, Lisp_CopyTree, "copy-tree list"},
2545dfecf96Smrg    {LispFunction, Lisp_Close, "close stream &key abort"},
2555dfecf96Smrg    {LispFunction, Lisp_C_r, "caar list", 0, 0, Com_C_r},
2565dfecf96Smrg    {LispFunction, Lisp_C_r, "cadr list", 0, 0, Com_C_r},
2575dfecf96Smrg    {LispFunction, Lisp_C_r, "cdar list", 0, 0, Com_C_r},
2585dfecf96Smrg    {LispFunction, Lisp_C_r, "cddr list", 0, 0, Com_C_r},
2595dfecf96Smrg    {LispFunction, Lisp_C_r, "caaar list", 0, 0, Com_C_r},
2605dfecf96Smrg    {LispFunction, Lisp_C_r, "caadr list", 0, 0, Com_C_r},
2615dfecf96Smrg    {LispFunction, Lisp_C_r, "cadar list", 0, 0, Com_C_r},
2625dfecf96Smrg    {LispFunction, Lisp_C_r, "caddr list", 0, 0, Com_C_r},
2635dfecf96Smrg    {LispFunction, Lisp_C_r, "cdaar list", 0, 0, Com_C_r},
2645dfecf96Smrg    {LispFunction, Lisp_C_r, "cdadr list", 0, 0, Com_C_r},
2655dfecf96Smrg    {LispFunction, Lisp_C_r, "cddar list", 0, 0, Com_C_r},
2665dfecf96Smrg    {LispFunction, Lisp_C_r, "cdddr list", 0, 0, Com_C_r},
2675dfecf96Smrg    {LispFunction, Lisp_C_r, "caaaar list", 0, 0, Com_C_r},
2685dfecf96Smrg    {LispFunction, Lisp_C_r, "caaadr list", 0, 0, Com_C_r},
2695dfecf96Smrg    {LispFunction, Lisp_C_r, "caadar list", 0, 0, Com_C_r},
2705dfecf96Smrg    {LispFunction, Lisp_C_r, "caaddr list", 0, 0, Com_C_r},
2715dfecf96Smrg    {LispFunction, Lisp_C_r, "cadaar list", 0, 0, Com_C_r},
2725dfecf96Smrg    {LispFunction, Lisp_C_r, "cadadr list", 0, 0, Com_C_r},
2735dfecf96Smrg    {LispFunction, Lisp_C_r, "caddar list", 0, 0, Com_C_r},
2745dfecf96Smrg    {LispFunction, Lisp_C_r, "cadddr list", 0, 0, Com_C_r},
2755dfecf96Smrg    {LispFunction, Lisp_C_r, "cdaaar list", 0, 0, Com_C_r},
2765dfecf96Smrg    {LispFunction, Lisp_C_r, "cdaadr list", 0, 0, Com_C_r},
2775dfecf96Smrg    {LispFunction, Lisp_C_r, "cdadar list", 0, 0, Com_C_r},
2785dfecf96Smrg    {LispFunction, Lisp_C_r, "cdaddr list", 0, 0, Com_C_r},
2795dfecf96Smrg    {LispFunction, Lisp_C_r, "cddaar list", 0, 0, Com_C_r},
2805dfecf96Smrg    {LispFunction, Lisp_C_r, "cddadr list", 0, 0, Com_C_r},
2815dfecf96Smrg    {LispFunction, Lisp_C_r, "cdddar list", 0, 0, Com_C_r},
2825dfecf96Smrg    {LispFunction, Lisp_C_r, "cddddr list", 0, 0, Com_C_r},
2835dfecf96Smrg    {LispMacro, Lisp_Decf, "decf place &optional delta"},
2845dfecf96Smrg    {LispMacro, Lisp_Defconstant, "defconstant name initial-value &optional documentation"},
2855dfecf96Smrg    {LispMacro, Lisp_Defmacro, "defmacro name lambda-list &rest body"},
2865dfecf96Smrg    {LispMacro, Lisp_Defstruct, "defstruct name &rest description"},
2875dfecf96Smrg    {LispMacro, Lisp_Defun, "defun name lambda-list &rest body"},
2885dfecf96Smrg    {LispMacro, Lisp_Defsetf, "defsetf function lambda-list &rest body"},
2895dfecf96Smrg    {LispMacro, Lisp_Defparameter, "defparameter name initial-value &optional documentation"},
2905dfecf96Smrg    {LispMacro, Lisp_Defvar, "defvar name &optional initial-value documentation"},
2915dfecf96Smrg    {LispFunction, Lisp_Delete, "delete item sequence &key from-end test test-not start end count key"},
2925dfecf96Smrg    {LispFunction, Lisp_DeleteDuplicates, "delete-duplicates sequence &key from-end test test-not start end key"},
2935dfecf96Smrg    {LispFunction, Lisp_DeleteIf, "delete-if predicate sequence &key from-end start end count key"},
2945dfecf96Smrg    {LispFunction, Lisp_DeleteIfNot, "delete-if-not predicate sequence &key from-end start end count key"},
2955dfecf96Smrg    {LispFunction, Lisp_DeleteFile, "delete-file filename"},
2965dfecf96Smrg    {LispFunction, Lisp_Denominator, "denominator rational"},
2975dfecf96Smrg    {LispFunction, Lisp_DigitChar, "digit-char weight &optional radix"},
2985dfecf96Smrg    {LispFunction, Lisp_DigitCharP, "digit-char-p character &optional radix"},
2995dfecf96Smrg    {LispFunction, Lisp_Directory, "directory pathname &key all if-cannot-read"},
3005dfecf96Smrg    {LispFunction, Lisp_DirectoryNamestring, "directory-namestring pathname"},
3015dfecf96Smrg    {LispFunction, Lisp_Disassemble, "disassemble function"},
3025dfecf96Smrg    {LispMacro, Lisp_Do, "do init test &rest body"},
3035dfecf96Smrg    {LispMacro, Lisp_DoP, "do* init test &rest body"},
3045dfecf96Smrg    {LispFunction, Lisp_Documentation, "documentation symbol type"},
3055dfecf96Smrg    {LispMacro, Lisp_DoList, "dolist init &rest body", 0, 0, Com_Dolist},
3065dfecf96Smrg    {LispMacro, Lisp_DoTimes, "dotimes init &rest body"},
3075dfecf96Smrg    {LispMacro, Lisp_DoAllSymbols, "do-all-symbols init &rest body"},
3085dfecf96Smrg    {LispMacro, Lisp_DoExternalSymbols, "do-external-symbols init &rest body"},
3095dfecf96Smrg    {LispMacro, Lisp_DoSymbols, "do-symbols init &rest body"},
3105dfecf96Smrg    {LispFunction, Lisp_Elt, "elt sequence index"},
3115dfecf96Smrg    {LispFunction, Lisp_Endp, "endp object"},
3125dfecf96Smrg    {LispFunction, Lisp_EnoughNamestring, "enough-namestring pathname &optional defaults"},
3135dfecf96Smrg    {LispFunction, Lisp_Eq, "eq left right", 0, 0, Com_Eq},
3145dfecf96Smrg    {LispFunction, Lisp_Eql, "eql left right", 0, 0, Com_Eq},
3155dfecf96Smrg    {LispFunction, Lisp_Equal, "equal left right", 0, 0, Com_Eq},
3165dfecf96Smrg    {LispFunction, Lisp_Equalp, "equalp left right", 0, 0, Com_Eq},
3175dfecf96Smrg    {LispFunction, Lisp_Error, "error control-string &rest arguments"},
3185dfecf96Smrg    {LispFunction, Lisp_Evenp, "evenp integer"},
3195dfecf96Smrg    {LispFunction, Lisp_Export, "export symbols &optional package"},
3205dfecf96Smrg    {LispFunction, Lisp_Eval, "eval form"},
3215dfecf96Smrg    {LispFunction, Lisp_Every, "every predicate sequence &rest more-sequences"},
3225dfecf96Smrg    {LispFunction, Lisp_Some, "some predicate sequence &rest more-sequences"},
3235dfecf96Smrg    {LispFunction, Lisp_Notevery, "notevery predicate sequence &rest more-sequences"},
3245dfecf96Smrg    {LispFunction, Lisp_Notany, "notany predicate sequence &rest more-sequences"},
3255dfecf96Smrg    {LispFunction, Lisp_Fboundp, "fboundp symbol"},
3265dfecf96Smrg    {LispFunction, Lisp_Find, "find item sequence &key from-end test test-not start end key"},
3275dfecf96Smrg    {LispFunction, Lisp_FindIf, "find-if predicate sequence &key from-end start end key"},
3285dfecf96Smrg    {LispFunction, Lisp_FindIfNot, "find-if-not predicate sequence &key from-end start end key"},
3295dfecf96Smrg    {LispFunction, Lisp_FileNamestring, "file-namestring pathname"},
3305dfecf96Smrg    {LispFunction, Lisp_Fill, "fill sequence item &key start end"},
3315dfecf96Smrg    {LispFunction, Lisp_FindAllSymbols, "find-all-symbols string-or-symbol"},
3325dfecf96Smrg    {LispFunction, Lisp_FindSymbol, "find-symbol string &optional package", 1},
3335dfecf96Smrg    {LispFunction, Lisp_FindPackage, "find-package name"},
3345dfecf96Smrg    {LispFunction, Lisp_Float, "float number &optional other"},
3355dfecf96Smrg    {LispFunction, Lisp_Floatp, "floatp object"},
3365dfecf96Smrg    {LispFunction, Lisp_Floor, "floor number &optional divisor", 1},
3375dfecf96Smrg    {LispFunction, Lisp_Ffloor, "ffloor number &optional divisor", 1},
3385dfecf96Smrg    {LispFunction, Lisp_Fmakunbound, "fmakunbound symbol"},
3395dfecf96Smrg    {LispFunction, Lisp_Format, "format destination control-string &rest arguments"},
3405dfecf96Smrg    {LispFunction, Lisp_FreshLine, "fresh-line &optional output-stream"},
3415dfecf96Smrg    {LispFunction, Lisp_Funcall, "funcall function &rest arguments", 1},
3425dfecf96Smrg    {LispFunction, Lisp_Functionp, "functionp object"},
3435dfecf96Smrg    {LispFunction, Lisp_Gc, "gc &optional car cdr"},
3445dfecf96Smrg    {LispFunction, Lisp_Gcd, "gcd &rest integers"},
3455dfecf96Smrg    {LispFunction, Lisp_Gensym, "gensym &optional arg"},
3465dfecf96Smrg    {LispFunction, Lisp_Get, "get symbol indicator &optional default"},
3475dfecf96Smrg    {LispFunction, Lisp_Gethash, "gethash key hash-table &optional default", 1},
3485dfecf96Smrg    {LispMacro, Lisp_Go, "go tag", 0, 0, Com_Go},
3495dfecf96Smrg    {LispFunction, Lisp_GraphicCharP, "graphic-char-p char"},
3505dfecf96Smrg    {LispFunction, Lisp_HashTableP, "hash-table-p object"},
3515dfecf96Smrg    {LispFunction, Lisp_HashTableCount, "hash-table-count hash-table"},
3525dfecf96Smrg    {LispFunction, Lisp_HashTableRehashSize, "hash-table-rehash-size hash-table"},
3535dfecf96Smrg    {LispFunction, Lisp_HashTableRehashThreshold, "hash-table-rehash-threshold hash-table"},
3545dfecf96Smrg    {LispFunction, Lisp_HashTableSize, "hash-table-size hash-table"},
3555dfecf96Smrg    {LispFunction, Lisp_HashTableTest, "hash-table-test hash-table"},
3565dfecf96Smrg    {LispFunction, Lisp_HostNamestring, "host-namestring pathname"},
3575dfecf96Smrg    {LispMacro, Lisp_If, "if test then &optional else", 0, 0, Com_If},
3585dfecf96Smrg    {LispMacro, Lisp_IgnoreErrors, "ignore-errors &rest body", 1},
3595dfecf96Smrg    {LispFunction, Lisp_Imagpart, "imagpart number"},
3605dfecf96Smrg    {LispMacro, Lisp_InPackage, "in-package name"},
3615dfecf96Smrg    {LispMacro, Lisp_Incf, "incf place &optional delta"},
3625dfecf96Smrg    {LispFunction, Lisp_Import, "import symbols &optional package"},
3635dfecf96Smrg    {LispFunction, Lisp_InputStreamP, "input-stream-p stream"},
3645dfecf96Smrg    {LispFunction, Lisp_IntChar, "int-char integer"},
3655dfecf96Smrg    {LispFunction, Lisp_Integerp, "integerp object"},
3665dfecf96Smrg    {LispFunction, Lisp_Intern, "intern string &optional package", 1},
3675dfecf96Smrg    {LispFunction, Lisp_Intersection, "intersection list1 list2 &key test test-not key"},
3685dfecf96Smrg    {LispFunction, Lisp_Nintersection, "nintersection list1 list2 &key test test-not key"},
3695dfecf96Smrg    {LispFunction, Lisp_Isqrt, "isqrt natural"},
3705dfecf96Smrg    {LispFunction, Lisp_Keywordp, "keywordp object"},
3715dfecf96Smrg    {LispFunction, Lisp_Last, "last list &optional count", 0, 0, Com_Last},
3725dfecf96Smrg    {LispMacro, Lisp_Lambda, "lambda lambda-list &rest body"},
3735dfecf96Smrg    {LispFunction, Lisp_Lcm, "lcm &rest integers"},
3745dfecf96Smrg    {LispFunction, Lisp_Length, "length sequence", 0, 0, Com_Length},
3755dfecf96Smrg    {LispMacro, Lisp_Let, "let init &rest body", 1, 0, Com_Let},
3765dfecf96Smrg    {LispMacro, Lisp_LetP, "let* init &rest body", 1, 0, Com_Letx},
3775dfecf96Smrg    {LispFunction, Lisp_ListP, "list* object &rest more-objects"},
3785dfecf96Smrg    {LispFunction, Lisp_ListAllPackages, "list-all-packages"},
3795dfecf96Smrg    {LispFunction, Lisp_List, "list &rest args"},
3805dfecf96Smrg    {LispFunction, Lisp_ListLength, "list-length list"},
3815dfecf96Smrg    {LispFunction, Lisp_Listp, "listp object", 0, 0, Com_Listp},
3825dfecf96Smrg    {LispFunction, Lisp_Listen, "listen &optional input-stream"},
3835dfecf96Smrg    {LispFunction, Lisp_Load, "load filename &key verbose print if-does-not-exist"},
3845dfecf96Smrg    {LispFunction, Lisp_Logand, "logand &rest integers"},
3855dfecf96Smrg    {LispFunction, Lisp_Logeqv, "logeqv &rest integers"},
3865dfecf96Smrg    {LispFunction, Lisp_Logior, "logior &rest integers"},
3875dfecf96Smrg    {LispFunction, Lisp_Lognot, "lognot integer"},
3885dfecf96Smrg    {LispFunction, Lisp_Logxor, "logxor &rest integers"},
3895dfecf96Smrg    {LispMacro, Lisp_Loop, "loop &rest body", 0, 0, Com_Loop},
3905dfecf96Smrg    {LispFunction, Lisp_LowerCaseP, "lower-case-p character"},
3915dfecf96Smrg    {LispFunction, Lisp_MakeArray, "make-array dimensions &key element-type initial-element initial-contents adjustable fill-pointer displaced-to displaced-index-offset"},
3925dfecf96Smrg    {LispFunction, Lisp_MakeHashTable, "make-hash-table &key test size rehash-size rehash-threshold initial-contents"},
3935dfecf96Smrg    {LispFunction, Lisp_MakeList, "make-list size &key initial-element"},
3945dfecf96Smrg    {LispFunction, Lisp_MakePackage, "make-package package-name &key nicknames use"},
3955dfecf96Smrg    {LispFunction, Lisp_MakePathname, "make-pathname &key host device directory name type version defaults"},
3965dfecf96Smrg    {LispFunction, Lisp_MakeString, "make-string size &key initial-element element-type"},
3975dfecf96Smrg    {LispFunction, Lisp_MakeSymbol, "make-symbol name"},
3985dfecf96Smrg    {LispFunction, Lisp_MakeStringInputStream, "make-string-input-stream string &optional start end"},
3995dfecf96Smrg    {LispFunction, Lisp_MakeStringOutputStream, "make-string-output-stream &key element-type"},
4005dfecf96Smrg    {LispFunction, Lisp_GetOutputStreamString, "get-output-stream-string string-output-stream"},
4015dfecf96Smrg    {LispFunction, Lisp_Makunbound, "makunbound symbol"},
4025dfecf96Smrg    {LispFunction, Lisp_Mapc, "mapc function list &rest more-lists"},
4035dfecf96Smrg    {LispFunction, Lisp_Mapcar, "mapcar function list &rest more-lists"},
4045dfecf96Smrg    {LispFunction, Lisp_Mapcan, "mapcan function list &rest more-lists"},
4055dfecf96Smrg    {LispFunction, Lisp_Maphash, "maphash function hash-table"},
4065dfecf96Smrg    {LispFunction, Lisp_Mapl, "mapl function list &rest more-lists"},
4075dfecf96Smrg    {LispFunction, Lisp_Maplist, "maplist function list &rest more-lists"},
4085dfecf96Smrg    {LispFunction, Lisp_Mapcon, "mapcon function list &rest more-lists"},
4095dfecf96Smrg    {LispFunction, Lisp_Member, "member item list &key test test-not key"},
4105dfecf96Smrg    {LispFunction, Lisp_MemberIf, "member-if predicate list &key key"},
4115dfecf96Smrg    {LispFunction, Lisp_MemberIfNot, "member-if-not predicate list &key key"},
4125dfecf96Smrg    {LispFunction, Lisp_Minusp, "minusp number"},
4135dfecf96Smrg    {LispFunction, Lisp_Mod, "mod number divisor"},
4145dfecf96Smrg    {LispMacro, Lisp_MultipleValueBind, "multiple-value-bind symbols values &rest body"},
4155dfecf96Smrg    {LispMacro, Lisp_MultipleValueCall, "multiple-value-call function &rest form", 1},
4165dfecf96Smrg    {LispMacro, Lisp_MultipleValueProg1, "multiple-value-prog1 first-form &rest form", 1},
4175dfecf96Smrg    {LispMacro, Lisp_MultipleValueList, "multiple-value-list form"},
4185dfecf96Smrg    {LispMacro, Lisp_MultipleValueSetq, "multiple-value-setq symbols form"},
4195dfecf96Smrg    {LispFunction, Lisp_Nconc, "nconc &rest lists"},
4205dfecf96Smrg    {LispFunction, Lisp_Nreverse, "nreverse sequence"},
4215dfecf96Smrg    {LispFunction, Lisp_NsetDifference, "nset-difference list1 list2 &key test test-not key"},
4225dfecf96Smrg    {LispFunction, Lisp_Nsubstitute, "nsubstitute newitem olditem sequence &key from-end test test-not start end count key"},
4235dfecf96Smrg    {LispFunction, Lisp_NsubstituteIf, "nsubstitute-if newitem test sequence &key from-end start end count key"},
4245dfecf96Smrg    {LispFunction, Lisp_NsubstituteIfNot, "nsubstitute-if-not newitem test sequence &key from-end start end count key"},
4255dfecf96Smrg    {LispFunction, Lisp_Nth, "nth index list"},
4265dfecf96Smrg    {LispFunction, Lisp_Nthcdr, "nthcdr index list", 0, 0, Com_Nthcdr},
4275dfecf96Smrg    {LispMacro, Lisp_NthValue, "nth-value index form"},
4285dfecf96Smrg    {LispFunction, Lisp_Numerator, "numerator rational"},
4295dfecf96Smrg    {LispFunction, Lisp_Namestring, "namestring pathname"},
4305dfecf96Smrg    {LispFunction, Lisp_Null, "not arg", 0, 0, Com_Null},
4315dfecf96Smrg    {LispFunction, Lisp_Null, "null list", 0, 0, Com_Null},
4325dfecf96Smrg    {LispFunction, Lisp_Numberp, "numberp object", 0, 0, Com_Numberp},
4335dfecf96Smrg    {LispFunction, Lisp_Oddp, "oddp integer"},
4345dfecf96Smrg    {LispFunction, Lisp_Open, "open filename &key direction element-type if-exists if-does-not-exist external-format"},
4355dfecf96Smrg    {LispFunction, Lisp_OpenStreamP, "open-stream-p stream"},
4365dfecf96Smrg    {LispMacro, Lisp_Or, "or &rest args", 1, 0, Com_Or},
4375dfecf96Smrg    {LispFunction, Lisp_OutputStreamP, "output-stream-p stream"},
4385dfecf96Smrg    {LispFunction, Lisp_Packagep, "packagep object"},
4395dfecf96Smrg    {LispFunction, Lisp_PackageName, "package-name package"},
4405dfecf96Smrg    {LispFunction, Lisp_PackageNicknames, "package-nicknames package"},
4415dfecf96Smrg    {LispFunction, Lisp_PackageUseList, "package-use-list package"},
4425dfecf96Smrg    {LispFunction, Lisp_PackageUsedByList, "package-used-by-list package"},
4435dfecf96Smrg    {LispFunction, Lisp_Pairlis, "pairlis key data &optional alist"},
4445dfecf96Smrg    {LispFunction, Lisp_ParseInteger, "parse-integer string &key start end radix junk-allowed", 1},
4455dfecf96Smrg    {LispFunction, Lisp_ParseNamestring, "parse-namestring object &optional host defaults &key start end junk-allowed", 1},
4465dfecf96Smrg    {LispFunction, Lisp_PathnameHost, "pathname-host pathname"},
4475dfecf96Smrg    {LispFunction, Lisp_PathnameDevice, "pathname-device pathname"},
4485dfecf96Smrg    {LispFunction, Lisp_PathnameDirectory, "pathname-directory pathname"},
4495dfecf96Smrg    {LispFunction, Lisp_PathnameName, "pathname-name pathname"},
4505dfecf96Smrg    {LispFunction, Lisp_PathnameType, "pathname-type pathname"},
4515dfecf96Smrg    {LispFunction, Lisp_PathnameVersion, "pathname-version pathname"},
4525dfecf96Smrg    {LispFunction, Lisp_Pathnamep, "pathnamep object"},
4535dfecf96Smrg    {LispFunction, Lisp_Plusp, "plusp number"},
4545dfecf96Smrg    {LispMacro, Lisp_Pop, "pop place"},
4555dfecf96Smrg    {LispFunction, Lisp_Position, "position item sequence &key from-end test test-not start end key"},
4565dfecf96Smrg    {LispFunction, Lisp_PositionIf, "position-if predicate sequence &key from-end start end key"},
4575dfecf96Smrg    {LispFunction, Lisp_PositionIfNot, "position-if-not predicate sequence &key from-end start end key"},
4585dfecf96Smrg    {LispFunction, Lisp_Prin1, "prin1 object &optional output-stream"},
4595dfecf96Smrg    {LispFunction, Lisp_Princ, "princ object &optional output-stream"},
4605dfecf96Smrg    {LispFunction, Lisp_Print, "print object &optional output-stream"},
4615dfecf96Smrg    {LispFunction, Lisp_ProbeFile, "probe-file pathname"},
4625dfecf96Smrg    {LispFunction, Lisp_Proclaim, "proclaim declaration"},
4635dfecf96Smrg    {LispMacro, Lisp_Prog1, "prog1 first &rest body"},
4645dfecf96Smrg    {LispMacro, Lisp_Prog2, "prog2 first second &rest body"},
4655dfecf96Smrg    {LispMacro, Lisp_Progn, "progn &rest body", 1, 0, Com_Progn},
4665dfecf96Smrg    {LispMacro, Lisp_Progv, "progv symbols values &rest body", 1},
4675dfecf96Smrg    {LispFunction, Lisp_Provide, "provide module"},
4685dfecf96Smrg    {LispMacro, Lisp_Push, "push item place"},
4695dfecf96Smrg    {LispMacro, Lisp_Pushnew, "pushnew item place &key key test test-not"},
4705dfecf96Smrg    {LispFunction, Lisp_Quit, "quit &optional status"},
4715dfecf96Smrg    {LispMacro, Lisp_Quote, "quote object"},
4725dfecf96Smrg    {LispFunction, Lisp_Rational, "rational number"},
4735dfecf96Smrg    {LispFunction, Lisp_Rationalp, "rationalp object"},
4745dfecf96Smrg    {LispFunction, Lisp_Read, "read &optional input-stream eof-error-p eof-value recursive-p"},
4755dfecf96Smrg    {LispFunction, Lisp_ReadChar, "read-char &optional input-stream eof-error-p eof-value recursive-p"},
4765dfecf96Smrg    {LispFunction, Lisp_ReadCharNoHang, "read-char-no-hang &optional input-stream eof-error-p eof-value recursive-p"},
4775dfecf96Smrg    {LispFunction, Lisp_ReadLine, "read-line &optional input-stream eof-error-p eof-value recursive-p", 1},
4785dfecf96Smrg    {LispFunction, Lisp_Realpart, "realpart number"},
4795dfecf96Smrg    {LispFunction, Lisp_Replace, "replace sequence1 sequence2 &key start1 end1 start2 end2"},
4805dfecf96Smrg    {LispFunction, Lisp_ReadFromString, "read-from-string string &optional eof-error-p eof-value &key start end preserve-whitespace", 1},
4815dfecf96Smrg    {LispFunction, Lisp_Require, "require module &optional pathname"},
4825dfecf96Smrg    {LispFunction, Lisp_Rem, "rem number divisor"},
4835dfecf96Smrg    {LispFunction, Lisp_Remhash, "remhash key hash-table"},
4845dfecf96Smrg    {LispFunction, Lisp_Remove, "remove item sequence &key from-end test test-not start end count key"},
4855dfecf96Smrg    {LispFunction, Lisp_RemoveDuplicates, "remove-duplicates sequence &key from-end test test-not start end key"},
4865dfecf96Smrg    {LispFunction, Lisp_RemoveIf, "remove-if predicate sequence &key from-end start end count key"},
4875dfecf96Smrg    {LispFunction, Lisp_RemoveIfNot, "remove-if-not predicate sequence &key from-end start end count key"},
4885dfecf96Smrg    {LispFunction, Lisp_Remprop, "remprop symbol indicator"},
4895dfecf96Smrg    {LispFunction, Lisp_RenameFile, "rename-file filename new-name", 1},
4905dfecf96Smrg    {LispMacro, Lisp_Return, "return &optional result", 1, 0, Com_Return},
4915dfecf96Smrg    {LispMacro, Lisp_ReturnFrom, "return-from name &optional result", 1, 0, Com_ReturnFrom},
4925dfecf96Smrg    {LispFunction, Lisp_Reverse, "reverse sequence"},
4935dfecf96Smrg    {LispFunction, Lisp_Round, "round number &optional divisor", 1},
4945dfecf96Smrg    {LispFunction, Lisp_Fround, "fround number &optional divisor", 1},
4955dfecf96Smrg    {LispFunction, Lisp_Rplaca, "rplaca place value", 0, 0, Com_Rplac_},
4965dfecf96Smrg    {LispFunction, Lisp_Rplacd, "rplacd place value", 0, 0, Com_Rplac_},
4975dfecf96Smrg    {LispFunction, Lisp_Search, "search sequence1 sequence2 &key from-end test test-not key start1 start2 end1 end2"},
4985dfecf96Smrg    {LispFunction, Lisp_Set, "set symbol value"},
4995dfecf96Smrg    {LispFunction, Lisp_SetDifference, "set-difference list1 list2 &key test test-not key"},
5005dfecf96Smrg    {LispFunction, Lisp_SetExclusiveOr, "set-exclusive-or list1 list2 &key test test-not key"},
5015dfecf96Smrg    {LispFunction, Lisp_NsetExclusiveOr, "nset-exclusive-or list1 list2 &key test test-not key"},
5025dfecf96Smrg    {LispMacro, Lisp_Setf, "setf &rest form"},
5035dfecf96Smrg    {LispMacro, Lisp_Psetf, "psetf &rest form"},
5045dfecf96Smrg    {LispMacro, Lisp_SetQ, "setq &rest form", 0, 0, Com_Setq},
5055dfecf96Smrg    {LispMacro, Lisp_Psetq, "psetq &rest form"},
5065dfecf96Smrg    {LispFunction, Lisp_Sleep, "sleep seconds"},
5075dfecf96Smrg    {LispFunction, Lisp_Sort, "sort sequence predicate &key key"},
5085dfecf96Smrg    {LispFunction, Lisp_Sqrt, "sqrt number"},
5095dfecf96Smrg    {LispFunction, Lisp_Elt, "svref sequence index"},
5105dfecf96Smrg    {LispFunction, Lisp_Sort, "stable-sort sequence predicate &key key"},
5115dfecf96Smrg    {LispFunction, Lisp_Streamp, "streamp object"},
5125dfecf96Smrg    {LispFunction, Lisp_String, "string object"},
5135dfecf96Smrg    {LispFunction, Lisp_Stringp, "stringp object"},
5145dfecf96Smrg    {LispFunction, Lisp_StringEqual_, "string= string1 string2 &key start1 end1 start2 end2"},
5155dfecf96Smrg    {LispFunction, Lisp_StringLess, "string< string1 string2 &key start1 end1 start2 end2"},
5165dfecf96Smrg    {LispFunction, Lisp_StringGreater, "string> string1 string2 &key start1 end1 start2 end2"},
5175dfecf96Smrg    {LispFunction, Lisp_StringLessEqual, "string<= string1 string2 &key start1 end1 start2 end2"},
5185dfecf96Smrg    {LispFunction, Lisp_StringGreaterEqual, "string>= string1 string2 &key start1 end1 start2 end2"},
5195dfecf96Smrg    {LispFunction, Lisp_StringNotEqual_, "string/= string1 string2 &key start1 end1 start2 end2"},
5205dfecf96Smrg    {LispFunction, Lisp_StringConcat, "string-concat &rest strings"},
5215dfecf96Smrg    {LispFunction, Lisp_StringEqual, "string-equal string1 string2 &key start1 end1 start2 end2"},
5225dfecf96Smrg    {LispFunction, Lisp_StringGreaterp, "string-greaterp string1 string2 &key start1 end1 start2 end2"},
5235dfecf96Smrg    {LispFunction, Lisp_StringNotEqual, "string-not-equal string1 string2 &key start1 end1 start2 end2"},
5245dfecf96Smrg    {LispFunction, Lisp_StringNotGreaterp, "string-not-greaterp string1 string2 &key start1 end1 start2 end2"},
5255dfecf96Smrg    {LispFunction, Lisp_StringNotLessp, "string-not-lessp string1 string2 &key start1 end1 start2 end2"},
5265dfecf96Smrg    {LispFunction, Lisp_StringLessp, "string-lessp string1 string2 &key start1 end1 start2 end2"},
5275dfecf96Smrg    {LispFunction, Lisp_StringTrim, "string-trim character-bag string"},
5285dfecf96Smrg    {LispFunction, Lisp_StringLeftTrim, "string-left-trim character-bag string"},
5295dfecf96Smrg    {LispFunction, Lisp_StringRightTrim, "string-right-trim character-bag string"},
5305dfecf96Smrg    {LispFunction, Lisp_StringUpcase, "string-upcase string &key start end"},
5315dfecf96Smrg    {LispFunction, Lisp_NstringUpcase, "nstring-upcase string &key start end"},
5325dfecf96Smrg    {LispFunction, Lisp_StringDowncase, "string-downcase string &key start end"},
5335dfecf96Smrg    {LispFunction, Lisp_NstringDowncase, "nstring-downcase string &key start end"},
5345dfecf96Smrg    {LispFunction, Lisp_StringCapitalize, "string-capitalize string &key start end"},
5355dfecf96Smrg    {LispFunction, Lisp_NstringCapitalize, "nstring-capitalize string &key start end"},
5365dfecf96Smrg    {LispFunction, Lisp_Subseq, "subseq sequence start &optional end"},
5375dfecf96Smrg    {LispFunction, Lisp_Subsetp, "subsetp list1 list2 &key test test-not key"},
5385dfecf96Smrg    {LispFunction, Lisp_Substitute, "substitute newitem olditem sequence &key from-end test test-not start end count key"},
5395dfecf96Smrg    {LispFunction, Lisp_SubstituteIf, "substitute-if newitem test sequence &key from-end start end count key"},
5405dfecf96Smrg    {LispFunction, Lisp_SubstituteIfNot, "substitute-if-not newitem test sequence &key from-end start end count key"},
5415dfecf96Smrg    {LispFunction, Lisp_SymbolFunction, "symbol-function symbol"},
5425dfecf96Smrg    {LispFunction, Lisp_SymbolName, "symbol-name symbol"},
5435dfecf96Smrg    {LispFunction, Lisp_Symbolp, "symbolp object"},
5445dfecf96Smrg    {LispFunction, Lisp_SymbolPlist, "symbol-plist symbol"},
5455dfecf96Smrg    {LispFunction, Lisp_SymbolPackage, "symbol-package symbol"},
5465dfecf96Smrg    {LispFunction, Lisp_SymbolValue, "symbol-value symbol"},
5475dfecf96Smrg    {LispMacro, Lisp_Tagbody, "tagbody &rest body", 0, 0, Com_Tagbody},
5485dfecf96Smrg    {LispFunction, Lisp_Terpri, "terpri &optional output-stream"},
5495dfecf96Smrg    {LispFunction, Lisp_Typep, "typep object type"},
5505dfecf96Smrg    {LispMacro, Lisp_The, "the value-type form"},
5515dfecf96Smrg    {LispMacro, Lisp_Throw, "throw tag result", 1},
5525dfecf96Smrg    {LispMacro, Lisp_Time, "time form"},
5535dfecf96Smrg    {LispFunction, Lisp_Truename, "truename pathname"},
5545dfecf96Smrg    {LispFunction, Lisp_TreeEqual, "tree-equal tree-1 tree-2 &key test test-not"},
5555dfecf96Smrg    {LispFunction, Lisp_Truncate, "truncate number &optional divisor", 1},
5565dfecf96Smrg    {LispFunction, Lisp_Ftruncate, "ftruncate number &optional divisor", 1},
5575dfecf96Smrg    {LispFunction, Lisp_Unexport, "unexport symbols &optional package"},
5585dfecf96Smrg    {LispFunction, Lisp_Union, "union list1 list2 &key test test-not key"},
5595dfecf96Smrg    {LispFunction, Lisp_Nunion, "nunion list1 list2 &key test test-not key"},
5605dfecf96Smrg    {LispMacro, Lisp_Unless, "unless test &rest body", 1, 0, Com_Unless},
5615dfecf96Smrg    {LispFunction, Lisp_UserHomedirPathname, "user-homedir-pathname &optional host"},
5625dfecf96Smrg    {LispMacro, Lisp_UnwindProtect, "unwind-protect protect &rest cleanup"},
5635dfecf96Smrg    {LispFunction, Lisp_UpperCaseP, "upper-case-p character"},
5645dfecf96Smrg    {LispFunction, Lisp_Values, "values &rest objects", 1},
5655dfecf96Smrg    {LispFunction, Lisp_ValuesList, "values-list list", 1},
5665dfecf96Smrg    {LispFunction, Lisp_Vector, "vector &rest objects"},
5675dfecf96Smrg    {LispMacro, Lisp_When, "when test &rest body", 1, 0, Com_When},
5685dfecf96Smrg    {LispFunction, Lisp_Write, " write object &key case circle escape length level lines pretty readably right-margin stream"},
5695dfecf96Smrg    {LispFunction, Lisp_WriteChar, "write-char string &optional output-stream"},
5705dfecf96Smrg    {LispFunction, Lisp_WriteLine, "write-line string &optional output-stream &key start end"},
5715dfecf96Smrg    {LispFunction, Lisp_WriteString, "write-string string &optional output-stream &key start end"},
5725dfecf96Smrg    {LispFunction, Lisp_XeditCharStore, "lisp::char-store string index value", 0, 1},
5735dfecf96Smrg    {LispFunction, Lisp_XeditEltStore, "lisp::elt-store sequence index value", 0, 1},
5745dfecf96Smrg    {LispFunction, Lisp_XeditMakeStruct, "lisp::make-struct atom &rest init", 0, 1},
5755dfecf96Smrg    {LispFunction, Lisp_XeditPut, " lisp::put symbol indicator value", 0, 1},
5765dfecf96Smrg    {LispFunction, Lisp_XeditPuthash, "lisp::puthash key hash-table value", 0, 1},
5775dfecf96Smrg    {LispFunction, Lisp_XeditSetSymbolPlist, "lisp::set-symbol-plist symbol list", 0, 1},
5785dfecf96Smrg    {LispFunction, Lisp_XeditStructAccess, "lisp::struct-access atom struct", 0, 1},
5795dfecf96Smrg    {LispFunction, Lisp_XeditStructType, "lisp::struct-type atom struct", 0, 1},
5805dfecf96Smrg    {LispFunction, Lisp_XeditStructStore, "lisp::struct-store atom struct value", 0, 1},
5815dfecf96Smrg    {LispFunction, Lisp_XeditVectorStore, "lisp::vector-store array &rest values", 0, 1},
5825dfecf96Smrg    {LispFunction, Lisp_XeditDocumentationStore, "lisp::documentation-store symbol type string", 0, 1},
5835dfecf96Smrg    {LispFunction, Lisp_Zerop, "zerop number"},
5845dfecf96Smrg};
5855dfecf96Smrg
5865dfecf96Smrgstatic LispBuiltin extbuiltins[] = {
5875dfecf96Smrg    {LispFunction, Lisp_Getenv, "getenv name"},
5885dfecf96Smrg    {LispFunction, Lisp_MakePipe, "make-pipe command-line &key direction element-type external-format"},
5895dfecf96Smrg    {LispFunction, Lisp_PipeBroken, "pipe-broken pipe-stream"},
5905dfecf96Smrg    {LispFunction, Lisp_PipeErrorStream, "pipe-error-stream pipe-stream"},
5915dfecf96Smrg    {LispFunction, Lisp_PipeInputDescriptor, "pipe-input-descriptor pipe-stream"},
5925dfecf96Smrg    {LispFunction, Lisp_PipeErrorDescriptor, "pipe-error-descriptor pipe-stream"},
5935dfecf96Smrg    {LispFunction, Lisp_Recomp, "re-comp pattern &key nospec icase nosub newline"},
5945dfecf96Smrg    {LispFunction, Lisp_Reexec, "re-exec regex string &key count start end notbol noteol"},
5955dfecf96Smrg    {LispFunction, Lisp_Rep, "re-p object"},
5965dfecf96Smrg    {LispFunction, Lisp_Setenv, "setenv name value &optional overwrite"},
5975dfecf96Smrg    {LispFunction, Lisp_Unsetenv, "unsetenv name"},
5985dfecf96Smrg    {LispFunction, Lisp_NstringTrim, "nstring-trim character-bag string"},
5995dfecf96Smrg    {LispFunction, Lisp_NstringLeftTrim, "nstring-left-trim character-bag string"},
6005dfecf96Smrg    {LispFunction, Lisp_NstringRightTrim, "nstring-right-trim character-bag string"},
6015dfecf96Smrg    {LispMacro, Lisp_Until, "until test &rest body", 0, 0, Com_Until},
6025dfecf96Smrg    {LispMacro, Lisp_While, "while test &rest body", 0, 0, Com_While},
6035dfecf96Smrg};
6045dfecf96Smrg
6055dfecf96Smrg/* byte code function argument list for functions that don't change it's
6065dfecf96Smrg * &REST argument list. */
6075dfecf96Smrgextern LispObj x_cons[8];
6085dfecf96Smrg
6095dfecf96Smrg/*
6105dfecf96Smrg * Implementation
6115dfecf96Smrg */
6125dfecf96Smrgstatic int
6135dfecf96SmrgLispGetPageSize(void)
6145dfecf96Smrg{
6155dfecf96Smrg    static int pagesize = -1;
6165dfecf96Smrg
6175dfecf96Smrg    if (pagesize != -1)
6185dfecf96Smrg	return pagesize;
6195dfecf96Smrg
6205dfecf96Smrg    /* Try each supported method in the preferred order */
6215dfecf96Smrg
622f765521fSmrg#if defined(_SC_PAGESIZE) || defined(HAVE_DECL__SC_PAGESIZE)
6235dfecf96Smrg    pagesize = sysconf(_SC_PAGESIZE);
6245dfecf96Smrg#endif
6255dfecf96Smrg
6265dfecf96Smrg#ifdef _SC_PAGE_SIZE
6275dfecf96Smrg    if (pagesize == -1)
6285dfecf96Smrg	pagesize = sysconf(_SC_PAGE_SIZE);
6295dfecf96Smrg#endif
6305dfecf96Smrg
631f765521fSmrg#ifdef HAVE_GETPAGESIZE
6325dfecf96Smrg    if (pagesize == -1)
6335dfecf96Smrg	pagesize = getpagesize();
6345dfecf96Smrg#endif
6355dfecf96Smrg
6365dfecf96Smrg#ifdef PAGE_SIZE
6375dfecf96Smrg    if (pagesize == -1)
6385dfecf96Smrg	pagesize = PAGE_SIZE;
6395dfecf96Smrg#endif
6405dfecf96Smrg
6415dfecf96Smrg    if (pagesize < sizeof(LispObj) * 16)
6425dfecf96Smrg	pagesize = sizeof(LispObj) * 16;	/* need a reasonable sane size */
6435dfecf96Smrg
6445dfecf96Smrg    return pagesize;
6455dfecf96Smrg}
6465dfecf96Smrg
6475dfecf96Smrgvoid
648f765521fSmrgLispDestroy(const char *fmt, ...)
6495dfecf96Smrg{
6505dfecf96Smrg    static char Error[] = "*** ";
6515dfecf96Smrg
6525dfecf96Smrg    if (!lisp__data.destroyed) {
6535dfecf96Smrg	char string[128];
6545dfecf96Smrg	va_list ap;
6555dfecf96Smrg
6565dfecf96Smrg	va_start(ap, fmt);
6575dfecf96Smrg	vsnprintf(string, sizeof(string), fmt, ap);
6585dfecf96Smrg	va_end(ap);
6595dfecf96Smrg
6605dfecf96Smrg	if (!lisp__data.ignore_errors) {
6615dfecf96Smrg	    if (Stderr->column)
6625dfecf96Smrg		LispFputc(Stderr, '\n');
6635dfecf96Smrg	    LispFputs(Stderr, Error);
6645dfecf96Smrg	    LispFputs(Stderr, string);
6655dfecf96Smrg	    LispFputc(Stderr, '\n');
6665dfecf96Smrg	    LispFflush(Stderr);
6675dfecf96Smrg	}
6685dfecf96Smrg	else
6695dfecf96Smrg	    lisp__data.error_condition = STRING(string);
6705dfecf96Smrg
6715dfecf96Smrg#ifdef DEBUGGER
6725dfecf96Smrg	if (lisp__data.debugging) {
6735dfecf96Smrg	    LispDebugger(LispDebugCallWatch, NIL, NIL);
6745dfecf96Smrg	    LispDebugger(LispDebugCallFatal, NIL, NIL);
6755dfecf96Smrg	}
6765dfecf96Smrg#endif
6775dfecf96Smrg
6785dfecf96Smrg	lisp__data.destroyed = 1;
6795dfecf96Smrg	LispBlockUnwind(NULL);
6805dfecf96Smrg	if (lisp__data.errexit)
6815dfecf96Smrg	    exit(1);
6825dfecf96Smrg    }
6835dfecf96Smrg
6845dfecf96Smrg#ifdef DEBUGGER
6855dfecf96Smrg    if (lisp__data.debugging) {
6865dfecf96Smrg	/* when stack variables could be changed, this must be also changed! */
6875dfecf96Smrg	lisp__data.debug_level = -1;
6885dfecf96Smrg	lisp__data.debug = LispDebugUnspec;
6895dfecf96Smrg    }
6905dfecf96Smrg#endif
6915dfecf96Smrg
6925dfecf96Smrg    while (lisp__data.mem.level) {
6935dfecf96Smrg	--lisp__data.mem.level;
6945dfecf96Smrg	if (lisp__data.mem.mem[lisp__data.mem.level])
6955dfecf96Smrg	    free(lisp__data.mem.mem[lisp__data.mem.level]);
6965dfecf96Smrg    }
6975dfecf96Smrg    lisp__data.mem.index = 0;
6985dfecf96Smrg
6995dfecf96Smrg    /* If the package was changed and an error happened */
700c2cbb186Smrg    if (lisp__data.savepackage != NULL)
701c2cbb186Smrg        PACKAGE = lisp__data.savepackage;
7025dfecf96Smrg    lisp__data.pack = lisp__data.savepack;
7035dfecf96Smrg
7045dfecf96Smrg    LispTopLevel();
7055dfecf96Smrg
7065dfecf96Smrg    if (!lisp__data.running) {
707f765521fSmrg	static const char *Fatal = "*** Fatal: nowhere to longjmp.\n";
7085dfecf96Smrg
7095dfecf96Smrg	LispFputs(Stderr, Fatal);
7105dfecf96Smrg	LispFflush(Stderr);
7115dfecf96Smrg	abort();
7125dfecf96Smrg    }
7135dfecf96Smrg
7145dfecf96Smrg    siglongjmp(lisp__data.jmp, 1);
7155dfecf96Smrg}
7165dfecf96Smrg
7175dfecf96Smrgvoid
718f765521fSmrgLispContinuable(const char *fmt, ...)
7195dfecf96Smrg{
7205dfecf96Smrg    va_list ap;
7215dfecf96Smrg    char string[128];
722f765521fSmrg    static const char *Error = "*** Error: ";
7235dfecf96Smrg
7245dfecf96Smrg    if (Stderr->column)
7255dfecf96Smrg	LispFputc(Stderr, '\n');
7265dfecf96Smrg    LispFputs(Stderr, Error);
7275dfecf96Smrg    va_start(ap, fmt);
7285dfecf96Smrg    vsnprintf(string, sizeof(string), fmt, ap);
7295dfecf96Smrg    va_end(ap);
7305dfecf96Smrg    LispFputs(Stderr, string);
7315dfecf96Smrg    LispFputc(Stderr, '\n');
7325dfecf96Smrg    LispFputs(Stderr, "Type 'continue' if you want to proceed: ");
7335dfecf96Smrg    LispFflush(Stderr);
7345dfecf96Smrg
7355dfecf96Smrg    /* NOTE: does not check if stdin is a tty */
7365dfecf96Smrg    if (LispFgets(Stdin, string, sizeof(string)) &&
7375dfecf96Smrg	strcmp(string, "continue\n") == 0)
7385dfecf96Smrg	return;
7395dfecf96Smrg
7405dfecf96Smrg    LispDestroy("aborted on continuable error");
7415dfecf96Smrg}
7425dfecf96Smrg
7435dfecf96Smrgvoid
744f765521fSmrgLispMessage(const char *fmt, ...)
7455dfecf96Smrg{
7465dfecf96Smrg    va_list ap;
7475dfecf96Smrg    char string[128];
7485dfecf96Smrg
7495dfecf96Smrg    if (Stderr->column)
7505dfecf96Smrg	LispFputc(Stderr, '\n');
7515dfecf96Smrg    va_start(ap, fmt);
7525dfecf96Smrg    vsnprintf(string, sizeof(string), fmt, ap);
7535dfecf96Smrg    va_end(ap);
7545dfecf96Smrg    LispFputs(Stderr, string);
7555dfecf96Smrg    LispFputc(Stderr, '\n');
7565dfecf96Smrg    LispFflush(Stderr);
7575dfecf96Smrg}
7585dfecf96Smrg
7595dfecf96Smrgvoid
760f765521fSmrgLispWarning(const char *fmt, ...)
7615dfecf96Smrg{
7625dfecf96Smrg    va_list ap;
7635dfecf96Smrg    char string[128];
764f765521fSmrg    static const char *Warning = "*** Warning: ";
7655dfecf96Smrg
7665dfecf96Smrg    if (Stderr->column)
7675dfecf96Smrg	LispFputc(Stderr, '\n');
7685dfecf96Smrg    LispFputs(Stderr, Warning);
7695dfecf96Smrg    va_start(ap, fmt);
7705dfecf96Smrg    vsnprintf(string, sizeof(string), fmt, ap);
7715dfecf96Smrg    va_end(ap);
7725dfecf96Smrg    LispFputs(Stderr, string);
7735dfecf96Smrg    LispFputc(Stderr, '\n');
7745dfecf96Smrg    LispFflush(Stderr);
7755dfecf96Smrg}
7765dfecf96Smrg
7775dfecf96Smrgvoid
7785dfecf96SmrgLispTopLevel(void)
7795dfecf96Smrg{
7805dfecf96Smrg    int count;
7815dfecf96Smrg
7825dfecf96Smrg    COD = NIL;
7835dfecf96Smrg#ifdef DEBUGGER
7845dfecf96Smrg    if (lisp__data.debugging) {
7855dfecf96Smrg	DBG = NIL;
7865dfecf96Smrg	if (lisp__data.debug == LispDebugFinish)
7875dfecf96Smrg	    lisp__data.debug = LispDebugUnspec;
7885dfecf96Smrg	lisp__data.debug_level = -1;
7895dfecf96Smrg	lisp__data.debug_step = 0;
7905dfecf96Smrg    }
7915dfecf96Smrg#endif
7925dfecf96Smrg    gcpro = 0;
7935dfecf96Smrg    lisp__data.block.block_level = 0;
7945dfecf96Smrg    if (lisp__data.block.block_size) {
7955dfecf96Smrg	while (lisp__data.block.block_size)
7965dfecf96Smrg	    free(lisp__data.block.block[--lisp__data.block.block_size]);
7975dfecf96Smrg	free(lisp__data.block.block);
7985dfecf96Smrg	lisp__data.block.block = NULL;
7995dfecf96Smrg    }
8005dfecf96Smrg
8015dfecf96Smrg    lisp__data.destroyed = lisp__data.ignore_errors = 0;
8025dfecf96Smrg
8035dfecf96Smrg    if (CONSP(lisp__data.input_list)) {
8045dfecf96Smrg	LispUngetInfo **info, *unget = lisp__data.unget[0];
8055dfecf96Smrg
8065dfecf96Smrg	while (CONSP(lisp__data.input_list))
8075dfecf96Smrg	    lisp__data.input_list = CDR(lisp__data.input_list);
8085dfecf96Smrg	SINPUT = lisp__data.input_list;
8095dfecf96Smrg	while (lisp__data.nunget > 1)
8105dfecf96Smrg	    free(lisp__data.unget[--lisp__data.nunget]);
8115dfecf96Smrg	if ((info = realloc(lisp__data.unget, sizeof(LispUngetInfo*))) != NULL)
8125dfecf96Smrg	    lisp__data.unget = info;
8135dfecf96Smrg	lisp__data.unget[0] = unget;
8145dfecf96Smrg	lisp__data.iunget = 0;
8155dfecf96Smrg	lisp__data.eof = 0;
8165dfecf96Smrg    }
8175dfecf96Smrg
8185dfecf96Smrg    for (count = 0; lisp__data.mem.level;) {
8195dfecf96Smrg	--lisp__data.mem.level;
8205dfecf96Smrg	if (lisp__data.mem.mem[lisp__data.mem.level]) {
8215dfecf96Smrg	    ++count;
8225dfecf96Smrg#if 0
8235dfecf96Smrg	    printf("LEAK: %p\n", lisp__data.mem.mem[lisp__data.mem.level]);
8245dfecf96Smrg#endif
8255dfecf96Smrg	}
8265dfecf96Smrg    }
8275dfecf96Smrg    lisp__data.mem.index = 0;
8285dfecf96Smrg    if (count)
8295dfecf96Smrg	LispWarning("%d raw memory pointer(s) left. Probably a leak.", count);
8305dfecf96Smrg
8315dfecf96Smrg    lisp__data.stack.base = lisp__data.stack.length =
8325dfecf96Smrg	lisp__data.env.lex = lisp__data.env.length = lisp__data.env.head = 0;
8335dfecf96Smrg    RETURN_COUNT = 0;
8345dfecf96Smrg    lisp__data.protect.length = 0;
8355dfecf96Smrg
8365dfecf96Smrg    lisp__data.savepackage = PACKAGE;
8375dfecf96Smrg    lisp__data.savepack = lisp__data.pack;
8385dfecf96Smrg
8395dfecf96Smrg    lisp__disable_int = lisp__interrupted = 0;
8405dfecf96Smrg}
8415dfecf96Smrg
8425dfecf96Smrgvoid
8435dfecf96SmrgLispGC(LispObj *car, LispObj *cdr)
8445dfecf96Smrg{
8455dfecf96Smrg    Lisp__GC(car, cdr);
8465dfecf96Smrg}
8475dfecf96Smrg
8485dfecf96Smrgstatic void
8495dfecf96SmrgLisp__GC(LispObj *car, LispObj *cdr)
8505dfecf96Smrg{
8515dfecf96Smrg    register LispObj *entry, *last, *freeobj, **pentry, **eentry;
8525dfecf96Smrg    register int nfree;
8535dfecf96Smrg    unsigned i, j;
8545dfecf96Smrg    LispAtom *atom;
8555dfecf96Smrg    struct timeval start, end;
8565dfecf96Smrg#ifdef DEBUG
8575dfecf96Smrg    long sec, msec;
8585dfecf96Smrg    int count = objseg.nfree;
8595dfecf96Smrg#else
8605dfecf96Smrg    long msec;
8615dfecf96Smrg#endif
8625dfecf96Smrg
8635dfecf96Smrg    if (gcpro)
8645dfecf96Smrg	return;
8655dfecf96Smrg
8665dfecf96Smrg    DISABLE_INTERRUPTS();
8675dfecf96Smrg
8685dfecf96Smrg    nfree = 0;
8695dfecf96Smrg    freeobj = NIL;
8705dfecf96Smrg
8715dfecf96Smrg    ++lisp__data.gc.count;
8725dfecf96Smrg
8735dfecf96Smrg#ifdef DEBUG
8745dfecf96Smrg    gettimeofday(&start, NULL);
8755dfecf96Smrg#else
8765dfecf96Smrg    if (lisp__data.gc.timebits)
8775dfecf96Smrg	gettimeofday(&start, NULL);
8785dfecf96Smrg#endif
8795dfecf96Smrg
8805dfecf96Smrg    /*  Need to measure timings again to check if it is not better/faster
8815dfecf96Smrg     * to just mark these fields as any other data, as the interface was
8825dfecf96Smrg     * changed to properly handle circular lists in the function body itself.
8835dfecf96Smrg     */
8845dfecf96Smrg    if (lisp__data.gc.immutablebits) {
8855dfecf96Smrg	for (j = 0; j < objseg.nsegs; j++) {
8865dfecf96Smrg	    for (entry = objseg.objects[j], last = entry + segsize;
8875dfecf96Smrg		 entry < last; entry++)
8885dfecf96Smrg		entry->prot = 0;
8895dfecf96Smrg	}
8905dfecf96Smrg    }
8915dfecf96Smrg
8925dfecf96Smrg    /* Protect all packages */
8935dfecf96Smrg    for (entry = PACK; CONSP(entry); entry = CDR(entry)) {
8945dfecf96Smrg	LispObj *package = CAR(entry);
8955dfecf96Smrg	LispPackage *pack = package->data.package.package;
8965dfecf96Smrg
8975dfecf96Smrg	/* Protect cons cell */
8985dfecf96Smrg	entry->mark = 1;
8995dfecf96Smrg
9005dfecf96Smrg	/* Protect the package cell */
9015dfecf96Smrg	package->mark = 1;
9025dfecf96Smrg
9035dfecf96Smrg	/* Protect package name */
9045dfecf96Smrg	package->data.package.name->mark = 1;
9055dfecf96Smrg
9065dfecf96Smrg	/* Protect package nicknames */
9075dfecf96Smrg	LispMark(package->data.package.nicknames);
9085dfecf96Smrg
9095dfecf96Smrg	/* Protect global symbols */
9105dfecf96Smrg	for (pentry = pack->glb.pairs, eentry = pentry + pack->glb.length;
9115dfecf96Smrg	    pentry < eentry; pentry++)
9125dfecf96Smrg	    LispMark((*pentry)->data.atom->property->value);
9135dfecf96Smrg
9145dfecf96Smrg	/* Traverse atom list, protecting properties, and function/structure
9155dfecf96Smrg	 * definitions if lisp__data.gc.immutablebits set */
916f14f4646Smrg	for (atom = (LispAtom *)hash_iter_first(pack->atoms);
917f14f4646Smrg	     atom;
918f14f4646Smrg	     atom = (LispAtom *)hash_iter_next(pack->atoms)) {
919f14f4646Smrg	    if (atom->property != NOPROPERTY) {
920f14f4646Smrg		if (atom->a_property)
921f14f4646Smrg		    LispMark(atom->property->properties);
922f14f4646Smrg		if (lisp__data.gc.immutablebits) {
923f14f4646Smrg		    if (atom->a_function || atom->a_compiled)
924f14f4646Smrg			LispProt(atom->property->fun.function);
925f14f4646Smrg		    if (atom->a_defsetf)
926f14f4646Smrg			LispProt(atom->property->setf);
927f14f4646Smrg		    if (atom->a_defstruct)
928f14f4646Smrg			LispProt(atom->property->structure.definition);
9295dfecf96Smrg		}
9305dfecf96Smrg	    }
9315dfecf96Smrg	}
9325dfecf96Smrg    }
9335dfecf96Smrg
9345dfecf96Smrg    /* protect environment */
9355dfecf96Smrg    for (pentry = lisp__data.env.values,
9365dfecf96Smrg	 eentry = pentry + lisp__data.env.length;
9375dfecf96Smrg	 pentry < eentry; pentry++)
9385dfecf96Smrg	LispMark(*pentry);
9395dfecf96Smrg
9405dfecf96Smrg    /* protect multiple return values */
9415dfecf96Smrg    for (pentry = lisp__data.returns.values,
9425dfecf96Smrg	 eentry = pentry + lisp__data.returns.count;
9435dfecf96Smrg	 pentry < eentry; pentry++)
9445dfecf96Smrg	LispMark(*pentry);
9455dfecf96Smrg
9465dfecf96Smrg    /* protect stack of arguments to builtin functions */
9475dfecf96Smrg    for (pentry = lisp__data.stack.values,
9485dfecf96Smrg	 eentry = pentry + lisp__data.stack.length;
9495dfecf96Smrg	 pentry < eentry; pentry++)
9505dfecf96Smrg	LispMark(*pentry);
9515dfecf96Smrg
9525dfecf96Smrg    /* protect temporary data used by builtin functions */
9535dfecf96Smrg    for (pentry = lisp__data.protect.objects,
9545dfecf96Smrg	 eentry = pentry + lisp__data.protect.length;
9555dfecf96Smrg	 pentry < eentry; pentry++)
9565dfecf96Smrg	LispMark(*pentry);
9575dfecf96Smrg
9585dfecf96Smrg    for (i = 0; i < sizeof(x_cons) / sizeof(x_cons[0]); i++)
9595dfecf96Smrg	x_cons[i].mark = 0;
9605dfecf96Smrg
9615dfecf96Smrg    LispMark(COD);
9625dfecf96Smrg#ifdef DEBUGGER
9635dfecf96Smrg    LispMark(DBG);
9645dfecf96Smrg    LispMark(BRK);
9655dfecf96Smrg#endif
9665dfecf96Smrg    LispMark(PRO);
9675dfecf96Smrg    LispMark(lisp__data.input_list);
9685dfecf96Smrg    LispMark(lisp__data.output_list);
9695dfecf96Smrg    LispMark(car);
9705dfecf96Smrg    LispMark(cdr);
9715dfecf96Smrg
9725dfecf96Smrg    for (j = 0; j < objseg.nsegs; j++) {
9735dfecf96Smrg	for (entry = objseg.objects[j], last = entry + segsize;
9745dfecf96Smrg	     entry < last; entry++) {
9755dfecf96Smrg	    if (entry->prot)
9765dfecf96Smrg		continue;
9775dfecf96Smrg	    else if (entry->mark)
9785dfecf96Smrg		entry->mark = 0;
9795dfecf96Smrg	    else {
9805dfecf96Smrg		switch (XOBJECT_TYPE(entry)) {
9815dfecf96Smrg		    case LispString_t:
9825dfecf96Smrg			free(THESTR(entry));
9835dfecf96Smrg			entry->type = LispCons_t;
9845dfecf96Smrg			break;
9855dfecf96Smrg		    case LispStream_t:
9865dfecf96Smrg			switch (entry->data.stream.type) {
9875dfecf96Smrg			    case LispStreamString:
9885dfecf96Smrg				free(SSTREAMP(entry)->string);
9895dfecf96Smrg				free(SSTREAMP(entry));
9905dfecf96Smrg				break;
9915dfecf96Smrg			    case LispStreamFile:
9925dfecf96Smrg				if (FSTREAMP(entry))
9935dfecf96Smrg				    LispFclose(FSTREAMP(entry));
9945dfecf96Smrg				break;
9955dfecf96Smrg			    case LispStreamPipe:
9965dfecf96Smrg				/* XXX may need special handling if child hangs */
9975dfecf96Smrg				if (PSTREAMP(entry)) {
9985dfecf96Smrg				    if (IPSTREAMP(entry))
9995dfecf96Smrg					LispFclose(IPSTREAMP(entry));
10005dfecf96Smrg				    if (OPSTREAMP(entry))
10015dfecf96Smrg					LispFclose(OPSTREAMP(entry));
10025dfecf96Smrg				    /* don't bother with error stream, will also
10035dfecf96Smrg				     * freed in this GC call, maybe just out
10045dfecf96Smrg				     * of order */
10055dfecf96Smrg				    if (PIDPSTREAMP(entry) > 0) {
10065dfecf96Smrg					kill(PIDPSTREAMP(entry), SIGTERM);
10075dfecf96Smrg					waitpid(PIDPSTREAMP(entry), NULL, 0);
10085dfecf96Smrg				    }
10095dfecf96Smrg				    free(PSTREAMP(entry));
10105dfecf96Smrg				}
10115dfecf96Smrg				break;
10125dfecf96Smrg			    default:
10135dfecf96Smrg				break;
10145dfecf96Smrg			}
10155dfecf96Smrg			entry->type = LispCons_t;
10165dfecf96Smrg			break;
10175dfecf96Smrg		    case LispBignum_t:
10185dfecf96Smrg			mpi_clear(entry->data.mp.integer);
10195dfecf96Smrg			free(entry->data.mp.integer);
10205dfecf96Smrg			entry->type = LispCons_t;
10215dfecf96Smrg			break;
10225dfecf96Smrg		    case LispBigratio_t:
10235dfecf96Smrg			mpr_clear(entry->data.mp.ratio);
10245dfecf96Smrg			free(entry->data.mp.ratio);
10255dfecf96Smrg			entry->type = LispCons_t;
10265dfecf96Smrg			break;
10275dfecf96Smrg		    case LispLambda_t:
10285dfecf96Smrg			if (!SYMBOLP(entry->data.lambda.name))
10295dfecf96Smrg			    LispFreeArgList((LispArgList*)
10305dfecf96Smrg				entry->data.lambda.name->data.opaque.data);
10315dfecf96Smrg			entry->type = LispCons_t;
10325dfecf96Smrg			break;
10335dfecf96Smrg		    case LispRegex_t:
10345dfecf96Smrg			refree(entry->data.regex.regex);
10355dfecf96Smrg			free(entry->data.regex.regex);
10365dfecf96Smrg			entry->type = LispCons_t;
10375dfecf96Smrg			break;
10385dfecf96Smrg		    case LispBytecode_t:
10395dfecf96Smrg			free(entry->data.bytecode.bytecode->code);
10405dfecf96Smrg			free(entry->data.bytecode.bytecode);
10415dfecf96Smrg			entry->type = LispCons_t;
10425dfecf96Smrg			break;
10435dfecf96Smrg		    case LispHashTable_t:
10445dfecf96Smrg			LispFreeHashTable(entry->data.hash.table);
10455dfecf96Smrg			entry->type = LispCons_t;
10465dfecf96Smrg			break;
10475dfecf96Smrg		    case LispCons_t:
10485dfecf96Smrg			break;
10495dfecf96Smrg		    default:
10505dfecf96Smrg			entry->type = LispCons_t;
10515dfecf96Smrg			break;
10525dfecf96Smrg		}
10535dfecf96Smrg		CDR(entry) = freeobj;
10545dfecf96Smrg		freeobj = entry;
10555dfecf96Smrg		++nfree;
10565dfecf96Smrg	    }
10575dfecf96Smrg	}
10585dfecf96Smrg    }
10595dfecf96Smrg
10605dfecf96Smrg    objseg.nfree = nfree;
10615dfecf96Smrg    objseg.freeobj = freeobj;
10625dfecf96Smrg
10635dfecf96Smrg    lisp__data.gc.immutablebits = 0;
10645dfecf96Smrg
10655dfecf96Smrg#ifdef DEBUG
10665dfecf96Smrg    gettimeofday(&end, NULL);
10675dfecf96Smrg    sec = end.tv_sec - start.tv_sec;
10685dfecf96Smrg    msec = end.tv_usec - start.tv_usec;
10695dfecf96Smrg    if (msec < 0) {
10705dfecf96Smrg	--sec;
10715dfecf96Smrg	msec += 1000000;
10725dfecf96Smrg    }
10735dfecf96Smrg    LispMessage("gc: "
10745dfecf96Smrg		"%ld sec, %ld msec, "
10755dfecf96Smrg		"%d recovered, %d free, %d protected, %d total",
10765dfecf96Smrg		sec, msec,
10775dfecf96Smrg		objseg.nfree - count, objseg.nfree,
10785dfecf96Smrg		objseg.nobjs - objseg.nfree, objseg.nobjs);
10795dfecf96Smrg#else
10805dfecf96Smrg    if (lisp__data.gc.timebits) {
10815dfecf96Smrg	gettimeofday(&end, NULL);
10825dfecf96Smrg	if ((msec = end.tv_usec - start.tv_usec) < 0)
10835dfecf96Smrg	    msec += 1000000;
10845dfecf96Smrg	lisp__data.gc.gctime += msec;
10855dfecf96Smrg    }
10865dfecf96Smrg#endif
10875dfecf96Smrg
10885dfecf96Smrg    ENABLE_INTERRUPTS();
10895dfecf96Smrg}
10905dfecf96Smrg
10915dfecf96Smrgstatic INLINE void
10925dfecf96SmrgLispCheckMemLevel(void)
10935dfecf96Smrg{
10945dfecf96Smrg    int i;
10955dfecf96Smrg
10965dfecf96Smrg    /* Check for a free slot before the end. */
10975dfecf96Smrg    for (i = lisp__data.mem.index; i < lisp__data.mem.level; i++)
10985dfecf96Smrg	if (lisp__data.mem.mem[i] == NULL) {
10995dfecf96Smrg	    lisp__data.mem.index = i;
11005dfecf96Smrg	    return;
11015dfecf96Smrg	}
11025dfecf96Smrg
11035dfecf96Smrg    /* Check for a free slot in the beginning */
11045dfecf96Smrg    for (i = 0; i < lisp__data.mem.index; i++)
11055dfecf96Smrg	if (lisp__data.mem.mem[i] == NULL) {
11065dfecf96Smrg	    lisp__data.mem.index = i;
11075dfecf96Smrg	    return;
11085dfecf96Smrg	}
11095dfecf96Smrg
11105dfecf96Smrg    lisp__data.mem.index = lisp__data.mem.level;
11115dfecf96Smrg    ++lisp__data.mem.level;
11125dfecf96Smrg    if (lisp__data.mem.index < lisp__data.mem.space)
11135dfecf96Smrg	/* There is free space to store pointer. */
11145dfecf96Smrg	return;
11155dfecf96Smrg    else {
11165dfecf96Smrg	void **ptr = (void**)realloc(lisp__data.mem.mem,
11175dfecf96Smrg				     (lisp__data.mem.space + 16) *
11185dfecf96Smrg				     sizeof(void*));
11195dfecf96Smrg
11205dfecf96Smrg	if (ptr == NULL)
11215dfecf96Smrg	    LispDestroy("out of memory");
11225dfecf96Smrg	lisp__data.mem.mem = ptr;
11235dfecf96Smrg	lisp__data.mem.space += 16;
11245dfecf96Smrg    }
11255dfecf96Smrg}
11265dfecf96Smrg
11275dfecf96Smrgvoid
11285dfecf96SmrgLispMused(void *pointer)
11295dfecf96Smrg{
11305dfecf96Smrg    int i;
11315dfecf96Smrg
11325dfecf96Smrg    DISABLE_INTERRUPTS();
11335dfecf96Smrg    for (i = lisp__data.mem.index; i >= 0; i--)
11345dfecf96Smrg	if (lisp__data.mem.mem[i] == pointer) {
11355dfecf96Smrg	    lisp__data.mem.mem[i] = NULL;
11365dfecf96Smrg	    lisp__data.mem.index = i;
11375dfecf96Smrg	    goto mused_done;
11385dfecf96Smrg	}
11395dfecf96Smrg
11405dfecf96Smrg    for (i = lisp__data.mem.level - 1; i > lisp__data.mem.index; i--)
11415dfecf96Smrg	if (lisp__data.mem.mem[i] == pointer) {
11425dfecf96Smrg	    lisp__data.mem.mem[i] = NULL;
11435dfecf96Smrg	    lisp__data.mem.index = i;
11445dfecf96Smrg	    break;
11455dfecf96Smrg	}
11465dfecf96Smrg
11475dfecf96Smrgmused_done:
11485dfecf96Smrg    ENABLE_INTERRUPTS();
11495dfecf96Smrg}
11505dfecf96Smrg
11515dfecf96Smrgvoid *
11525dfecf96SmrgLispMalloc(size_t size)
11535dfecf96Smrg{
11545dfecf96Smrg    void *pointer;
11555dfecf96Smrg
11565dfecf96Smrg    DISABLE_INTERRUPTS();
11575dfecf96Smrg    LispCheckMemLevel();
11585dfecf96Smrg    if ((pointer = malloc(size)) == NULL)
11595dfecf96Smrg	LispDestroy("out of memory, couldn't allocate %lu bytes",
11605dfecf96Smrg		    (unsigned long)size);
11615dfecf96Smrg
11625dfecf96Smrg    lisp__data.mem.mem[lisp__data.mem.index] = pointer;
11635dfecf96Smrg    ENABLE_INTERRUPTS();
11645dfecf96Smrg
11655dfecf96Smrg    return (pointer);
11665dfecf96Smrg}
11675dfecf96Smrg
11685dfecf96Smrgvoid *
11695dfecf96SmrgLispCalloc(size_t nmemb, size_t size)
11705dfecf96Smrg{
11715dfecf96Smrg    void *pointer;
11725dfecf96Smrg
11735dfecf96Smrg    DISABLE_INTERRUPTS();
11745dfecf96Smrg    LispCheckMemLevel();
11755dfecf96Smrg    if ((pointer = calloc(nmemb, size)) == NULL)
11765dfecf96Smrg	LispDestroy("out of memory, couldn't allocate %lu bytes",
11775dfecf96Smrg		    (unsigned long)size);
11785dfecf96Smrg
11795dfecf96Smrg    lisp__data.mem.mem[lisp__data.mem.index] = pointer;
11805dfecf96Smrg    ENABLE_INTERRUPTS();
11815dfecf96Smrg
11825dfecf96Smrg    return (pointer);
11835dfecf96Smrg}
11845dfecf96Smrg
11855dfecf96Smrgvoid *
11865dfecf96SmrgLispRealloc(void *pointer, size_t size)
11875dfecf96Smrg{
11885dfecf96Smrg    void *ptr;
11895dfecf96Smrg    int i;
11905dfecf96Smrg
11915dfecf96Smrg    DISABLE_INTERRUPTS();
11925dfecf96Smrg    if (pointer != NULL) {
11935dfecf96Smrg	for (i = lisp__data.mem.index; i >= 0; i--)
11945dfecf96Smrg	    if (lisp__data.mem.mem[i] == pointer)
11955dfecf96Smrg		goto index_found;
11965dfecf96Smrg
11975dfecf96Smrg	for (i = lisp__data.mem.index + 1; i < lisp__data.mem.level; i++)
11985dfecf96Smrg	    if (lisp__data.mem.mem[i] == pointer)
11995dfecf96Smrg		goto index_found;
12005dfecf96Smrg
12015dfecf96Smrg    }
12025dfecf96Smrg    LispCheckMemLevel();
12035dfecf96Smrg    i = lisp__data.mem.index;
12045dfecf96Smrg
12055dfecf96Smrgindex_found:
12065dfecf96Smrg    if ((ptr = realloc(pointer, size)) == NULL)
12075dfecf96Smrg	LispDestroy("out of memory, couldn't realloc");
12085dfecf96Smrg
12095dfecf96Smrg    lisp__data.mem.mem[i] = ptr;
12105dfecf96Smrg    ENABLE_INTERRUPTS();
12115dfecf96Smrg
12125dfecf96Smrg    return (ptr);
12135dfecf96Smrg}
12145dfecf96Smrg
12155dfecf96Smrgchar *
1216f765521fSmrgLispStrdup(const char *str)
12175dfecf96Smrg{
12185dfecf96Smrg    char *ptr = LispMalloc(strlen(str) + 1);
12195dfecf96Smrg
12205dfecf96Smrg    strcpy(ptr, str);
12215dfecf96Smrg
12225dfecf96Smrg    return (ptr);
12235dfecf96Smrg}
12245dfecf96Smrg
12255dfecf96Smrgvoid
12265dfecf96SmrgLispFree(void *pointer)
12275dfecf96Smrg{
12285dfecf96Smrg    int i;
12295dfecf96Smrg
12305dfecf96Smrg    DISABLE_INTERRUPTS();
12315dfecf96Smrg    for (i = lisp__data.mem.index; i >= 0; i--)
12325dfecf96Smrg	if (lisp__data.mem.mem[i] == pointer) {
12335dfecf96Smrg	    lisp__data.mem.mem[i] = NULL;
12345dfecf96Smrg	    lisp__data.mem.index = i;
12355dfecf96Smrg	    goto free_done;
12365dfecf96Smrg	}
12375dfecf96Smrg
12385dfecf96Smrg    for (i = lisp__data.mem.level - 1; i > lisp__data.mem.index; i--)
12395dfecf96Smrg	if (lisp__data.mem.mem[i] == pointer) {
12405dfecf96Smrg	    lisp__data.mem.mem[i] = NULL;
12415dfecf96Smrg	    lisp__data.mem.index = i;
12425dfecf96Smrg	    break;
12435dfecf96Smrg	}
12445dfecf96Smrg
12455dfecf96Smrgfree_done:
12465dfecf96Smrg    free(pointer);
12475dfecf96Smrg    ENABLE_INTERRUPTS();
12485dfecf96Smrg}
12495dfecf96Smrg
12505dfecf96SmrgLispObj *
1251f765521fSmrgLispSetVariable(LispObj *var, LispObj *val, const char *fname, int eval)
12525dfecf96Smrg{
12535dfecf96Smrg    if (!SYMBOLP(var))
12545dfecf96Smrg	LispDestroy("%s: %s is not a symbol", fname, STROBJ(var));
12555dfecf96Smrg    if (eval)
12565dfecf96Smrg	val = EVAL(val);
12575dfecf96Smrg
12585dfecf96Smrg    return (LispSetVar(var, val));
12595dfecf96Smrg}
12605dfecf96Smrg
12615dfecf96Smrgint
1262f765521fSmrgLispRegisterOpaqueType(const char *desc)
12635dfecf96Smrg{
1264f14f4646Smrg    int length;
12655dfecf96Smrg    LispOpaque *opaque;
12665dfecf96Smrg
1267f14f4646Smrg    length = strlen(desc);
1268f14f4646Smrg    opaque = (LispOpaque *)hash_check(lisp__data.opqs, desc, length);
1269f14f4646Smrg
1270f14f4646Smrg    if (opaque == NULL) {
1271f14f4646Smrg	opaque = (LispOpaque*)LispMalloc(sizeof(LispOpaque));
1272f14f4646Smrg	opaque->desc = (hash_key*)LispCalloc(1, sizeof(hash_key));
1273f14f4646Smrg	opaque->desc->value = LispStrdup(desc);
1274f14f4646Smrg	opaque->desc->length = length;
1275f14f4646Smrg	hash_put(lisp__data.opqs, (hash_entry *)opaque);
1276f14f4646Smrg	LispMused(opaque->desc->value);
1277f14f4646Smrg	LispMused(opaque->desc);
1278f14f4646Smrg	LispMused(opaque);
1279f14f4646Smrg	opaque->type = ++lisp__data.opaque;
1280f14f4646Smrg    }
12815dfecf96Smrg
1282f14f4646Smrg    return (opaque->type);
12835dfecf96Smrg}
12845dfecf96Smrg
12855dfecf96Smrgchar *
12865dfecf96SmrgLispIntToOpaqueType(int type)
12875dfecf96Smrg{
12885dfecf96Smrg    LispOpaque *opaque;
12895dfecf96Smrg
12905dfecf96Smrg    if (type) {
1291f14f4646Smrg	for (opaque = (LispOpaque *)hash_iter_first(lisp__data.opqs);
1292f14f4646Smrg	     opaque;
1293f14f4646Smrg	     opaque = (LispOpaque *)hash_iter_next(lisp__data.opqs)) {
1294f14f4646Smrg	    if (opaque->type == type)
1295f14f4646Smrg		return (opaque->desc->value);
12965dfecf96Smrg	}
12975dfecf96Smrg	LispDestroy("Opaque type %d not registered", type);
12985dfecf96Smrg    }
12995dfecf96Smrg
1300f14f4646Smrg    return (Snil->value);
13015dfecf96Smrg}
13025dfecf96Smrg
1303f14f4646Smrghash_key *
1304f765521fSmrgLispGetAtomKey(const char *string, int perm)
13055dfecf96Smrg{
1306f14f4646Smrg    int length;
1307f14f4646Smrg    hash_entry *entry;
1308f14f4646Smrg
1309f14f4646Smrg    length = strlen(string);
1310f14f4646Smrg    entry = hash_check(lisp__data.strings, string, length);
1311f14f4646Smrg    if (entry == NULL) {
1312f14f4646Smrg	entry = LispCalloc(1, sizeof(hash_entry));
1313f14f4646Smrg	entry->key = LispCalloc(1, sizeof(hash_key));
1314f14f4646Smrg	if (perm)
1315f765521fSmrg	    entry->key->value = (char *) string;
1316f14f4646Smrg	else
1317f14f4646Smrg	    entry->key->value = LispStrdup(string);
1318f14f4646Smrg	entry->key->length = length;
1319f14f4646Smrg
1320f14f4646Smrg	hash_put(lisp__data.strings, entry);
1321f14f4646Smrg	if (!perm)
1322f14f4646Smrg	    LispMused(entry->key->value);
1323f14f4646Smrg	LispMused(entry->key);
1324f14f4646Smrg	LispMused(entry);
1325f14f4646Smrg    }
13265dfecf96Smrg
1327f14f4646Smrg    return (entry->key);
13285dfecf96Smrg}
13295dfecf96Smrg
13305dfecf96SmrgLispAtom *
1331f765521fSmrgLispDoGetAtom(const char *str, int perm)
13325dfecf96Smrg{
1333f14f4646Smrg    int length;
13345dfecf96Smrg    LispAtom *atom;
13355dfecf96Smrg
1336f14f4646Smrg    length = strlen(str);
1337f14f4646Smrg    atom = (LispAtom *)hash_check(lisp__data.pack->atoms, str, length);
13385dfecf96Smrg
1339f14f4646Smrg    if (atom == NULL) {
1340f14f4646Smrg	atom = (LispAtom*)LispCalloc(1, sizeof(LispAtom));
1341f14f4646Smrg	atom->key = LispGetAtomKey(str, perm);
1342f14f4646Smrg	hash_put(lisp__data.pack->atoms, (hash_entry *)atom);
1343f14f4646Smrg	atom->property = NOPROPERTY;
1344f14f4646Smrg	LispMused(atom);
1345f14f4646Smrg    }
13465dfecf96Smrg
13475dfecf96Smrg    return (atom);
13485dfecf96Smrg}
13495dfecf96Smrg
13505dfecf96Smrgstatic void
13515dfecf96SmrgLispAllocAtomProperty(LispAtom *atom)
13525dfecf96Smrg{
13535dfecf96Smrg    LispProperty *property;
13545dfecf96Smrg
13555dfecf96Smrg    if (atom->property != NOPROPERTY)
13565dfecf96Smrg	LispDestroy("internal error at ALLOC-ATOM-PROPERTY");
13575dfecf96Smrg
13585dfecf96Smrg    property = LispCalloc(1, sizeof(LispProperty));
13595dfecf96Smrg    LispMused(property);
13605dfecf96Smrg    atom->property = property;
13615dfecf96Smrg    property->package = lisp__data.pack;
13625dfecf96Smrg    if (atom->package == NULL)
13635dfecf96Smrg	atom->package = PACKAGE;
13645dfecf96Smrg
13655dfecf96Smrg    LispIncrementAtomReference(atom);
13665dfecf96Smrg}
13675dfecf96Smrg
13685dfecf96Smrgstatic void
13695dfecf96SmrgLispIncrementAtomReference(LispAtom *atom)
13705dfecf96Smrg{
13715dfecf96Smrg    if (atom->property != NOPROPERTY)
13725dfecf96Smrg	/* if atom->property is NOPROPERTY, this is an unbound symbol */
13735dfecf96Smrg	++atom->property->refcount;
13745dfecf96Smrg}
13755dfecf96Smrg
13765dfecf96Smrg/* Assumes atom property is not NOPROPERTY */
13775dfecf96Smrgstatic void
13785dfecf96SmrgLispDecrementAtomReference(LispAtom *atom)
13795dfecf96Smrg{
13805dfecf96Smrg    if (atom->property == NOPROPERTY)
13815dfecf96Smrg	/* if atom->property is NOPROPERTY, this is an unbound symbol */
13825dfecf96Smrg	return;
13835dfecf96Smrg
13845dfecf96Smrg    if (atom->property->refcount <= 0)
13855dfecf96Smrg	LispDestroy("internal error at DECREMENT-ATOM-REFERENCE");
13865dfecf96Smrg
13875dfecf96Smrg    --atom->property->refcount;
13885dfecf96Smrg
13895dfecf96Smrg    if (atom->property->refcount == 0) {
13905dfecf96Smrg	LispRemAtomAllProperties(atom);
13915dfecf96Smrg	free(atom->property);
13925dfecf96Smrg	atom->property = NOPROPERTY;
13935dfecf96Smrg    }
13945dfecf96Smrg}
13955dfecf96Smrg
13965dfecf96Smrgstatic void
13975dfecf96SmrgLispRemAtomAllProperties(LispAtom *atom)
13985dfecf96Smrg{
13995dfecf96Smrg    if (atom->property != NOPROPERTY) {
14005dfecf96Smrg	if (atom->a_object)
14015dfecf96Smrg	    LispRemAtomObjectProperty(atom);
14025dfecf96Smrg	if (atom->a_function) {
14035dfecf96Smrg	    lisp__data.gc.immutablebits = 1;
14045dfecf96Smrg	    LispRemAtomFunctionProperty(atom);
14055dfecf96Smrg	}
14065dfecf96Smrg	else if (atom->a_compiled) {
14075dfecf96Smrg	    lisp__data.gc.immutablebits = 1;
14085dfecf96Smrg	    LispRemAtomCompiledProperty(atom);
14095dfecf96Smrg	}
14105dfecf96Smrg	else if (atom->a_builtin) {
14115dfecf96Smrg	    lisp__data.gc.immutablebits = 1;
14125dfecf96Smrg	    LispRemAtomBuiltinProperty(atom);
14135dfecf96Smrg	}
14145dfecf96Smrg	if (atom->a_defsetf) {
14155dfecf96Smrg	    lisp__data.gc.immutablebits = 1;
14165dfecf96Smrg	    LispRemAtomSetfProperty(atom);
14175dfecf96Smrg	}
14185dfecf96Smrg	if (atom->a_defstruct) {
14195dfecf96Smrg	    lisp__data.gc.immutablebits = 1;
14205dfecf96Smrg	    LispRemAtomStructProperty(atom);
14215dfecf96Smrg	}
14225dfecf96Smrg    }
14235dfecf96Smrg}
14245dfecf96Smrg
14255dfecf96Smrgvoid
14265dfecf96SmrgLispSetAtomObjectProperty(LispAtom *atom, LispObj *object)
14275dfecf96Smrg{
14285dfecf96Smrg    if (atom->property == NOPROPERTY)
14295dfecf96Smrg	LispAllocAtomProperty(atom);
14305dfecf96Smrg    else if (atom->watch) {
14315dfecf96Smrg	if (atom->object == lisp__data.package) {
14325dfecf96Smrg	    if (!PACKAGEP(object))
14335dfecf96Smrg		LispDestroy("Symbol %s must be a package, not %s",
1434f14f4646Smrg			    ATOMID(lisp__data.package)->value, STROBJ(object));
14355dfecf96Smrg	    lisp__data.pack = object->data.package.package;
14365dfecf96Smrg	}
14375dfecf96Smrg    }
14385dfecf96Smrg
14395dfecf96Smrg    atom->a_object = 1;
14405dfecf96Smrg    SETVALUE(atom, object);
14415dfecf96Smrg}
14425dfecf96Smrg
14435dfecf96Smrgstatic void
14445dfecf96SmrgLispRemAtomObjectProperty(LispAtom *atom)
14455dfecf96Smrg{
14465dfecf96Smrg    if (atom->a_object) {
14475dfecf96Smrg	atom->a_object = 0;
14485dfecf96Smrg	atom->property->value = NULL;
14495dfecf96Smrg    }
14505dfecf96Smrg}
14515dfecf96Smrg
14525dfecf96Smrgvoid
14535dfecf96SmrgLispSetAtomCompiledProperty(LispAtom *atom, LispObj *bytecode)
14545dfecf96Smrg{
14555dfecf96Smrg    if (atom->property == NOPROPERTY)
14565dfecf96Smrg	LispAllocAtomProperty(atom);
14575dfecf96Smrg
14585dfecf96Smrg    lisp__data.gc.immutablebits = 1;
14595dfecf96Smrg    if (atom->a_builtin) {
14605dfecf96Smrg	atom->a_builtin = 0;
14615dfecf96Smrg	LispFreeArgList(atom->property->alist);
14625dfecf96Smrg    }
14635dfecf96Smrg    else
14645dfecf96Smrg	atom->a_function = 0;
14655dfecf96Smrg    atom->a_compiled = 1;
14665dfecf96Smrg    atom->property->fun.function = bytecode;
14675dfecf96Smrg}
14685dfecf96Smrg
14695dfecf96Smrgvoid
14705dfecf96SmrgLispRemAtomCompiledProperty(LispAtom *atom)
14715dfecf96Smrg{
14725dfecf96Smrg    if (atom->a_compiled) {
14735dfecf96Smrg	lisp__data.gc.immutablebits = 1;
14745dfecf96Smrg	atom->property->fun.function = NULL;
14755dfecf96Smrg	atom->a_compiled = 0;
14765dfecf96Smrg	LispFreeArgList(atom->property->alist);
14775dfecf96Smrg	atom->property->alist = NULL;
14785dfecf96Smrg    }
14795dfecf96Smrg}
14805dfecf96Smrg
14815dfecf96Smrgvoid
14825dfecf96SmrgLispSetAtomFunctionProperty(LispAtom *atom, LispObj *function,
14835dfecf96Smrg			    LispArgList *alist)
14845dfecf96Smrg{
14855dfecf96Smrg    if (atom->property == NOPROPERTY)
14865dfecf96Smrg	LispAllocAtomProperty(atom);
14875dfecf96Smrg
14885dfecf96Smrg    lisp__data.gc.immutablebits = 1;
14895dfecf96Smrg    if (atom->a_function == 0 && atom->a_builtin == 0 && atom->a_compiled == 0)
14905dfecf96Smrg	atom->a_function = 1;
14915dfecf96Smrg    else {
14925dfecf96Smrg	if (atom->a_builtin) {
14935dfecf96Smrg	    atom->a_builtin = 0;
14945dfecf96Smrg	    LispFreeArgList(atom->property->alist);
14955dfecf96Smrg	}
14965dfecf96Smrg	else
14975dfecf96Smrg	    atom->a_compiled = 0;
14985dfecf96Smrg	atom->a_function = 1;
14995dfecf96Smrg    }
15005dfecf96Smrg
15015dfecf96Smrg    atom->property->fun.function = function;
15025dfecf96Smrg    atom->property->alist = alist;
15035dfecf96Smrg}
15045dfecf96Smrg
15055dfecf96Smrgvoid
15065dfecf96SmrgLispRemAtomFunctionProperty(LispAtom *atom)
15075dfecf96Smrg{
15085dfecf96Smrg    if (atom->a_function) {
15095dfecf96Smrg	lisp__data.gc.immutablebits = 1;
15105dfecf96Smrg	atom->property->fun.function = NULL;
15115dfecf96Smrg	atom->a_function = 0;
15125dfecf96Smrg	LispFreeArgList(atom->property->alist);
15135dfecf96Smrg	atom->property->alist = NULL;
15145dfecf96Smrg    }
15155dfecf96Smrg}
15165dfecf96Smrg
15175dfecf96Smrgvoid
15185dfecf96SmrgLispSetAtomBuiltinProperty(LispAtom *atom, LispBuiltin *builtin,
15195dfecf96Smrg			   LispArgList *alist)
15205dfecf96Smrg{
15215dfecf96Smrg    if (atom->property == NOPROPERTY)
15225dfecf96Smrg	LispAllocAtomProperty(atom);
15235dfecf96Smrg
15245dfecf96Smrg    lisp__data.gc.immutablebits = 1;
15255dfecf96Smrg    if (atom->a_builtin == 0 && atom->a_function == 0)
15265dfecf96Smrg	atom->a_builtin = 1;
15275dfecf96Smrg    else {
15285dfecf96Smrg	if (atom->a_function) {
15295dfecf96Smrg	    atom->a_function = 0;
15305dfecf96Smrg	    LispFreeArgList(atom->property->alist);
15315dfecf96Smrg	}
15325dfecf96Smrg    }
15335dfecf96Smrg
15345dfecf96Smrg    atom->property->fun.builtin = builtin;
15355dfecf96Smrg    atom->property->alist = alist;
15365dfecf96Smrg}
15375dfecf96Smrg
15385dfecf96Smrgvoid
15395dfecf96SmrgLispRemAtomBuiltinProperty(LispAtom *atom)
15405dfecf96Smrg{
15415dfecf96Smrg    if (atom->a_builtin) {
15425dfecf96Smrg	lisp__data.gc.immutablebits = 1;
15435dfecf96Smrg	atom->property->fun.function = NULL;
15445dfecf96Smrg	atom->a_builtin = 0;
15455dfecf96Smrg	LispFreeArgList(atom->property->alist);
15465dfecf96Smrg	atom->property->alist = NULL;
15475dfecf96Smrg    }
15485dfecf96Smrg}
15495dfecf96Smrg
15505dfecf96Smrgvoid
15515dfecf96SmrgLispSetAtomSetfProperty(LispAtom *atom, LispObj *setf, LispArgList *alist)
15525dfecf96Smrg{
15535dfecf96Smrg    if (atom->property == NOPROPERTY)
15545dfecf96Smrg	LispAllocAtomProperty(atom);
15555dfecf96Smrg
15565dfecf96Smrg    lisp__data.gc.immutablebits = 1;
15575dfecf96Smrg    if (atom->a_defsetf)
15585dfecf96Smrg	LispFreeArgList(atom->property->salist);
15595dfecf96Smrg
15605dfecf96Smrg    atom->a_defsetf = 1;
15615dfecf96Smrg    atom->property->setf = setf;
15625dfecf96Smrg    atom->property->salist = alist;
15635dfecf96Smrg}
15645dfecf96Smrg
15655dfecf96Smrgvoid
15665dfecf96SmrgLispRemAtomSetfProperty(LispAtom *atom)
15675dfecf96Smrg{
15685dfecf96Smrg    if (atom->a_defsetf) {
15695dfecf96Smrg	lisp__data.gc.immutablebits = 1;
15705dfecf96Smrg	atom->property->setf = NULL;
15715dfecf96Smrg	atom->a_defsetf = 0;
15725dfecf96Smrg	LispFreeArgList(atom->property->salist);
15735dfecf96Smrg	atom->property->salist = NULL;
15745dfecf96Smrg    }
15755dfecf96Smrg}
15765dfecf96Smrg
15775dfecf96Smrgvoid
15785dfecf96SmrgLispSetAtomStructProperty(LispAtom *atom, LispObj *def, int fun)
15795dfecf96Smrg{
15805dfecf96Smrg    if (fun > 0xff)
15815dfecf96Smrg	/* Not suported by the bytecode compiler... */
15825dfecf96Smrg	LispDestroy("SET-ATOM-STRUCT-PROPERTY: "
15835dfecf96Smrg		    "more than 256 fields not supported");
15845dfecf96Smrg
15855dfecf96Smrg    if (atom->property == NOPROPERTY)
15865dfecf96Smrg	LispAllocAtomProperty(atom);
15875dfecf96Smrg
15885dfecf96Smrg    lisp__data.gc.immutablebits = 1;
15895dfecf96Smrg    atom->a_defstruct = 1;
15905dfecf96Smrg    atom->property->structure.definition = def;
15915dfecf96Smrg    atom->property->structure.function = fun;
15925dfecf96Smrg}
15935dfecf96Smrg
15945dfecf96Smrgvoid
15955dfecf96SmrgLispRemAtomStructProperty(LispAtom *atom)
15965dfecf96Smrg{
15975dfecf96Smrg    if (atom->a_defstruct) {
15985dfecf96Smrg	lisp__data.gc.immutablebits = 1;
15995dfecf96Smrg	atom->property->structure.definition = NULL;
16005dfecf96Smrg	atom->a_defstruct = 0;
16015dfecf96Smrg    }
16025dfecf96Smrg}
16035dfecf96Smrg
16045dfecf96SmrgLispAtom *
1605f765521fSmrgLispGetAtom(const char *str)
16065dfecf96Smrg{
16075dfecf96Smrg    return (LispDoGetAtom(str, 0));
16085dfecf96Smrg}
16095dfecf96Smrg
16105dfecf96SmrgLispAtom *
1611f765521fSmrgLispGetPermAtom(const char *str)
16125dfecf96Smrg{
16135dfecf96Smrg    return (LispDoGetAtom(str, 1));
16145dfecf96Smrg}
16155dfecf96Smrg
16165dfecf96Smrg#define GET_PROPERTY	0
16175dfecf96Smrg#define ADD_PROPERTY	1
16185dfecf96Smrg#define REM_PROPERTY	2
16195dfecf96Smrgstatic LispObj *
16205dfecf96SmrgLispAtomPropertyFunction(LispAtom *atom, LispObj *key, int function)
16215dfecf96Smrg{
16225dfecf96Smrg    LispObj *list = NIL, *result = NIL;
16235dfecf96Smrg
16245dfecf96Smrg    if (function == ADD_PROPERTY) {
16255dfecf96Smrg	if (atom->property == NOPROPERTY)
16265dfecf96Smrg	    LispAllocAtomProperty(atom);
16275dfecf96Smrg	if (atom->property->properties == NULL) {
16285dfecf96Smrg	    atom->a_property = 1;
16295dfecf96Smrg	    atom->property->properties = NIL;
16305dfecf96Smrg	}
16315dfecf96Smrg    }
16325dfecf96Smrg
16335dfecf96Smrg    if (atom->a_property) {
16345dfecf96Smrg	LispObj *base;
16355dfecf96Smrg
16365dfecf96Smrg	for (base = list = atom->property->properties;
16375dfecf96Smrg	     CONSP(list);
16385dfecf96Smrg	     list = CDR(list)) {
16395dfecf96Smrg	    if (key == CAR(list)) {
16405dfecf96Smrg		result = CDR(list);
16415dfecf96Smrg		break;
16425dfecf96Smrg	    }
16435dfecf96Smrg	    base = list;
16445dfecf96Smrg	    list = CDR(list);
16455dfecf96Smrg	    if (!CONSP(list))
16465dfecf96Smrg		LispDestroy("%s: %s has an odd property list length",
16475dfecf96Smrg			    STROBJ(atom->object),
16485dfecf96Smrg			    function == REM_PROPERTY ? "REMPROP" : "GET");
16495dfecf96Smrg	}
16505dfecf96Smrg	if (CONSP(list) && function == REM_PROPERTY) {
16515dfecf96Smrg	    if (!CONSP(CDR(list)))
16525dfecf96Smrg		LispDestroy("REMPROP: %s has an odd property list length",
16535dfecf96Smrg			    STROBJ(atom->object));
16545dfecf96Smrg	    if (base == list)
16555dfecf96Smrg		atom->property->properties = CDDR(list);
16565dfecf96Smrg	    else
16575dfecf96Smrg		RPLACD(CDR(base), CDDR(list));
16585dfecf96Smrg	}
16595dfecf96Smrg    }
16605dfecf96Smrg
16615dfecf96Smrg    if (!CONSP(list)) {
16625dfecf96Smrg	if (function == ADD_PROPERTY) {
16635dfecf96Smrg	    atom->property->properties =
16645dfecf96Smrg		CONS(key, CONS(NIL, atom->property->properties));
16655dfecf96Smrg	    result = CDR(atom->property->properties);
16665dfecf96Smrg	}
16675dfecf96Smrg    }
16685dfecf96Smrg    else if (function == REM_PROPERTY)
16695dfecf96Smrg	result = T;
16705dfecf96Smrg
16715dfecf96Smrg    return (result);
16725dfecf96Smrg}
16735dfecf96Smrg
16745dfecf96SmrgLispObj *
16755dfecf96SmrgLispGetAtomProperty(LispAtom *atom, LispObj *key)
16765dfecf96Smrg{
16775dfecf96Smrg    return (LispAtomPropertyFunction(atom, key, GET_PROPERTY));
16785dfecf96Smrg}
16795dfecf96Smrg
16805dfecf96SmrgLispObj *
16815dfecf96SmrgLispPutAtomProperty(LispAtom *atom, LispObj *key, LispObj *value)
16825dfecf96Smrg{
16835dfecf96Smrg    LispObj *result = LispAtomPropertyFunction(atom, key, ADD_PROPERTY);
16845dfecf96Smrg
16855dfecf96Smrg    RPLACA(result, value);
16865dfecf96Smrg
16875dfecf96Smrg    return (result);
16885dfecf96Smrg}
16895dfecf96Smrg
16905dfecf96SmrgLispObj *
16915dfecf96SmrgLispRemAtomProperty(LispAtom *atom, LispObj *key)
16925dfecf96Smrg{
16935dfecf96Smrg    return (LispAtomPropertyFunction(atom, key, REM_PROPERTY));
16945dfecf96Smrg}
16955dfecf96Smrg
16965dfecf96SmrgLispObj *
16975dfecf96SmrgLispReplaceAtomPropertyList(LispAtom *atom, LispObj *list)
16985dfecf96Smrg{
16995dfecf96Smrg    if (atom->property == NOPROPERTY)
17005dfecf96Smrg	LispAllocAtomProperty(atom);
17015dfecf96Smrg    if (atom->property->properties == NULL)
17025dfecf96Smrg	atom->a_property = 1;
17035dfecf96Smrg    atom->property->properties = list;
17045dfecf96Smrg
17055dfecf96Smrg    return (list);
17065dfecf96Smrg}
17075dfecf96Smrg#undef GET_PROPERTY
17085dfecf96Smrg#undef ADD_PROPERTY
17095dfecf96Smrg#undef REM_PROPERTY
17105dfecf96Smrg
17115dfecf96Smrg
17125dfecf96Smrg/* Used to make sure that when defining a function like:
17135dfecf96Smrg *	(defun my-function (... &key key1 key2 key3 ...)
17145dfecf96Smrg * key1, key2, and key3 will be in the keyword package
17155dfecf96Smrg */
17165dfecf96Smrgstatic LispObj *
17175dfecf96SmrgLispCheckKeyword(LispObj *keyword)
17185dfecf96Smrg{
17195dfecf96Smrg    if (KEYWORDP(keyword))
17205dfecf96Smrg	return (keyword);
17215dfecf96Smrg
1722f14f4646Smrg    return (KEYWORD(ATOMID(keyword)->value));
17235dfecf96Smrg}
17245dfecf96Smrg
17255dfecf96Smrgvoid
17265dfecf96SmrgLispUseArgList(LispArgList *alist)
17275dfecf96Smrg{
17285dfecf96Smrg    if (alist->normals.num_symbols)
17295dfecf96Smrg	LispMused(alist->normals.symbols);
17305dfecf96Smrg    if (alist->optionals.num_symbols) {
17315dfecf96Smrg	LispMused(alist->optionals.symbols);
17325dfecf96Smrg	LispMused(alist->optionals.defaults);
17335dfecf96Smrg	LispMused(alist->optionals.sforms);
17345dfecf96Smrg    }
17355dfecf96Smrg    if (alist->keys.num_symbols) {
17365dfecf96Smrg	LispMused(alist->keys.symbols);
17375dfecf96Smrg	LispMused(alist->keys.defaults);
17385dfecf96Smrg	LispMused(alist->keys.sforms);
17395dfecf96Smrg	LispMused(alist->keys.keys);
17405dfecf96Smrg    }
17415dfecf96Smrg    if (alist->auxs.num_symbols) {
17425dfecf96Smrg	LispMused(alist->auxs.symbols);
17435dfecf96Smrg	LispMused(alist->auxs.initials);
17445dfecf96Smrg    }
17455dfecf96Smrg    LispMused(alist);
17465dfecf96Smrg}
17475dfecf96Smrg
17485dfecf96Smrgvoid
17495dfecf96SmrgLispFreeArgList(LispArgList *alist)
17505dfecf96Smrg{
17515dfecf96Smrg    if (alist->normals.num_symbols)
17525dfecf96Smrg	LispFree(alist->normals.symbols);
17535dfecf96Smrg    if (alist->optionals.num_symbols) {
17545dfecf96Smrg	LispFree(alist->optionals.symbols);
17555dfecf96Smrg	LispFree(alist->optionals.defaults);
17565dfecf96Smrg	LispFree(alist->optionals.sforms);
17575dfecf96Smrg    }
17585dfecf96Smrg    if (alist->keys.num_symbols) {
17595dfecf96Smrg	LispFree(alist->keys.symbols);
17605dfecf96Smrg	LispFree(alist->keys.defaults);
17615dfecf96Smrg	LispFree(alist->keys.sforms);
17625dfecf96Smrg	LispFree(alist->keys.keys);
17635dfecf96Smrg    }
17645dfecf96Smrg    if (alist->auxs.num_symbols) {
17655dfecf96Smrg	LispFree(alist->auxs.symbols);
17665dfecf96Smrg	LispFree(alist->auxs.initials);
17675dfecf96Smrg    }
17685dfecf96Smrg    LispFree(alist);
17695dfecf96Smrg}
17705dfecf96Smrg
17715dfecf96Smrgstatic LispObj *
17725dfecf96SmrgLispCheckNeedProtect(LispObj *object)
17735dfecf96Smrg{
17745dfecf96Smrg    if (object) {
17755dfecf96Smrg	switch (OBJECT_TYPE(object)) {
17765dfecf96Smrg	    case LispNil_t:
17775dfecf96Smrg	    case LispAtom_t:
17785dfecf96Smrg	    case LispFunction_t:
17795dfecf96Smrg	    case LispFixnum_t:
17805dfecf96Smrg	    case LispSChar_t:
17815dfecf96Smrg		return (NULL);
17825dfecf96Smrg	    default:
17835dfecf96Smrg		return (object);
17845dfecf96Smrg	}
17855dfecf96Smrg    }
17865dfecf96Smrg    return (NULL);
17875dfecf96Smrg}
17885dfecf96Smrg
17895dfecf96SmrgLispObj *
17905dfecf96SmrgLispListProtectedArguments(LispArgList *alist)
17915dfecf96Smrg{
17925dfecf96Smrg    int i;
17935dfecf96Smrg    GC_ENTER();
17945dfecf96Smrg    LispObj *arguments, *cons, *obj, *prev;
17955dfecf96Smrg
17965dfecf96Smrg    arguments = cons = prev = NIL;
17975dfecf96Smrg    for (i = 0; i < alist->optionals.num_symbols; i++) {
17985dfecf96Smrg	if ((obj = LispCheckNeedProtect(alist->optionals.defaults[i])) != NULL) {
17995dfecf96Smrg	    if (arguments == NIL) {
18005dfecf96Smrg		arguments = cons = prev = CONS(obj, NIL);
18015dfecf96Smrg		GC_PROTECT(arguments);
18025dfecf96Smrg	    }
18035dfecf96Smrg	    else {
18045dfecf96Smrg		RPLACD(cons, CONS(obj, NIL));
18055dfecf96Smrg		prev = cons;
18065dfecf96Smrg		cons = CDR(cons);
18075dfecf96Smrg	    }
18085dfecf96Smrg	}
18095dfecf96Smrg    }
18105dfecf96Smrg    for (i = 0; i < alist->keys.num_symbols; i++) {
18115dfecf96Smrg	if ((obj = LispCheckNeedProtect(alist->keys.defaults[i])) != NULL) {
18125dfecf96Smrg	    if (arguments == NIL) {
18135dfecf96Smrg		arguments = cons = prev = CONS(obj, NIL);
18145dfecf96Smrg		GC_PROTECT(arguments);
18155dfecf96Smrg	    }
18165dfecf96Smrg	    else {
18175dfecf96Smrg		RPLACD(cons, CONS(obj, NIL));
18185dfecf96Smrg		prev = cons;
18195dfecf96Smrg		cons = CDR(cons);
18205dfecf96Smrg	    }
18215dfecf96Smrg	}
18225dfecf96Smrg    }
18235dfecf96Smrg    for (i = 0; i < alist->auxs.num_symbols; i++) {
18245dfecf96Smrg	if ((obj = LispCheckNeedProtect(alist->auxs.initials[i])) != NULL) {
18255dfecf96Smrg	    if (arguments == NIL) {
18265dfecf96Smrg		arguments = cons = prev = CONS(obj, NIL);
18275dfecf96Smrg		GC_PROTECT(arguments);
18285dfecf96Smrg	    }
18295dfecf96Smrg	    else {
18305dfecf96Smrg		RPLACD(cons, CONS(obj, NIL));
18315dfecf96Smrg		prev = cons;
18325dfecf96Smrg		cons = CDR(cons);
18335dfecf96Smrg	    }
18345dfecf96Smrg	}
18355dfecf96Smrg    }
18365dfecf96Smrg    GC_LEAVE();
18375dfecf96Smrg
18385dfecf96Smrg    /* Don't add a NIL cell at the end, to save some space */
18395dfecf96Smrg    if (arguments != NIL) {
18405dfecf96Smrg	if (arguments == cons)
18415dfecf96Smrg	    arguments = CAR(cons);
18425dfecf96Smrg	else
18435dfecf96Smrg	    CDR(prev) = CAR(cons);
18445dfecf96Smrg    }
18455dfecf96Smrg
18465dfecf96Smrg    return (arguments);
18475dfecf96Smrg}
18485dfecf96Smrg
18495dfecf96SmrgLispArgList *
1850f765521fSmrgLispCheckArguments(LispFunType type, LispObj *list, const char *name, int builtin)
18515dfecf96Smrg{
1852f765521fSmrg    static const char *types[4] = {"LAMBDA-LIST", "FUNCTION", "MACRO", "SETF-METHOD"};
1853f765521fSmrg    static const char *fnames[4] = {"LAMBDA", "DEFUN", "DEFMACRO", "DEFSETF"};
18545dfecf96Smrg#define IKEY		0
18555dfecf96Smrg#define IOPTIONAL	1
18565dfecf96Smrg#define IREST		2
18575dfecf96Smrg#define IAUX		3
1858f765521fSmrg    static const char *keys[4] = {"&KEY", "&OPTIONAL", "&REST", "&AUX"};
18595dfecf96Smrg    int rest, optional, key, aux, count;
18605dfecf96Smrg    LispArgList *alist;
18615dfecf96Smrg    LispObj *spec, *sform, *defval, *default_value;
18625dfecf96Smrg    char description[8], *desc;
18635dfecf96Smrg
18645dfecf96Smrg/* If LispRealloc fails, the previous memory will be released
18655dfecf96Smrg * in LispTopLevel, unless LispMused was called on the pointer */
18665dfecf96Smrg#define REALLOC_OBJECTS(pointer, count)		\
18675dfecf96Smrg    pointer = LispRealloc(pointer, (count) * sizeof(LispObj*))
18685dfecf96Smrg
18695dfecf96Smrg    alist = LispCalloc(1, sizeof(LispArgList));
18705dfecf96Smrg    if (!CONSP(list)) {
18715dfecf96Smrg	if (list != NIL)
18725dfecf96Smrg	    LispDestroy("%s %s: %s cannot be a %s argument list",
18735dfecf96Smrg			fnames[type], name, STROBJ(list), types[type]);
1874f14f4646Smrg	alist->description = GETATOMID("")->value;
18755dfecf96Smrg
18765dfecf96Smrg	return (alist);
18775dfecf96Smrg    }
18785dfecf96Smrg
18795dfecf96Smrg    default_value = builtin ? UNSPEC : NIL;
18805dfecf96Smrg
18815dfecf96Smrg    description[0] = '\0';
18825dfecf96Smrg    desc = description;
18835dfecf96Smrg    rest = optional = key = aux = 0;
18845dfecf96Smrg    for (; CONSP(list); list = CDR(list)) {
18855dfecf96Smrg	spec = CAR(list);
18865dfecf96Smrg
18875dfecf96Smrg	if (CONSP(spec)) {
18885dfecf96Smrg	    if (builtin)
18895dfecf96Smrg		LispDestroy("builtin function argument cannot have default value");
18905dfecf96Smrg	    if (aux) {
18915dfecf96Smrg		if (!SYMBOLP(CAR(spec)) ||
18925dfecf96Smrg		    (CDR(spec) != NIL && CDDR(spec) != NIL))
18935dfecf96Smrg		    LispDestroy("%s %s: bad &AUX argument %s",
18945dfecf96Smrg				fnames[type], name, STROBJ(spec));
18955dfecf96Smrg		defval = CDR(spec) != NIL ? CADR(spec) : NIL;
18965dfecf96Smrg		count = alist->auxs.num_symbols;
18975dfecf96Smrg		REALLOC_OBJECTS(alist->auxs.symbols, count + 1);
18985dfecf96Smrg		REALLOC_OBJECTS(alist->auxs.initials, count + 1);
18995dfecf96Smrg		alist->auxs.symbols[count] = CAR(spec);
19005dfecf96Smrg		alist->auxs.initials[count] = defval;
19015dfecf96Smrg		++alist->auxs.num_symbols;
19025dfecf96Smrg		if (count == 0)
19035dfecf96Smrg		    *desc++ = 'a';
19045dfecf96Smrg		++alist->num_arguments;
19055dfecf96Smrg	    }
19065dfecf96Smrg	    else if (rest)
19075dfecf96Smrg		LispDestroy("%s %s: syntax error parsing %s",
19085dfecf96Smrg			    fnames[type], name, keys[IREST]);
19095dfecf96Smrg	    else if (key) {
19105dfecf96Smrg		LispObj *akey = CAR(spec);
19115dfecf96Smrg
19125dfecf96Smrg		defval = default_value;
19135dfecf96Smrg		sform = NULL;
19145dfecf96Smrg		if (CONSP(akey)) {
19155dfecf96Smrg		    /* check for special case, as in:
19165dfecf96Smrg		     *	(defun a (&key ((key name) 'default-value)) name)
19175dfecf96Smrg		     *	(a 'key 'test)	=> TEST
19185dfecf96Smrg		     *	(a)		=> DEFAULT-VALUE
19195dfecf96Smrg		     */
19205dfecf96Smrg		    if (!SYMBOLP(CAR(akey)) || !CONSP(CDR(akey)) ||
19215dfecf96Smrg			!SYMBOLP(CADR(akey)) || CDDR(akey) != NIL ||
19225dfecf96Smrg			(CDR(spec) != NIL && CDDR(spec) != NIL))
19235dfecf96Smrg			LispDestroy("%s %s: bad special &KEY %s",
19245dfecf96Smrg				    fnames[type], name, STROBJ(spec));
19255dfecf96Smrg		    if (CDR(spec) != NIL)
19265dfecf96Smrg			defval = CADR(spec);
19275dfecf96Smrg		    spec = CADR(akey);
19285dfecf96Smrg		    akey = CAR(akey);
19295dfecf96Smrg		}
19305dfecf96Smrg		else {
19315dfecf96Smrg		    akey = NULL;
19325dfecf96Smrg
19335dfecf96Smrg		    if (!SYMBOLP(CAR(spec)))
19345dfecf96Smrg			LispDestroy("%s %s: %s cannot be a %s argument name",
19355dfecf96Smrg				    fnames[type], name,
19365dfecf96Smrg				    STROBJ(CAR(spec)), types[type]);
19375dfecf96Smrg		    /* check if default value provided, and optionally a `svar' */
19385dfecf96Smrg		    else if (CDR(spec) != NIL && (!CONSP(CDR(spec)) ||
19395dfecf96Smrg			      (CDDR(spec) != NIL &&
19405dfecf96Smrg			       (!SYMBOLP(CAR(CDDR(spec))) ||
19415dfecf96Smrg				CDR(CDDR(spec)) != NIL))))
19425dfecf96Smrg			LispDestroy("%s %s: bad argument specification %s",
19435dfecf96Smrg				    fnames[type], name, STROBJ(spec));
19445dfecf96Smrg		    if (CONSP(CDR(spec))) {
19455dfecf96Smrg			defval = CADR(spec);
19465dfecf96Smrg			if (CONSP(CDDR(spec)))
19475dfecf96Smrg			    sform = CAR(CDDR(spec));
19485dfecf96Smrg		    }
19495dfecf96Smrg		    /* Add to keyword package, and set the keyword in the
19505dfecf96Smrg		     * argument list, so that a function argument keyword
19515dfecf96Smrg		     * will reference the same object, and make comparison
19525dfecf96Smrg		     * simpler. */
19535dfecf96Smrg		    spec = LispCheckKeyword(CAR(spec));
19545dfecf96Smrg		}
19555dfecf96Smrg
19565dfecf96Smrg		count = alist->keys.num_symbols;
19575dfecf96Smrg		REALLOC_OBJECTS(alist->keys.keys, count + 1);
19585dfecf96Smrg		REALLOC_OBJECTS(alist->keys.defaults, count + 1);
19595dfecf96Smrg		REALLOC_OBJECTS(alist->keys.sforms, count + 1);
19605dfecf96Smrg		REALLOC_OBJECTS(alist->keys.symbols, count + 1);
19615dfecf96Smrg		alist->keys.symbols[count] = spec;
19625dfecf96Smrg		alist->keys.defaults[count] = defval;
19635dfecf96Smrg		alist->keys.sforms[count] = sform;
19645dfecf96Smrg		alist->keys.keys[count] = akey;
19655dfecf96Smrg		++alist->keys.num_symbols;
19665dfecf96Smrg		if (count == 0)
19675dfecf96Smrg		    *desc++ = 'k';
19685dfecf96Smrg		alist->num_arguments += 1 + (sform != NULL);
19695dfecf96Smrg	    }
19705dfecf96Smrg	    else if (optional) {
19715dfecf96Smrg		defval = default_value;
19725dfecf96Smrg		sform = NULL;
19735dfecf96Smrg
19745dfecf96Smrg		if (!SYMBOLP(CAR(spec)))
19755dfecf96Smrg		    LispDestroy("%s %s: %s cannot be a %s argument name",
19765dfecf96Smrg				fnames[type], name,
19775dfecf96Smrg				STROBJ(CAR(spec)), types[type]);
19785dfecf96Smrg		/* check if default value provided, and optionally a `svar' */
19795dfecf96Smrg		else if (CDR(spec) != NIL && (!CONSP(CDR(spec)) ||
19805dfecf96Smrg			  (CDDR(spec) != NIL &&
19815dfecf96Smrg			   (!SYMBOLP(CAR(CDDR(spec))) ||
19825dfecf96Smrg			    CDR(CDDR(spec)) != NIL))))
19835dfecf96Smrg		    LispDestroy("%s %s: bad argument specification %s",
19845dfecf96Smrg				fnames[type], name, STROBJ(spec));
19855dfecf96Smrg		if (CONSP(CDR(spec))) {
19865dfecf96Smrg		    defval = CADR(spec);
19875dfecf96Smrg		    if (CONSP(CDDR(spec)))
19885dfecf96Smrg			sform = CAR(CDDR(spec));
19895dfecf96Smrg		}
19905dfecf96Smrg		spec = CAR(spec);
19915dfecf96Smrg
19925dfecf96Smrg		count = alist->optionals.num_symbols;
19935dfecf96Smrg		REALLOC_OBJECTS(alist->optionals.symbols, count + 1);
19945dfecf96Smrg		REALLOC_OBJECTS(alist->optionals.defaults, count + 1);
19955dfecf96Smrg		REALLOC_OBJECTS(alist->optionals.sforms, count + 1);
19965dfecf96Smrg		alist->optionals.symbols[count] = spec;
19975dfecf96Smrg		alist->optionals.defaults[count] = defval;
19985dfecf96Smrg		alist->optionals.sforms[count] = sform;
19995dfecf96Smrg		++alist->optionals.num_symbols;
20005dfecf96Smrg		if (count == 0)
20015dfecf96Smrg		    *desc++ = 'o';
20025dfecf96Smrg		alist->num_arguments += 1 + (sform != NULL);
20035dfecf96Smrg	    }
20045dfecf96Smrg
20055dfecf96Smrg	    /* Normal arguments cannot have default value */
20065dfecf96Smrg	    else
20075dfecf96Smrg		LispDestroy("%s %s: syntax error parsing %s",
20085dfecf96Smrg			    fnames[type], name, STROBJ(spec));
20095dfecf96Smrg	}
20105dfecf96Smrg
20115dfecf96Smrg	/* spec must be an atom, excluding keywords */
20125dfecf96Smrg	else if (!SYMBOLP(spec) || KEYWORDP(spec))
20135dfecf96Smrg	    LispDestroy("%s %s: %s cannot be a %s argument",
20145dfecf96Smrg			fnames[type], name, STROBJ(spec), types[type]);
20155dfecf96Smrg	else {
20165dfecf96Smrg	    Atom_id atom = ATOMID(spec);
20175dfecf96Smrg
2018f14f4646Smrg	    if (atom->value[0] == '&') {
20195dfecf96Smrg		if (atom == Srest) {
20205dfecf96Smrg		    if (rest || aux || CDR(list) == NIL || !SYMBOLP(CADR(list))
20215dfecf96Smrg			/* only &aux allowed after &rest */
20225dfecf96Smrg			|| (CDDR(list) != NIL && !SYMBOLP(CAR(CDDR(list))) &&
20235dfecf96Smrg			    ATOMID(CAR(CDDR(list))) != Saux))
20245dfecf96Smrg			LispDestroy("%s %s: syntax error parsing %s",
2025f14f4646Smrg				    fnames[type], name, ATOMID(spec)->value);
20265dfecf96Smrg		    if (key)
20275dfecf96Smrg			LispDestroy("%s %s: %s not allowed after %s",
20285dfecf96Smrg				    fnames[type], name, keys[IREST], keys[IKEY]);
20295dfecf96Smrg		    rest = 1;
20305dfecf96Smrg		    continue;
20315dfecf96Smrg		}
20325dfecf96Smrg
20335dfecf96Smrg		else if (atom == Skey) {
20345dfecf96Smrg		    if (rest || aux)
20355dfecf96Smrg			LispDestroy("%s %s: %s not allowed after %s",
2036f14f4646Smrg				    fnames[type], name, ATOMID(spec)->value,
20375dfecf96Smrg				    rest ? keys[IREST] : keys[IAUX]);
20385dfecf96Smrg		    key = 1;
20395dfecf96Smrg		    continue;
20405dfecf96Smrg		}
20415dfecf96Smrg
20425dfecf96Smrg		else if (atom == Soptional) {
20435dfecf96Smrg		    if (rest || optional || aux || key)
20445dfecf96Smrg			LispDestroy("%s %s: %s not allowed after %s",
2045f14f4646Smrg				    fnames[type], name, ATOMID(spec)->value,
20465dfecf96Smrg				    rest ? keys[IREST] :
20475dfecf96Smrg					optional ?
20485dfecf96Smrg					keys[IOPTIONAL] :
20495dfecf96Smrg					    aux ? keys[IAUX] : keys[IKEY]);
20505dfecf96Smrg		    optional = 1;
20515dfecf96Smrg		    continue;
20525dfecf96Smrg		}
20535dfecf96Smrg
20545dfecf96Smrg		else if (atom == Saux) {
20555dfecf96Smrg		    /* &AUX must be the last keyword parameter */
20565dfecf96Smrg		    if (aux)
20575dfecf96Smrg			LispDestroy("%s %s: syntax error parsing %s",
2058f14f4646Smrg				    fnames[type], name, ATOMID(spec)->value);
20595dfecf96Smrg		    else if (builtin)
20605dfecf96Smrg			LispDestroy("builtin function cannot have &AUX arguments");
20615dfecf96Smrg		    aux = 1;
20625dfecf96Smrg		    continue;
20635dfecf96Smrg		}
20645dfecf96Smrg
20655dfecf96Smrg		/* Untill more lambda-list keywords supported, don't allow
20665dfecf96Smrg		 * argument names starting with the '&' character */
20675dfecf96Smrg		else
20685dfecf96Smrg		    LispDestroy("%s %s: %s not allowed/implemented",
2069f14f4646Smrg				fnames[type], name, ATOMID(spec)->value);
20705dfecf96Smrg	    }
20715dfecf96Smrg
20725dfecf96Smrg	    /* Add argument to alist */
20735dfecf96Smrg	    if (aux) {
20745dfecf96Smrg		count = alist->auxs.num_symbols;
20755dfecf96Smrg		REALLOC_OBJECTS(alist->auxs.symbols, count + 1);
20765dfecf96Smrg		REALLOC_OBJECTS(alist->auxs.initials, count + 1);
20775dfecf96Smrg		alist->auxs.symbols[count] = spec;
20785dfecf96Smrg		alist->auxs.initials[count] = default_value;
20795dfecf96Smrg		++alist->auxs.num_symbols;
20805dfecf96Smrg		if (count == 0)
20815dfecf96Smrg		    *desc++ = 'a';
20825dfecf96Smrg		++alist->num_arguments;
20835dfecf96Smrg	    }
20845dfecf96Smrg	    else if (rest) {
20855dfecf96Smrg		alist->rest = spec;
20865dfecf96Smrg		*desc++ = 'r';
20875dfecf96Smrg		++alist->num_arguments;
20885dfecf96Smrg	    }
20895dfecf96Smrg	    else if (key) {
20905dfecf96Smrg		/* Add to keyword package, and set the keyword in the
20915dfecf96Smrg		 * argument list, so that a function argument keyword
20925dfecf96Smrg		 * will reference the same object, and make comparison
20935dfecf96Smrg		 * simpler. */
20945dfecf96Smrg		spec = LispCheckKeyword(spec);
20955dfecf96Smrg		count = alist->keys.num_symbols;
20965dfecf96Smrg		REALLOC_OBJECTS(alist->keys.keys, count + 1);
20975dfecf96Smrg		REALLOC_OBJECTS(alist->keys.defaults, count + 1);
20985dfecf96Smrg		REALLOC_OBJECTS(alist->keys.sforms, count + 1);
20995dfecf96Smrg		REALLOC_OBJECTS(alist->keys.symbols, count + 1);
21005dfecf96Smrg		alist->keys.symbols[count] = spec;
21015dfecf96Smrg		alist->keys.defaults[count] = default_value;
21025dfecf96Smrg		alist->keys.sforms[count] = NULL;
21035dfecf96Smrg		alist->keys.keys[count] = NULL;
21045dfecf96Smrg		++alist->keys.num_symbols;
21055dfecf96Smrg		if (count == 0)
21065dfecf96Smrg		    *desc++ = 'k';
21075dfecf96Smrg		++alist->num_arguments;
21085dfecf96Smrg	    }
21095dfecf96Smrg	    else if (optional) {
21105dfecf96Smrg		count = alist->optionals.num_symbols;
21115dfecf96Smrg		REALLOC_OBJECTS(alist->optionals.symbols, count + 1);
21125dfecf96Smrg		REALLOC_OBJECTS(alist->optionals.defaults, count + 1);
21135dfecf96Smrg		REALLOC_OBJECTS(alist->optionals.sforms, count + 1);
21145dfecf96Smrg		alist->optionals.symbols[count] = spec;
21155dfecf96Smrg		alist->optionals.defaults[count] = default_value;
21165dfecf96Smrg		alist->optionals.sforms[count] = NULL;
21175dfecf96Smrg		++alist->optionals.num_symbols;
21185dfecf96Smrg		if (count == 0)
21195dfecf96Smrg		    *desc++ = 'o';
21205dfecf96Smrg		++alist->num_arguments;
21215dfecf96Smrg	    }
21225dfecf96Smrg	    else {
21235dfecf96Smrg		count = alist->normals.num_symbols;
21245dfecf96Smrg		REALLOC_OBJECTS(alist->normals.symbols, count + 1);
21255dfecf96Smrg		alist->normals.symbols[count] = spec;
21265dfecf96Smrg		++alist->normals.num_symbols;
21275dfecf96Smrg		if (count == 0)
21285dfecf96Smrg		    *desc++ = '.';
21295dfecf96Smrg		++alist->num_arguments;
21305dfecf96Smrg	    }
21315dfecf96Smrg	}
21325dfecf96Smrg    }
21335dfecf96Smrg
21345dfecf96Smrg    /* Check for dotted argument list */
21355dfecf96Smrg    if (list != NIL)
21365dfecf96Smrg	LispDestroy("%s %s: %s cannot end %s arguments",
21375dfecf96Smrg		    fnames[type], name, STROBJ(list), types[type]);
21385dfecf96Smrg
21395dfecf96Smrg    *desc = '\0';
2140f14f4646Smrg    alist->description = LispGetAtomKey(description, 0)->value;
21415dfecf96Smrg
21425dfecf96Smrg    return (alist);
21435dfecf96Smrg}
21445dfecf96Smrg
21455dfecf96Smrgvoid
21465dfecf96SmrgLispAddBuiltinFunction(LispBuiltin *builtin)
21475dfecf96Smrg{
21485dfecf96Smrg    static LispObj stream;
21495dfecf96Smrg    static LispString string;
21505dfecf96Smrg    static int first = 1;
21515dfecf96Smrg    LispObj *name, *obj, *list, *cons, *code;
21525dfecf96Smrg    LispAtom *atom;
21535dfecf96Smrg    LispArgList *alist;
21545dfecf96Smrg    int length = lisp__data.protect.length;
21555dfecf96Smrg
21565dfecf96Smrg    if (first) {
21575dfecf96Smrg	stream.type = LispStream_t;
21585dfecf96Smrg	stream.data.stream.source.string = &string;
21595dfecf96Smrg	stream.data.stream.pathname = NIL;
21605dfecf96Smrg	stream.data.stream.type = LispStreamString;
21615dfecf96Smrg	stream.data.stream.readable = 1;
21625dfecf96Smrg	stream.data.stream.writable = 0;
21635dfecf96Smrg	string.output = 0;
21645dfecf96Smrg	first = 0;
21655dfecf96Smrg    }
21665dfecf96Smrg    string.string = builtin->declaration;
21675dfecf96Smrg    string.length = strlen(builtin->declaration);
21685dfecf96Smrg    string.input = 0;
21695dfecf96Smrg
21705dfecf96Smrg    code = COD;
21715dfecf96Smrg    LispPushInput(&stream);
21725dfecf96Smrg    name = LispRead();
21735dfecf96Smrg    list = cons = CONS(name, NIL);
21745dfecf96Smrg    if (length + 1 >= lisp__data.protect.space)
21755dfecf96Smrg	LispMoreProtects();
21765dfecf96Smrg    lisp__data.protect.objects[lisp__data.protect.length++] = list;
21775dfecf96Smrg    while ((obj = LispRead()) != NULL) {
21785dfecf96Smrg	RPLACD(cons, CONS(obj, NIL));
21795dfecf96Smrg	cons = CDR(cons);
21805dfecf96Smrg    }
21815dfecf96Smrg    LispPopInput(&stream);
21825dfecf96Smrg
21835dfecf96Smrg    atom = name->data.atom;
2184f14f4646Smrg    alist = LispCheckArguments(builtin->type, CDR(list), atom->key->value, 1);
21855dfecf96Smrg    builtin->symbol = CAR(list);
21865dfecf96Smrg    LispSetAtomBuiltinProperty(atom, builtin, alist);
21875dfecf96Smrg    LispUseArgList(alist);
21885dfecf96Smrg
21895dfecf96Smrg    /* Make function a extern symbol, unless told to not do so */
21905dfecf96Smrg    if (!builtin->internal)
21915dfecf96Smrg	LispExportSymbol(name);
21925dfecf96Smrg
21935dfecf96Smrg    lisp__data.protect.length = length;
21945dfecf96Smrg    COD = code;			/* LispRead protect data in COD */
21955dfecf96Smrg}
21965dfecf96Smrg
21975dfecf96Smrgvoid
21985dfecf96SmrgLispAllocSeg(LispObjSeg *seg, int cellcount)
21995dfecf96Smrg{
22005dfecf96Smrg    unsigned int i;
22015dfecf96Smrg    LispObj **list, *obj;
22025dfecf96Smrg
22035dfecf96Smrg    DISABLE_INTERRUPTS();
22045dfecf96Smrg    while (seg->nfree < cellcount) {
22055dfecf96Smrg	if ((obj = (LispObj*)calloc(1, sizeof(LispObj) * segsize)) == NULL) {
22065dfecf96Smrg	    ENABLE_INTERRUPTS();
22075dfecf96Smrg	    LispDestroy("out of memory");
22085dfecf96Smrg	}
22095dfecf96Smrg	if ((list = (LispObj**)realloc(seg->objects,
22105dfecf96Smrg	    sizeof(LispObj*) * (seg->nsegs + 1))) == NULL) {
22115dfecf96Smrg	    free(obj);
22125dfecf96Smrg	    ENABLE_INTERRUPTS();
22135dfecf96Smrg	    LispDestroy("out of memory");
22145dfecf96Smrg	}
22155dfecf96Smrg	seg->objects = list;
22165dfecf96Smrg	seg->objects[seg->nsegs] = obj;
22175dfecf96Smrg
22185dfecf96Smrg	seg->nfree += segsize;
22195dfecf96Smrg	seg->nobjs += segsize;
22205dfecf96Smrg	for (i = 1; i < segsize; i++, obj++) {
22215dfecf96Smrg	    /* Objects of type cons are the most used, save some time
22225dfecf96Smrg	     * by not setting it's type in LispNewCons. */
22235dfecf96Smrg	    obj->type = LispCons_t;
22245dfecf96Smrg	    CDR(obj) = obj + 1;
22255dfecf96Smrg	}
22265dfecf96Smrg	obj->type = LispCons_t;
22275dfecf96Smrg	CDR(obj) = seg->freeobj;
22285dfecf96Smrg	seg->freeobj = seg->objects[seg->nsegs];
22295dfecf96Smrg	++seg->nsegs;
22305dfecf96Smrg    }
22315dfecf96Smrg#ifdef DEBUG
22325dfecf96Smrg    LispMessage("gc: %d cell(s) allocated at %d segment(s)",
22335dfecf96Smrg		seg->nobjs, seg->nsegs);
22345dfecf96Smrg#endif
22355dfecf96Smrg    ENABLE_INTERRUPTS();
22365dfecf96Smrg}
22375dfecf96Smrg
22385dfecf96Smrgstatic INLINE void
22395dfecf96SmrgLispMark(register LispObj *object)
22405dfecf96Smrg{
22415dfecf96Smrgmark_again:
22425dfecf96Smrg    switch (OBJECT_TYPE(object)) {
22435dfecf96Smrg	case LispNil_t:
22445dfecf96Smrg	case LispAtom_t:
22455dfecf96Smrg	case LispFixnum_t:
22465dfecf96Smrg	case LispSChar_t:
22475dfecf96Smrg	case LispFunction_t:
22485dfecf96Smrg	    return;
22495dfecf96Smrg	case LispLambda_t:
22505dfecf96Smrg	    if (OPAQUEP(object->data.lambda.name))
22515dfecf96Smrg		object->data.lambda.name->mark = 1;
22525dfecf96Smrg	    object->mark = 1;
22535dfecf96Smrg	    LispMark(object->data.lambda.data);
22545dfecf96Smrg	    object = object->data.lambda.code;
22555dfecf96Smrg	    goto mark_cons;
22565dfecf96Smrg	case LispQuote_t:
22575dfecf96Smrg	case LispBackquote_t:
22585dfecf96Smrg	case LispFunctionQuote_t:
22595dfecf96Smrg	    object->mark = 1;
22605dfecf96Smrg	    object = object->data.quote;
22615dfecf96Smrg	    goto mark_again;
22625dfecf96Smrg	case LispPathname_t:
22635dfecf96Smrg	    object->mark = 1;
22645dfecf96Smrg	    object = object->data.pathname;
22655dfecf96Smrg	    goto mark_again;
22665dfecf96Smrg	case LispComma_t:
22675dfecf96Smrg	    object->mark = 1;
22685dfecf96Smrg	    object = object->data.comma.eval;
22695dfecf96Smrg	    goto mark_again;
22705dfecf96Smrg	case LispComplex_t:
22715dfecf96Smrg	    if (POINTERP(object->data.complex.real))
22725dfecf96Smrg		object->data.complex.real->mark = 1;
22735dfecf96Smrg	    if (POINTERP(object->data.complex.imag))
22745dfecf96Smrg		object->data.complex.imag->mark = 1;
22755dfecf96Smrg	    break;
22765dfecf96Smrg	case LispCons_t:
22775dfecf96Smrgmark_cons:
22785dfecf96Smrg	    for (; CONSP(object) && !object->mark; object = CDR(object)) {
22795dfecf96Smrg		object->mark = 1;
22805dfecf96Smrg		switch (OBJECT_TYPE(CAR(object))) {
22815dfecf96Smrg		    case LispNil_t:
22825dfecf96Smrg		    case LispAtom_t:
22835dfecf96Smrg		    case LispFixnum_t:
22845dfecf96Smrg		    case LispSChar_t:
22855dfecf96Smrg		    case LispPackage_t:		/* protected in gc */
22865dfecf96Smrg			break;
22875dfecf96Smrg		    case LispInteger_t:
22885dfecf96Smrg		    case LispDFloat_t:
22895dfecf96Smrg		    case LispString_t:
22905dfecf96Smrg		    case LispRatio_t:
22915dfecf96Smrg		    case LispOpaque_t:
22925dfecf96Smrg		    case LispBignum_t:
22935dfecf96Smrg		    case LispBigratio_t:
22945dfecf96Smrg			CAR(object)->mark = 1;
22955dfecf96Smrg			break;
22965dfecf96Smrg		    default:
22975dfecf96Smrg			LispMark(CAR(object));
22985dfecf96Smrg			break;
22995dfecf96Smrg		}
23005dfecf96Smrg	    }
23015dfecf96Smrg	    if (POINTERP(object) && !object->mark)
23025dfecf96Smrg		goto mark_again;
23035dfecf96Smrg	    return;
23045dfecf96Smrg	case LispArray_t:
23055dfecf96Smrg	    LispMark(object->data.array.list);
23065dfecf96Smrg	    object->mark = 1;
23075dfecf96Smrg	    object = object->data.array.dim;
23085dfecf96Smrg	    goto mark_cons;
23095dfecf96Smrg	case LispStruct_t:
23105dfecf96Smrg	    object->mark = 1;
23115dfecf96Smrg	    object = object->data.struc.fields;
23125dfecf96Smrg	    goto mark_cons;
23135dfecf96Smrg	case LispStream_t:
23145dfecf96Smrgmark_stream:
23155dfecf96Smrg	    LispMark(object->data.stream.pathname);
23165dfecf96Smrg	    if (object->data.stream.type == LispStreamPipe) {
23175dfecf96Smrg		object->mark = 1;
23185dfecf96Smrg		object = object->data.stream.source.program->errorp;
23195dfecf96Smrg		goto mark_stream;
23205dfecf96Smrg	    }
23215dfecf96Smrg	    break;
23225dfecf96Smrg	case LispRegex_t:
23235dfecf96Smrg	    object->data.regex.pattern->mark = 1;
23245dfecf96Smrg	    break;
23255dfecf96Smrg	case LispBytecode_t:
23265dfecf96Smrg	    object->mark = 1;
23275dfecf96Smrg	    object = object->data.bytecode.code;
23285dfecf96Smrg	    goto mark_again;
23295dfecf96Smrg	case LispHashTable_t: {
23305dfecf96Smrg	    unsigned long i;
23315dfecf96Smrg	    LispHashEntry *entry = object->data.hash.table->entries,
23325dfecf96Smrg			  *last = entry + object->data.hash.table->num_entries;
23335dfecf96Smrg
23345dfecf96Smrg	    if (object->mark)
23355dfecf96Smrg		return;
23365dfecf96Smrg	    object->mark = 1;
23375dfecf96Smrg	    for (; entry < last; entry++) {
23385dfecf96Smrg		for (i = 0; i < entry->count; i++) {
23395dfecf96Smrg		    switch (OBJECT_TYPE(entry->keys[i])) {
23405dfecf96Smrg			case LispNil_t:
23415dfecf96Smrg			case LispAtom_t:
23425dfecf96Smrg			case LispFixnum_t:
23435dfecf96Smrg			case LispSChar_t:
23445dfecf96Smrg			case LispFunction_t:
23455dfecf96Smrg			case LispPackage_t:
23465dfecf96Smrg			    break;
23475dfecf96Smrg			case LispInteger_t:
23485dfecf96Smrg			case LispDFloat_t:
23495dfecf96Smrg			case LispString_t:
23505dfecf96Smrg			case LispRatio_t:
23515dfecf96Smrg			case LispOpaque_t:
23525dfecf96Smrg			case LispBignum_t:
23535dfecf96Smrg			case LispBigratio_t:
23545dfecf96Smrg			    entry->keys[i]->mark = 1;
23555dfecf96Smrg			    break;
23565dfecf96Smrg			default:
23575dfecf96Smrg			    LispMark(entry->keys[i]);
23585dfecf96Smrg			    break;
23595dfecf96Smrg		    }
23605dfecf96Smrg		    switch (OBJECT_TYPE(entry->values[i])) {
23615dfecf96Smrg			case LispNil_t:
23625dfecf96Smrg			case LispAtom_t:
23635dfecf96Smrg			case LispFixnum_t:
23645dfecf96Smrg			case LispSChar_t:
23655dfecf96Smrg			case LispFunction_t:
23665dfecf96Smrg			case LispPackage_t:
23675dfecf96Smrg			    break;
23685dfecf96Smrg			case LispInteger_t:
23695dfecf96Smrg			case LispDFloat_t:
23705dfecf96Smrg			case LispString_t:
23715dfecf96Smrg			case LispRatio_t:
23725dfecf96Smrg			case LispOpaque_t:
23735dfecf96Smrg			case LispBignum_t:
23745dfecf96Smrg			case LispBigratio_t:
23755dfecf96Smrg			    entry->values[i]->mark = 1;
23765dfecf96Smrg			    break;
23775dfecf96Smrg			default:
23785dfecf96Smrg			    LispMark(entry->values[i]);
23795dfecf96Smrg			    break;
23805dfecf96Smrg		    }
23815dfecf96Smrg		}
23825dfecf96Smrg	    }
23835dfecf96Smrg	}   return;
23845dfecf96Smrg	default:
23855dfecf96Smrg	    break;
23865dfecf96Smrg    }
23875dfecf96Smrg    object->mark = 1;
23885dfecf96Smrg}
23895dfecf96Smrg
23905dfecf96Smrgstatic INLINE void
23915dfecf96SmrgLispProt(register LispObj *object)
23925dfecf96Smrg{
23935dfecf96Smrgprot_again:
23945dfecf96Smrg    switch (OBJECT_TYPE(object)) {
23955dfecf96Smrg	case LispNil_t:
23965dfecf96Smrg	case LispAtom_t:
23975dfecf96Smrg	case LispFixnum_t:
23985dfecf96Smrg	case LispSChar_t:
23995dfecf96Smrg	case LispFunction_t:
24005dfecf96Smrg	    return;
24015dfecf96Smrg	case LispLambda_t:
24025dfecf96Smrg	    if (OPAQUEP(object->data.lambda.name))
24035dfecf96Smrg		object->data.lambda.name->prot = 1;
24045dfecf96Smrg	    object->prot = 1;
24055dfecf96Smrg	    LispProt(object->data.lambda.data);
24065dfecf96Smrg	    object = object->data.lambda.code;
24075dfecf96Smrg	    goto prot_cons;
24085dfecf96Smrg	case LispQuote_t:
24095dfecf96Smrg	case LispBackquote_t:
24105dfecf96Smrg	case LispFunctionQuote_t:
24115dfecf96Smrg	    object->prot = 1;
24125dfecf96Smrg	    object = object->data.quote;
24135dfecf96Smrg	    goto prot_again;
24145dfecf96Smrg	case LispPathname_t:
24155dfecf96Smrg	    object->prot = 1;
24165dfecf96Smrg	    object = object->data.pathname;
24175dfecf96Smrg	    goto prot_again;
24185dfecf96Smrg	case LispComma_t:
24195dfecf96Smrg	    object->prot = 1;
24205dfecf96Smrg	    object = object->data.comma.eval;
24215dfecf96Smrg	    goto prot_again;
24225dfecf96Smrg	case LispComplex_t:
24235dfecf96Smrg	    if (POINTERP(object->data.complex.real))
24245dfecf96Smrg		object->data.complex.real->prot = 1;
24255dfecf96Smrg	    if (POINTERP(object->data.complex.imag))
24265dfecf96Smrg		object->data.complex.imag->prot = 1;
24275dfecf96Smrg	    break;
24285dfecf96Smrg	case LispCons_t:
24295dfecf96Smrgprot_cons:
24305dfecf96Smrg	    for (; CONSP(object) && !object->prot; object = CDR(object)) {
24315dfecf96Smrg		object->prot = 1;
24325dfecf96Smrg		switch (OBJECT_TYPE(CAR(object))) {
24335dfecf96Smrg		    case LispNil_t:
24345dfecf96Smrg		    case LispAtom_t:
24355dfecf96Smrg		    case LispFixnum_t:
24365dfecf96Smrg		    case LispSChar_t:
24375dfecf96Smrg		    case LispFunction_t:
24385dfecf96Smrg		    case LispPackage_t:		/* protected in gc */
24395dfecf96Smrg			break;
24405dfecf96Smrg		    case LispInteger_t:
24415dfecf96Smrg		    case LispDFloat_t:
24425dfecf96Smrg		    case LispString_t:
24435dfecf96Smrg		    case LispRatio_t:
24445dfecf96Smrg		    case LispOpaque_t:
24455dfecf96Smrg		    case LispBignum_t:
24465dfecf96Smrg		    case LispBigratio_t:
24475dfecf96Smrg			CAR(object)->prot = 1;
24485dfecf96Smrg			break;
24495dfecf96Smrg		    default:
24505dfecf96Smrg			LispProt(CAR(object));
24515dfecf96Smrg			break;
24525dfecf96Smrg		}
24535dfecf96Smrg	    }
24545dfecf96Smrg	    if (POINTERP(object) && !object->prot)
24555dfecf96Smrg		goto prot_again;
24565dfecf96Smrg	    return;
24575dfecf96Smrg	case LispArray_t:
24585dfecf96Smrg	    LispProt(object->data.array.list);
24595dfecf96Smrg	    object->prot = 1;
24605dfecf96Smrg	    object = object->data.array.dim;
24615dfecf96Smrg	    goto prot_cons;
24625dfecf96Smrg	case LispStruct_t:
24635dfecf96Smrg	    object->prot = 1;
24645dfecf96Smrg	    object = object->data.struc.fields;
24655dfecf96Smrg	    goto prot_cons;
24665dfecf96Smrg	case LispStream_t:
24675dfecf96Smrgprot_stream:
24685dfecf96Smrg	    LispProt(object->data.stream.pathname);
24695dfecf96Smrg	    if (object->data.stream.type == LispStreamPipe) {
24705dfecf96Smrg		object->prot = 1;
24715dfecf96Smrg		object = object->data.stream.source.program->errorp;
24725dfecf96Smrg		goto prot_stream;
24735dfecf96Smrg	    }
24745dfecf96Smrg	    break;
24755dfecf96Smrg	case LispRegex_t:
24765dfecf96Smrg	    object->data.regex.pattern->prot = 1;
24775dfecf96Smrg	    break;
24785dfecf96Smrg	case LispBytecode_t:
24795dfecf96Smrg	    object->prot = 1;
24805dfecf96Smrg	    object = object->data.bytecode.code;
24815dfecf96Smrg	    goto prot_again;
24825dfecf96Smrg	case LispHashTable_t: {
24835dfecf96Smrg	    unsigned long i;
24845dfecf96Smrg	    LispHashEntry *entry = object->data.hash.table->entries,
24855dfecf96Smrg			  *last = entry + object->data.hash.table->num_entries;
24865dfecf96Smrg
24875dfecf96Smrg	    if (object->prot)
24885dfecf96Smrg		return;
24895dfecf96Smrg	    object->prot = 1;
24905dfecf96Smrg	    for (; entry < last; entry++) {
24915dfecf96Smrg		for (i = 0; i < entry->count; i++) {
24925dfecf96Smrg		    switch (OBJECT_TYPE(entry->keys[i])) {
24935dfecf96Smrg			case LispNil_t:
24945dfecf96Smrg			case LispAtom_t:
24955dfecf96Smrg			case LispFixnum_t:
24965dfecf96Smrg			case LispSChar_t:
24975dfecf96Smrg			case LispFunction_t:
24985dfecf96Smrg			case LispPackage_t:
24995dfecf96Smrg			    break;
25005dfecf96Smrg			case LispInteger_t:
25015dfecf96Smrg			case LispDFloat_t:
25025dfecf96Smrg			case LispString_t:
25035dfecf96Smrg			case LispRatio_t:
25045dfecf96Smrg			case LispOpaque_t:
25055dfecf96Smrg			case LispBignum_t:
25065dfecf96Smrg			case LispBigratio_t:
25075dfecf96Smrg			    entry->keys[i]->prot = 1;
25085dfecf96Smrg			    break;
25095dfecf96Smrg			default:
25105dfecf96Smrg			    LispProt(entry->keys[i]);
25115dfecf96Smrg			    break;
25125dfecf96Smrg		    }
25135dfecf96Smrg		    switch (OBJECT_TYPE(entry->values[i])) {
25145dfecf96Smrg			case LispNil_t:
25155dfecf96Smrg			case LispAtom_t:
25165dfecf96Smrg			case LispFixnum_t:
25175dfecf96Smrg			case LispSChar_t:
25185dfecf96Smrg			case LispFunction_t:
25195dfecf96Smrg			case LispPackage_t:
25205dfecf96Smrg			    break;
25215dfecf96Smrg			case LispInteger_t:
25225dfecf96Smrg			case LispDFloat_t:
25235dfecf96Smrg			case LispString_t:
25245dfecf96Smrg			case LispRatio_t:
25255dfecf96Smrg			case LispOpaque_t:
25265dfecf96Smrg			case LispBignum_t:
25275dfecf96Smrg			case LispBigratio_t:
25285dfecf96Smrg			    entry->values[i]->prot = 1;
25295dfecf96Smrg			    break;
25305dfecf96Smrg			default:
25315dfecf96Smrg			    LispProt(entry->values[i]);
25325dfecf96Smrg			    break;
25335dfecf96Smrg		    }
25345dfecf96Smrg		}
25355dfecf96Smrg	    }
25365dfecf96Smrg	}   return;
25375dfecf96Smrg	default:
25385dfecf96Smrg	    break;
25395dfecf96Smrg    }
25405dfecf96Smrg    object->prot = 1;
25415dfecf96Smrg}
25425dfecf96Smrg
25435dfecf96Smrgvoid
25445dfecf96SmrgLispProtect(LispObj *key, LispObj *list)
25455dfecf96Smrg{
25465dfecf96Smrg    PRO = CONS(CONS(key, list), PRO);
25475dfecf96Smrg}
25485dfecf96Smrg
25495dfecf96Smrgvoid
25505dfecf96SmrgLispUProtect(LispObj *key, LispObj *list)
25515dfecf96Smrg{
25525dfecf96Smrg    LispObj *prev, *obj;
25535dfecf96Smrg
25545dfecf96Smrg    for (prev = obj = PRO; obj != NIL; prev = obj, obj = CDR(obj))
25555dfecf96Smrg	if (CAR(CAR(obj)) == key && CDR(CAR(obj)) == list) {
25565dfecf96Smrg	    if (obj == PRO)
25575dfecf96Smrg		PRO = CDR(PRO);
25585dfecf96Smrg	    else
25595dfecf96Smrg		CDR(prev) = CDR(obj);
25605dfecf96Smrg	    return;
25615dfecf96Smrg	}
25625dfecf96Smrg
25635dfecf96Smrg    LispDestroy("no match for %s, at UPROTECT", STROBJ(key));
25645dfecf96Smrg}
25655dfecf96Smrg
25665dfecf96Smrgstatic LispObj *
25675dfecf96SmrgLisp__New(LispObj *car, LispObj *cdr)
25685dfecf96Smrg{
25695dfecf96Smrg    int cellcount;
25705dfecf96Smrg    LispObj *obj;
25715dfecf96Smrg
25725dfecf96Smrg    Lisp__GC(car, cdr);
25735dfecf96Smrg#if 0
25745dfecf96Smrg    lisp__data.gc.average = (objseg.nfree + lisp__data.gc.average) >> 1;
25755dfecf96Smrg    if (lisp__data.gc.average < minfree) {
25765dfecf96Smrg	if (lisp__data.gc.expandbits < 6)
25775dfecf96Smrg	    ++lisp__data.gc.expandbits;
25785dfecf96Smrg    }
25795dfecf96Smrg    else if (lisp__data.gc.expandbits)
25805dfecf96Smrg	--lisp__data.gc.expandbits;
25815dfecf96Smrg    /* For 32 bit computers, where sizeof(LispObj) == 16,
25825dfecf96Smrg     * minfree is set to 1024, and expandbits limited to 6,
25835dfecf96Smrg     * the maximum extra memory requested here should be 1Mb
25845dfecf96Smrg     */
25855dfecf96Smrg    cellcount = minfree << lisp__data.gc.expandbits;
25865dfecf96Smrg#else
25875dfecf96Smrg    /* Try to keep at least 3 times more free cells than the de number
25885dfecf96Smrg     * of used cells in the freelist, to amenize the cost of the gc time,
25895dfecf96Smrg     * in the, currently, very simple gc strategy code. */
25905dfecf96Smrg    cellcount = (objseg.nobjs - objseg.nfree) * 3;
25915dfecf96Smrg    cellcount = cellcount + (minfree - (cellcount % minfree));
25925dfecf96Smrg#endif
25935dfecf96Smrg
25945dfecf96Smrg    if (objseg.freeobj == NIL || objseg.nfree < cellcount)
25955dfecf96Smrg	LispAllocSeg(&objseg, cellcount);
25965dfecf96Smrg
25975dfecf96Smrg    obj = objseg.freeobj;
25985dfecf96Smrg    objseg.freeobj = CDR(obj);
25995dfecf96Smrg    --objseg.nfree;
26005dfecf96Smrg
26015dfecf96Smrg    return (obj);
26025dfecf96Smrg}
26035dfecf96Smrg
26045dfecf96SmrgLispObj *
26055dfecf96SmrgLispNew(LispObj *car, LispObj *cdr)
26065dfecf96Smrg{
26075dfecf96Smrg    LispObj *obj = objseg.freeobj;
26085dfecf96Smrg
26095dfecf96Smrg    if (obj == NIL)
26105dfecf96Smrg	obj = Lisp__New(car, cdr);
26115dfecf96Smrg    else {
26125dfecf96Smrg	objseg.freeobj = CDR(obj);
26135dfecf96Smrg	--objseg.nfree;
26145dfecf96Smrg    }
26155dfecf96Smrg
26165dfecf96Smrg    return (obj);
26175dfecf96Smrg}
26185dfecf96Smrg
26195dfecf96SmrgLispObj *
2620f765521fSmrgLispNewAtom(const char *str, int intern)
26215dfecf96Smrg{
26225dfecf96Smrg    LispObj *object;
26235dfecf96Smrg    LispAtom *atom = LispDoGetAtom(str, 0);
26245dfecf96Smrg
26255dfecf96Smrg    if (atom->object) {
26265dfecf96Smrg	if (intern && atom->package == NULL)
26275dfecf96Smrg	    atom->package = PACKAGE;
26285dfecf96Smrg
26295dfecf96Smrg	return (atom->object);
26305dfecf96Smrg    }
26315dfecf96Smrg
26325dfecf96Smrg    if (atomseg.freeobj == NIL)
26335dfecf96Smrg	LispAllocSeg(&atomseg, pagesize);
26345dfecf96Smrg    object = atomseg.freeobj;
26355dfecf96Smrg    atomseg.freeobj = CDR(object);
26365dfecf96Smrg    --atomseg.nfree;
26375dfecf96Smrg
26385dfecf96Smrg    object->type = LispAtom_t;
26395dfecf96Smrg    object->data.atom = atom;
26405dfecf96Smrg    atom->object = object;
26415dfecf96Smrg    if (intern)
26425dfecf96Smrg	atom->package = PACKAGE;
26435dfecf96Smrg
26445dfecf96Smrg    return (object);
26455dfecf96Smrg}
26465dfecf96Smrg
26475dfecf96SmrgLispObj *
2648f765521fSmrgLispNewStaticAtom(const char *str)
26495dfecf96Smrg{
26505dfecf96Smrg    LispObj *object;
26515dfecf96Smrg    LispAtom *atom = LispDoGetAtom(str, 1);
26525dfecf96Smrg
26535dfecf96Smrg    object = LispNewSymbol(atom);
26545dfecf96Smrg
26555dfecf96Smrg    return (object);
26565dfecf96Smrg}
26575dfecf96Smrg
26585dfecf96SmrgLispObj *
26595dfecf96SmrgLispNewSymbol(LispAtom *atom)
26605dfecf96Smrg{
26615dfecf96Smrg    if (atom->object) {
26625dfecf96Smrg	if (atom->package == NULL)
26635dfecf96Smrg	    atom->package = PACKAGE;
26645dfecf96Smrg
26655dfecf96Smrg	return (atom->object);
26665dfecf96Smrg    }
26675dfecf96Smrg    else {
26685dfecf96Smrg	LispObj *symbol;
26695dfecf96Smrg
26705dfecf96Smrg	if (atomseg.freeobj == NIL)
26715dfecf96Smrg	    LispAllocSeg(&atomseg, pagesize);
26725dfecf96Smrg	symbol = atomseg.freeobj;
26735dfecf96Smrg	atomseg.freeobj = CDR(symbol);
26745dfecf96Smrg	--atomseg.nfree;
26755dfecf96Smrg
26765dfecf96Smrg	symbol->type = LispAtom_t;
26775dfecf96Smrg	symbol->data.atom = atom;
26785dfecf96Smrg	atom->object = symbol;
26795dfecf96Smrg	atom->package = PACKAGE;
26805dfecf96Smrg
26815dfecf96Smrg	return (symbol);
26825dfecf96Smrg    }
26835dfecf96Smrg}
26845dfecf96Smrg
26855dfecf96Smrg/* function representation is created on demand and never released,
26865dfecf96Smrg * even if the function is undefined and never defined again */
26875dfecf96SmrgLispObj *
26885dfecf96SmrgLispNewFunction(LispObj *symbol)
26895dfecf96Smrg{
26905dfecf96Smrg    LispObj *function;
26915dfecf96Smrg
26925dfecf96Smrg    if (symbol->data.atom->function)
26935dfecf96Smrg	return (symbol->data.atom->function);
26945dfecf96Smrg
26955dfecf96Smrg    if (symbol->data.atom->package == NULL)
26965dfecf96Smrg	symbol->data.atom->package = PACKAGE;
26975dfecf96Smrg
26985dfecf96Smrg    if (atomseg.freeobj == NIL)
26995dfecf96Smrg	LispAllocSeg(&atomseg, pagesize);
27005dfecf96Smrg    function = atomseg.freeobj;
27015dfecf96Smrg    atomseg.freeobj = CDR(function);
27025dfecf96Smrg    --atomseg.nfree;
27035dfecf96Smrg
27045dfecf96Smrg    function->type = LispFunction_t;
27055dfecf96Smrg    function->data.atom = symbol->data.atom;
27065dfecf96Smrg    symbol->data.atom->function = function;
27075dfecf96Smrg
27085dfecf96Smrg    return (function);
27095dfecf96Smrg}
27105dfecf96Smrg
27115dfecf96Smrg/* symbol name representation is created on demand and never released */
27125dfecf96SmrgLispObj *
27135dfecf96SmrgLispSymbolName(LispObj *symbol)
27145dfecf96Smrg{
27155dfecf96Smrg    LispObj *name;
27165dfecf96Smrg    LispAtom *atom = symbol->data.atom;
27175dfecf96Smrg
27185dfecf96Smrg    if (atom->name)
27195dfecf96Smrg	return (atom->name);
27205dfecf96Smrg
27215dfecf96Smrg    if (atomseg.freeobj == NIL)
27225dfecf96Smrg	LispAllocSeg(&atomseg, pagesize);
27235dfecf96Smrg    name = atomseg.freeobj;
27245dfecf96Smrg    atomseg.freeobj = CDR(name);
27255dfecf96Smrg    --atomseg.nfree;
27265dfecf96Smrg
27275dfecf96Smrg    name->type = LispString_t;
2728f14f4646Smrg    THESTR(name) = atom->key->value;
2729f14f4646Smrg    STRLEN(name) = atom->key->length;
27305dfecf96Smrg    name->data.string.writable = 0;
27315dfecf96Smrg    atom->name = name;
27325dfecf96Smrg
27335dfecf96Smrg    return (name);
27345dfecf96Smrg}
27355dfecf96Smrg
27365dfecf96SmrgLispObj *
27375dfecf96SmrgLispNewFunctionQuote(LispObj *object)
27385dfecf96Smrg{
27395dfecf96Smrg    LispObj *quote = LispNew(object, NIL);
27405dfecf96Smrg
27415dfecf96Smrg    quote->type = LispFunctionQuote_t;
27425dfecf96Smrg    quote->data.quote = object;
27435dfecf96Smrg
27445dfecf96Smrg    return (quote);
27455dfecf96Smrg}
27465dfecf96Smrg
27475dfecf96SmrgLispObj *
27485dfecf96SmrgLispNewDFloat(double value)
27495dfecf96Smrg{
27505dfecf96Smrg    LispObj *dfloat = objseg.freeobj;
27515dfecf96Smrg
27525dfecf96Smrg    if (dfloat == NIL)
27535dfecf96Smrg	dfloat = Lisp__New(NIL, NIL);
27545dfecf96Smrg    else {
27555dfecf96Smrg	objseg.freeobj = CDR(dfloat);
27565dfecf96Smrg	--objseg.nfree;
27575dfecf96Smrg    }
27585dfecf96Smrg    dfloat->type = LispDFloat_t;
27595dfecf96Smrg    dfloat->data.dfloat = value;
27605dfecf96Smrg
27615dfecf96Smrg    return (dfloat);
27625dfecf96Smrg}
27635dfecf96Smrg
27645dfecf96SmrgLispObj *
2765f765521fSmrgLispNewString(const char *str, long length)
2766f765521fSmrg{
2767f765521fSmrg    char *cstring = LispMalloc(length + 1);
2768f765521fSmrg    memcpy(cstring, str, length);
2769f765521fSmrg    cstring[length] = '\0';
2770f765521fSmrg    return LispNewStringAlloced(cstring, length);
2771f765521fSmrg}
2772f765521fSmrg
2773f765521fSmrgLispObj *
2774f765521fSmrgLispNewStringAlloced(char *cstring, long length)
27755dfecf96Smrg{
27765dfecf96Smrg    LispObj *string = objseg.freeobj;
27775dfecf96Smrg
27785dfecf96Smrg    if (string == NIL)
27795dfecf96Smrg	string = Lisp__New(NIL, NIL);
27805dfecf96Smrg    else {
27815dfecf96Smrg	objseg.freeobj = CDR(string);
27825dfecf96Smrg	--objseg.nfree;
27835dfecf96Smrg    }
27845dfecf96Smrg    LispMused(cstring);
27855dfecf96Smrg    string->type = LispString_t;
27865dfecf96Smrg    THESTR(string) = cstring;
27875dfecf96Smrg    STRLEN(string) = length;
27885dfecf96Smrg    string->data.string.writable = 1;
27895dfecf96Smrg
27905dfecf96Smrg    return (string);
27915dfecf96Smrg}
27925dfecf96Smrg
27935dfecf96SmrgLispObj *
27945dfecf96SmrgLispNewComplex(LispObj *realpart, LispObj *imagpart)
27955dfecf96Smrg{
27965dfecf96Smrg    LispObj *complexp = objseg.freeobj;
27975dfecf96Smrg
27985dfecf96Smrg    if (complexp == NIL)
27995dfecf96Smrg	complexp = Lisp__New(realpart, imagpart);
28005dfecf96Smrg    else {
28015dfecf96Smrg	objseg.freeobj = CDR(complexp);
28025dfecf96Smrg	--objseg.nfree;
28035dfecf96Smrg    }
28045dfecf96Smrg    complexp->type = LispComplex_t;
28055dfecf96Smrg    complexp->data.complex.real = realpart;
28065dfecf96Smrg    complexp->data.complex.imag = imagpart;
28075dfecf96Smrg
28085dfecf96Smrg    return (complexp);
28095dfecf96Smrg}
28105dfecf96Smrg
28115dfecf96SmrgLispObj *
28125dfecf96SmrgLispNewInteger(long integer)
28135dfecf96Smrg{
28145dfecf96Smrg    if (integer > MOST_POSITIVE_FIXNUM || integer < MOST_NEGATIVE_FIXNUM) {
28155dfecf96Smrg	LispObj *object = objseg.freeobj;
28165dfecf96Smrg
28175dfecf96Smrg	if (object == NIL)
28185dfecf96Smrg	    object = Lisp__New(NIL, NIL);
28195dfecf96Smrg	else {
28205dfecf96Smrg	    objseg.freeobj = CDR(object);
28215dfecf96Smrg	    --objseg.nfree;
28225dfecf96Smrg	}
28235dfecf96Smrg	object->type = LispInteger_t;
28245dfecf96Smrg	object->data.integer = integer;
28255dfecf96Smrg
28265dfecf96Smrg	return (object);
28275dfecf96Smrg    }
28285dfecf96Smrg    return (FIXNUM(integer));
28295dfecf96Smrg}
28305dfecf96Smrg
28315dfecf96SmrgLispObj *
28325dfecf96SmrgLispNewRatio(long num, long den)
28335dfecf96Smrg{
28345dfecf96Smrg    LispObj *ratio = objseg.freeobj;
28355dfecf96Smrg
28365dfecf96Smrg    if (ratio == NIL)
28375dfecf96Smrg	ratio = Lisp__New(NIL, NIL);
28385dfecf96Smrg    else {
28395dfecf96Smrg	objseg.freeobj = CDR(ratio);
28405dfecf96Smrg	--objseg.nfree;
28415dfecf96Smrg    }
28425dfecf96Smrg    ratio->type = LispRatio_t;
28435dfecf96Smrg    ratio->data.ratio.numerator = num;
28445dfecf96Smrg    ratio->data.ratio.denominator = den;
28455dfecf96Smrg
28465dfecf96Smrg    return (ratio);
28475dfecf96Smrg}
28485dfecf96Smrg
28495dfecf96SmrgLispObj *
28505dfecf96SmrgLispNewVector(LispObj *objects)
28515dfecf96Smrg{
28525dfecf96Smrg    GC_ENTER();
28535dfecf96Smrg    long count;
28545dfecf96Smrg    LispObj *array, *dimension;
28555dfecf96Smrg
28565dfecf96Smrg    for (count = 0, array = objects; CONSP(array); count++, array = CDR(array))
28575dfecf96Smrg	;
28585dfecf96Smrg
28595dfecf96Smrg    GC_PROTECT(objects);
28605dfecf96Smrg    dimension = CONS(FIXNUM(count), NIL);
28615dfecf96Smrg    array = LispNew(objects, dimension);
28625dfecf96Smrg    array->type = LispArray_t;
28635dfecf96Smrg    array->data.array.list = objects;
28645dfecf96Smrg    array->data.array.dim = dimension;
28655dfecf96Smrg    array->data.array.rank = 1;
28665dfecf96Smrg    array->data.array.type = LispNil_t;
28675dfecf96Smrg    array->data.array.zero = count == 0;
28685dfecf96Smrg    GC_LEAVE();
28695dfecf96Smrg
28705dfecf96Smrg    return (array);
28715dfecf96Smrg}
28725dfecf96Smrg
28735dfecf96SmrgLispObj *
28745dfecf96SmrgLispNewQuote(LispObj *object)
28755dfecf96Smrg{
28765dfecf96Smrg    LispObj *quote = LispNew(object, NIL);
28775dfecf96Smrg
28785dfecf96Smrg    quote->type = LispQuote_t;
28795dfecf96Smrg    quote->data.quote = object;
28805dfecf96Smrg
28815dfecf96Smrg    return (quote);
28825dfecf96Smrg}
28835dfecf96Smrg
28845dfecf96SmrgLispObj *
28855dfecf96SmrgLispNewBackquote(LispObj *object)
28865dfecf96Smrg{
28875dfecf96Smrg    LispObj *backquote = LispNew(object, NIL);
28885dfecf96Smrg
28895dfecf96Smrg    backquote->type = LispBackquote_t;
28905dfecf96Smrg    backquote->data.quote = object;
28915dfecf96Smrg
28925dfecf96Smrg    return (backquote);
28935dfecf96Smrg}
28945dfecf96Smrg
28955dfecf96SmrgLispObj *
28965dfecf96SmrgLispNewComma(LispObj *object, int atlist)
28975dfecf96Smrg{
28985dfecf96Smrg    LispObj *comma = LispNew(object, NIL);
28995dfecf96Smrg
29005dfecf96Smrg    comma->type = LispComma_t;
29015dfecf96Smrg    comma->data.comma.eval = object;
29025dfecf96Smrg    comma->data.comma.atlist = atlist;
29035dfecf96Smrg
29045dfecf96Smrg    return (comma);
29055dfecf96Smrg}
29065dfecf96Smrg
29075dfecf96SmrgLispObj *
29085dfecf96SmrgLispNewCons(LispObj *car, LispObj *cdr)
29095dfecf96Smrg{
29105dfecf96Smrg    LispObj *cons = objseg.freeobj;
29115dfecf96Smrg
29125dfecf96Smrg    if (cons == NIL)
29135dfecf96Smrg	cons = Lisp__New(car, cdr);
29145dfecf96Smrg    else {
29155dfecf96Smrg	objseg.freeobj = CDR(cons);
29165dfecf96Smrg	--objseg.nfree;
29175dfecf96Smrg    }
29185dfecf96Smrg    CAR(cons) = car;
29195dfecf96Smrg    CDR(cons) = cdr;
29205dfecf96Smrg
29215dfecf96Smrg    return (cons);
29225dfecf96Smrg}
29235dfecf96Smrg
29245dfecf96SmrgLispObj *
29255dfecf96SmrgLispNewLambda(LispObj *name, LispObj *code, LispObj *data, LispFunType type)
29265dfecf96Smrg{
29275dfecf96Smrg    LispObj *fun = LispNew(data, code);
29285dfecf96Smrg
29295dfecf96Smrg    fun->type = LispLambda_t;
29305dfecf96Smrg    fun->funtype = type;
29315dfecf96Smrg    fun->data.lambda.name = name;
29325dfecf96Smrg    fun->data.lambda.code = code;
29335dfecf96Smrg    fun->data.lambda.data = data;
29345dfecf96Smrg
29355dfecf96Smrg    return (fun);
29365dfecf96Smrg}
29375dfecf96Smrg
29385dfecf96SmrgLispObj *
29395dfecf96SmrgLispNewStruct(LispObj *fields, LispObj *def)
29405dfecf96Smrg{
29415dfecf96Smrg    LispObj *struc = LispNew(fields, def);
29425dfecf96Smrg
29435dfecf96Smrg    struc->type = LispStruct_t;
29445dfecf96Smrg    struc->data.struc.fields = fields;
29455dfecf96Smrg    struc->data.struc.def = def;
29465dfecf96Smrg
29475dfecf96Smrg    return (struc);
29485dfecf96Smrg}
29495dfecf96Smrg
29505dfecf96SmrgLispObj *
29515dfecf96SmrgLispNewOpaque(void *data, int type)
29525dfecf96Smrg{
29535dfecf96Smrg    LispObj *opaque = LispNew(NIL, NIL);
29545dfecf96Smrg
29555dfecf96Smrg    opaque->type = LispOpaque_t;
29565dfecf96Smrg    opaque->data.opaque.data = data;
29575dfecf96Smrg    opaque->data.opaque.type = type;
29585dfecf96Smrg
29595dfecf96Smrg    return (opaque);
29605dfecf96Smrg}
29615dfecf96Smrg
29625dfecf96Smrg/* string argument must be static, or allocated */
29635dfecf96SmrgLispObj *
2964f765521fSmrgLispNewKeyword(const char *string)
29655dfecf96Smrg{
29665dfecf96Smrg    LispObj *keyword;
29675dfecf96Smrg
29685dfecf96Smrg    if (PACKAGE != lisp__data.keyword) {
29695dfecf96Smrg	LispObj *savepackage;
29705dfecf96Smrg	LispPackage *savepack;
29715dfecf96Smrg
29725dfecf96Smrg	/* Save package environment */
29735dfecf96Smrg	savepackage = PACKAGE;
29745dfecf96Smrg	savepack = lisp__data.pack;
29755dfecf96Smrg
29765dfecf96Smrg	/* Change package environment */
29775dfecf96Smrg	PACKAGE = lisp__data.keyword;
29785dfecf96Smrg	lisp__data.pack = lisp__data.key;
29795dfecf96Smrg
29805dfecf96Smrg	/* Create symbol in keyword package */
29815dfecf96Smrg	keyword = LispNewStaticAtom(string);
29825dfecf96Smrg
29835dfecf96Smrg	/* Restore package environment */
29845dfecf96Smrg	PACKAGE = savepackage;
29855dfecf96Smrg	lisp__data.pack = savepack;
29865dfecf96Smrg    }
29875dfecf96Smrg    else
29885dfecf96Smrg	/* Just create symbol in keyword package */
29895dfecf96Smrg	keyword = LispNewStaticAtom(string);
29905dfecf96Smrg
29915dfecf96Smrg    /* Export keyword symbol */
29925dfecf96Smrg    LispExportSymbol(keyword);
29935dfecf96Smrg
29945dfecf96Smrg    /* All keywords are constants */
29955dfecf96Smrg    keyword->data.atom->constant = 1;
29965dfecf96Smrg
29975dfecf96Smrg    /* XXX maybe should bound the keyword to itself, but that would
29985dfecf96Smrg     * require allocating a LispProperty structure for every keyword */
29995dfecf96Smrg
30005dfecf96Smrg    return (keyword);
30015dfecf96Smrg}
30025dfecf96Smrg
30035dfecf96SmrgLispObj *
30045dfecf96SmrgLispNewPathname(LispObj *obj)
30055dfecf96Smrg{
30065dfecf96Smrg    LispObj *path = LispNew(obj, NIL);
30075dfecf96Smrg
30085dfecf96Smrg    path->type = LispPathname_t;
30095dfecf96Smrg    path->data.pathname = obj;
30105dfecf96Smrg
30115dfecf96Smrg    return (path);
30125dfecf96Smrg}
30135dfecf96Smrg
30145dfecf96SmrgLispObj *
3015f765521fSmrgLispNewStringStream(const char *string, int flags, long length)
3016f765521fSmrg{
3017f765521fSmrg    char *newstring = LispMalloc(length + 1);
3018f765521fSmrg    memcpy(newstring, string, length);
3019f765521fSmrg    newstring[length] = '\0';
3020f765521fSmrg
3021f765521fSmrg    return LispNewStringStreamAlloced(newstring, flags, length);
3022f765521fSmrg}
3023f765521fSmrg
3024f765521fSmrgLispObj *
3025f765521fSmrgLispNewStringStreamAlloced(char *string, int flags, long length)
30265dfecf96Smrg{
30275dfecf96Smrg    LispObj *stream = LispNew(NIL, NIL);
30285dfecf96Smrg
30295dfecf96Smrg    SSTREAMP(stream) = LispCalloc(1, sizeof(LispString));
3030f765521fSmrg    SSTREAMP(stream)->string = string;
30315dfecf96Smrg
30325dfecf96Smrg    stream->type = LispStream_t;
30335dfecf96Smrg
30345dfecf96Smrg    SSTREAMP(stream)->length = length;
30355dfecf96Smrg    LispMused(SSTREAMP(stream));
30365dfecf96Smrg    LispMused(SSTREAMP(stream)->string);
30375dfecf96Smrg    stream->data.stream.type = LispStreamString;
30385dfecf96Smrg    stream->data.stream.readable = (flags & STREAM_READ) != 0;
30395dfecf96Smrg    stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
30405dfecf96Smrg    SSTREAMP(stream)->space = length + 1;
30415dfecf96Smrg
30425dfecf96Smrg    stream->data.stream.pathname = NIL;
30435dfecf96Smrg
30445dfecf96Smrg    return (stream);
30455dfecf96Smrg}
30465dfecf96Smrg
30475dfecf96SmrgLispObj *
30485dfecf96SmrgLispNewFileStream(LispFile *file, LispObj *path, int flags)
30495dfecf96Smrg{
30505dfecf96Smrg    LispObj *stream = LispNew(NIL, NIL);
30515dfecf96Smrg
30525dfecf96Smrg    stream->type = LispStream_t;
30535dfecf96Smrg    FSTREAMP(stream) = file;
30545dfecf96Smrg    stream->data.stream.pathname = path;
30555dfecf96Smrg    stream->data.stream.type = LispStreamFile;
30565dfecf96Smrg    stream->data.stream.readable = (flags & STREAM_READ) != 0;
30575dfecf96Smrg    stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
30585dfecf96Smrg
30595dfecf96Smrg    return (stream);
30605dfecf96Smrg}
30615dfecf96Smrg
30625dfecf96SmrgLispObj *
30635dfecf96SmrgLispNewPipeStream(LispPipe *program, LispObj *path, int flags)
30645dfecf96Smrg{
30655dfecf96Smrg    LispObj *stream = LispNew(NIL, NIL);
30665dfecf96Smrg
30675dfecf96Smrg    stream->type = LispStream_t;
30685dfecf96Smrg    PSTREAMP(stream) = program;
30695dfecf96Smrg    stream->data.stream.pathname = path;
30705dfecf96Smrg    stream->data.stream.type = LispStreamPipe;
30715dfecf96Smrg    stream->data.stream.readable = (flags & STREAM_READ) != 0;
30725dfecf96Smrg    stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
30735dfecf96Smrg
30745dfecf96Smrg    return (stream);
30755dfecf96Smrg}
30765dfecf96Smrg
30775dfecf96SmrgLispObj *
30785dfecf96SmrgLispNewStandardStream(LispFile *file, LispObj *description, int flags)
30795dfecf96Smrg{
30805dfecf96Smrg    LispObj *stream = LispNew(NIL, NIL);
30815dfecf96Smrg
30825dfecf96Smrg    stream->type = LispStream_t;
30835dfecf96Smrg    FSTREAMP(stream) = file;
30845dfecf96Smrg    stream->data.stream.pathname = description;
30855dfecf96Smrg    stream->data.stream.type = LispStreamStandard;
30865dfecf96Smrg    stream->data.stream.readable = (flags & STREAM_READ) != 0;
30875dfecf96Smrg    stream->data.stream.writable = (flags & STREAM_WRITE) != 0;
30885dfecf96Smrg
30895dfecf96Smrg    return (stream);
30905dfecf96Smrg}
30915dfecf96Smrg
30925dfecf96SmrgLispObj *
30935dfecf96SmrgLispNewBignum(mpi *bignum)
30945dfecf96Smrg{
30955dfecf96Smrg    LispObj *integer = LispNew(NIL, NIL);
30965dfecf96Smrg
30975dfecf96Smrg    integer->type = LispBignum_t;
30985dfecf96Smrg    integer->data.mp.integer = bignum;
30995dfecf96Smrg    LispMused(bignum->digs);
31005dfecf96Smrg    LispMused(bignum);
31015dfecf96Smrg
31025dfecf96Smrg    return (integer);
31035dfecf96Smrg}
31045dfecf96Smrg
31055dfecf96SmrgLispObj *
31065dfecf96SmrgLispNewBigratio(mpr *bigratio)
31075dfecf96Smrg{
31085dfecf96Smrg    LispObj *ratio = LispNew(NIL, NIL);
31095dfecf96Smrg
31105dfecf96Smrg    ratio->type = LispBigratio_t;
31115dfecf96Smrg    ratio->data.mp.ratio = bigratio;
31125dfecf96Smrg    LispMused(mpr_num(bigratio)->digs);
31135dfecf96Smrg    LispMused(mpr_den(bigratio)->digs);
31145dfecf96Smrg    LispMused(bigratio);
31155dfecf96Smrg
31165dfecf96Smrg    return (ratio);
31175dfecf96Smrg}
31185dfecf96Smrg
31195dfecf96Smrg/* name must be of type LispString_t */
31205dfecf96SmrgLispObj *
31215dfecf96SmrgLispNewPackage(LispObj *name, LispObj *nicknames)
31225dfecf96Smrg{
31235dfecf96Smrg    LispObj *package = LispNew(name, nicknames);
31245dfecf96Smrg    LispPackage *pack = LispCalloc(1, sizeof(LispPackage));
31255dfecf96Smrg
31265dfecf96Smrg    package->type = LispPackage_t;
31275dfecf96Smrg    package->data.package.name = name;
31285dfecf96Smrg    package->data.package.nicknames = nicknames;
31295dfecf96Smrg    package->data.package.package = pack;
31305dfecf96Smrg
3131f14f4646Smrg    package->data.package.package->atoms = hash_new(STRTBLSZ, NULL);
3132f14f4646Smrg
31335dfecf96Smrg    LispMused(pack);
31345dfecf96Smrg
31355dfecf96Smrg    return (package);
31365dfecf96Smrg}
31375dfecf96Smrg
31385dfecf96SmrgLispObj *
31395dfecf96SmrgLispSymbolFunction(LispObj *symbol)
31405dfecf96Smrg{
31415dfecf96Smrg    LispAtom *atom = symbol->data.atom;
31425dfecf96Smrg
31435dfecf96Smrg    if ((atom->a_builtin &&
31445dfecf96Smrg	 atom->property->fun.builtin->type == LispFunction) ||
31455dfecf96Smrg	(atom->a_function &&
31465dfecf96Smrg	 atom->property->fun.function->funtype == LispFunction) ||
31475dfecf96Smrg	(atom->a_defstruct &&
31485dfecf96Smrg	 atom->property->structure.function != STRUCT_NAME) ||
31495dfecf96Smrg	/* XXX currently bytecode is only generated for functions */
31505dfecf96Smrg	atom->a_compiled)
31515dfecf96Smrg	symbol = FUNCTION(symbol);
31525dfecf96Smrg    else
31535dfecf96Smrg	LispDestroy("SYMBOL-FUNCTION: %s is not a function", STROBJ(symbol));
31545dfecf96Smrg
31555dfecf96Smrg    return (symbol);
31565dfecf96Smrg}
31575dfecf96Smrg
31585dfecf96Smrg
31595dfecf96Smrgstatic INLINE LispObj *
31605dfecf96SmrgLispGetVarPack(LispObj *symbol)
31615dfecf96Smrg{
31625dfecf96Smrg    LispAtom *atom;
31635dfecf96Smrg
3164f14f4646Smrg    atom = (LispAtom *)hash_get(lisp__data.pack->atoms,
3165f14f4646Smrg				 symbol->data.atom->key);
31665dfecf96Smrg
3167f14f4646Smrg    return (atom ? atom->object : NULL);
31685dfecf96Smrg}
31695dfecf96Smrg
31705dfecf96Smrg/* package must be of type LispPackage_t */
31715dfecf96Smrgvoid
31725dfecf96SmrgLispUsePackage(LispObj *package)
31735dfecf96Smrg{
31745dfecf96Smrg    LispAtom *atom;
31755dfecf96Smrg    LispPackage *pack;
31765dfecf96Smrg    LispObj **pentry, **eentry;
31775dfecf96Smrg
31785dfecf96Smrg    /* Already using its own symbols... */
31795dfecf96Smrg    if (package == PACKAGE)
31805dfecf96Smrg	return;
31815dfecf96Smrg
31825dfecf96Smrg    /* Check if package not already in use-package list */
31835dfecf96Smrg    for (pentry = lisp__data.pack->use.pairs,
31845dfecf96Smrg	 eentry = pentry + lisp__data.pack->use.length;
31855dfecf96Smrg	 pentry < eentry; pentry++)
31865dfecf96Smrg	if (*pentry == package)
31875dfecf96Smrg	return;
31885dfecf96Smrg
31895dfecf96Smrg    /* Remember this package is in the use-package list */
31905dfecf96Smrg    if (lisp__data.pack->use.length + 1 >= lisp__data.pack->use.space) {
31915dfecf96Smrg	LispObj **pairs = realloc(lisp__data.pack->use.pairs,
31925dfecf96Smrg				  (lisp__data.pack->use.space + 1) *
31935dfecf96Smrg				  sizeof(LispObj*));
31945dfecf96Smrg
31955dfecf96Smrg	if (pairs == NULL)
31965dfecf96Smrg	    LispDestroy("out of memory");
31975dfecf96Smrg
31985dfecf96Smrg	lisp__data.pack->use.pairs = pairs;
31995dfecf96Smrg	++lisp__data.pack->use.space;
32005dfecf96Smrg    }
32015dfecf96Smrg    lisp__data.pack->use.pairs[lisp__data.pack->use.length++] = package;
32025dfecf96Smrg
32035dfecf96Smrg    /* Import all extern symbols from package */
32045dfecf96Smrg    pack = package->data.package.package;
32055dfecf96Smrg
32065dfecf96Smrg    /* Traverse atom list, searching for extern symbols */
3207f14f4646Smrg    for (atom = (LispAtom *)hash_iter_first(pack->atoms);
3208f14f4646Smrg	 atom;
3209f14f4646Smrg	 atom = (LispAtom *)hash_iter_next(pack->atoms)) {
3210f14f4646Smrg	if (atom->ext)
3211f14f4646Smrg	    LispImportSymbol(atom->object);
32125dfecf96Smrg    }
32135dfecf96Smrg}
32145dfecf96Smrg
32155dfecf96Smrg/* symbol must be of type LispAtom_t */
32165dfecf96Smrgvoid
32175dfecf96SmrgLispImportSymbol(LispObj *symbol)
32185dfecf96Smrg{
32195dfecf96Smrg    int increment;
32205dfecf96Smrg    LispAtom *atom;
32215dfecf96Smrg    LispObj *current;
32225dfecf96Smrg
32235dfecf96Smrg    current = LispGetVarPack(symbol);
32245dfecf96Smrg    if (current == NULL || current->data.atom->property == NOPROPERTY) {
32255dfecf96Smrg	/* No conflicts */
32265dfecf96Smrg
32275dfecf96Smrg	if (symbol->data.atom->a_object) {
32285dfecf96Smrg	    /* If it is a bounded variable */
32295dfecf96Smrg	    if (lisp__data.pack->glb.length + 1 >= lisp__data.pack->glb.space)
32305dfecf96Smrg		LispMoreGlobals(lisp__data.pack);
32315dfecf96Smrg	    lisp__data.pack->glb.pairs[lisp__data.pack->glb.length++] = symbol;
32325dfecf96Smrg	}
32335dfecf96Smrg
32345dfecf96Smrg	/* Create copy of atom in current package */
3235f14f4646Smrg	atom = LispDoGetAtom(ATOMID(symbol)->value, 0);
32365dfecf96Smrg	/*   Need to create a copy because if anything new is atached to the
32375dfecf96Smrg	 * property, the current package is the owner, not the previous one. */
32385dfecf96Smrg
32395dfecf96Smrg	/* And reference the same properties */
32405dfecf96Smrg	atom->property = symbol->data.atom->property;
32415dfecf96Smrg
32425dfecf96Smrg	increment = 1;
32435dfecf96Smrg    }
32445dfecf96Smrg    else if (current->data.atom->property != symbol->data.atom->property) {
32455dfecf96Smrg	/* Symbol already exists in the current package,
32465dfecf96Smrg	 * but does not reference the same variable */
32475dfecf96Smrg	LispContinuable("Symbol %s already defined in package %s. Redefine?",
3248f14f4646Smrg			ATOMID(symbol)->value, THESTR(PACKAGE->data.package.name));
32495dfecf96Smrg
32505dfecf96Smrg	atom = current->data.atom;
32515dfecf96Smrg
32525dfecf96Smrg	/* Continued from error, redefine variable */
32535dfecf96Smrg	LispDecrementAtomReference(atom);
32545dfecf96Smrg	atom->property = symbol->data.atom->property;
32555dfecf96Smrg
32565dfecf96Smrg	atom->a_object = atom->a_function = atom->a_builtin =
32575dfecf96Smrg	    atom->a_property = atom->a_defsetf = atom->a_defstruct = 0;
32585dfecf96Smrg
32595dfecf96Smrg	increment = 1;
32605dfecf96Smrg    }
32615dfecf96Smrg    else {
32625dfecf96Smrg	/* Symbol is already available in the current package, just update */
32635dfecf96Smrg	atom = current->data.atom;
32645dfecf96Smrg
32655dfecf96Smrg	increment = 0;
32665dfecf96Smrg    }
32675dfecf96Smrg
32685dfecf96Smrg    /* If importing an important system variable */
32695dfecf96Smrg    atom->watch = symbol->data.atom->watch;
32705dfecf96Smrg
32715dfecf96Smrg    /* Update constant flag */
32725dfecf96Smrg    atom->constant = symbol->data.atom->constant;
32735dfecf96Smrg
32745dfecf96Smrg    /* Set home-package and unique-atom associated with symbol */
32755dfecf96Smrg    atom->package = symbol->data.atom->package;
32765dfecf96Smrg    atom->object = symbol->data.atom->object;
32775dfecf96Smrg
32785dfecf96Smrg    if (symbol->data.atom->a_object)
32795dfecf96Smrg	atom->a_object = 1;
32805dfecf96Smrg    if (symbol->data.atom->a_function)
32815dfecf96Smrg	atom->a_function = 1;
32825dfecf96Smrg    else if (symbol->data.atom->a_builtin)
32835dfecf96Smrg	atom->a_builtin = 1;
32845dfecf96Smrg    else if (symbol->data.atom->a_compiled)
32855dfecf96Smrg	atom->a_compiled = 1;
32865dfecf96Smrg    if (symbol->data.atom->a_property)
32875dfecf96Smrg	atom->a_property = 1;
32885dfecf96Smrg    if (symbol->data.atom->a_defsetf)
32895dfecf96Smrg	atom->a_defsetf = 1;
32905dfecf96Smrg    if (symbol->data.atom->a_defstruct)
32915dfecf96Smrg	atom->a_defstruct = 1;
32925dfecf96Smrg
32935dfecf96Smrg    if (increment)
32945dfecf96Smrg	/* Increase reference count, more than one package using the symbol */
32955dfecf96Smrg	LispIncrementAtomReference(symbol->data.atom);
32965dfecf96Smrg}
32975dfecf96Smrg
32985dfecf96Smrg/* symbol must be of type LispAtom_t */
32995dfecf96Smrgvoid
33005dfecf96SmrgLispExportSymbol(LispObj *symbol)
33015dfecf96Smrg{
33025dfecf96Smrg    /* This does not automatically export symbols to another package using
33035dfecf96Smrg     * the symbols of the current package */
33045dfecf96Smrg    symbol->data.atom->ext = 1;
33055dfecf96Smrg}
33065dfecf96Smrg
33075dfecf96Smrg#ifdef __GNUC__
33085dfecf96SmrgLispObj *
33095dfecf96SmrgLispGetVar(LispObj *atom)
33105dfecf96Smrg{
33115dfecf96Smrg    return (LispDoGetVar(atom));
33125dfecf96Smrg}
33135dfecf96Smrg
33145dfecf96Smrgstatic INLINE LispObj *
33155dfecf96SmrgLispDoGetVar(LispObj *atom)
33165dfecf96Smrg#else
33175dfecf96Smrg#define LispDoGetVar LispGetVar
33185dfecf96SmrgLispObj *
33195dfecf96SmrgLispGetVar(LispObj *atom)
33205dfecf96Smrg#endif
33215dfecf96Smrg{
33225dfecf96Smrg    LispAtom *name;
33235dfecf96Smrg    int i, base, offset;
33245dfecf96Smrg    Atom_id id;
33255dfecf96Smrg
33265dfecf96Smrg    name = atom->data.atom;
33275dfecf96Smrg    if (name->constant && name->package == lisp__data.keyword)
33285dfecf96Smrg	return (atom);
33295dfecf96Smrg
33305dfecf96Smrg    /* XXX offset should be stored elsewhere, it is unique, like the string
33315dfecf96Smrg     * pointer. Unless a multi-thread interface is implemented (where
33325dfecf96Smrg     * multiple stacks would be required, the offset value should be
33335dfecf96Smrg     * stored with the string, so that a few cpu cicles could be saved
33345dfecf96Smrg     * by initializing the value to -1, and only searching for the symbol
33355dfecf96Smrg     * binding if it is not -1, and if no binding is found, because the
33365dfecf96Smrg     * lexical scope was left, reset offset to -1. */
33375dfecf96Smrg    offset = name->offset;
3338f14f4646Smrg    id = name->key;
33395dfecf96Smrg    base = lisp__data.env.lex;
33405dfecf96Smrg    i = lisp__data.env.head - 1;
33415dfecf96Smrg
33425dfecf96Smrg    if (offset <= i && (offset >= base || name->dyn) &&
33435dfecf96Smrg	lisp__data.env.names[offset] == id)
33445dfecf96Smrg	return (lisp__data.env.values[offset]);
33455dfecf96Smrg
33465dfecf96Smrg    for (; i >= base; i--)
33475dfecf96Smrg	if (lisp__data.env.names[i] == id) {
33485dfecf96Smrg	    name->offset = i;
33495dfecf96Smrg
33505dfecf96Smrg	    return (lisp__data.env.values[i]);
33515dfecf96Smrg	}
33525dfecf96Smrg
33535dfecf96Smrg    if (name->dyn) {
33545dfecf96Smrg	/* Keep searching as maybe a rebound dynamic variable */
33555dfecf96Smrg	for (; i >= 0; i--)
33565dfecf96Smrg	    if (lisp__data.env.names[i] == id) {
33575dfecf96Smrg		name->offset = i;
33585dfecf96Smrg
33595dfecf96Smrg	    return (lisp__data.env.values[i]);
33605dfecf96Smrg	}
33615dfecf96Smrg
33625dfecf96Smrg	if (name->a_object) {
33635dfecf96Smrg	    /* Check for a symbol defined as special, but not yet bound. */
33645dfecf96Smrg	    if (name->property->value == UNBOUND)
33655dfecf96Smrg		return (NULL);
33665dfecf96Smrg
33675dfecf96Smrg	    return (name->property->value);
33685dfecf96Smrg	}
33695dfecf96Smrg    }
33705dfecf96Smrg
33715dfecf96Smrg    return (name->a_object ? name->property->value : NULL);
33725dfecf96Smrg}
33735dfecf96Smrg
33745dfecf96Smrg#ifdef DEBUGGER
33755dfecf96Smrg/* Same code as LispDoGetVar, but returns the address of the pointer to
33765dfecf96Smrg * the object value. Used only by the debugger */
33775dfecf96Smrgvoid *
33785dfecf96SmrgLispGetVarAddr(LispObj *atom)
33795dfecf96Smrg{
33805dfecf96Smrg    LispAtom *name;
33815dfecf96Smrg    int i, base;
33825dfecf96Smrg    Atom_id id;
33835dfecf96Smrg
33845dfecf96Smrg    name = atom->data.atom;
33855dfecf96Smrg    if (name->constant && name->package == lisp__data.keyword)
33865dfecf96Smrg	return (&atom);
33875dfecf96Smrg
33885dfecf96Smrg    id = name->string;
33895dfecf96Smrg
33905dfecf96Smrg    i = lisp__data.env.head - 1;
33915dfecf96Smrg    for (base = lisp__data.env.lex; i >= base; i--)
33925dfecf96Smrg	if (lisp__data.env.names[i] == id)
33935dfecf96Smrg	    return (&(lisp__data.env.values[i]));
33945dfecf96Smrg
33955dfecf96Smrg    if (name->dyn) {
33965dfecf96Smrg	for (; i >= 0; i--)
33975dfecf96Smrg	    if (lisp__data.env.names[i] == id)
33985dfecf96Smrg		return (&(lisp__data.env.values[i]));
33995dfecf96Smrg
34005dfecf96Smrg	if (name->a_object) {
34015dfecf96Smrg	    /* Check for a symbol defined as special, but not yet bound */
34025dfecf96Smrg	    if (name->property->value == UNBOUND)
34035dfecf96Smrg		return (NULL);
34045dfecf96Smrg
34055dfecf96Smrg	    return (&(name->property->value));
34065dfecf96Smrg	}
34075dfecf96Smrg    }
34085dfecf96Smrg
34095dfecf96Smrg    return (name->a_object ? &(name->property->value) : NULL);
34105dfecf96Smrg}
34115dfecf96Smrg#endif
34125dfecf96Smrg
34135dfecf96Smrg/* Only removes global variables. To be called by makunbound
34145dfecf96Smrg * Local variables are unbounded once their block is closed anyway.
34155dfecf96Smrg */
34165dfecf96Smrgvoid
34175dfecf96SmrgLispUnsetVar(LispObj *atom)
34185dfecf96Smrg{
34195dfecf96Smrg    LispAtom *name = atom->data.atom;
34205dfecf96Smrg
34215dfecf96Smrg    if (name->package) {
34225dfecf96Smrg	int i;
34235dfecf96Smrg	LispPackage *pack = name->package->data.package.package;
34245dfecf96Smrg
34255dfecf96Smrg	for (i = pack->glb.length - 1; i > 0; i--)
34265dfecf96Smrg	    if (pack->glb.pairs[i] == atom) {
34275dfecf96Smrg		LispRemAtomObjectProperty(name);
34285dfecf96Smrg		--pack->glb.length;
34295dfecf96Smrg		if (i < pack->glb.length)
34305dfecf96Smrg		    memmove(pack->glb.pairs + i, pack->glb.pairs + i + 1,
34315dfecf96Smrg			    sizeof(LispObj*) * (pack->glb.length - i));
34325dfecf96Smrg
34335dfecf96Smrg		/* unset hint about dynamically binded variable */
34345dfecf96Smrg		if (name->dyn)
34355dfecf96Smrg		    name->dyn = 0;
34365dfecf96Smrg		break;
34375dfecf96Smrg	    }
34385dfecf96Smrg    }
34395dfecf96Smrg}
34405dfecf96Smrg
34415dfecf96SmrgLispObj *
34425dfecf96SmrgLispAddVar(LispObj *atom, LispObj *obj)
34435dfecf96Smrg{
34445dfecf96Smrg    if (lisp__data.env.length >= lisp__data.env.space)
34455dfecf96Smrg	LispMoreEnvironment();
34465dfecf96Smrg
34475dfecf96Smrg    LispDoAddVar(atom, obj);
34485dfecf96Smrg
34495dfecf96Smrg    return (obj);
34505dfecf96Smrg}
34515dfecf96Smrg
34525dfecf96Smrgstatic INLINE void
34535dfecf96SmrgLispDoAddVar(LispObj *symbol, LispObj *value)
34545dfecf96Smrg{
34555dfecf96Smrg    LispAtom *atom = symbol->data.atom;
34565dfecf96Smrg
34575dfecf96Smrg    atom->offset = lisp__data.env.length;
34585dfecf96Smrg    lisp__data.env.values[lisp__data.env.length] = value;
3459f14f4646Smrg    lisp__data.env.names[lisp__data.env.length++] = atom->key;
34605dfecf96Smrg}
34615dfecf96Smrg
34625dfecf96SmrgLispObj *
34635dfecf96SmrgLispSetVar(LispObj *atom, LispObj *obj)
34645dfecf96Smrg{
34655dfecf96Smrg    LispPackage *pack;
34665dfecf96Smrg    LispAtom *name;
34675dfecf96Smrg    int i, base, offset;
34685dfecf96Smrg    Atom_id id;
34695dfecf96Smrg
34705dfecf96Smrg    name = atom->data.atom;
34715dfecf96Smrg    offset = name->offset;
3472f14f4646Smrg    id = name->key;
34735dfecf96Smrg    base = lisp__data.env.lex;
34745dfecf96Smrg    i = lisp__data.env.head - 1;
34755dfecf96Smrg
34765dfecf96Smrg    if (offset <= i && (offset >= base || name->dyn) &&
34775dfecf96Smrg	lisp__data.env.names[offset] == id)
34785dfecf96Smrg	return (lisp__data.env.values[offset] = obj);
34795dfecf96Smrg
34805dfecf96Smrg    for (; i >= base; i--)
34815dfecf96Smrg	if (lisp__data.env.names[i] == id) {
34825dfecf96Smrg	    name->offset = i;
34835dfecf96Smrg
34845dfecf96Smrg	    return (lisp__data.env.values[i] = obj);
34855dfecf96Smrg	}
34865dfecf96Smrg
34875dfecf96Smrg    if (name->dyn) {
34885dfecf96Smrg	for (; i >= 0; i--)
34895dfecf96Smrg	    if (lisp__data.env.names[i] == id)
34905dfecf96Smrg		return (lisp__data.env.values[i] = obj);
34915dfecf96Smrg
34925dfecf96Smrg	if (name->watch) {
34935dfecf96Smrg	    LispSetAtomObjectProperty(name, obj);
34945dfecf96Smrg
34955dfecf96Smrg	    return (obj);
34965dfecf96Smrg	}
34975dfecf96Smrg
34985dfecf96Smrg	return (SETVALUE(name, obj));
34995dfecf96Smrg    }
35005dfecf96Smrg
35015dfecf96Smrg    if (name->a_object) {
35025dfecf96Smrg	if (name->watch) {
35035dfecf96Smrg	    LispSetAtomObjectProperty(name, obj);
35045dfecf96Smrg
35055dfecf96Smrg	    return (obj);
35065dfecf96Smrg	}
35075dfecf96Smrg
35085dfecf96Smrg	return (SETVALUE(name, obj));
35095dfecf96Smrg    }
35105dfecf96Smrg
35115dfecf96Smrg    LispSetAtomObjectProperty(name, obj);
35125dfecf96Smrg
35135dfecf96Smrg    pack = name->package->data.package.package;
35145dfecf96Smrg    if (pack->glb.length >= pack->glb.space)
35155dfecf96Smrg	LispMoreGlobals(pack);
35165dfecf96Smrg
35175dfecf96Smrg    pack->glb.pairs[pack->glb.length++] = atom;
35185dfecf96Smrg
35195dfecf96Smrg    return (obj);
35205dfecf96Smrg}
35215dfecf96Smrg
35225dfecf96Smrgvoid
35235dfecf96SmrgLispProclaimSpecial(LispObj *atom, LispObj *value, LispObj *doc)
35245dfecf96Smrg{
35255dfecf96Smrg    int i = 0, dyn, glb;
35265dfecf96Smrg    LispAtom *name;
35275dfecf96Smrg    LispPackage *pack;
35285dfecf96Smrg
35295dfecf96Smrg    glb = 0;
35305dfecf96Smrg    name = atom->data.atom;
35315dfecf96Smrg    pack = name->package->data.package.package;
35325dfecf96Smrg    dyn = name->dyn;
35335dfecf96Smrg
35345dfecf96Smrg    if (!dyn) {
35355dfecf96Smrg	/* Note: don't check if a local variable already is using the symbol */
35365dfecf96Smrg	for (i = pack->glb.length - 1; i >= 0; i--)
35375dfecf96Smrg	    if (pack->glb.pairs[i] == atom) {
35385dfecf96Smrg		glb = 1;
35395dfecf96Smrg		break;
35405dfecf96Smrg	    }
35415dfecf96Smrg    }
35425dfecf96Smrg
35435dfecf96Smrg    if (dyn) {
35445dfecf96Smrg	if (name->property->value == UNBOUND && value)
35455dfecf96Smrg	    /* if variable was just made special, but not bounded */
35465dfecf96Smrg	    LispSetAtomObjectProperty(name, value);
35475dfecf96Smrg    }
35485dfecf96Smrg    else if (glb)
35495dfecf96Smrg	/* Already a global variable, but not marked as special.
35505dfecf96Smrg	 * Set hint about dynamically binded variable. */
35515dfecf96Smrg	name->dyn = 1;
35525dfecf96Smrg    else {
35535dfecf96Smrg	/* create new special variable */
35545dfecf96Smrg	LispSetAtomObjectProperty(name, value ? value : UNBOUND);
35555dfecf96Smrg
35565dfecf96Smrg	if (pack->glb.length >= pack->glb.space)
35575dfecf96Smrg	    LispMoreGlobals(pack);
35585dfecf96Smrg
35595dfecf96Smrg	pack->glb.pairs[pack->glb.length] = atom;
35605dfecf96Smrg	++pack->glb.length;
35615dfecf96Smrg	/* set hint about possibly dynamically binded variable */
35625dfecf96Smrg	name->dyn = 1;
35635dfecf96Smrg    }
35645dfecf96Smrg
35655dfecf96Smrg    if (doc != NIL)
35665dfecf96Smrg	LispAddDocumentation(atom, doc, LispDocVariable);
35675dfecf96Smrg}
35685dfecf96Smrg
35695dfecf96Smrgvoid
35705dfecf96SmrgLispDefconstant(LispObj *atom, LispObj *value, LispObj *doc)
35715dfecf96Smrg{
35725dfecf96Smrg    int i;
35735dfecf96Smrg    LispAtom *name = atom->data.atom;
35745dfecf96Smrg    LispPackage *pack = name->package->data.package.package;
35755dfecf96Smrg
35765dfecf96Smrg    /* Unset hint about dynamically binded variable, if set. */
35775dfecf96Smrg    name->dyn = 0;
35785dfecf96Smrg
35795dfecf96Smrg    /* Check if variable is bounded as a global variable */
35805dfecf96Smrg    for (i = pack->glb.length - 1; i >= 0; i--)
35815dfecf96Smrg	if (pack->glb.pairs[i] == atom)
35825dfecf96Smrg	    break;
35835dfecf96Smrg
35845dfecf96Smrg    if (i < 0) {
35855dfecf96Smrg	/* Not a global variable */
35865dfecf96Smrg	if (pack->glb.length >= pack->glb.space)
35875dfecf96Smrg	    LispMoreGlobals(pack);
35885dfecf96Smrg
35895dfecf96Smrg	pack->glb.pairs[pack->glb.length] = atom;
35905dfecf96Smrg	++pack->glb.length;
35915dfecf96Smrg    }
35925dfecf96Smrg
35935dfecf96Smrg    /* If already a constant variable */
35945dfecf96Smrg    if (name->constant && name->a_object && name->property->value != value)
35955dfecf96Smrg	LispWarning("constant %s is being redefined", STROBJ(atom));
35965dfecf96Smrg    else
35975dfecf96Smrg	name->constant = 1;
35985dfecf96Smrg
35995dfecf96Smrg    /* Set constant value */
36005dfecf96Smrg    LispSetAtomObjectProperty(name, value);
36015dfecf96Smrg
36025dfecf96Smrg    if (doc != NIL)
36035dfecf96Smrg	LispAddDocumentation(atom, doc, LispDocVariable);
36045dfecf96Smrg}
36055dfecf96Smrg
36065dfecf96Smrgvoid
36075dfecf96SmrgLispAddDocumentation(LispObj *symbol, LispObj *documentation, LispDocType_t type)
36085dfecf96Smrg{
36095dfecf96Smrg    int length;
36105dfecf96Smrg    char *string;
36115dfecf96Smrg    LispAtom *atom;
36125dfecf96Smrg    LispObj *object;
36135dfecf96Smrg
36145dfecf96Smrg    if (!SYMBOLP(symbol) || !STRINGP(documentation))
36155dfecf96Smrg	LispDestroy("DOCUMENTATION: invalid argument");
36165dfecf96Smrg
36175dfecf96Smrg    atom = symbol->data.atom;
36185dfecf96Smrg    if (atom->documentation[type])
36195dfecf96Smrg	LispRemDocumentation(symbol, type);
36205dfecf96Smrg
36215dfecf96Smrg    /* allocate documentation in atomseg */
36225dfecf96Smrg    if (atomseg.freeobj == NIL)
36235dfecf96Smrg	LispAllocSeg(&atomseg, pagesize);
36245dfecf96Smrg    length = STRLEN(documentation);
36255dfecf96Smrg    string = LispMalloc(length);
36265dfecf96Smrg    memcpy(string, THESTR(documentation), length);
36275dfecf96Smrg    string[length] = '\0';
36285dfecf96Smrg    object = atomseg.freeobj;
36295dfecf96Smrg    atomseg.freeobj = CDR(object);
36305dfecf96Smrg    --atomseg.nfree;
36315dfecf96Smrg
36325dfecf96Smrg    object->type = LispString_t;
36335dfecf96Smrg    THESTR(object) = string;
36345dfecf96Smrg    STRLEN(object) = length;
36355dfecf96Smrg    object->data.string.writable = 0;
36365dfecf96Smrg    atom->documentation[type] = object;
36375dfecf96Smrg    LispMused(string);
36385dfecf96Smrg}
36395dfecf96Smrg
36405dfecf96Smrgvoid
36415dfecf96SmrgLispRemDocumentation(LispObj *symbol, LispDocType_t type)
36425dfecf96Smrg{
36435dfecf96Smrg    LispAtom *atom;
36445dfecf96Smrg
36455dfecf96Smrg    if (!SYMBOLP(symbol))
36465dfecf96Smrg	LispDestroy("DOCUMENTATION: invalid argument");
36475dfecf96Smrg
36485dfecf96Smrg    atom = symbol->data.atom;
36495dfecf96Smrg    if (atom->documentation[type]) {
36505dfecf96Smrg	/* reclaim object to atomseg */
36515dfecf96Smrg	free(THESTR(atom->documentation[type]));
36525dfecf96Smrg	CDR(atom->documentation[type]) = atomseg.freeobj;
36535dfecf96Smrg	atomseg.freeobj = atom->documentation[type];
36545dfecf96Smrg	atom->documentation[type] = NULL;
36555dfecf96Smrg	++atomseg.nfree;
36565dfecf96Smrg    }
36575dfecf96Smrg}
36585dfecf96Smrg
36595dfecf96SmrgLispObj *
36605dfecf96SmrgLispGetDocumentation(LispObj *symbol, LispDocType_t type)
36615dfecf96Smrg{
36625dfecf96Smrg    LispAtom *atom;
36635dfecf96Smrg
36645dfecf96Smrg    if (!SYMBOLP(symbol))
36655dfecf96Smrg	LispDestroy("DOCUMENTATION: invalid argument");
36665dfecf96Smrg
36675dfecf96Smrg    atom = symbol->data.atom;
36685dfecf96Smrg
36695dfecf96Smrg    return (atom->documentation[type] ? atom->documentation[type] : NIL);
36705dfecf96Smrg}
36715dfecf96Smrg
36725dfecf96SmrgLispObj *
36735dfecf96SmrgLispReverse(LispObj *list)
36745dfecf96Smrg{
36755dfecf96Smrg    LispObj *tmp, *res = NIL;
36765dfecf96Smrg
36775dfecf96Smrg    while (list != NIL) {
36785dfecf96Smrg	tmp = CDR(list);
36795dfecf96Smrg	CDR(list) = res;
36805dfecf96Smrg	res = list;
36815dfecf96Smrg	list = tmp;
36825dfecf96Smrg    }
36835dfecf96Smrg
36845dfecf96Smrg    return (res);
36855dfecf96Smrg}
36865dfecf96Smrg
36875dfecf96SmrgLispBlock *
36885dfecf96SmrgLispBeginBlock(LispObj *tag, LispBlockType type)
36895dfecf96Smrg{
36905dfecf96Smrg    LispBlock *block;
36915dfecf96Smrg    unsigned blevel = lisp__data.block.block_level + 1;
36925dfecf96Smrg
36935dfecf96Smrg    if (blevel > lisp__data.block.block_size) {
36945dfecf96Smrg	LispBlock **blk;
36955dfecf96Smrg
36965dfecf96Smrg	if (blevel > MAX_STACK_DEPTH)
36975dfecf96Smrg	    LispDestroy("stack overflow");
36985dfecf96Smrg
36995dfecf96Smrg	DISABLE_INTERRUPTS();
37005dfecf96Smrg	blk = realloc(lisp__data.block.block, sizeof(LispBlock*) * (blevel + 1));
37015dfecf96Smrg
37025dfecf96Smrg	block = NULL;
37035dfecf96Smrg	if (blk == NULL || (block = malloc(sizeof(LispBlock))) == NULL) {
37045dfecf96Smrg	    ENABLE_INTERRUPTS();
37055dfecf96Smrg	    LispDestroy("out of memory");
37065dfecf96Smrg	}
37075dfecf96Smrg	lisp__data.block.block = blk;
37085dfecf96Smrg	lisp__data.block.block[lisp__data.block.block_size] = block;
37095dfecf96Smrg	lisp__data.block.block_size = blevel;
37105dfecf96Smrg	ENABLE_INTERRUPTS();
37115dfecf96Smrg    }
37125dfecf96Smrg    block = lisp__data.block.block[lisp__data.block.block_level];
37135dfecf96Smrg    if (type == LispBlockCatch && !CONSTANTP(tag)) {
37145dfecf96Smrg	tag = EVAL(tag);
37155dfecf96Smrg	lisp__data.protect.objects[lisp__data.protect.length++] = tag;
37165dfecf96Smrg    }
37175dfecf96Smrg    block->type = type;
37185dfecf96Smrg    block->tag = tag;
37195dfecf96Smrg    block->stack = lisp__data.stack.length;
37205dfecf96Smrg    block->protect = lisp__data.protect.length;
37215dfecf96Smrg    block->block_level = lisp__data.block.block_level;
37225dfecf96Smrg
37235dfecf96Smrg    lisp__data.block.block_level = blevel;
37245dfecf96Smrg
37255dfecf96Smrg#ifdef DEBUGGER
37265dfecf96Smrg    if (lisp__data.debugging) {
37275dfecf96Smrg	block->debug_level = lisp__data.debug_level;
37285dfecf96Smrg	block->debug_step = lisp__data.debug_step;
37295dfecf96Smrg    }
37305dfecf96Smrg#endif
37315dfecf96Smrg
37325dfecf96Smrg    return (block);
37335dfecf96Smrg}
37345dfecf96Smrg
37355dfecf96Smrgvoid
37365dfecf96SmrgLispEndBlock(LispBlock *block)
37375dfecf96Smrg{
37385dfecf96Smrg    lisp__data.protect.length = block->protect;
37395dfecf96Smrg    lisp__data.block.block_level = block->block_level;
37405dfecf96Smrg
37415dfecf96Smrg#ifdef DEBUGGER
37425dfecf96Smrg    if (lisp__data.debugging) {
37435dfecf96Smrg	if (lisp__data.debug_level >= block->debug_level) {
37445dfecf96Smrg	    while (lisp__data.debug_level > block->debug_level) {
37455dfecf96Smrg		DBG = CDR(DBG);
37465dfecf96Smrg		--lisp__data.debug_level;
37475dfecf96Smrg	    }
37485dfecf96Smrg	}
37495dfecf96Smrg	lisp__data.debug_step = block->debug_step;
37505dfecf96Smrg    }
37515dfecf96Smrg#endif
37525dfecf96Smrg}
37535dfecf96Smrg
37545dfecf96Smrgvoid
37555dfecf96SmrgLispBlockUnwind(LispBlock *block)
37565dfecf96Smrg{
37575dfecf96Smrg    LispBlock *unwind;
37585dfecf96Smrg    int blevel = lisp__data.block.block_level;
37595dfecf96Smrg
37605dfecf96Smrg    while (blevel > 0) {
37615dfecf96Smrg	unwind = lisp__data.block.block[--blevel];
37625dfecf96Smrg	if (unwind->type == LispBlockProtect) {
37635dfecf96Smrg	    BLOCKJUMP(unwind);
37645dfecf96Smrg	}
37655dfecf96Smrg	if (unwind == block)
37665dfecf96Smrg	    /* jump above unwind block */
37675dfecf96Smrg	    break;
37685dfecf96Smrg    }
37695dfecf96Smrg}
37705dfecf96Smrg
37715dfecf96Smrgstatic LispObj *
37725dfecf96SmrgLispEvalBackquoteObject(LispObj *argument, int list, int quote)
37735dfecf96Smrg{
37745dfecf96Smrg    LispObj *result = argument, *object;
37755dfecf96Smrg
37765dfecf96Smrg    if (!POINTERP(argument))
37775dfecf96Smrg	return (argument);
37785dfecf96Smrg
37795dfecf96Smrg    else if (XCOMMAP(argument)) {
37805dfecf96Smrg	/* argument may need to be evaluated */
37815dfecf96Smrg
37825dfecf96Smrg	int atlist;
37835dfecf96Smrg
37845dfecf96Smrg	if (!list && argument->data.comma.atlist)
37855dfecf96Smrg	    /* cannot append, not in a list */
37865dfecf96Smrg	    LispDestroy("EVAL: ,@ only allowed on lists");
37875dfecf96Smrg
37885dfecf96Smrg	--quote;
37895dfecf96Smrg	if (quote < 0)
37905dfecf96Smrg	    LispDestroy("EVAL: comma outside of backquote");
37915dfecf96Smrg
37925dfecf96Smrg	result = object = argument->data.comma.eval;
37935dfecf96Smrg	atlist = COMMAP(object) && object->data.comma.atlist;
37945dfecf96Smrg
37955dfecf96Smrg	if (POINTERP(result) && (XCOMMAP(result) || XBACKQUOTEP(result)))
37965dfecf96Smrg	    /* nested commas, reduce 1 level, or backquote,
37975dfecf96Smrg	     * don't call LispEval or quote argument will be reset */
37985dfecf96Smrg	    result = LispEvalBackquoteObject(object, 0, quote);
37995dfecf96Smrg
38005dfecf96Smrg	else if (quote == 0)
38015dfecf96Smrg	   /* just evaluate it */
38025dfecf96Smrg	    result = EVAL(result);
38035dfecf96Smrg
38045dfecf96Smrg	if (quote != 0)
38055dfecf96Smrg	    result = result == object ? argument : COMMA(result, atlist);
38065dfecf96Smrg    }
38075dfecf96Smrg
38085dfecf96Smrg    else if (XBACKQUOTEP(argument)) {
38095dfecf96Smrg	object = argument->data.quote;
38105dfecf96Smrg
38115dfecf96Smrg	result = LispEvalBackquote(object, quote + 1);
38125dfecf96Smrg	if (quote)
38135dfecf96Smrg	    result = result == object ? argument : BACKQUOTE(result);
38145dfecf96Smrg    }
38155dfecf96Smrg
38165dfecf96Smrg    else if (XQUOTEP(argument) && POINTERP(argument->data.quote) &&
38175dfecf96Smrg	     (XCOMMAP(argument->data.quote) ||
38185dfecf96Smrg	      XBACKQUOTEP(argument->data.quote) ||
38195dfecf96Smrg	      XCONSP(argument->data.quote))) {
38205dfecf96Smrg	/* ensures `',sym to be the same as `(quote ,sym) */
38215dfecf96Smrg	object = argument->data.quote;
38225dfecf96Smrg
38235dfecf96Smrg	result = LispEvalBackquote(argument->data.quote, quote);
38245dfecf96Smrg	result = result == object ? argument : QUOTE(result);
38255dfecf96Smrg    }
38265dfecf96Smrg
38275dfecf96Smrg    return (result);
38285dfecf96Smrg}
38295dfecf96Smrg
38305dfecf96SmrgLispObj *
38315dfecf96SmrgLispEvalBackquote(LispObj *argument, int quote)
38325dfecf96Smrg{
38335dfecf96Smrg    int protect;
38345dfecf96Smrg    LispObj *result, *object, *cons, *cdr;
38355dfecf96Smrg
38365dfecf96Smrg    if (!CONSP(argument))
38375dfecf96Smrg	return (LispEvalBackquoteObject(argument, 0, quote));
38385dfecf96Smrg
38395dfecf96Smrg    result = cdr = NIL;
38405dfecf96Smrg    protect = lisp__data.protect.length;
38415dfecf96Smrg
38425dfecf96Smrg    /* always generate a new list for the result, even if nothing
38435dfecf96Smrg     * is evaluated. It is not expected to use backqoutes when
38445dfecf96Smrg     * not required. */
38455dfecf96Smrg
38465dfecf96Smrg    /* reserve a GC protected slot for the result */
38475dfecf96Smrg    if (protect + 1 >= lisp__data.protect.space)
38485dfecf96Smrg	LispMoreProtects();
38495dfecf96Smrg    lisp__data.protect.objects[lisp__data.protect.length++] = NIL;
38505dfecf96Smrg
38515dfecf96Smrg    for (cons = argument; ; cons = CDR(cons)) {
38525dfecf96Smrg	/* if false, last argument, and if cons is not NIL, a dotted list */
38535dfecf96Smrg	int list = CONSP(cons), insert;
38545dfecf96Smrg
38555dfecf96Smrg	if (list)
38565dfecf96Smrg	    object = CAR(cons);
38575dfecf96Smrg	else
38585dfecf96Smrg	    object = cons;
38595dfecf96Smrg
38605dfecf96Smrg	if (COMMAP(object))
38615dfecf96Smrg	    /* need to insert list elements in result, not just cons it? */
38625dfecf96Smrg	    insert = object->data.comma.atlist;
38635dfecf96Smrg	else
38645dfecf96Smrg	    insert = 0;
38655dfecf96Smrg
38665dfecf96Smrg	/* evaluate object, if required */
38675dfecf96Smrg	if (CONSP(object))
38685dfecf96Smrg	    object = LispEvalBackquote(object, quote);
38695dfecf96Smrg	else
38705dfecf96Smrg	    object = LispEvalBackquoteObject(object, insert, quote);
38715dfecf96Smrg
38725dfecf96Smrg	if (result == NIL) {
38735dfecf96Smrg	    /* if starting result list */
38745dfecf96Smrg	    if (!insert) {
38755dfecf96Smrg		if (list)
38765dfecf96Smrg		    result = cdr = CONS(object, NIL);
38775dfecf96Smrg		else
38785dfecf96Smrg		    result = cdr = object;
38795dfecf96Smrg		/* gc protect result */
38805dfecf96Smrg		lisp__data.protect.objects[protect] = result;
38815dfecf96Smrg	    }
38825dfecf96Smrg	    else {
38835dfecf96Smrg		if (!CONSP(object)) {
38845dfecf96Smrg		    result = cdr = object;
38855dfecf96Smrg		    /* gc protect result */
38865dfecf96Smrg		    lisp__data.protect.objects[protect] = result;
38875dfecf96Smrg		}
38885dfecf96Smrg		else {
38895dfecf96Smrg		    result = cdr = CONS(CAR(object), NIL);
38905dfecf96Smrg		    /* gc protect result */
38915dfecf96Smrg		    lisp__data.protect.objects[protect] = result;
38925dfecf96Smrg
38935dfecf96Smrg		    /* add remaining elements to result */
38945dfecf96Smrg		    for (object = CDR(object);
38955dfecf96Smrg			 CONSP(object);
38965dfecf96Smrg			 object = CDR(object)) {
38975dfecf96Smrg			RPLACD(cdr, CONS(CAR(object), NIL));
38985dfecf96Smrg			cdr = CDR(cdr);
38995dfecf96Smrg		    }
39005dfecf96Smrg		    if (object != NIL) {
39015dfecf96Smrg			/* object was a dotted list */
39025dfecf96Smrg			RPLACD(cdr, object);
39035dfecf96Smrg			cdr = CDR(cdr);
39045dfecf96Smrg		    }
39055dfecf96Smrg		}
39065dfecf96Smrg	    }
39075dfecf96Smrg	}
39085dfecf96Smrg	else {
39095dfecf96Smrg	    if (!CONSP(cdr))
39105dfecf96Smrg		LispDestroy("EVAL: cannot append to %s", STROBJ(cdr));
39115dfecf96Smrg
39125dfecf96Smrg	    if (!insert) {
39135dfecf96Smrg		if (list) {
39145dfecf96Smrg		    RPLACD(cdr, CONS(object, NIL));
39155dfecf96Smrg		    cdr = CDR(cdr);
39165dfecf96Smrg		}
39175dfecf96Smrg		else {
39185dfecf96Smrg		    RPLACD(cdr, object);
39195dfecf96Smrg		    cdr = object;
39205dfecf96Smrg		}
39215dfecf96Smrg	    }
39225dfecf96Smrg	    else {
39235dfecf96Smrg		if (!CONSP(object)) {
39245dfecf96Smrg		    RPLACD(cdr, object);
39255dfecf96Smrg		    /* if object is NIL, it is a empty list appended, not
39265dfecf96Smrg		     * creating a dotted list. */
39275dfecf96Smrg		    if (object != NIL)
39285dfecf96Smrg			cdr = object;
39295dfecf96Smrg		}
39305dfecf96Smrg		else {
39315dfecf96Smrg		    for (; CONSP(object); object = CDR(object)) {
39325dfecf96Smrg			RPLACD(cdr, CONS(CAR(object), NIL));
39335dfecf96Smrg			cdr = CDR(cdr);
39345dfecf96Smrg		    }
39355dfecf96Smrg		    if (object != NIL) {
39365dfecf96Smrg			/* object was a dotted list */
39375dfecf96Smrg			RPLACD(cdr, object);
39385dfecf96Smrg			cdr = CDR(cdr);
39395dfecf96Smrg		    }
39405dfecf96Smrg		}
39415dfecf96Smrg	    }
39425dfecf96Smrg	}
39435dfecf96Smrg
39445dfecf96Smrg	/* if last argument list element processed */
39455dfecf96Smrg	if (!list)
39465dfecf96Smrg	    break;
39475dfecf96Smrg    }
39485dfecf96Smrg
39495dfecf96Smrg    lisp__data.protect.length = protect;
39505dfecf96Smrg
39515dfecf96Smrg    return (result);
39525dfecf96Smrg}
39535dfecf96Smrg
39545dfecf96Smrgvoid
39555dfecf96SmrgLispMoreEnvironment(void)
39565dfecf96Smrg{
39575dfecf96Smrg    Atom_id *names;
39585dfecf96Smrg    LispObj **values;
39595dfecf96Smrg
39605dfecf96Smrg    DISABLE_INTERRUPTS();
39615dfecf96Smrg    names = realloc(lisp__data.env.names,
39625dfecf96Smrg		    (lisp__data.env.space + 256) * sizeof(Atom_id));
39635dfecf96Smrg    if (names != NULL) {
39645dfecf96Smrg	values = realloc(lisp__data.env.values,
39655dfecf96Smrg			 (lisp__data.env.space + 256) * sizeof(LispObj*));
39665dfecf96Smrg	if (values != NULL) {
39675dfecf96Smrg	    lisp__data.env.names = names;
39685dfecf96Smrg	    lisp__data.env.values = values;
39695dfecf96Smrg	    lisp__data.env.space += 256;
39705dfecf96Smrg	    ENABLE_INTERRUPTS();
39715dfecf96Smrg	    return;
39725dfecf96Smrg	}
39735dfecf96Smrg	else
39745dfecf96Smrg	    free(names);
39755dfecf96Smrg    }
39765dfecf96Smrg    ENABLE_INTERRUPTS();
39775dfecf96Smrg    LispDestroy("out of memory");
39785dfecf96Smrg}
39795dfecf96Smrg
39805dfecf96Smrgvoid
39815dfecf96SmrgLispMoreStack(void)
39825dfecf96Smrg{
39835dfecf96Smrg    LispObj **values;
39845dfecf96Smrg
39855dfecf96Smrg    DISABLE_INTERRUPTS();
39865dfecf96Smrg    values = realloc(lisp__data.stack.values,
39875dfecf96Smrg		     (lisp__data.stack.space + 256) * sizeof(LispObj*));
39885dfecf96Smrg    if (values == NULL) {
39895dfecf96Smrg	ENABLE_INTERRUPTS();
39905dfecf96Smrg	LispDestroy("out of memory");
39915dfecf96Smrg    }
39925dfecf96Smrg    lisp__data.stack.values = values;
39935dfecf96Smrg    lisp__data.stack.space += 256;
39945dfecf96Smrg    ENABLE_INTERRUPTS();
39955dfecf96Smrg}
39965dfecf96Smrg
39975dfecf96Smrgvoid
39985dfecf96SmrgLispMoreGlobals(LispPackage *pack)
39995dfecf96Smrg{
40005dfecf96Smrg    LispObj **pairs;
40015dfecf96Smrg
40025dfecf96Smrg    DISABLE_INTERRUPTS();
40035dfecf96Smrg    pairs = realloc(pack->glb.pairs,
40045dfecf96Smrg		    (pack->glb.space + 256) * sizeof(LispObj*));
40055dfecf96Smrg    if (pairs == NULL) {
40065dfecf96Smrg	ENABLE_INTERRUPTS();
40075dfecf96Smrg	LispDestroy("out of memory");
40085dfecf96Smrg    }
40095dfecf96Smrg    pack->glb.pairs = pairs;
40105dfecf96Smrg    pack->glb.space += 256;
40115dfecf96Smrg    ENABLE_INTERRUPTS();
40125dfecf96Smrg}
40135dfecf96Smrg
40145dfecf96Smrgvoid
40155dfecf96SmrgLispMoreProtects(void)
40165dfecf96Smrg{
40175dfecf96Smrg    LispObj **objects;
40185dfecf96Smrg
40195dfecf96Smrg    DISABLE_INTERRUPTS();
40205dfecf96Smrg    objects = realloc(lisp__data.protect.objects,
40215dfecf96Smrg		      (lisp__data.protect.space + 256) * sizeof(LispObj*));
40225dfecf96Smrg    if (objects == NULL) {
40235dfecf96Smrg	ENABLE_INTERRUPTS();
40245dfecf96Smrg	LispDestroy("out of memory");
40255dfecf96Smrg    }
40265dfecf96Smrg    lisp__data.protect.objects = objects;
40275dfecf96Smrg    lisp__data.protect.space += 256;
40285dfecf96Smrg    ENABLE_INTERRUPTS();
40295dfecf96Smrg}
40305dfecf96Smrg
40315dfecf96Smrgstatic int
40325dfecf96SmrgLispMakeEnvironment(LispArgList *alist, LispObj *values,
40335dfecf96Smrg		    LispObj *name, int eval, int builtin)
40345dfecf96Smrg{
40355dfecf96Smrg    char *desc;
40365dfecf96Smrg    int i, count, base;
40375dfecf96Smrg    LispObj **symbols, **defaults, **sforms;
40385dfecf96Smrg
40395dfecf96Smrg#define BUILTIN_ARGUMENT(value)				\
40405dfecf96Smrg    lisp__data.stack.values[lisp__data.stack.length++] = value
40415dfecf96Smrg
40425dfecf96Smrg/* If the index value is from register variables, this
40435dfecf96Smrg * can save some cpu time. Useful for normal arguments
40445dfecf96Smrg * that are the most common, and thus the ones that
40455dfecf96Smrg * consume more time in LispMakeEnvironment. */
40465dfecf96Smrg#define BUILTIN_NO_EVAL_ARGUMENT(index, value)		\
40475dfecf96Smrg    lisp__data.stack.values[index] = value
40485dfecf96Smrg
40495dfecf96Smrg#define NORMAL_ARGUMENT(symbol, value)			\
40505dfecf96Smrg    LispDoAddVar(symbol, value)
40515dfecf96Smrg
40525dfecf96Smrg    if (builtin) {
40535dfecf96Smrg	base = lisp__data.stack.length;
40545dfecf96Smrg	if (base + alist->num_arguments > lisp__data.stack.space) {
40555dfecf96Smrg	    do
40565dfecf96Smrg		LispMoreStack();
40575dfecf96Smrg	    while (base + alist->num_arguments > lisp__data.stack.space);
40585dfecf96Smrg	}
40595dfecf96Smrg    }
40605dfecf96Smrg    else {
40615dfecf96Smrg	base = lisp__data.env.length;
40625dfecf96Smrg	if (base + alist->num_arguments > lisp__data.env.space) {
40635dfecf96Smrg	    do
40645dfecf96Smrg		LispMoreEnvironment();
40655dfecf96Smrg	    while (base + alist->num_arguments > lisp__data.env.space);
40665dfecf96Smrg	}
40675dfecf96Smrg    }
40685dfecf96Smrg
40695dfecf96Smrg    desc = alist->description;
40705dfecf96Smrg    switch (*desc++) {
40715dfecf96Smrg	case '.':
40725dfecf96Smrg	    goto normal_label;
40735dfecf96Smrg	case 'o':
40745dfecf96Smrg	    goto optional_label;
40755dfecf96Smrg	case 'k':
40765dfecf96Smrg	    goto key_label;
40775dfecf96Smrg	case 'r':
40785dfecf96Smrg	    goto rest_label;
40795dfecf96Smrg	case 'a':
40805dfecf96Smrg	    goto aux_label;
40815dfecf96Smrg	default:
40825dfecf96Smrg	    goto done_label;
40835dfecf96Smrg    }
40845dfecf96Smrg
40855dfecf96Smrg
40865dfecf96Smrg    /* Code below is done in several almost identical loops, to avoid
40875dfecf96Smrg     * checking the value of the arguments eval and builtin too much times */
40885dfecf96Smrg
40895dfecf96Smrg
40905dfecf96Smrg    /* Normal arguments */
40915dfecf96Smrgnormal_label:
40925dfecf96Smrg    i = 0;
40935dfecf96Smrg    count = alist->normals.num_symbols;
40945dfecf96Smrg    if (builtin) {
40955dfecf96Smrg	if (eval) {
40965dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
40975dfecf96Smrg		BUILTIN_ARGUMENT(EVAL(CAR(values)));
40985dfecf96Smrg	    }
40995dfecf96Smrg	}
41005dfecf96Smrg	else {
41015dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
41025dfecf96Smrg		BUILTIN_NO_EVAL_ARGUMENT(base + i, CAR(values));
41035dfecf96Smrg	    }
41045dfecf96Smrg	    /* macro BUILTIN_NO_EVAL_ARGUMENT does not update
41055dfecf96Smrg	     * lisp__data.stack.length, as there is no risk of GC while
41065dfecf96Smrg	     * adding the arguments. */
41075dfecf96Smrg	    lisp__data.stack.length += i;
41085dfecf96Smrg	}
41095dfecf96Smrg    }
41105dfecf96Smrg    else {
41115dfecf96Smrg	symbols = alist->normals.symbols;
41125dfecf96Smrg	if (eval) {
41135dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
41145dfecf96Smrg		NORMAL_ARGUMENT(symbols[i], EVAL(CAR(values)));
41155dfecf96Smrg	    }
41165dfecf96Smrg	}
41175dfecf96Smrg	else {
41185dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
41195dfecf96Smrg		NORMAL_ARGUMENT(symbols[i], CAR(values));
41205dfecf96Smrg	    }
41215dfecf96Smrg	}
41225dfecf96Smrg    }
41235dfecf96Smrg    if (i < count)
41245dfecf96Smrg	LispDestroy("%s: too few arguments", STROBJ(name));
41255dfecf96Smrg
41265dfecf96Smrg    switch (*desc++) {
41275dfecf96Smrg	case 'o':
41285dfecf96Smrg	    goto optional_label;
41295dfecf96Smrg	case 'k':
41305dfecf96Smrg	    goto key_label;
41315dfecf96Smrg	case 'r':
41325dfecf96Smrg	    goto rest_label;
41335dfecf96Smrg	case 'a':
41345dfecf96Smrg	    goto aux_label;
41355dfecf96Smrg	default:
41365dfecf96Smrg	    goto done_label;
41375dfecf96Smrg    }
41385dfecf96Smrg
41395dfecf96Smrg    /* &OPTIONAL */
41405dfecf96Smrgoptional_label:
41415dfecf96Smrg    i = 0;
41425dfecf96Smrg    count = alist->optionals.num_symbols;
41435dfecf96Smrg    defaults = alist->optionals.defaults;
41445dfecf96Smrg    sforms = alist->optionals.sforms;
41455dfecf96Smrg    if (builtin) {
41465dfecf96Smrg	if (eval) {
41475dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values))
41485dfecf96Smrg		BUILTIN_ARGUMENT(EVAL(CAR(values)));
41495dfecf96Smrg	    for (; i < count; i++)
41505dfecf96Smrg		BUILTIN_ARGUMENT(UNSPEC);
41515dfecf96Smrg	}
41525dfecf96Smrg	else {
41535dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values))
41545dfecf96Smrg		BUILTIN_ARGUMENT(CAR(values));
41555dfecf96Smrg	    for (; i < count; i++)
41565dfecf96Smrg		BUILTIN_ARGUMENT(UNSPEC);
41575dfecf96Smrg	}
41585dfecf96Smrg    }
41595dfecf96Smrg    else {
41605dfecf96Smrg	symbols = alist->optionals.symbols;
41615dfecf96Smrg	if (eval) {
41625dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
41635dfecf96Smrg		NORMAL_ARGUMENT(symbols[i], EVAL(CAR(values)));
41645dfecf96Smrg		if (sforms[i]) {
41655dfecf96Smrg		    NORMAL_ARGUMENT(sforms[i], T);
41665dfecf96Smrg		}
41675dfecf96Smrg	    }
41685dfecf96Smrg	}
41695dfecf96Smrg	else {
41705dfecf96Smrg	    for (; i < count && CONSP(values); i++, values = CDR(values)) {
41715dfecf96Smrg		NORMAL_ARGUMENT(symbols[i], CAR(values));
41725dfecf96Smrg		if (sforms[i]) {
41735dfecf96Smrg		    NORMAL_ARGUMENT(sforms[i], T);
41745dfecf96Smrg		}
41755dfecf96Smrg	    }
41765dfecf96Smrg	}
41775dfecf96Smrg
41785dfecf96Smrg	/* default arguments are evaluated for macros */
41795dfecf96Smrg	for (; i < count; i++) {
41805dfecf96Smrg	    if (!CONSTANTP(defaults[i])) {
41815dfecf96Smrg		int head = lisp__data.env.head;
41825dfecf96Smrg		int lex = lisp__data.env.lex;
41835dfecf96Smrg
41845dfecf96Smrg		lisp__data.env.lex = base;
41855dfecf96Smrg		lisp__data.env.head = lisp__data.env.length;
41865dfecf96Smrg		NORMAL_ARGUMENT(symbols[i], EVAL(defaults[i]));
41875dfecf96Smrg		lisp__data.env.head = head;
41885dfecf96Smrg		lisp__data.env.lex = lex;
41895dfecf96Smrg	    }
41905dfecf96Smrg	    else {
41915dfecf96Smrg		NORMAL_ARGUMENT(symbols[i], defaults[i]);
41925dfecf96Smrg	    }
41935dfecf96Smrg	    if (sforms[i]) {
41945dfecf96Smrg		NORMAL_ARGUMENT(sforms[i], NIL);
41955dfecf96Smrg	    }
41965dfecf96Smrg	}
41975dfecf96Smrg    }
41985dfecf96Smrg    switch (*desc++) {
41995dfecf96Smrg	case 'k':
42005dfecf96Smrg	    goto key_label;
42015dfecf96Smrg	case 'r':
42025dfecf96Smrg	    goto rest_label;
42035dfecf96Smrg	case 'a':
42045dfecf96Smrg	    goto aux_label;
42055dfecf96Smrg	default:
42065dfecf96Smrg	    goto done_label;
42075dfecf96Smrg    }
42085dfecf96Smrg
42095dfecf96Smrg    /* &KEY */
42105dfecf96Smrgkey_label:
42115dfecf96Smrg    {
42125dfecf96Smrg	int argc, nused;
42135dfecf96Smrg	LispObj *val, *karg, **keys;
42145dfecf96Smrg
42155dfecf96Smrg	/* Count number of remaining arguments */
42165dfecf96Smrg	for (karg = values, argc = 0; CONSP(karg); karg = CDR(karg), argc++) {
42175dfecf96Smrg	    karg = CDR(karg);
42185dfecf96Smrg	    if (!CONSP(karg))
42195dfecf96Smrg		LispDestroy("%s: &KEY needs arguments as pairs",
42205dfecf96Smrg			    STROBJ(name));
42215dfecf96Smrg	}
42225dfecf96Smrg
42235dfecf96Smrg
42245dfecf96Smrg	/* OPTIMIZATION:
42255dfecf96Smrg	 * Builtin functions require that the keyword be in the keyword package.
42265dfecf96Smrg	 * User functions don't need the arguments being pushed in the stack
42275dfecf96Smrg	 * in the declared order (bytecode expects it...).
42285dfecf96Smrg	 * XXX Error checking should be done elsewhere, code may be looping
42295dfecf96Smrg	 * and doing error check here may consume too much cpu time.
42305dfecf96Smrg	 * XXX Would also be good to already have the arguments specified in
42315dfecf96Smrg	 * the correct order.
42325dfecf96Smrg	 */
42335dfecf96Smrg
42345dfecf96Smrg
42355dfecf96Smrg	nused = 0;
42365dfecf96Smrg	val = NIL;
42375dfecf96Smrg	count = alist->keys.num_symbols;
42385dfecf96Smrg	symbols = alist->keys.symbols;
42395dfecf96Smrg	defaults = alist->keys.defaults;
42405dfecf96Smrg	sforms = alist->keys.sforms;
42415dfecf96Smrg	if (builtin) {
42425dfecf96Smrg
42435dfecf96Smrg	    /* Arguments must be created in the declared order */
42445dfecf96Smrg	    i = 0;
42455dfecf96Smrg	    if (eval) {
42465dfecf96Smrg		for (; i < count; i++) {
42475dfecf96Smrg		    for (karg = values; CONSP(karg); karg = CDDR(karg)) {
42485dfecf96Smrg			/* This is only true if both point to the
42495dfecf96Smrg			 * same symbol in the keyword package. */
42505dfecf96Smrg			if (symbols[i] == CAR(karg)) {
42515dfecf96Smrg			    if (karg == values)
42525dfecf96Smrg				values = CDDR(values);
42535dfecf96Smrg			    ++nused;
42545dfecf96Smrg			    BUILTIN_ARGUMENT(EVAL(CADR(karg)));
42555dfecf96Smrg			    goto keyword_builtin_eval_used_label;
42565dfecf96Smrg			}
42575dfecf96Smrg		    }
42585dfecf96Smrg		    BUILTIN_ARGUMENT(UNSPEC);
42595dfecf96Smrgkeyword_builtin_eval_used_label:;
42605dfecf96Smrg		}
42615dfecf96Smrg	    }
42625dfecf96Smrg	    else {
42635dfecf96Smrg		for (; i < count; i++) {
42645dfecf96Smrg		    for (karg = values; CONSP(karg); karg = CDDR(karg)) {
42655dfecf96Smrg			if (symbols[i] == CAR(karg)) {
42665dfecf96Smrg			    if (karg == values)
42675dfecf96Smrg				values = CDDR(values);
42685dfecf96Smrg			    ++nused;
42695dfecf96Smrg			    BUILTIN_ARGUMENT(CADR(karg));
42705dfecf96Smrg			    goto keyword_builtin_used_label;
42715dfecf96Smrg			}
42725dfecf96Smrg		    }
42735dfecf96Smrg		    BUILTIN_ARGUMENT(UNSPEC);
42745dfecf96Smrgkeyword_builtin_used_label:;
42755dfecf96Smrg		}
42765dfecf96Smrg	    }
42775dfecf96Smrg
42785dfecf96Smrg	    if (argc != nused) {
42795dfecf96Smrg		/* Argument(s) may be incorrectly specified, or specified
42805dfecf96Smrg		 * twice (what is not an error). */
42815dfecf96Smrg		for (karg = values; CONSP(karg); karg = CDDR(karg)) {
42825dfecf96Smrg		    val = CAR(karg);
42835dfecf96Smrg		    if (KEYWORDP(val)) {
42845dfecf96Smrg			for (i = 0; i < count; i++)
42855dfecf96Smrg			    if (symbols[i] == val)
42865dfecf96Smrg				break;
42875dfecf96Smrg		    }
42885dfecf96Smrg		    else
42895dfecf96Smrg			/* Just make the error test true */
42905dfecf96Smrg			i = count;
42915dfecf96Smrg
42925dfecf96Smrg		    if (i == count)
42935dfecf96Smrg			goto invalid_keyword_label;
42945dfecf96Smrg		}
42955dfecf96Smrg	    }
42965dfecf96Smrg	}
42975dfecf96Smrg
42985dfecf96Smrg#if 0
42995dfecf96Smrg	else {
43005dfecf96Smrg	    /* The base offset of the atom in the stack, to check for
43015dfecf96Smrg	     * keywords specified twice. */
43025dfecf96Smrg	    LispObj *symbol;
43035dfecf96Smrg	    int offset = lisp__data.env.length;
43045dfecf96Smrg
43055dfecf96Smrg	    keys = alist->keys.keys;
43065dfecf96Smrg	    for (karg = values; CONSP(karg); karg = CDDR(karg)) {
43075dfecf96Smrg		symbol = CAR(karg);
43085dfecf96Smrg		if (SYMBOLP(symbol)) {
43095dfecf96Smrg		    /* Must be a keyword, but even if it is a keyword, may
43105dfecf96Smrg		     * be a typo, so assume it is correct. If it is not
43115dfecf96Smrg		     * in the argument list, it is an error. */
43125dfecf96Smrg		    for (i = 0; i < count; i++) {
43135dfecf96Smrg			if (!keys[i] && symbols[i] == symbol) {
43145dfecf96Smrg			    LispAtom *atom = symbol->data.atom;
43155dfecf96Smrg
43165dfecf96Smrg			    /* Symbol found in the argument list. */
43175dfecf96Smrg			    if (atom->offset >= offset &&
43185dfecf96Smrg				atom->offset < offset + nused &&
43195dfecf96Smrg				lisp__data.env.names[atom->offset] ==
43205dfecf96Smrg				atom->string)
43215dfecf96Smrg				/* Specified more than once... */
43225dfecf96Smrg				goto keyword_duplicated_label;
43235dfecf96Smrg			    break;
43245dfecf96Smrg			}
43255dfecf96Smrg		    }
43265dfecf96Smrg		}
43275dfecf96Smrg		else {
43285dfecf96Smrg		    Atom_id id;
43295dfecf96Smrg
43305dfecf96Smrg		    if (!QUOTEP(symbol) || !SYMBOLP(val = symbol->data.quote)) {
43315dfecf96Smrg			/* Bad argument. */
43325dfecf96Smrg			val = symbol;
43335dfecf96Smrg			goto invalid_keyword_label;
43345dfecf96Smrg		    }
43355dfecf96Smrg
43365dfecf96Smrg		    id = ATOMID(val);
43375dfecf96Smrg		    for (i = 0; i < count; i++) {
43385dfecf96Smrg			if (keys[i] && ATOMID(keys[i]) == id) {
43395dfecf96Smrg			    LispAtom *atom = val->data.atom;
43405dfecf96Smrg
43415dfecf96Smrg			    /* Symbol found in the argument list. */
43425dfecf96Smrg			    if (atom->offset >= offset &&
43435dfecf96Smrg				atom->offset < offset + nused &&
43445dfecf96Smrg				lisp__data.env.names[atom->offset] ==
43455dfecf96Smrg				atom->string)
43465dfecf96Smrg				/* Specified more than once... */
43475dfecf96Smrg				goto keyword_duplicated_label;
43485dfecf96Smrg			    break;
43495dfecf96Smrg			}
43505dfecf96Smrg		    }
43515dfecf96Smrg		}
43525dfecf96Smrg		if (i == count) {
43535dfecf96Smrg		    /* Argument specification not found. */
43545dfecf96Smrg		    val = symbol;
43555dfecf96Smrg		    goto invalid_keyword_label;
43565dfecf96Smrg		}
43575dfecf96Smrg		++nused;
43585dfecf96Smrg		if (eval) {
43595dfecf96Smrg		    NORMAL_ARGUMENT(symbols[i], EVAL(CADR(karg)));
43605dfecf96Smrg		}
43615dfecf96Smrg		else {
43625dfecf96Smrg		    NORMAL_ARGUMENT(symbols[i], CADR(karg));
43635dfecf96Smrg		}
43645dfecf96Smrg		if (sforms[i]) {
43655dfecf96Smrg		    NORMAL_ARGUMENT(sforms[i], T);
43665dfecf96Smrg		}
43675dfecf96Smrgkeyword_duplicated_label:;
43685dfecf96Smrg	    }
43695dfecf96Smrg
43705dfecf96Smrg	    /* Add variables that were not specified in the function call. */
43715dfecf96Smrg	    if (nused < count) {
43725dfecf96Smrg		int j;
43735dfecf96Smrg
43745dfecf96Smrg		for (i = 0; i < count; i++) {
43755dfecf96Smrg		    Atom_id id = ATOMID(symbols[i]);
43765dfecf96Smrg
43775dfecf96Smrg		    for (j = offset + nused - 1; j >= offset; j--) {
43785dfecf96Smrg			if (lisp__data.env.names[j] == id)
43795dfecf96Smrg			    break;
43805dfecf96Smrg		    }
43815dfecf96Smrg
43825dfecf96Smrg		    if (j < offset) {
43835dfecf96Smrg			/* Argument not specified. Use default value */
43845dfecf96Smrg
43855dfecf96Smrg			/* default arguments are evaluated for macros */
43865dfecf96Smrg			if (!CONSTANTP(defaults[i])) {
43875dfecf96Smrg			    int head = lisp__data.env.head;
43885dfecf96Smrg			    int lex = lisp__data.env.lex;
43895dfecf96Smrg
43905dfecf96Smrg			    lisp__data.env.lex = base;
43915dfecf96Smrg			    lisp__data.env.head = lisp__data.env.length;
43925dfecf96Smrg			    NORMAL_ARGUMENT(symbols[i], EVAL(defaults[i]));
43935dfecf96Smrg			    lisp__data.env.head = head;
43945dfecf96Smrg			    lisp__data.env.lex = lex;
43955dfecf96Smrg			}
43965dfecf96Smrg			else {
43975dfecf96Smrg			    NORMAL_ARGUMENT(symbols[i], defaults[i]);
43985dfecf96Smrg			}
43995dfecf96Smrg			if (sforms[i]) {
44005dfecf96Smrg			    NORMAL_ARGUMENT(sforms[i], NIL);
44015dfecf96Smrg			}
44025dfecf96Smrg		    }
44035dfecf96Smrg		}
44045dfecf96Smrg	    }
44055dfecf96Smrg	}
44065dfecf96Smrg#else
44075dfecf96Smrg	else {
44085dfecf96Smrg	    int varset;
44095dfecf96Smrg
44105dfecf96Smrg	    sforms = alist->keys.sforms;
44115dfecf96Smrg	    keys = alist->keys.keys;
44125dfecf96Smrg
44135dfecf96Smrg	    /* Add variables */
44145dfecf96Smrg	    for (i = 0; i < alist->keys.num_symbols; i++) {
44155dfecf96Smrg		val = defaults[i];
44165dfecf96Smrg		varset = 0;
44175dfecf96Smrg		if (keys[i]) {
44185dfecf96Smrg		    Atom_id atom = ATOMID(keys[i]);
44195dfecf96Smrg
44205dfecf96Smrg		    /* Special keyword specification, need to compare ATOMID
44215dfecf96Smrg		     * and keyword specification must be a quoted object */
44225dfecf96Smrg		    for (karg = values; CONSP(karg); karg = CDR(karg)) {
44235dfecf96Smrg			val = CAR(karg);
44245dfecf96Smrg		 	if (QUOTEP(val) && atom == ATOMID(val->data.quote)) {
44255dfecf96Smrg			    val = CADR(karg);
44265dfecf96Smrg			    varset = 1;
44275dfecf96Smrg			    ++nused;
44285dfecf96Smrg			    break;
44295dfecf96Smrg			}
44305dfecf96Smrg			karg = CDR(karg);
44315dfecf96Smrg		    }
44325dfecf96Smrg		}
44335dfecf96Smrg
44345dfecf96Smrg		else {
44355dfecf96Smrg		    /* Normal keyword specification, can compare object pointers,
44365dfecf96Smrg		     * as they point to the same object in the keyword package */
44375dfecf96Smrg		    for (karg = values; CONSP(karg); karg = CDR(karg)) {
44385dfecf96Smrg			/* Don't check if argument is a valid keyword or
44395dfecf96Smrg			 * special quoted keyword */
44405dfecf96Smrg			if (symbols[i] == CAR(karg)) {
44415dfecf96Smrg			    val = CADR(karg);
44425dfecf96Smrg			    varset = 1;
44435dfecf96Smrg			    ++nused;
44445dfecf96Smrg			    break;
44455dfecf96Smrg			}
44465dfecf96Smrg			karg = CDR(karg);
44475dfecf96Smrg		    }
44485dfecf96Smrg		}
44495dfecf96Smrg
44505dfecf96Smrg		/* Add the variable to environment */
44515dfecf96Smrg		if (varset) {
44525dfecf96Smrg		    NORMAL_ARGUMENT(symbols[i], eval ? EVAL(val) : val);
44535dfecf96Smrg		    if (sforms[i]) {
44545dfecf96Smrg			NORMAL_ARGUMENT(sforms[i], T);
44555dfecf96Smrg		    }
44565dfecf96Smrg		}
44575dfecf96Smrg		else {
44585dfecf96Smrg		    /* default arguments are evaluated for macros */
44595dfecf96Smrg		    if (!CONSTANTP(val)) {
44605dfecf96Smrg			int head = lisp__data.env.head;
44615dfecf96Smrg			int lex = lisp__data.env.lex;
44625dfecf96Smrg
44635dfecf96Smrg			lisp__data.env.lex = base;
44645dfecf96Smrg			lisp__data.env.head = lisp__data.env.length;
44655dfecf96Smrg			NORMAL_ARGUMENT(symbols[i], EVAL(val));
44665dfecf96Smrg			lisp__data.env.head = head;
44675dfecf96Smrg			lisp__data.env.lex = lex;
44685dfecf96Smrg		    }
44695dfecf96Smrg		    else {
44705dfecf96Smrg			NORMAL_ARGUMENT(symbols[i], val);
44715dfecf96Smrg		    }
44725dfecf96Smrg		    if (sforms[i]) {
44735dfecf96Smrg			NORMAL_ARGUMENT(sforms[i], NIL);
44745dfecf96Smrg		    }
44755dfecf96Smrg		}
44765dfecf96Smrg	    }
44775dfecf96Smrg
44785dfecf96Smrg	    if (argc != nused) {
44795dfecf96Smrg		/* Argument(s) may be incorrectly specified, or specified
44805dfecf96Smrg		 * twice (what is not an error). */
44815dfecf96Smrg		for (karg = values; CONSP(karg); karg = CDDR(karg)) {
44825dfecf96Smrg		    val = CAR(karg);
44835dfecf96Smrg		    if (KEYWORDP(val)) {
44845dfecf96Smrg			for (i = 0; i < count; i++)
44855dfecf96Smrg			    if (symbols[i] == val)
44865dfecf96Smrg				break;
44875dfecf96Smrg		    }
44885dfecf96Smrg		    else if (QUOTEP(val) && SYMBOLP(val->data.quote)) {
44895dfecf96Smrg			Atom_id atom = ATOMID(val->data.quote);
44905dfecf96Smrg
44915dfecf96Smrg			for (i = 0; i < count; i++)
44925dfecf96Smrg			    if (ATOMID(keys[i]) == atom)
44935dfecf96Smrg				break;
44945dfecf96Smrg		    }
44955dfecf96Smrg		    else
44965dfecf96Smrg			/* Just make the error test true */
44975dfecf96Smrg			i = count;
44985dfecf96Smrg
44995dfecf96Smrg		    if (i == count)
45005dfecf96Smrg			goto invalid_keyword_label;
45015dfecf96Smrg		}
45025dfecf96Smrg	    }
45035dfecf96Smrg	}
45045dfecf96Smrg#endif
45055dfecf96Smrg	goto check_aux_label;
45065dfecf96Smrg
45075dfecf96Smrginvalid_keyword_label:
45085dfecf96Smrg	{
45095dfecf96Smrg	    /* If not in argument specification list... */
45105dfecf96Smrg	    char function_name[36];
45115dfecf96Smrg
45125dfecf96Smrg	    strcpy(function_name, STROBJ(name));
45135dfecf96Smrg	    LispDestroy("%s: %s is an invalid keyword",
45145dfecf96Smrg			function_name, STROBJ(val));
45155dfecf96Smrg	}
45165dfecf96Smrg    }
45175dfecf96Smrg
45185dfecf96Smrgcheck_aux_label:
45195dfecf96Smrg    if (*desc == 'a') {
45205dfecf96Smrg	/* &KEY uses all remaining arguments */
45215dfecf96Smrg	values = NIL;
45225dfecf96Smrg	goto aux_label;
45235dfecf96Smrg    }
45245dfecf96Smrg    goto finished_label;
45255dfecf96Smrg
45265dfecf96Smrg    /* &REST */
45275dfecf96Smrgrest_label:
45285dfecf96Smrg    if (!CONSP(values)) {
45295dfecf96Smrg	if (builtin) {
45305dfecf96Smrg	    BUILTIN_ARGUMENT(values);
45315dfecf96Smrg	}
45325dfecf96Smrg	else {
45335dfecf96Smrg	    NORMAL_ARGUMENT(alist->rest, values);
45345dfecf96Smrg	}
45355dfecf96Smrg	values = NIL;
45365dfecf96Smrg    }
45375dfecf96Smrg    /* always allocate a new list, don't know if it will be retained */
45385dfecf96Smrg    else if (eval) {
45395dfecf96Smrg	LispObj *cons;
45405dfecf96Smrg
45415dfecf96Smrg	cons = CONS(EVAL(CAR(values)), NIL);
45425dfecf96Smrg	if (builtin) {
45435dfecf96Smrg	    BUILTIN_ARGUMENT(cons);
45445dfecf96Smrg	}
45455dfecf96Smrg	else {
45465dfecf96Smrg	    NORMAL_ARGUMENT(alist->rest, cons);
45475dfecf96Smrg	}
45485dfecf96Smrg	values = CDR(values);
45495dfecf96Smrg	for (; CONSP(values); values = CDR(values)) {
45505dfecf96Smrg	    RPLACD(cons, CONS(EVAL(CAR(values)), NIL));
45515dfecf96Smrg	    cons = CDR(cons);
45525dfecf96Smrg	}
45535dfecf96Smrg    }
45545dfecf96Smrg    else {
45555dfecf96Smrg	LispObj *cons;
45565dfecf96Smrg
45575dfecf96Smrg	cons = CONS(CAR(values), NIL);
45585dfecf96Smrg	if (builtin) {
45595dfecf96Smrg	    BUILTIN_ARGUMENT(cons);
45605dfecf96Smrg	}
45615dfecf96Smrg	else {
45625dfecf96Smrg	    NORMAL_ARGUMENT(alist->rest, cons);
45635dfecf96Smrg	}
45645dfecf96Smrg	values = CDR(values);
45655dfecf96Smrg	for (; CONSP(values); values = CDR(values)) {
45665dfecf96Smrg	    RPLACD(cons, CONS(CAR(values), NIL));
45675dfecf96Smrg	    cons = CDR(cons);
45685dfecf96Smrg	}
45695dfecf96Smrg    }
45705dfecf96Smrg    if (*desc != 'a')
45715dfecf96Smrg	goto finished_label;
45725dfecf96Smrg
45735dfecf96Smrg    /* &AUX */
45745dfecf96Smrgaux_label:
45755dfecf96Smrg    i = 0;
45765dfecf96Smrg    count = alist->auxs.num_symbols;
45775dfecf96Smrg    defaults = alist->auxs.initials;
45785dfecf96Smrg    symbols = alist->auxs.symbols;
45795dfecf96Smrg    {
45805dfecf96Smrg	int lex = lisp__data.env.lex;
45815dfecf96Smrg
45825dfecf96Smrg	lisp__data.env.lex = base;
45835dfecf96Smrg	lisp__data.env.head = lisp__data.env.length;
45845dfecf96Smrg	for (; i < count; i++) {
45855dfecf96Smrg	    NORMAL_ARGUMENT(symbols[i], EVAL(defaults[i]));
45865dfecf96Smrg	    ++lisp__data.env.head;
45875dfecf96Smrg	}
45885dfecf96Smrg	lisp__data.env.lex = lex;
45895dfecf96Smrg    }
45905dfecf96Smrg
45915dfecf96Smrgdone_label:
45925dfecf96Smrg    if (CONSP(values))
45935dfecf96Smrg	LispDestroy("%s: too many arguments", STROBJ(name));
45945dfecf96Smrg
45955dfecf96Smrgfinished_label:
45965dfecf96Smrg    if (builtin)
45975dfecf96Smrg	lisp__data.stack.base = base;
45985dfecf96Smrg    else {
45995dfecf96Smrg	lisp__data.env.head = lisp__data.env.length;
46005dfecf96Smrg    }
46015dfecf96Smrg#undef BULTIN_ARGUMENT
46025dfecf96Smrg#undef NORMAL_ARGUMENT
46035dfecf96Smrg#undef BUILTIN_NO_EVAL_ARGUMENT
46045dfecf96Smrg
46055dfecf96Smrg    return (base);
46065dfecf96Smrg}
46075dfecf96Smrg
46085dfecf96SmrgLispObj *
46095dfecf96SmrgLispFuncall(LispObj *function, LispObj *arguments, int eval)
46105dfecf96Smrg{
46115dfecf96Smrg    LispAtom *atom;
46125dfecf96Smrg    LispArgList *alist;
46135dfecf96Smrg    LispBuiltin *builtin;
46145dfecf96Smrg    LispObj *lambda, *result;
46155dfecf96Smrg    int macro, base;
46165dfecf96Smrg
46175dfecf96Smrg#ifdef DEBUGGER
46185dfecf96Smrg    if (lisp__data.debugging)
46195dfecf96Smrg	LispDebugger(LispDebugCallBegin, function, arguments);
46205dfecf96Smrg#endif
46215dfecf96Smrg
46225dfecf96Smrg    switch (OBJECT_TYPE(function)) {
46235dfecf96Smrg	case LispFunction_t:
46245dfecf96Smrg	    function = function->data.atom->object;
46255dfecf96Smrg	case LispAtom_t:
46265dfecf96Smrg	    atom = function->data.atom;
46275dfecf96Smrg	    if (atom->a_builtin) {
46285dfecf96Smrg		builtin = atom->property->fun.builtin;
46295dfecf96Smrg
46305dfecf96Smrg		if (eval)
46315dfecf96Smrg		    eval = builtin->type != LispMacro;
46325dfecf96Smrg		base = LispMakeEnvironment(atom->property->alist,
46335dfecf96Smrg					   arguments, function, eval, 1);
46345dfecf96Smrg		if (builtin->multiple_values) {
46355dfecf96Smrg		    RETURN_COUNT = 0;
46365dfecf96Smrg		    result = builtin->function(builtin);
46375dfecf96Smrg		}
46385dfecf96Smrg		else {
46395dfecf96Smrg		    result = builtin->function(builtin);
46405dfecf96Smrg		    RETURN_COUNT = 0;
46415dfecf96Smrg		}
46425dfecf96Smrg		lisp__data.stack.base = lisp__data.stack.length = base;
46435dfecf96Smrg	    }
46445dfecf96Smrg	    else if (atom->a_compiled) {
46455dfecf96Smrg		int lex = lisp__data.env.lex;
46465dfecf96Smrg		lambda = atom->property->fun.function;
46475dfecf96Smrg		alist = atom->property->alist;
46485dfecf96Smrg
46495dfecf96Smrg		base = LispMakeEnvironment(alist, arguments, function, eval, 0);
46505dfecf96Smrg		lisp__data.env.lex = base;
46515dfecf96Smrg		result = LispExecuteBytecode(lambda);
46525dfecf96Smrg		lisp__data.env.lex = lex;
46535dfecf96Smrg		lisp__data.env.head = lisp__data.env.length = base;
46545dfecf96Smrg	    }
46555dfecf96Smrg	    else if (atom->a_function) {
46565dfecf96Smrg		lambda = atom->property->fun.function;
46575dfecf96Smrg		macro = lambda->funtype == LispMacro;
46585dfecf96Smrg		alist = atom->property->alist;
46595dfecf96Smrg
46605dfecf96Smrg		lambda = lambda->data.lambda.code;
46615dfecf96Smrg		if (eval)
46625dfecf96Smrg		    eval = !macro;
46635dfecf96Smrg		base = LispMakeEnvironment(alist, arguments, function, eval, 0);
46645dfecf96Smrg		result = LispRunFunMac(function, lambda, macro, base);
46655dfecf96Smrg	    }
46665dfecf96Smrg	    else if (atom->a_defstruct &&
46675dfecf96Smrg		     atom->property->structure.function != STRUCT_NAME) {
46685dfecf96Smrg		LispObj cons;
46695dfecf96Smrg
46705dfecf96Smrg		if (atom->property->structure.function == STRUCT_CONSTRUCTOR)
46715dfecf96Smrg		    atom = Omake_struct->data.atom;
46725dfecf96Smrg		else if (atom->property->structure.function == STRUCT_CHECK)
46735dfecf96Smrg		    atom = Ostruct_type->data.atom;
46745dfecf96Smrg		else
46755dfecf96Smrg		    atom = Ostruct_access->data.atom;
46765dfecf96Smrg		builtin = atom->property->fun.builtin;
46775dfecf96Smrg
46785dfecf96Smrg		cons.type = LispCons_t;
46795dfecf96Smrg		cons.data.cons.cdr = arguments;
46805dfecf96Smrg		if (eval) {
46815dfecf96Smrg		    LispObj quote;
46825dfecf96Smrg
46835dfecf96Smrg		    quote.type = LispQuote_t;
46845dfecf96Smrg		    quote.data.quote = function;
46855dfecf96Smrg		    cons.data.cons.car = &quote;
46865dfecf96Smrg		    base = LispMakeEnvironment(atom->property->alist,
46875dfecf96Smrg					       &cons, function, 1, 1);
46885dfecf96Smrg		}
46895dfecf96Smrg		else {
46905dfecf96Smrg		    cons.data.cons.car = function;
46915dfecf96Smrg		    base = LispMakeEnvironment(atom->property->alist,
46925dfecf96Smrg					       &cons, function, 0, 1);
46935dfecf96Smrg		}
46945dfecf96Smrg		result = builtin->function(builtin);
46955dfecf96Smrg		RETURN_COUNT = 0;
46965dfecf96Smrg		lisp__data.stack.length = base;
46975dfecf96Smrg	    }
46985dfecf96Smrg	    else {
46995dfecf96Smrg		LispDestroy("EVAL: the function %s is not defined",
47005dfecf96Smrg			    STROBJ(function));
47015dfecf96Smrg		/*NOTREACHED*/
47025dfecf96Smrg		result = NIL;
47035dfecf96Smrg	    }
47045dfecf96Smrg	    break;
47055dfecf96Smrg	case LispLambda_t:
47065dfecf96Smrg	    lambda = function->data.lambda.code;
47075dfecf96Smrg	    alist = (LispArgList*)function->data.lambda.name->data.opaque.data;
47085dfecf96Smrg	    base = LispMakeEnvironment(alist, arguments, function, eval, 0);
47095dfecf96Smrg	    result = LispRunFunMac(function, lambda, 0, base);
47105dfecf96Smrg	    break;
47115dfecf96Smrg	case LispCons_t:
47125dfecf96Smrg	    if (CAR(function) == Olambda) {
47135dfecf96Smrg		function = EVAL(function);
47145dfecf96Smrg		if (LAMBDAP(function)) {
47155dfecf96Smrg		    GC_ENTER();
47165dfecf96Smrg
47175dfecf96Smrg		    GC_PROTECT(function);
47185dfecf96Smrg		    lambda = function->data.lambda.code;
47195dfecf96Smrg		    alist = (LispArgList*)function->data.lambda.name->data.opaque.data;
47205dfecf96Smrg		    base = LispMakeEnvironment(alist, arguments, NIL, eval, 0);
47215dfecf96Smrg		    result = LispRunFunMac(NIL, lambda, 0, base);
47225dfecf96Smrg		    GC_LEAVE();
47235dfecf96Smrg		    break;
47245dfecf96Smrg		}
47255dfecf96Smrg	    }
47265dfecf96Smrg	default:
47275dfecf96Smrg	    LispDestroy("EVAL: %s is invalid as a function",
47285dfecf96Smrg			STROBJ(function));
47295dfecf96Smrg	    /*NOTREACHED*/
47305dfecf96Smrg	    result = NIL;
47315dfecf96Smrg	    break;
47325dfecf96Smrg    }
47335dfecf96Smrg
47345dfecf96Smrg#ifdef DEBUGGER
47355dfecf96Smrg    if (lisp__data.debugging)
47365dfecf96Smrg	LispDebugger(LispDebugCallEnd, function, result);
47375dfecf96Smrg#endif
47385dfecf96Smrg
47395dfecf96Smrg    return (result);
47405dfecf96Smrg}
47415dfecf96Smrg
47425dfecf96SmrgLispObj *
47435dfecf96SmrgLispEval(LispObj *object)
47445dfecf96Smrg{
47455dfecf96Smrg    LispObj *result;
47465dfecf96Smrg
47475dfecf96Smrg    switch (OBJECT_TYPE(object)) {
47485dfecf96Smrg	case LispAtom_t:
47495dfecf96Smrg	    if ((result = LispDoGetVar(object)) == NULL)
47505dfecf96Smrg		LispDestroy("EVAL: the variable %s is unbound", STROBJ(object));
47515dfecf96Smrg	    break;
47525dfecf96Smrg	case LispCons_t:
47535dfecf96Smrg	    result = LispFuncall(CAR(object), CDR(object), 1);
47545dfecf96Smrg	    break;
47555dfecf96Smrg	case LispQuote_t:
47565dfecf96Smrg	    result = object->data.quote;
47575dfecf96Smrg	    break;
47585dfecf96Smrg	case LispFunctionQuote_t:
47595dfecf96Smrg	    result = object->data.quote;
47605dfecf96Smrg	    if (SYMBOLP(result))
47615dfecf96Smrg		result = LispSymbolFunction(result);
47625dfecf96Smrg	    else if (CONSP(result) && CAR(result) == Olambda)
47635dfecf96Smrg		result = EVAL(result);
47645dfecf96Smrg	    else
47655dfecf96Smrg		LispDestroy("FUNCTION: %s is not a function", STROBJ(result));
47665dfecf96Smrg	    break;
47675dfecf96Smrg	case LispBackquote_t:
47685dfecf96Smrg	    result = LispEvalBackquote(object->data.quote, 1);
47695dfecf96Smrg	    break;
47705dfecf96Smrg	case LispComma_t:
47715dfecf96Smrg	    LispDestroy("EVAL: comma outside of backquote");
47725dfecf96Smrg	default:
47735dfecf96Smrg	    result = object;
47745dfecf96Smrg	    break;
47755dfecf96Smrg    }
47765dfecf96Smrg
47775dfecf96Smrg    return (result);
47785dfecf96Smrg}
47795dfecf96Smrg
47805dfecf96SmrgLispObj *
47815dfecf96SmrgLispApply1(LispObj *function, LispObj *argument)
47825dfecf96Smrg{
47835dfecf96Smrg    LispObj arguments;
47845dfecf96Smrg
47855dfecf96Smrg    arguments.type = LispCons_t;
47865dfecf96Smrg    arguments.data.cons.car = argument;
47875dfecf96Smrg    arguments.data.cons.cdr = NIL;
47885dfecf96Smrg
47895dfecf96Smrg    return (LispFuncall(function, &arguments, 0));
47905dfecf96Smrg}
47915dfecf96Smrg
47925dfecf96SmrgLispObj *
47935dfecf96SmrgLispApply2(LispObj *function, LispObj *argument1, LispObj *argument2)
47945dfecf96Smrg{
47955dfecf96Smrg    LispObj arguments, cdr;
47965dfecf96Smrg
47975dfecf96Smrg    arguments.type = cdr.type = LispCons_t;
47985dfecf96Smrg    arguments.data.cons.car = argument1;
47995dfecf96Smrg    arguments.data.cons.cdr = &cdr;
48005dfecf96Smrg    cdr.data.cons.car = argument2;
48015dfecf96Smrg    cdr.data.cons.cdr = NIL;
48025dfecf96Smrg
48035dfecf96Smrg    return (LispFuncall(function, &arguments, 0));
48045dfecf96Smrg}
48055dfecf96Smrg
48065dfecf96SmrgLispObj *
48075dfecf96SmrgLispApply3(LispObj *function, LispObj *arg1, LispObj *arg2, LispObj *arg3)
48085dfecf96Smrg{
48095dfecf96Smrg    LispObj arguments, car, cdr;
48105dfecf96Smrg
48115dfecf96Smrg    arguments.type = car.type = cdr.type = LispCons_t;
48125dfecf96Smrg    arguments.data.cons.car = arg1;
48135dfecf96Smrg    arguments.data.cons.cdr = &car;
48145dfecf96Smrg    car.data.cons.car = arg2;
48155dfecf96Smrg    car.data.cons.cdr = &cdr;
48165dfecf96Smrg    cdr.data.cons.car = arg3;
48175dfecf96Smrg    cdr.data.cons.cdr = NIL;
48185dfecf96Smrg
48195dfecf96Smrg    return (LispFuncall(function, &arguments, 0));
48205dfecf96Smrg}
48215dfecf96Smrg
48225dfecf96Smrgstatic LispObj *
48235dfecf96SmrgLispRunFunMac(LispObj *name, LispObj *code, int macro, int base)
48245dfecf96Smrg{
48255dfecf96Smrg    LispObj *result = NIL;
48265dfecf96Smrg
48275dfecf96Smrg    if (!macro) {
48285dfecf96Smrg	int lex = lisp__data.env.lex;
48295dfecf96Smrg	int did_jump = 1;
48305dfecf96Smrg	LispBlock *block;
48315dfecf96Smrg
48325dfecf96Smrg	block = LispBeginBlock(name, LispBlockClosure);
48335dfecf96Smrg	lisp__data.env.lex = base;
48345dfecf96Smrg	if (setjmp(block->jmp) == 0) {
48355dfecf96Smrg	    for (; CONSP(code); code = CDR(code))
48365dfecf96Smrg		result = EVAL(CAR(code));
48375dfecf96Smrg	    did_jump = 0;
48385dfecf96Smrg	}
48395dfecf96Smrg	LispEndBlock(block);
48405dfecf96Smrg	if (did_jump)
48415dfecf96Smrg	    result = lisp__data.block.block_ret;
48425dfecf96Smrg	lisp__data.env.lex = lex;
48435dfecf96Smrg	lisp__data.env.head = lisp__data.env.length = base;
48445dfecf96Smrg    }
48455dfecf96Smrg    else {
48465dfecf96Smrg	GC_ENTER();
48475dfecf96Smrg
48485dfecf96Smrg	for (; CONSP(code); code = CDR(code))
48495dfecf96Smrg	    result = EVAL(CAR(code));
48505dfecf96Smrg	/* FIXME this does not work if macro has &aux variables,
48515dfecf96Smrg	 * but there are several other missing features, like
48525dfecf96Smrg	 * destructuring and more lambda list keywords still missing.
48535dfecf96Smrg	 * TODO later.
48545dfecf96Smrg	 */
48555dfecf96Smrg	lisp__data.env.head = lisp__data.env.length = base;
48565dfecf96Smrg
48575dfecf96Smrg	GC_PROTECT(result);
48585dfecf96Smrg	result = EVAL(result);
48595dfecf96Smrg	GC_LEAVE();
48605dfecf96Smrg    }
48615dfecf96Smrg
48625dfecf96Smrg    return (result);
48635dfecf96Smrg}
48645dfecf96Smrg
48655dfecf96SmrgLispObj *
48665dfecf96SmrgLispRunSetf(LispArgList *alist, LispObj *setf, LispObj *place, LispObj *value)
48675dfecf96Smrg{
48685dfecf96Smrg    GC_ENTER();
48695dfecf96Smrg    LispObj *store, *code, *expression, *result, quote;
48705dfecf96Smrg    int base;
48715dfecf96Smrg
48725dfecf96Smrg    code = setf->data.lambda.code;
48735dfecf96Smrg    store = setf->data.lambda.data;
48745dfecf96Smrg
48755dfecf96Smrg    quote.type = LispQuote_t;
48765dfecf96Smrg    quote.data.quote = value;
48775dfecf96Smrg    LispDoAddVar(CAR(store), &quote);
48785dfecf96Smrg    ++lisp__data.env.head;
48795dfecf96Smrg    base = LispMakeEnvironment(alist, place, Oexpand_setf_method, 0, 0);
48805dfecf96Smrg
48815dfecf96Smrg    /* build expansion macro */
48825dfecf96Smrg    expression = NIL;
48835dfecf96Smrg    for (; CONSP(code); code = CDR(code))
48845dfecf96Smrg	expression = EVAL(CAR(code));
48855dfecf96Smrg
48865dfecf96Smrg    /* Minus 1 to pop the added variable */
48875dfecf96Smrg    lisp__data.env.head = lisp__data.env.length = base - 1;
48885dfecf96Smrg
48895dfecf96Smrg    /* protect expansion, and executes it */
48905dfecf96Smrg    GC_PROTECT(expression);
48915dfecf96Smrg    result = EVAL(expression);
48925dfecf96Smrg    GC_LEAVE();
48935dfecf96Smrg
48945dfecf96Smrg    return (result);
48955dfecf96Smrg}
48965dfecf96Smrg
48975dfecf96SmrgLispObj *
48985dfecf96SmrgLispRunSetfMacro(LispAtom *atom, LispObj *arguments, LispObj *value)
48995dfecf96Smrg{
49005dfecf96Smrg    int base;
49015dfecf96Smrg    GC_ENTER();
49025dfecf96Smrg    LispObj *place, *body, *result, quote;
49035dfecf96Smrg
49045dfecf96Smrg    place = NIL;
49055dfecf96Smrg    base = LispMakeEnvironment(atom->property->alist,
49065dfecf96Smrg			       arguments, atom->object, 0, 0);
49075dfecf96Smrg    body = atom->property->fun.function->data.lambda.code;
49085dfecf96Smrg
49095dfecf96Smrg    /* expand macro body */
49105dfecf96Smrg    for (; CONSP(body); body = CDR(body))
49115dfecf96Smrg	place = EVAL(CAR(body));
49125dfecf96Smrg
49135dfecf96Smrg    /* protect expansion */
49145dfecf96Smrg    GC_PROTECT(place);
49155dfecf96Smrg
49165dfecf96Smrg    /* restore environment */
49175dfecf96Smrg    lisp__data.env.head = lisp__data.env.length = base;
49185dfecf96Smrg
49195dfecf96Smrg    /* value is already evaluated */
49205dfecf96Smrg    quote.type = LispQuote_t;
49215dfecf96Smrg    quote.data.quote = value;
49225dfecf96Smrg
49235dfecf96Smrg    /* call setf again */
49245dfecf96Smrg    result = APPLY2(Osetf, place, &quote);
49255dfecf96Smrg
49265dfecf96Smrg    GC_LEAVE();
49275dfecf96Smrg
49285dfecf96Smrg    return (result);
49295dfecf96Smrg}
49305dfecf96Smrg
49315dfecf96Smrgchar *
49325dfecf96SmrgLispStrObj(LispObj *object)
49335dfecf96Smrg{
49345dfecf96Smrg    static int first = 1;
49355dfecf96Smrg    static char buffer[34];
49365dfecf96Smrg    static LispObj stream;
49375dfecf96Smrg    static LispString string;
49385dfecf96Smrg
49395dfecf96Smrg    if (first) {
49405dfecf96Smrg	stream.type = LispStream_t;
49415dfecf96Smrg	stream.data.stream.source.string = &string;
49425dfecf96Smrg	stream.data.stream.pathname = NIL;
49435dfecf96Smrg	stream.data.stream.type = LispStreamString;
49445dfecf96Smrg	stream.data.stream.readable = 0;
49455dfecf96Smrg	stream.data.stream.writable = 1;
49465dfecf96Smrg
49475dfecf96Smrg	string.string = buffer;
49485dfecf96Smrg	string.fixed = 1;
49495dfecf96Smrg	string.space = sizeof(buffer) - 1;
49505dfecf96Smrg	first = 0;
49515dfecf96Smrg    }
49525dfecf96Smrg
49535dfecf96Smrg    string.length = string.output = 0;
49545dfecf96Smrg
49555dfecf96Smrg    LispWriteObject(&stream, object);
49565dfecf96Smrg
49575dfecf96Smrg    /* make sure string is nul terminated */
49585dfecf96Smrg    string.string[string.length] = '\0';
49595dfecf96Smrg    if (string.length >= 32) {
49605dfecf96Smrg	if (buffer[0] == '(')
49615dfecf96Smrg	    strcpy(buffer + 27, "...)");
49625dfecf96Smrg	else
49635dfecf96Smrg	    strcpy(buffer + 28, "...");
49645dfecf96Smrg    }
49655dfecf96Smrg
49665dfecf96Smrg    return (buffer);
49675dfecf96Smrg}
49685dfecf96Smrg
49695dfecf96Smrgvoid
49705dfecf96SmrgLispPrint(LispObj *object, LispObj *stream, int newline)
49715dfecf96Smrg{
49725dfecf96Smrg    if (stream != NIL && !STREAMP(stream)) {
49735dfecf96Smrg	LispDestroy("PRINT: %s is not a stream", STROBJ(stream));
49745dfecf96Smrg    }
49755dfecf96Smrg    if (newline && LispGetColumn(stream))
49765dfecf96Smrg	LispWriteChar(stream, '\n');
49775dfecf96Smrg    LispWriteObject(stream, object);
49785dfecf96Smrg    if (stream == NIL || (stream->data.stream.type == LispStreamStandard &&
49795dfecf96Smrg	stream->data.stream.source.file == Stdout))
49805dfecf96Smrg	LispFflush(Stdout);
49815dfecf96Smrg}
49825dfecf96Smrg
49835dfecf96Smrgvoid
49845dfecf96SmrgLispUpdateResults(LispObj *cod, LispObj *res)
49855dfecf96Smrg{
49865dfecf96Smrg    LispSetVar(RUN[2], LispGetVar(RUN[1]));
49875dfecf96Smrg    LispSetVar(RUN[1], LispGetVar(RUN[0]));
49885dfecf96Smrg    LispSetVar(RUN[0], cod);
49895dfecf96Smrg
49905dfecf96Smrg    LispSetVar(RES[2], LispGetVar(RES[1]));
49915dfecf96Smrg    LispSetVar(RES[1], LispGetVar(RES[0]));
49925dfecf96Smrg    LispSetVar(RES[0], res);
49935dfecf96Smrg}
49945dfecf96Smrg
49955dfecf96Smrgvoid
49965dfecf96SmrgLispSignalHandler(int signum)
49975dfecf96Smrg{
49985dfecf96Smrg    LispSignal(signum);
49995dfecf96Smrg}
50005dfecf96Smrg
50015dfecf96Smrgvoid
50025dfecf96SmrgLispSignal(int signum)
50035dfecf96Smrg{
5004f765521fSmrg    const char *errstr;
50055dfecf96Smrg    char buffer[32];
50065dfecf96Smrg
50075dfecf96Smrg    if (lisp__disable_int) {
50085dfecf96Smrg	lisp__interrupted = signum;
50095dfecf96Smrg	return;
50105dfecf96Smrg    }
50115dfecf96Smrg    switch (signum) {
50125dfecf96Smrg	case SIGINT:
50135dfecf96Smrg	    errstr = "interrupted";
50145dfecf96Smrg	    break;
50155dfecf96Smrg	case SIGFPE:
50165dfecf96Smrg	    errstr = "floating point exception";
50175dfecf96Smrg	    break;
50185dfecf96Smrg	default:
50195dfecf96Smrg	    sprintf(buffer, "signal %d received", signum);
50205dfecf96Smrg	    errstr = buffer;
50215dfecf96Smrg	    break;
50225dfecf96Smrg    }
502331de2854Smrg    LispDestroy("%s", errstr);
50245dfecf96Smrg}
50255dfecf96Smrg
50265dfecf96Smrgvoid
50275dfecf96SmrgLispDisableInterrupts(void)
50285dfecf96Smrg{
50295dfecf96Smrg    ++lisp__disable_int;
50305dfecf96Smrg}
50315dfecf96Smrg
50325dfecf96Smrgvoid
50335dfecf96SmrgLispEnableInterrupts(void)
50345dfecf96Smrg{
50355dfecf96Smrg    --lisp__disable_int;
50365dfecf96Smrg    if (lisp__disable_int <= 0 && lisp__interrupted)
50375dfecf96Smrg	LispSignal(lisp__interrupted);
50385dfecf96Smrg}
50395dfecf96Smrg
50405dfecf96Smrgvoid
50415dfecf96SmrgLispMachine(void)
50425dfecf96Smrg{
50435dfecf96Smrg    LispObj *cod, *obj;
50445dfecf96Smrg
50455dfecf96Smrg    lisp__data.sigint = signal(SIGINT, LispSignalHandler);
50465dfecf96Smrg    lisp__data.sigfpe = signal(SIGFPE, LispSignalHandler);
50475dfecf96Smrg
50485dfecf96Smrg    /*CONSTCOND*/
50495dfecf96Smrg    while (1) {
50505dfecf96Smrg	if (sigsetjmp(lisp__data.jmp, 1) == 0) {
50515dfecf96Smrg	    lisp__data.running = 1;
50525dfecf96Smrg	    if (lisp__data.interactive && lisp__data.prompt) {
50535dfecf96Smrg		LispFputs(Stdout, lisp__data.prompt);
50545dfecf96Smrg		LispFflush(Stdout);
50555dfecf96Smrg	    }
50565dfecf96Smrg	    if ((cod = LispRead()) != NULL) {
50575dfecf96Smrg		obj = EVAL(cod);
50585dfecf96Smrg		if (lisp__data.interactive) {
50595dfecf96Smrg		    if (RETURN_COUNT >= 0)
50605dfecf96Smrg			LispPrint(obj, NIL, 1);
50615dfecf96Smrg		    if (RETURN_COUNT > 0) {
50625dfecf96Smrg			int i;
50635dfecf96Smrg
50645dfecf96Smrg			for (i = 0; i < RETURN_COUNT; i++)
50655dfecf96Smrg			    LispPrint(RETURN(i), NIL, 1);
50665dfecf96Smrg		    }
50675dfecf96Smrg		    LispUpdateResults(cod, obj);
50685dfecf96Smrg		    if (LispGetColumn(NIL))
50695dfecf96Smrg			LispWriteChar(NIL, '\n');
50705dfecf96Smrg		}
50715dfecf96Smrg	    }
50725dfecf96Smrg	    LispTopLevel();
50735dfecf96Smrg	}
50745dfecf96Smrg	if (lisp__data.eof)
50755dfecf96Smrg	    break;
50765dfecf96Smrg    }
50775dfecf96Smrg
50785dfecf96Smrg    signal(SIGINT, lisp__data.sigint);
50795dfecf96Smrg    signal(SIGFPE, lisp__data.sigfpe);
50805dfecf96Smrg
50815dfecf96Smrg    lisp__data.running = 0;
50825dfecf96Smrg}
50835dfecf96Smrg
50845dfecf96Smrgvoid *
50855dfecf96SmrgLispExecute(char *str)
50865dfecf96Smrg{
50875dfecf96Smrg    static LispObj stream;
50885dfecf96Smrg    static LispString string;
50895dfecf96Smrg    static int first = 1;
50905dfecf96Smrg
50915dfecf96Smrg    int running = lisp__data.running;
50925dfecf96Smrg    LispObj *result, *cod, *obj, **presult = &result;
50935dfecf96Smrg
50945dfecf96Smrg    if (str == NULL || *str == '\0')
50955dfecf96Smrg	return (NIL);
50965dfecf96Smrg
50975dfecf96Smrg    *presult = NIL;
50985dfecf96Smrg
50995dfecf96Smrg    if (first) {
51005dfecf96Smrg	stream.type = LispStream_t;
51015dfecf96Smrg	stream.data.stream.source.string = &string;
51025dfecf96Smrg	stream.data.stream.pathname = NIL;
51035dfecf96Smrg	stream.data.stream.type = LispStreamString;
51045dfecf96Smrg	stream.data.stream.readable = 1;
51055dfecf96Smrg	stream.data.stream.writable = 0;
51065dfecf96Smrg	string.output = 0;
51075dfecf96Smrg	first = 0;
51085dfecf96Smrg    }
51095dfecf96Smrg    string.string = str;
51105dfecf96Smrg    string.length = strlen(str);
51115dfecf96Smrg    string.input = 0;
51125dfecf96Smrg
51135dfecf96Smrg    LispPushInput(&stream);
51145dfecf96Smrg    if (!running) {
51155dfecf96Smrg	lisp__data.running = 1;
51165dfecf96Smrg	if (sigsetjmp(lisp__data.jmp, 1) != 0)
51175dfecf96Smrg	    return (NULL);
51185dfecf96Smrg    }
51195dfecf96Smrg
51205dfecf96Smrg    cod = COD;
51215dfecf96Smrg    /*CONSTCOND*/
51225dfecf96Smrg    while (1) {
51235dfecf96Smrg	if ((obj = LispRead()) != NULL) {
51245dfecf96Smrg	    result = EVAL(obj);
51255dfecf96Smrg	    COD = cod;
51265dfecf96Smrg	}
51275dfecf96Smrg	if (lisp__data.eof)
51285dfecf96Smrg	    break;
51295dfecf96Smrg    }
51305dfecf96Smrg    LispPopInput(&stream);
51315dfecf96Smrg
51325dfecf96Smrg    lisp__data.running = running;
51335dfecf96Smrg
51345dfecf96Smrg    return (result);
51355dfecf96Smrg}
51365dfecf96Smrg
51375dfecf96Smrgvoid
51385dfecf96SmrgLispBegin(void)
51395dfecf96Smrg{
51405dfecf96Smrg    int i;
51415dfecf96Smrg    LispAtom *atom;
51425dfecf96Smrg    char results[4];
51435dfecf96Smrg    LispObj *object, *path, *ext;
51445dfecf96Smrg
51455dfecf96Smrg    pagesize = LispGetPageSize();
51465dfecf96Smrg    segsize = pagesize / sizeof(LispObj);
51475dfecf96Smrg
5148f14f4646Smrg    lisp__data.strings = hash_new(STRTBLSZ, NULL);
5149f14f4646Smrg    lisp__data.opqs = hash_new(STRTBLSZ, NULL);
5150f14f4646Smrg
51515dfecf96Smrg    /* Initialize memory management */
51525dfecf96Smrg    lisp__data.mem.mem = (void**)calloc(lisp__data.mem.space = 16,
51535dfecf96Smrg					sizeof(void*));
51545dfecf96Smrg    lisp__data.mem.index = lisp__data.mem.level = 0;
51555dfecf96Smrg
51565dfecf96Smrg    /* Allow LispGetVar to check ATOMID() of unbound symbols */
51575dfecf96Smrg    UNBOUND->data.atom = (LispAtom*)LispCalloc(1, sizeof(LispAtom));
51585dfecf96Smrg    LispMused(UNBOUND->data.atom);
51595dfecf96Smrg    noproperty.value = UNBOUND;
51605dfecf96Smrg
51615dfecf96Smrg    if (Stdin == NULL)
51625dfecf96Smrg	Stdin = LispFdopen(0, FILE_READ);
51635dfecf96Smrg    if (Stdout == NULL)
51645dfecf96Smrg	Stdout = LispFdopen(1, FILE_WRITE | FILE_BUFFERED);
51655dfecf96Smrg    if (Stderr == NULL)
51665dfecf96Smrg	Stderr = LispFdopen(2, FILE_WRITE);
51675dfecf96Smrg
51685dfecf96Smrg    /* minimum number of free cells after GC
51695dfecf96Smrg     * if sizeof(LispObj) == 16, than a minfree of 1024 would try to keep
51705dfecf96Smrg     * at least 16Kb of free cells.
51715dfecf96Smrg     */
51725dfecf96Smrg    minfree = 1024;
51735dfecf96Smrg
51745dfecf96Smrg    MOD = COD = PRO = NIL;
51755dfecf96Smrg#ifdef DEBUGGER
51765dfecf96Smrg    DBG = BRK = NIL;
51775dfecf96Smrg#endif
51785dfecf96Smrg
51795dfecf96Smrg    /* allocate initial object cells */
51805dfecf96Smrg    LispAllocSeg(&objseg, minfree);
51815dfecf96Smrg    LispAllocSeg(&atomseg, pagesize);
51825dfecf96Smrg    lisp__data.gc.average = segsize;
51835dfecf96Smrg
51845dfecf96Smrg    /* Don't allow gc in initialization */
51855dfecf96Smrg    GCDisable();
51865dfecf96Smrg
51875dfecf96Smrg    /* Initialize package system, the current package is LISP. Order of
51885dfecf96Smrg     * initialization is very important here */
51895dfecf96Smrg    lisp__data.lisp = LispNewPackage(STRING("LISP"),
51905dfecf96Smrg				     CONS(STRING("COMMON-LISP"), NIL));
51915dfecf96Smrg
51925dfecf96Smrg    /* Make LISP package the current one */
51935dfecf96Smrg    lisp__data.pack = lisp__data.savepack =
51945dfecf96Smrg	lisp__data.lisp->data.package.package;
51955dfecf96Smrg
51965dfecf96Smrg    /* Allocate space in LISP package */
51975dfecf96Smrg    LispMoreGlobals(lisp__data.pack);
51985dfecf96Smrg
51995dfecf96Smrg    /* Allocate  space for multiple value return values */
52005dfecf96Smrg    lisp__data.returns.values = malloc(MULTIPLE_VALUES_LIMIT *
52015dfecf96Smrg				       (sizeof(LispObj*)));
52025dfecf96Smrg
52035dfecf96Smrg    /*  Create the first atom, do it "by hand" because macro "PACKAGE"
52045dfecf96Smrg     * cannot yet be used. */
52055dfecf96Smrg    atom = LispGetPermAtom("*PACKAGE*");
52065dfecf96Smrg    lisp__data.package = atomseg.freeobj;
52075dfecf96Smrg    atomseg.freeobj = CDR(atomseg.freeobj);
52085dfecf96Smrg    --atomseg.nfree;
52095dfecf96Smrg    lisp__data.package->type = LispAtom_t;
52105dfecf96Smrg    lisp__data.package->data.atom = atom;
52115dfecf96Smrg    atom->object = lisp__data.package;
52125dfecf96Smrg    atom->package = lisp__data.lisp;
52135dfecf96Smrg
52145dfecf96Smrg    /* Set package list, to be used by (gc) and (list-all-packages) */
52155dfecf96Smrg    PACK = CONS(lisp__data.lisp, NIL);
52165dfecf96Smrg
52175dfecf96Smrg    /* Make *PACKAGE* a special variable */
52185dfecf96Smrg    LispProclaimSpecial(lisp__data.package, lisp__data.lisp, NIL);
52195dfecf96Smrg
52205dfecf96Smrg	/* Value of macro "PACKAGE" is now properly available */
52215dfecf96Smrg
52225dfecf96Smrg    /* Changing *PACKAGE* is like calling (in-package) */
52235dfecf96Smrg    lisp__data.package->data.atom->watch = 1;
52245dfecf96Smrg
52255dfecf96Smrg    /* And available to other packages */
52265dfecf96Smrg    LispExportSymbol(lisp__data.package);
52275dfecf96Smrg
52285dfecf96Smrg    /* Initialize stacks */
52295dfecf96Smrg    LispMoreEnvironment();
52305dfecf96Smrg    LispMoreStack();
52315dfecf96Smrg
52325dfecf96Smrg    /* Create the KEYWORD package */
52335dfecf96Smrg    Skeyword = GETATOMID("KEYWORD");
5234f14f4646Smrg    object = LispNewPackage(STRING(Skeyword->value),
52355dfecf96Smrg			    CONS(STRING(""), NIL));
52365dfecf96Smrg
52375dfecf96Smrg    /* Update list of packages */
52385dfecf96Smrg    PACK = CONS(object, PACK);
52395dfecf96Smrg
52405dfecf96Smrg    /* Allow easy access to the keyword package */
52415dfecf96Smrg    lisp__data.keyword = object;
52425dfecf96Smrg    lisp__data.key = object->data.package.package;
52435dfecf96Smrg
52445dfecf96Smrg    /* Initialize some static important symbols */
52455dfecf96Smrg    Olambda		= STATIC_ATOM("LAMBDA");
52465dfecf96Smrg    LispExportSymbol(Olambda);
52475dfecf96Smrg    Okey		= STATIC_ATOM("&KEY");
52485dfecf96Smrg    LispExportSymbol(Okey);
52495dfecf96Smrg    Orest		= STATIC_ATOM("&REST");
52505dfecf96Smrg    LispExportSymbol(Orest);
52515dfecf96Smrg    Ooptional		= STATIC_ATOM("&OPTIONAL");
52525dfecf96Smrg    LispExportSymbol(Ooptional);
52535dfecf96Smrg    Oaux		= STATIC_ATOM("&AUX");
52545dfecf96Smrg    LispExportSymbol(Oaux);
52555dfecf96Smrg    Kunspecific		= KEYWORD("UNSPECIFIC");
52565dfecf96Smrg    Oformat		= STATIC_ATOM("FORMAT");
52575dfecf96Smrg    Oexpand_setf_method	= STATIC_ATOM("EXPAND-SETF-METHOD");
52585dfecf96Smrg
52595dfecf96Smrg    Omake_struct	= STATIC_ATOM("MAKE-STRUCT");
52605dfecf96Smrg    Ostruct_access	= STATIC_ATOM("STRUCT-ACCESS");
52615dfecf96Smrg    Ostruct_store	= STATIC_ATOM("STRUCT-STORE");
52625dfecf96Smrg    Ostruct_type	= STATIC_ATOM("STRUCT-TYPE");
52635dfecf96Smrg    Smake_struct	= ATOMID(Omake_struct);
52645dfecf96Smrg    Sstruct_access	= ATOMID(Ostruct_access);
52655dfecf96Smrg    Sstruct_store	= ATOMID(Ostruct_store);
52665dfecf96Smrg    Sstruct_type	= ATOMID(Ostruct_type);
52675dfecf96Smrg
52685dfecf96Smrg    /* Initialize some static atom ids */
52695dfecf96Smrg    Snil		= GETATOMID("NIL");
52705dfecf96Smrg    St			= GETATOMID("T");
52715dfecf96Smrg    Saux		= ATOMID(Oaux);
52725dfecf96Smrg    Skey		= ATOMID(Okey);
52735dfecf96Smrg    Soptional		= ATOMID(Ooptional);
52745dfecf96Smrg    Srest		= ATOMID(Orest);
52755dfecf96Smrg    Sand		= GETATOMID("AND");
52765dfecf96Smrg    Sor			= GETATOMID("OR");
52775dfecf96Smrg    Snot		= GETATOMID("NOT");
52785dfecf96Smrg    Satom		= GETATOMID("ATOM");
52795dfecf96Smrg    Ssymbol		= GETATOMID("SYMBOL");
52805dfecf96Smrg    Sinteger		= GETATOMID("INTEGER");
52815dfecf96Smrg    Scharacter		= GETATOMID("CHARACTER");
52825dfecf96Smrg    Sstring		= GETATOMID("STRING");
52835dfecf96Smrg    Slist		= GETATOMID("LIST");
52845dfecf96Smrg    Scons		= GETATOMID("CONS");
52855dfecf96Smrg    Svector		= GETATOMID("VECTOR");
52865dfecf96Smrg    Sarray		= GETATOMID("ARRAY");
52875dfecf96Smrg    Sstruct		= GETATOMID("STRUCT");
52885dfecf96Smrg    Sfunction		= GETATOMID("FUNCTION");
52895dfecf96Smrg    Spathname		= GETATOMID("PATHNAME");
52905dfecf96Smrg    Srational		= GETATOMID("RATIONAL");
52915dfecf96Smrg    Sfloat		= GETATOMID("FLOAT");
52925dfecf96Smrg    Scomplex		= GETATOMID("COMPLEX");
52935dfecf96Smrg    Sopaque		= GETATOMID("OPAQUE");
52945dfecf96Smrg    Sdefault		= GETATOMID("DEFAULT");
52955dfecf96Smrg
52965dfecf96Smrg    LispArgList_t	= LispRegisterOpaqueType("LispArgList*");
52975dfecf96Smrg
52985dfecf96Smrg    lisp__data.unget = malloc(sizeof(LispUngetInfo*));
52995dfecf96Smrg    lisp__data.unget[0] = calloc(1, sizeof(LispUngetInfo));
53005dfecf96Smrg    lisp__data.nunget = 1;
53015dfecf96Smrg
53025dfecf96Smrg    lisp__data.standard_input = ATOM2("*STANDARD-INPUT*");
53035dfecf96Smrg    SINPUT = STANDARDSTREAM(Stdin, lisp__data.standard_input, STREAM_READ);
53045dfecf96Smrg    lisp__data.interactive = 1;
53055dfecf96Smrg    LispProclaimSpecial(lisp__data.standard_input,
53065dfecf96Smrg			lisp__data.input_list = SINPUT, NIL);
53075dfecf96Smrg    LispExportSymbol(lisp__data.standard_input);
53085dfecf96Smrg
53095dfecf96Smrg    lisp__data.standard_output = ATOM2("*STANDARD-OUTPUT*");
53105dfecf96Smrg    SOUTPUT = STANDARDSTREAM(Stdout, lisp__data.standard_output, STREAM_WRITE);
53115dfecf96Smrg    LispProclaimSpecial(lisp__data.standard_output,
53125dfecf96Smrg			lisp__data.output_list = SOUTPUT, NIL);
53135dfecf96Smrg    LispExportSymbol(lisp__data.standard_output);
53145dfecf96Smrg
53155dfecf96Smrg    object = ATOM2("*STANDARD-ERROR*");
53165dfecf96Smrg    lisp__data.error_stream = STANDARDSTREAM(Stderr, object, STREAM_WRITE);
53175dfecf96Smrg    LispProclaimSpecial(object, lisp__data.error_stream, NIL);
53185dfecf96Smrg    LispExportSymbol(object);
53195dfecf96Smrg
53205dfecf96Smrg    lisp__data.modules = ATOM2("*MODULES*");
53215dfecf96Smrg    LispProclaimSpecial(lisp__data.modules, MOD, NIL);
53225dfecf96Smrg    LispExportSymbol(lisp__data.modules);
53235dfecf96Smrg
53245dfecf96Smrg    object = CONS(KEYWORD("UNIX"), CONS(KEYWORD("XEDIT"), NIL));
53255dfecf96Smrg    lisp__data.features = ATOM2("*FEATURES*");
53265dfecf96Smrg    LispProclaimSpecial(lisp__data.features, object, NIL);
53275dfecf96Smrg    LispExportSymbol(lisp__data.features);
53285dfecf96Smrg
53295dfecf96Smrg    object = ATOM2("MULTIPLE-VALUES-LIMIT");
53305dfecf96Smrg    LispDefconstant(object, FIXNUM(MULTIPLE_VALUES_LIMIT + 1), NIL);
53315dfecf96Smrg    LispExportSymbol(object);
53325dfecf96Smrg
53335dfecf96Smrg    /* Reenable gc */
53345dfecf96Smrg    GCEnable();
53355dfecf96Smrg
53365dfecf96Smrg    LispBytecodeInit();
53375dfecf96Smrg    LispPackageInit();
53385dfecf96Smrg    LispCoreInit();
53395dfecf96Smrg    LispMathInit();
53405dfecf96Smrg    LispPathnameInit();
53415dfecf96Smrg    LispStreamInit();
53425dfecf96Smrg    LispRegexInit();
53435dfecf96Smrg    LispWriteInit();
53445dfecf96Smrg
53455dfecf96Smrg    lisp__data.prompt = isatty(0) ? "> " : NULL;
53465dfecf96Smrg
53475dfecf96Smrg    lisp__data.errexit = !lisp__data.interactive;
53485dfecf96Smrg
53495dfecf96Smrg    if (lisp__data.interactive) {
53505dfecf96Smrg	/* add +, ++, +++, *, **, and *** */
53515dfecf96Smrg	for (i = 0; i < 3; i++) {
53525dfecf96Smrg	    results[i] = '+';
53535dfecf96Smrg	    results[i + 1] = '\0';
53545dfecf96Smrg	    RUN[i] = ATOM(results);
53555dfecf96Smrg	    LispSetVar(RUN[i], NIL);
53565dfecf96Smrg	    LispExportSymbol(RUN[i]);
53575dfecf96Smrg	}
53585dfecf96Smrg	for (i = 0; i < 3; i++) {
53595dfecf96Smrg	    results[i] = '*';
53605dfecf96Smrg	    results[i + 1] = '\0';
53615dfecf96Smrg	    RES[i] = ATOM(results);
53625dfecf96Smrg	    LispSetVar(RES[i], NIL);
53635dfecf96Smrg	    LispExportSymbol(RES[i]);
53645dfecf96Smrg	}
53655dfecf96Smrg    }
53665dfecf96Smrg    else
53675dfecf96Smrg	RUN[0] = RUN[1] = RUN[2] = RES[0] = RES[1] = RES[2] = NIL;
53685dfecf96Smrg
53695dfecf96Smrg    /* Add LISP builtin functions */
53705dfecf96Smrg    for (i = 0; i < sizeof(lispbuiltins) / sizeof(lispbuiltins[0]); i++)
53715dfecf96Smrg	LispAddBuiltinFunction(&lispbuiltins[i]);
53725dfecf96Smrg
53735dfecf96Smrg    EXECUTE("(require \"lisp\")");
53745dfecf96Smrg
53755dfecf96Smrg    object = ATOM2("*DEFAULT-PATHNAME-DEFAULTS*");
53765dfecf96Smrg#ifdef LISPDIR
53775dfecf96Smrg    {
53785dfecf96Smrg	int length;
5379f765521fSmrg	const char *pathname = LISPDIR;
53805dfecf96Smrg
53815dfecf96Smrg	length = strlen(pathname);
53825dfecf96Smrg	if (length && pathname[length - 1] != '/') {
5383f765521fSmrg	    char *fixed_pathname = LispMalloc(length + 2);
53845dfecf96Smrg
5385f765521fSmrg	    strcpy(fixed_pathname, LISPDIR);
5386f765521fSmrg	    strcpy(fixed_pathname + length, "/");
5387f765521fSmrg	    path = LSTRING2(fixed_pathname, length + 1);
53885dfecf96Smrg	}
53895dfecf96Smrg	else
53905dfecf96Smrg	    path = LSTRING(pathname, length);
53915dfecf96Smrg    }
53925dfecf96Smrg#else
53935dfecf96Smrg    path = STRING("");
53945dfecf96Smrg#endif
53955dfecf96Smrg    GCDisable();
53965dfecf96Smrg    LispProclaimSpecial(object, APPLY1(Oparse_namestring, path), NIL);
53975dfecf96Smrg    LispExportSymbol(object);
53985dfecf96Smrg    GCEnable();
53995dfecf96Smrg
54005dfecf96Smrg    /* Create and make EXT the current package */
54015dfecf96Smrg    PACKAGE = ext = LispNewPackage(STRING("EXT"), NIL);
54025dfecf96Smrg    lisp__data.pack = lisp__data.savepack = PACKAGE->data.package.package;
54035dfecf96Smrg
54045dfecf96Smrg    /* Update list of packages */
54055dfecf96Smrg    PACK = CONS(ext, PACK);
54065dfecf96Smrg
54075dfecf96Smrg    /* Import LISP external symbols in EXT package */
54085dfecf96Smrg    LispUsePackage(lisp__data.lisp);
54095dfecf96Smrg
54105dfecf96Smrg    /* Add EXT non standard builtin functions */
54115dfecf96Smrg    for (i = 0; i < sizeof(extbuiltins) / sizeof(extbuiltins[0]); i++)
54125dfecf96Smrg	LispAddBuiltinFunction(&extbuiltins[i]);
54135dfecf96Smrg
54145dfecf96Smrg    /* Create and make USER the current package */
54155dfecf96Smrg    GCDisable();
54165dfecf96Smrg    PACKAGE = LispNewPackage(STRING("USER"),
54175dfecf96Smrg			     CONS(STRING("COMMON-LISP-USER"), NIL));
54185dfecf96Smrg    GCEnable();
54195dfecf96Smrg    lisp__data.pack = lisp__data.savepack = PACKAGE->data.package.package;
54205dfecf96Smrg
54215dfecf96Smrg    /* Update list of packages */
54225dfecf96Smrg    PACK = CONS(PACKAGE, PACK);
54235dfecf96Smrg
54245dfecf96Smrg    /* USER package inherits all LISP external symbols */
54255dfecf96Smrg    LispUsePackage(lisp__data.lisp);
54265dfecf96Smrg    /* And all EXT external symbols */
54275dfecf96Smrg    LispUsePackage(ext);
54285dfecf96Smrg
54295dfecf96Smrg    LispTopLevel();
54305dfecf96Smrg}
54315dfecf96Smrg
54325dfecf96Smrgvoid
5433f14f4646SmrgLispEnd(void)
54345dfecf96Smrg{
54355dfecf96Smrg    /* XXX needs to free all used memory, not just close file descriptors */
54365dfecf96Smrg}
54375dfecf96Smrg
54385dfecf96Smrgvoid
5439f765521fSmrgLispSetPrompt(const char *prompt)
54405dfecf96Smrg{
54415dfecf96Smrg    lisp__data.prompt = prompt;
54425dfecf96Smrg}
54435dfecf96Smrg
54445dfecf96Smrgvoid
54455dfecf96SmrgLispSetInteractive(int interactive)
54465dfecf96Smrg{
54475dfecf96Smrg    lisp__data.interactive = !!interactive;
54485dfecf96Smrg}
54495dfecf96Smrg
54505dfecf96Smrgvoid
54515dfecf96SmrgLispSetExitOnError(int errexit)
54525dfecf96Smrg{
54535dfecf96Smrg    lisp__data.errexit = !!errexit;
54545dfecf96Smrg}
54555dfecf96Smrg
54565dfecf96Smrgvoid
54575dfecf96SmrgLispDebug(int enable)
54585dfecf96Smrg{
54595dfecf96Smrg    lisp__data.debugging = !!enable;
54605dfecf96Smrg
54615dfecf96Smrg#ifdef DEBUGGER
54625dfecf96Smrg    /* assumes we are at the toplevel */
54635dfecf96Smrg    DBG = BRK = NIL;
54645dfecf96Smrg    lisp__data.debug_level = -1;
54655dfecf96Smrg    lisp__data.debug_step = 0;
54665dfecf96Smrg#endif
54675dfecf96Smrg}
5468