/* xlisp - a small subset of lisp */
/*      Copyright (c) 1985, by David Michael Betz
        All Rights Reserved
        Permission is granted for unrestricted non-commercial use       */

/* system specific definitions */
/* #define unix */

#include <limits.h>
#include <stdio.h>
#include <ctype.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdarg.h>

#define isnumber xisnumber

/* NNODES       number of nodes to allocate in each request (1000) */
/* TDEPTH       trace stack depth (500) */
/* EDEPTH       evaluation stack depth (1000) */
/* FORWARD      type of a forward declaration () */
/* LOCAL        type of a local function (static) */
/* AFMT         printf format for addresses ("%x") */
/* FIXNUM       data type for fixed point numbers (long) */
/* ITYPE        fixed point input conversion routine type (long atol()) */
/* ICNV         fixed point input conversion routine (atol) */
/* IFMT         printf format for fixed point numbers ("%ld") */
/* FLONUM       data type for floating point numbers (float) */
/* FFMT         printf format for floating point ("%g") */
/* SYSTEM       enable the control-d command */

/* default important definitions */
#ifndef NNODES
#define NNODES          1000
#endif
#ifndef TDEPTH
#define TDEPTH          500
#endif
#ifndef EDEPTH
#define EDEPTH          1000
#endif
#ifndef FORWARD
#define FORWARD
#endif
#ifndef LOCAL
#define LOCAL           static
#endif
#ifndef AFMT
#define AFMT            "%p"
#define AFMTARG(x)      ((void*)(x))
#endif
#ifndef FIXNUM
#define FIXNUM          long
#endif
#ifndef ICNV
#define ICNV(n)         atol(n)
#endif
#ifndef IFMT
#define IFMT            "%ld"
#endif
#ifndef FLONUM
#define FLONUM          double
#define FFMT            "%lg"
#endif

/* useful definitions */
#define TRUE    1
#define FALSE   0
#ifndef NIL
#define NIL     (NODE *)0
#endif

/* program limits */
#define STRMAX          100             /* maximum length of a string constant */
#define HSIZE           199             /* symbol hash table size */
#define SAMPLE          100             /* control character sample rate */
        
/* node types */
#define FREE    0
#define SUBR    1
#define FSUBR   2
#define LIST    3
#define SYM     4
#define INT     5
#define STR     6
#define OBJ     7
#define FPTR    8
#define FLOAT   9
#define VECT    10

/* node flags */
#define MARK    1
#define LEFT    2

/* string types */
#define DYNAMIC 0
#define STATIC  1

/* new node access macros */
#define ntype(x)        ((x)->n_type)

/* type predicates */
#define atom(x)         ((x) == NIL || (x)->n_type != LIST)
#define null(x)         ((x) == NIL)
#define listp(x)        ((x) == NIL || (x)->n_type == LIST)
#define consp(x)        ((x) && (x)->n_type == LIST)
#define subrp(x)        ((x) && (x)->n_type == SUBR)
#define fsubrp(x)       ((x) && (x)->n_type == FSUBR)
#define stringp(x)      ((x) && (x)->n_type == STR)
#define symbolp(x)      ((x) && (x)->n_type == SYM)
#define filep(x)        ((x) && (x)->n_type == FPTR)
#define objectp(x)      ((x) && (x)->n_type == OBJ)
#define fixp(x)         ((x) && (x)->n_type == INT)
#define floatp(x)       ((x) && (x)->n_type == FLOAT)
#define vectorp(x)      ((x) && (x)->n_type == VECT)

/* cons access macros */
#define car(x)          ((x)->n_car)
#define cdr(x)          ((x)->n_cdr)
#define rplaca(x,y)     ((x)->n_car = (y))
#define rplacd(x,y)     ((x)->n_cdr = (y))

/* symbol access macros */
#define getvalue(x)     ((x)->n_symvalue)
#define setvalue(x,v)   ((x)->n_symvalue = (v))
#define getplist(x)     ((x)->n_symplist->n_cdr)
#define setplist(x,v)   ((x)->n_symplist->n_cdr = (v))
#define getpname(x)     ((x)->n_symplist->n_car)

/* vector access macros */
#define getsize(x)      ((x)->n_vsize)
#define getelement(x,i) ((x)->n_vdata[i])
#define setelement(x,i,v) ((x)->n_vdata[i] = (v))

/* object access macros */
#define getclass(x)     ((x)->n_vdata[0])
#define getivar(x,i)    ((x)->n_vdata[i+1])
#define setivar(x,i,v)  ((x)->n_vdata[i+1] = (v))

/* subr/fsubr access macros */
#define getsubr(x)      ((x)->n_subr)

/* fixnum/flonum access macros */
#define getfixnum(x)    ((x)->n_int)
#define getflonum(x)    ((x)->n_float)

/* string access macros */
#define getstring(x)    ((x)->n_str)
#define setstring(x,v)  ((x)->n_str = (v))

/* file access macros */
#define getfile(x)      ((x)->n_fp)
#define setfile(x,v)    ((x)->n_fp = (v))
#define getsavech(x)    ((x)->n_savech)
#define setsavech(x,v)  ((x)->n_savech = (v))

/* symbol node */
#define n_symplist      n_info.n_xsym.xsy_plist
#define n_symvalue      n_info.n_xsym.xsy_value

/* subr/fsubr node */
#define n_subr          n_info.n_xsubr.xsu_subr

/* list node */
#define n_car           n_info.n_xlist.xl_car
#define n_cdr           n_info.n_xlist.xl_cdr

/* integer node */
#define n_int           n_info.n_xint.xi_int

/* float node */
#define n_float         n_info.n_xfloat.xf_float

/* string node */
#define n_str           n_info.n_xstr.xst_str
#define n_strtype       n_info.n_xstr.xst_type

/* file pointer node */
#define n_fp            n_info.n_xfptr.xf_fp
#define n_savech        n_info.n_xfptr.xf_savech

/* vector/object node */
#define n_vsize         n_info.n_xvect.xv_size
#define n_vdata         n_info.n_xvect.xv_data

/* node structure */
typedef struct node {
    unsigned char n_type;                /* type of node */
    char n_flags;               /* flag bits */
    union {                     /* value */
        struct xsym {           /* symbol node */
            struct node *xsy_plist;     /* symbol plist - (name . plist) */
            struct node *xsy_value;     /* the current value */
        } n_xsym;
        struct xsubr {          /* subr/fsubr node */
            struct node *(*xsu_subr)(struct node *args);        /* pointer to an internal routine */
        } n_xsubr;
        struct xlist {          /* list node (cons) */
            struct node *xl_car;        /* the car pointer */
            struct node *xl_cdr;        /* the cdr pointer */
        } n_xlist;
        struct xint {           /* integer node */
            FIXNUM xi_int;              /* integer value */
        } n_xint;
        struct xfloat {         /* float node */
            FLONUM xf_float;            /* float value */
        } n_xfloat;
        struct xstr {           /* string node */
            int xst_type;               /* string type */
            char *xst_str;              /* string pointer */
        } n_xstr;
        struct xfptr {          /* file pointer node */
            FILE *xf_fp;                /* the file pointer */
            int xf_savech;              /* lookahead character for input files */
        } n_xfptr;
        struct xvect {          /* vector node */
            int xv_size;                /* vector size */
            struct node **xv_data;      /* vector data */
        } n_xvect;
    } n_info;
} NODE;

/* execution context flags */
#define CF_GO           1
#define CF_RETURN       2
#define CF_THROW        4
#define CF_ERROR        8
#define CF_CLEANUP      16
#define CF_CONTINUE     32
#define CF_TOPLEVEL     64

/* execution context */
typedef struct context {
    int c_flags;                        /* context type flags */
    struct node *c_expr;                /* expression (type dependant) */
    jmp_buf c_jmpbuf;                   /* longjmp context */
    struct context *c_xlcontext;        /* old value of xlcontext */
    struct node ***c_xlstack;           /* old value of xlstack */
    struct node *c_xlenv;               /* old value of xlenv */
    int c_xltrace;                      /* old value of xltrace */
} CONTEXT;

/* function table entry structure */
struct fdef {
    char *f_name;                       /* function name */
    int f_type;                         /* function type SUBR/FSUBR */
    struct node *(*f_fcn)(struct node *); /* function code */
};

/* memory segment structure definition */
struct segment {
    size_t sg_size;
    struct segment *sg_next;
    struct node sg_nodes[1];
};

/* external variable declarations */

/*** xlftab.c ***/
extern struct fdef ftab[];

/*** xlglob.c ***/
/* symbols */
extern NODE *s_true, *s_dot;
extern NODE *s_quote, *s_function;
extern NODE *s_bquote, *s_comma, *s_comat;
extern NODE *s_evalhook, *s_applyhook;
extern NODE *s_lambda, *s_macro;
extern NODE *s_stdin, *s_stdout, *s_rtable;
extern NODE *s_tracenable, *s_tlimit, *s_breakenable;
extern NODE *s_car, *s_cdr, *s_nth;
extern NODE *s_get, *s_svalue, *s_splist, *s_aref;
extern NODE *s_eql, *k_test, *k_tnot;
extern NODE *k_wspace, *k_const, *k_nmacro, *k_tmacro;
extern NODE *k_optional, *k_rest, *k_aux;
extern NODE *a_subr, *a_fsubr;
extern NODE *a_list, *a_sym, *a_int, *a_float;
extern NODE *a_str, *a_obj, *a_fptr, *a_vect;
extern NODE *obarray, *s_unbound;

/* evaluation variables */
extern NODE ***xlstack, ***xlstkbase, ***xlstktop;
extern NODE *xlenv;

/* exception handling variables */
extern CONTEXT *xlcontext;             /* current exception handler */
extern NODE *xlvalue;                  /* exception value */

/* debugging variables */
extern int xldebug;                    /* debug level */
extern int xltrace;                    /* trace stack pointer */
extern NODE **trace_stack;             /* trace stack */
extern int xlsample;                   /* control character sample rate */

/* gensym variables */
extern char gsprefix[STRMAX+1];        /* gensym prefix string */
extern FIXNUM gsnumber;                /* gensym number */

/* i/o variables */
extern int prompt;                     /* prompt flag */
extern int xlplevel;                   /* paren nesting level */
extern int xlfsize;                    /* flat size of current print call */

/* dynamic memory variables */
extern unsigned long total;            /* total memory in use */
extern size_t anodes;                  /* number of nodes to allocate */
extern unsigned long nnodes;           /* number of nodes allocated */
extern int nsegs;                      /* number of segments allocated */
extern unsigned long nfree;            /* number of nodes free */
extern int gccalls;                    /* number of gc calls */
extern struct segment *segs;           /* list of allocated segments */
extern NODE *fnodes;                   /* list of free nodes */

/* object programming variables */
extern NODE *self, *class, *object;
extern NODE *new, *isnew, *msgcls, *msgclass;

/* general purpose string buffer */
extern char buf[STRMAX+1];

/**** external procedure declarations ****/

/*** xlbfun.c ***/
extern NODE *xeval (NODE *args);
extern NODE *xapply (NODE *args);
extern NODE *xfuncall (NODE *args);
extern NODE *xquote (NODE *args);
extern NODE *xfunction (NODE *args);
extern NODE *xlambda (NODE *args);
extern NODE *xbquote (NODE *args);
extern NODE *xset (NODE *args);
extern NODE *xsetq (NODE *args);
extern NODE *xsetf (NODE *args);
extern NODE *xdefun (NODE *args);
extern NODE *xdefmacro (NODE *args);
extern NODE *xgensym (NODE *args);
extern NODE *xmakesymbol (NODE *args);
extern NODE *xintern (NODE *args);
extern NODE *xsymname (NODE *args);
extern NODE *xsymvalue (NODE *args);
extern NODE *xsymplist (NODE *args);
extern NODE *xget (NODE *args);
extern NODE *xputprop (NODE *args);
extern NODE *xremprop (NODE *args);
extern NODE *xhash (NODE *args);
extern NODE *xaref (NODE *args);
extern NODE *xmkarray (NODE *args);

/*** xlcont.c ***/
extern NODE *xcond (NODE *args);
extern NODE *xcase (NODE *args);
extern NODE *xand (NODE *args);
extern NODE *xor (NODE *args);
extern NODE *xif (NODE *args);
extern NODE *xlet (NODE *args);
extern NODE *xletstar (NODE *args);
extern NODE *xprog (NODE *args);
extern NODE *xprogstar (NODE *args);
extern NODE *xgo (NODE *args);
extern NODE *xreturn (NODE *args);
extern NODE *xprog1 (NODE *args);
extern NODE *xprog2 (NODE *args);
extern NODE *xprogn (NODE *args);
extern NODE *xdo (NODE *args);
extern NODE *xdostar (NODE *args);
extern NODE *xdolist (NODE *args);
extern NODE *xdotimes (NODE *args);
extern NODE *xcatch (NODE *args);
extern NODE *xthrow (NODE *args);
extern NODE *xerror (NODE *args);
extern NODE *xcerror (NODE *args);
extern NODE *xbreak (NODE *args);
extern NODE *xcleanup (NODE *args);
extern NODE *xcontinue (NODE *args);
extern NODE *xerrset (NODE *args);
extern NODE *xevalhook (NODE *args);

/*** xldbug.c ***/
extern _Noreturn void xlfail (char *emsg);
extern _Noreturn void xlabort (char *emsg);
extern void xlbreak (char *emsg, NODE *arg);
extern _Noreturn void xlerror (char *emsg, NODE *arg);
extern void xlcerror (char *cmsg, char *emsg, NODE *arg);
extern void xlerrprint (char *hdr, char *cmsg, char *emsg, NODE *arg);
extern void xlbaktrace (int n);
extern void xldinit (void);

/*** xldmem.c ***/
extern NODE *cons (NODE *x, NODE *y);
extern NODE *consa (NODE *x);
extern NODE *consd (NODE *x);
extern NODE *cvstring (char *str);
extern NODE *cvcstring (char *str);
extern NODE *cvsymbol (char *pname);
extern NODE *cvcsymbol (char *pname);
extern NODE *cvsubr (NODE *(*fcn) (NODE *), int type);
extern NODE *cvfile (FILE *fp);
extern NODE *cvfixnum (long n);
extern NODE *cvflonum (FLONUM n);
extern NODE *newstring (size_t size);
extern NODE *newobject (NODE *cls, size_t size);
extern NODE *newvector (size_t size);
extern void gc (void);
extern int addseg (void);
extern void stats (void);
extern void xlminit (void);

/*** xleval.c ***/
extern NODE *xleval (NODE *expr);
extern NODE *xlxeval (NODE *expr);
extern NODE *xlapply (NODE *fun, NODE *args);
extern NODE *xlevlist (NODE *args);
extern void xlunbound (NODE *sym);
extern void xlabind (NODE *fargs, NODE *aargs, NODE *env);
extern NODE ***xlsave (NODE **n, ...);

/*** xlfio.c ***/
extern NODE *xread (NODE *args);
extern NODE *xprint (NODE *args);
extern NODE *xprin1 (NODE *args);
extern NODE *xprinc (NODE *args);
extern NODE *xterpri (NODE *args);
extern NODE *xflatsize (NODE *args);
extern NODE *xflatc (NODE *args);
extern NODE *xopeni (NODE *args);
extern NODE *xopeno (NODE *args);
extern NODE *xclose (NODE *args);
extern NODE *xrdchar (NODE *args);
extern NODE *xpkchar (NODE *args);
extern NODE *xwrchar (NODE *args);
extern NODE *xreadline (NODE *args);

/*** xlinit.c ***/
extern void xlinit (void);

/*** xlio.c ***/
extern int xlgetc (NODE *fptr);
extern int xlpeek (NODE *fptr);
extern void xlputc (NODE *fptr, int ch);
extern void xlflush (void);

/*** xlisp.c ***/
extern int main (int argc, char *argv[]);
extern void stdprint (NODE *expr);
extern void stdputstr (char *str);

/*** xljump.c ***/
extern void xlbegin (CONTEXT *cptr, int flags, NODE *expr);
extern void xlend (CONTEXT *cptr);
extern _Noreturn void xljump (CONTEXT *cptr, int type, NODE *val);
extern _Noreturn void xltoplevel (void);
extern _Noreturn void xlcleanup (void);
extern _Noreturn void xlcontinue (void);
extern _Noreturn void xlgo (NODE *label);
extern _Noreturn void xlreturn (NODE *val);
extern _Noreturn void xlthrow (NODE *tag, NODE *val);
extern _Noreturn void xlsignal (char *emsg, NODE *arg);

/*** xllist.c ***/
extern NODE *xcar (NODE *args);
extern NODE *xcdr (NODE *args);
extern NODE *xcaar (NODE *args);
extern NODE *xcadr (NODE *args);
extern NODE *xcdar (NODE *args);
extern NODE *xcddr (NODE *args);
extern NODE *xcaaar (NODE *args);
extern NODE *xcaadr (NODE *args);
extern NODE *xcadar (NODE *args);
extern NODE *xcaddr (NODE *args);
extern NODE *xcdaar (NODE *args);
extern NODE *xcdadr (NODE *args);
extern NODE *xcddar (NODE *args);
extern NODE *xcdddr (NODE *args);
extern NODE *xcaaaar (NODE *args);
extern NODE *xcaaadr (NODE *args);
extern NODE *xcaadar (NODE *args);
extern NODE *xcaaddr (NODE *args);
extern NODE *xcadaar (NODE *args);
extern NODE *xcadadr (NODE *args);
extern NODE *xcaddar (NODE *args);
extern NODE *xcadddr (NODE *args);
extern NODE *xcdaaar (NODE *args);
extern NODE *xcdaadr (NODE *args);
extern NODE *xcdadar (NODE *args);
extern NODE *xcdaddr (NODE *args);
extern NODE *xcddaar (NODE *args);
extern NODE *xcddadr (NODE *args);
extern NODE *xcdddar (NODE *args);
extern NODE *xcddddr (NODE *args);
extern NODE *xcons (NODE *args);
extern NODE *xlist (NODE *args);
extern NODE *xappend (NODE *args);
extern NODE *xreverse (NODE *args);
extern NODE *xlast (NODE *args);
extern NODE *xmember (NODE *args);
extern NODE *xassoc (NODE *args);
extern NODE *xsubst (NODE *args);
extern NODE *xsublis (NODE *args);
extern NODE *xremove (NODE *args);
extern int dotest (NODE *arg1, NODE *arg2, NODE *fcn);
extern NODE *xnth (NODE *args);
extern NODE *xnthcdr (NODE *args);
extern NODE *xlength (NODE *args);
extern NODE *xmapc (NODE *args);
extern NODE *xmapcar (NODE *args);
extern NODE *xmapl (NODE *args);
extern NODE *xmaplist (NODE *args);
extern NODE *xrplca (NODE *args);
extern NODE *xrplcd (NODE *args);
extern NODE *xnconc (NODE *args);
extern NODE *xdelete (NODE *args);
extern NODE *xatom (NODE *args);
extern NODE *xsymbolp (NODE *args);
extern NODE *xnumberp (NODE *args);
extern NODE *xboundp (NODE *args);
extern NODE *xnull (NODE *args);
extern NODE *xlistp (NODE *args);
extern NODE *xconsp (NODE *args);
extern NODE *xeq (NODE *args);
extern NODE *xeql (NODE *args);
extern NODE *xequal (NODE *args);

/*** xlmath.c ***/
extern NODE *xadd (NODE *args);
extern NODE *xsub (NODE *args);
extern NODE *xmul (NODE *args);
extern NODE *xdiv (NODE *args);
extern NODE *xrem (NODE *args);
extern NODE *xmin (NODE *args);
extern NODE *xmax (NODE *args);
extern NODE *xexpt (NODE *args);
extern NODE *xbitand (NODE *args);
extern NODE *xbitior (NODE *args);
extern NODE *xbitxor (NODE *args);
extern void checkizero (FIXNUM iarg);
extern void checkfzero (FLONUM farg);
extern void checkfneg (FLONUM farg);
extern NODE *xbitnot (NODE *args);
extern NODE *xabs (NODE *args);
extern NODE *xadd1 (NODE *args);
extern NODE *xsub1 (NODE *args);
extern NODE *xsin (NODE *args);
extern NODE *xcos (NODE *args);
extern NODE *xtan (NODE *args);
extern NODE *xexp (NODE *args);
extern NODE *xsqrt (NODE *args);
extern NODE *xfix (NODE *args);
extern NODE *xfloat (NODE *args);
extern NODE *xrand (NODE *args);
extern NODE *xminusp (NODE *args);
extern NODE *xzerop (NODE *args);
extern NODE *xplusp (NODE *args);
extern NODE *xevenp (NODE *args);
extern NODE *xoddp (NODE *args);
extern NODE *xlss (NODE *args);
extern NODE *xleq (NODE *args);
extern NODE *xequ (NODE *args);
extern NODE *xneq (NODE *args);
extern NODE *xgeq (NODE *args);
extern NODE *xgtr (NODE *args);

/*** xlobj.c ***/
extern NODE *xlclass (char *name, int vcnt);
extern void xladdivar (NODE *cls, char *var);
extern void xladdmsg (NODE *cls, char *msg, NODE *(*code) (NODE *));
extern NODE *xlsend (NODE *obj, NODE *args);
extern int xlobgetvalue (NODE *sym, NODE **pval);
extern int xlobsetvalue (NODE *sym, NODE *val);
extern void xloinit (void);

/*** xlprin.c ***/
extern void xlprint (NODE *fptr, NODE *vptr, int flag);
extern void xlterpri (NODE *fptr);
extern void xlputstr (NODE *fptr, char *str);

/*** xlread.c ***/
extern int xlload (char *fname, int vflag, int pflag);
extern int xlread (NODE *fptr, NODE **pval, int rflag);
extern int readone (NODE *fptr, NODE **pval);
extern NODE *rmhash (NODE *args);
extern NODE *rmquote (NODE *args);
extern NODE *rmdquote (NODE *args);
extern NODE *rmbquote (NODE *args);
extern NODE *rmcomma (NODE *args);
extern NODE *rmlpar (NODE *args);
extern NODE *rmrpar (NODE *args);
extern NODE *rmsemi (NODE *args);
extern int isnumber (char *str, NODE **pval);
extern void defmacro (int ch, NODE *type, NODE *(*fun) (NODE *));
extern NODE *callmacro (NODE *fptr, int ch);
extern int needsextension (char *name);
extern void xlrinit (void);

/*** xlstr.c ***/
extern NODE *xstrcat (NODE *args);
extern NODE *xsubstr (NODE *args);
extern NODE *xstring (NODE *args);
extern NODE *xchar (NODE *args);

/*** xlsubr.c ***/
extern void xlsubr (char *sname, int type, NODE *(*subr) (NODE *));
extern NODE *xlarg (NODE **pargs);
extern NODE *xlmatch (int type, NODE **pargs);
extern NODE *xlevarg (NODE **pargs);
extern NODE *xlevmatch (int type, NODE **pargs);
extern void xltest (NODE **pfcn, int *ptresult, NODE **pargs);
extern NODE *xlgetfile (NODE **pargs);
extern void xllastarg (NODE *args);
extern int eq (NODE *arg1, NODE *arg2);
extern int eql (NODE *arg1, NODE *arg2);
extern int equal (NODE *arg1, NODE *arg2);

/*** xlsym.c ***/
extern NODE *xlenter (char *name, int type);
extern NODE *xlsenter (char *name);
extern NODE *xlmakesym (char *name, int type);
extern NODE *xlframe (NODE *env);
extern void xlbind (NODE *sym, NODE *val, NODE *env);
extern NODE *xlgetvalue (NODE *sym);
extern NODE *xlxgetvalue (NODE *sym);
extern NODE *xlygetvalue (NODE *sym);
extern void xlsetvalue (NODE *sym, NODE *val);
extern NODE *xlgetprop (NODE *sym, NODE *prp);
extern void xlputprop (NODE *sym, NODE *val, NODE *prp);
extern void xlremprop (NODE *sym, NODE *prp);
extern unsigned hash (char *str, unsigned len);
extern void xlsinit (void);

/*** xlsys.c ***/
extern NODE *xload (NODE *args);
extern NODE *xgc (NODE *args);
extern NODE *xexpand (NODE *args);
extern NODE *xalloc (NODE *args);
extern NODE *xmem (NODE *args);
extern NODE *xtype (NODE *args);
extern NODE *xbaktrace (NODE *args);
extern NODE *xexit (NODE *args);

/*** osstuff.c ***/
extern void osinit (char *banner);
extern int osrand (int);
extern int osgetc (FILE *fp);
extern void osputc (int, FILE *);
extern void oscheck (void);
extern void osfinit (void);
extern void osfinish (void);

/* ------------------------------------------------------------------------- */

static inline int getint (NODE *q, int minimum, int maximum) {
  FIXNUM n = getfixnum(q);
  if (n > maximum) xlfail("Fixnum too large.");
  if (n < minimum) xlfail("Fixnum too small.");
  return (int)n;
}

static inline size_t getsize_t (NODE *q, size_t minimum, size_t maximum) {
  FIXNUM i = getfixnum(q);
  unsigned FIXNUM n;
  if (i < 0) xlfail("Fixnum too large.");
  n = (unsigned FIXNUM)i;
  if (n > maximum) xlfail("Fixnum too large.");
  if (n < minimum) xlfail("Fixnum too small.");
  return (size_t)n;
}

