home *** CD-ROM | disk | FTP | other *** search
- /* lisp.c -- Core of the Lisp, reading and evaluating...
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
-
- #ifdef NEED_MEMORY_H
- # include <memory.h>
- #endif
-
- _PR VALUE readl(VALUE, int *);
-
- _PR VALUE eval_lambda(VALUE, VALUE, bool);
- _PR VALUE load_autoload(VALUE, VALUE);
- _PR VALUE funcall(VALUE, VALUE);
- _PR VALUE eval_string(u_char *, bool);
-
- _PR VALUE call_lisp0(VALUE);
- _PR VALUE call_lisp1(VALUE, VALUE);
- _PR VALUE call_lisp2(VALUE, VALUE, VALUE);
-
- _PR void lisp_prin(VALUE, VALUE);
- _PR void string_princ(VALUE, VALUE);
- _PR void string_print(VALUE, VALUE);
-
- _PR VALUE find_member_by_index(VALUE, int);
- _PR VALUE move_down_list(VALUE, int);
- _PR int list_length(VALUE);
- _PR VALUE copy_list(VALUE);
- _PR VALUE handle_var_int(VALUE, long *);
-
- _PR void handle_error(VALUE, VALUE);
- _PR VALUE signal_arg_error(VALUE, int);
- _PR VALUE mem_error(void);
-
- _PR void lisp_init(void);
-
- _PR VALUE sym_debug_entry, sym_debug_exit, sym_debug_error_entry;
- VALUE sym_debug_entry, sym_debug_exit, sym_debug_error_entry;
-
- _PR VALUE sym_quote, sym_lambda, sym_macro, sym_autoload, sym_function;
- VALUE sym_quote, sym_lambda, sym_macro, sym_autoload, sym_function;
-
- _PR VALUE sym_standard_input, sym_standard_output, sym_defun;
- VALUE sym_standard_input, sym_standard_output, sym_defun;
-
- _PR VALUE sym_amp_optional, sym_amp_rest, sym_amp_aux;
- VALUE sym_amp_optional, sym_amp_rest, sym_amp_aux;
-
- /* When a `throw' happens a function stuffs a cons-cell in here with,
- (TAG . VALUE).
- An error is the above with TAG=sym_error and VALUE a list of relevant
- data. */
- _PR VALUE throw_value;
- VALUE throw_value;
-
- /* This cons cell is used for interrupts. We don't know if it's safe to
- call cmd_cons() (maybe in gc?) so this is always valid. */
- _PR VALUE int_cell;
- VALUE int_cell;
-
- _PR VALUE sym_error, sym_error_message, sym_invalid_function;
- _PR VALUE sym_void_function, sym_void_value, sym_bad_arg, sym_invalid_read_syntax;
- _PR VALUE sym_end_of_stream, sym_invalid_lambda_list, sym_missing_arg;
- _PR VALUE sym_invalid_macro, sym_invalid_autoload, sym_no_catcher;
- _PR VALUE sym_buffer_read_only, sym_bad_event_desc, sym_file_error;
- _PR VALUE sym_invalid_stream, sym_setting_constant, sym_process_error;
- _PR VALUE sym_invalid_area, sym_no_memory, sym_user_interrupt;
-
- VALUE sym_error, sym_error_message, sym_invalid_function,
- sym_void_function, sym_void_value, sym_bad_arg, sym_invalid_read_syntax,
- sym_end_of_stream, sym_invalid_lambda_list, sym_missing_arg,
- sym_invalid_macro, sym_invalid_autoload, sym_no_catcher,
- sym_buffer_read_only, sym_bad_event_desc, sym_file_error,
- sym_invalid_stream, sym_setting_constant, sym_process_error,
- sym_invalid_area, sym_no_memory, sym_user_interrupt;
-
- #ifdef MINSTACK
- _PR VALUE sym_stack_error;
- VALUE sym_stack_error;
- #endif
-
- _PR VALUE debug_on_error, sym_error_info;
- VALUE debug_on_error, sym_error_info;
-
- /*
- * When TRUE cmd_eval() calls the "debug-entry" function
- */
- _PR bool single_step_flag;
- bool single_step_flag;
-
- _PR struct LispCall *lisp_call_stack;
- struct LispCall *lisp_call_stack;
-
- static long lisp_depth, max_lisp_depth = 250;
-
- /*
- * All of the read-related functions are now stream based. This will
- * probably add some (much?) overhead but I think it's worth it?
- *
- * The `c' variable which keeps coming up is the lookahead character,
- * since each read*() routine normally has to look at the next character
- * to see if it's what it wants. If not, this char is given to someone
- * else...
- */
-
- static VALUE
- read_list(VALUE strm, register int *c_p)
- {
- VALUE result = sym_nil;
- VALUE last = NULL;
- *c_p = stream_getc(strm);
- while(1)
- {
- switch(*c_p)
- {
- case EOF:
- return(cmd_signal(sym_end_of_stream, LIST_1(strm)));
-
- case ' ':
- case '\t':
- case '\n':
- case '\f':
- *c_p = stream_getc(strm);
- continue;
-
- case ';':
- {
- register int c;
- while((c = stream_getc(strm)) != EOF && c != '\n' && c != '\f')
- ;
- *c_p = stream_getc(strm);
- continue;
- }
-
- case '.':
- *c_p = stream_getc(strm);
- if(last)
- {
- if(!(VCDR(last) = readl(strm, c_p)))
- return(NULL);
- }
- else
- {
- return(cmd_signal(sym_invalid_read_syntax,
- LIST_1(MKSTR("Nothing to dot second element of cons-cell to"))));
- }
-
- case ')':
- case ']':
- *c_p = stream_getc(strm);
- return(result);
-
- default:
- {
- register VALUE this = cmd_cons(sym_nil, sym_nil);
- if(last)
- VCDR(last) = this;
- else
- result = this;
- if(!(VCAR(this) = readl(strm, c_p)))
- return(NULL);
- last = this;
- }
- }
- }
- }
-
- /*
- * could be number *or* symbol
- */
- static VALUE
- read_symbol(VALUE strm, int *c_p)
- {
- #define SYM_BUF_LEN 255
- VALUE result;
- u_char buff[SYM_BUF_LEN + 1];
- register u_char *buf = buff + 1;
- int c = *c_p;
- register int i = 0;
- bool couldbenum = TRUE;
- buff[0] = V_StaticString;
- while((c != EOF) && (i < SYM_BUF_LEN))
- {
- switch(c)
- {
- case ' ':
- case '\t':
- case '\n':
- case '\f':
- case '(':
- case ')':
- case '[':
- case ']':
- case '\'':
- case '"':
- case ';':
- goto done;
- case '\\':
- couldbenum = FALSE;
- c = stream_getc(strm);
- if(c == EOF)
- return(cmd_signal(sym_end_of_stream, LIST_1(strm)));
- buf[i++] = c;
- break;
- case '|':
- couldbenum = FALSE;
- c = stream_getc(strm);
- while((c != EOF) && (c != '|') && (i < SYM_BUF_LEN))
- {
- buf[i++] = c;
- c = stream_getc(strm);
- }
- if(c == EOF)
- return(cmd_signal(sym_end_of_stream, LIST_1(strm)));
- break;
- default:
- if(couldbenum)
- {
- /*
- * if c isn't a digit (decimal or hex) and c isn't a sign
- * at the start of the string then it's not a number!
- */
- if(!(isdigit(c) || ((i >= 2) && isxdigit(c)) || ((i == 1) && (toupper(c) == 'X'))))
- {
- if(!((i == 0) && ((c == '+') || (c == '-'))))
- couldbenum = FALSE;
- }
- }
- buf[i++] = c;
- }
- c = stream_getc(strm);
- }
- if(i >= SYM_BUF_LEN)
- {
- /* Guess I'd better fix this! */
- return(cmd_signal(sym_error,
- LIST_1(MKSTR("Internal buffer overrun"))));
- }
- done:
- buf[i] = 0;
- if(couldbenum && ((i > 1) || isdigit(*buf)))
- {
- char *dummy;
- result = make_number(strtol(buf, &dummy, 0));
- }
- else
- {
- if(!(result = cmd_find_symbol(VAL(buff), sym_nil))
- || (NILP(result) && strcmp(buf, "nil")))
- {
- VALUE name;
- if((name = string_dup(buf)) && (result = cmd_make_symbol(name)))
- result = cmd_intern_symbol(result, sym_nil);
- else
- result = NULL;
- }
- }
- *c_p = c;
- return(result);
- }
-
- static VALUE
- read_vector(VALUE strm, int *c_p)
- {
- VALUE result;
- VALUE list = read_list(strm, c_p);
- if(list)
- {
- VALUE cur = list;
- int len;
- for(len = 0; CONSP(cur); len++)
- cur = VCDR(cur);
- result = make_vector(len);
- if(result)
- {
- int i;
- cur = list;
- for(i = 0; i < len; i++)
- {
- VALUE nxt = VCDR(cur);
- VVECT(result)->vc_Array[i] = VCAR(cur);
- #if 1
- /* I think it's okay to put the cons cells back onto their
- freelist. There can't be any references to them?? */
- cons_free(cur);
- #endif
- cur = nxt;
- }
- }
- else
- result = NULL;
- }
- else
- result = NULL;
- return(result);
- }
-
- static VALUE
- read_str(VALUE strm, int *c_p)
- {
- VALUE result;
- int buflen = 128;
- int c = stream_getc(strm);
- u_char *buf = str_alloc(buflen);
- register u_char *cur = buf;
- u_char *bufend = buf + buflen;
- if(buf)
- {
- while((c != EOF) && (c != '"'))
- {
- if(cur == bufend)
- {
- register int newbuflen = buflen * 2;
- register u_char *newbuf = str_alloc(newbuflen);
- if(newbuf)
- {
- memcpy(newbuf, buf, cur - buf);
- str_free(buf);
- buf = newbuf;
- cur = buf + buflen;
- buflen = newbuflen;
- bufend = buf + buflen;
- }
- else
- return(mem_error());
- }
- if(c == '\\')
- {
- c = stream_getc(strm);
- if(c == '\n')
- /* escaped newline is ignored */
- c = stream_getc(strm);
- else
- *cur++ = (u_char)stream_read_esc(strm, &c);
- }
- else
- {
- *cur++ = c;
- c = stream_getc(strm);
- }
- }
- if(c == EOF)
- result = cmd_signal(sym_end_of_stream, LIST_1(strm));
- else
- {
- *c_p = stream_getc(strm);
- result = string_dupn(buf, cur - buf);
- }
- str_free(buf);
- return(result);
- }
- return(mem_error());
- }
-
- /*
- * Using the above readlisp*() functions this classifies each type
- * of expression and translates it into a lisp object (VALUE).
- * Returns NULL in case of error.
- */
- VALUE
- readl(VALUE strm, register int *c_p)
- {
- #ifdef MINSTACK
- if(STK_SIZE <= MINSTACK)
- {
- STK_WARN("read");
- return(cmd_signal(sym_stack_error, sym_nil));
- }
- #endif
- while(1)
- {
- switch(*c_p)
- {
- case EOF:
- return(sym_nil);
-
- case ' ':
- case '\t':
- case '\n':
- case '\f':
- *c_p = stream_getc(strm);
- continue;
-
- case ';':
- {
- register int c;
- while((c = stream_getc(strm)) != EOF && c != '\n' && c != '\f')
- ;
- *c_p = stream_getc(strm);
- continue;
- }
-
- case '\(':
- return(read_list(strm, c_p));
-
- case '\'':
- {
- /*
- * transmogrify 'X into (quote X)
- */
- register VALUE form;
- form = cmd_cons(sym_quote, cmd_cons(sym_nil, sym_nil));
- if((*c_p = stream_getc(strm)) == EOF)
- goto eof;
- else if((VCAR(VCDR(form)) = readl(strm, c_p)))
- return(form);
- return(NULL);
- }
-
- case '[':
- return(read_vector(strm, c_p));
-
- case '"':
- return(read_str(strm, c_p));
-
- case '?':
- {
- register int c;
- switch(c = stream_getc(strm))
- {
- case EOF:
- goto eof;
- case '\\':
- if((*c_p = stream_getc(strm)) == EOF)
- goto eof;
- else
- return(make_number(stream_read_esc(strm, c_p)));
- break;
- default:
- *c_p = stream_getc(strm);
- return(make_number(c));
- }
- }
-
- case '#':
- switch(*c_p = stream_getc(strm))
- {
- register VALUE form;
- case EOF:
- goto eof;
- case '\'':
- form = cmd_cons(sym_function, cmd_cons(sym_nil, sym_nil));
- if((*c_p = stream_getc(strm)) == EOF)
- goto eof;
- if(!(VCAR(VCDR(form)) = readl(strm, c_p)))
- return(NULL);
- return(form);
- default:
- return(cmd_signal(sym_invalid_read_syntax, LIST_1(strm)));
- }
-
- default:
- return(read_symbol(strm, c_p));
- }
- }
- /* NOT REACHED */
-
- eof:
- return(cmd_signal(sym_end_of_stream, LIST_1(strm)));
- }
-
- /*
- * Evaluates each element of `list' and builds them into a new list.
- */
- static VALUE
- eval_list(VALUE list)
- {
- VALUE result = sym_nil;
- VALUE *last = &result;
- GCVAL gcv_result, gcv_list;
- PUSHGC(gcv_result, result);
- PUSHGC(gcv_list, list);
- while(CONSP(list))
- {
- VALUE tmp;
- if(!(tmp = cmd_eval(VCAR(list))))
- {
- result = NULL;
- break;
- }
- if(!(*last = cmd_cons(tmp, sym_nil)))
- {
- result = NULL;
- break;
- }
- list = VCDR(list);
- last = &VCDR(*last);
- TEST_INT;
- if(INT_P)
- {
- result = NULL;
- break;
- }
- }
- if(result && last && !NILP(list))
- *last = cmd_eval(list);
- POPGC; POPGC;
- return(result);
- }
-
- /*
- * format of lambda-lists is something like,
- *
- * [{required-symbols}] [&optional {optional-symbols}] [&rest symbol]
- * [&aux {auxiliary-symbols}]
- *
- * NB: auxiliary symbols are set to nil.
- */
- static VALUE
- bindlambdalist(VALUE lambdaList, VALUE argList, int evalArgs)
- {
- #define STATE_REQUIRED 1
- #define STATE_OPTIONAL 2
- #define STATE_REST 3
- #define STATE_AUX 4
- VALUE boundlist = sym_nil;
- if(CONSP(lambdaList))
- {
- GCVAL gcv_boundlist;
- char state = STATE_REQUIRED;
- PUSHGC(gcv_boundlist, boundlist);
- while(CONSP(lambdaList) && SYMBOLP(VCAR(lambdaList)))
- {
- VALUE argobj;
- VALUE argspec = VCAR(lambdaList);
- if(VSTR(VSYM(argspec)->sym_Name)[0] == '&')
- {
- if(argspec == sym_amp_optional)
- {
- if(state > STATE_OPTIONAL)
- {
- cmd_signal(sym_invalid_lambda_list, LIST_1(lambdaList));
- goto error;
- }
- state = STATE_OPTIONAL;
- lambdaList = VCDR(lambdaList);
- continue;
- }
- else if(argspec == sym_amp_rest)
- {
- if(state > STATE_REST)
- {
- cmd_signal(sym_invalid_lambda_list, LIST_1(lambdaList));
- goto error;
- }
- state = STATE_REST;
- lambdaList = VCDR(lambdaList);
- continue;
- }
- else if(argspec == sym_amp_aux)
- {
- state = STATE_AUX;
- lambdaList = VCDR(lambdaList);
- continue;
- }
- }
- switch(state)
- {
- case STATE_REQUIRED:
- if(!CONSP(argList))
- {
- cmd_signal(sym_missing_arg, LIST_1(argspec));
- goto error;
- }
- /* FALL THROUGH */
- case STATE_OPTIONAL:
- if(CONSP(argList))
- {
- if(evalArgs)
- {
- if(!(argobj = cmd_eval(VCAR(argList))))
- goto error;
- }
- else
- argobj = VCAR(argList);
- argList = VCDR(argList);
- }
- else
- argobj = sym_nil;
- boundlist = bind_symbol(boundlist, argspec, argobj);
- break;
- case STATE_REST:
- if(evalArgs)
- {
- if(!(argobj = eval_list(argList)))
- goto error;
- }
- else
- argobj = argList;
- boundlist = bind_symbol(boundlist, argspec, argobj);
- state = STATE_AUX;
- break;
- case STATE_AUX:
- boundlist = bind_symbol(boundlist, argspec, sym_nil);
- }
- lambdaList = VCDR(lambdaList);
- TEST_INT;
- if(INT_P)
- goto error;
- }
- POPGC;
- }
- return(boundlist);
-
- error:
- POPGC;
- unbind_symbols(boundlist);
- return(NULL);
- }
-
- VALUE
- eval_lambda(VALUE lambdaExp, VALUE argList, bool evalArgs)
- {
- VALUE result = NULL;
- if(CONSP(VCDR(lambdaExp)))
- {
- VALUE boundlist;
- GCVAL gcv_lambdaExp, gcv_argList;
- PUSHGC(gcv_lambdaExp, lambdaExp);
- PUSHGC(gcv_argList, argList);
- lambdaExp = VCDR(lambdaExp);
- boundlist = bindlambdalist(VCAR(lambdaExp), argList, evalArgs);
- if(boundlist)
- {
- GCVAL gcv_boundlist;
- PUSHGC(gcv_boundlist, boundlist);
- result = cmd_progn(VCDR(lambdaExp));
- POPGC;
- unbind_symbols(boundlist);
- }
- else
- result = NULL;
- POPGC; POPGC;
- }
- return(result);
- }
-
- /* Autoloads a function, FUN is the symbol of the function, ALOAD-DEF is
- the `(autoload FILE-NAME ...)' object. This function may cause a gc.
- Returns the new function-value of FUN, or NULL for an error. */
- VALUE
- load_autoload(VALUE fun, VALUE aload_def)
- {
- if(!SYMBOLP(fun))
- {
- /* Unless the function we're calling is a symbol don't bother.
- (Because it wouldn't be possible to find the new definition.) */
- return(cmd_signal(sym_invalid_autoload,
- list_2(fun,
- MKSTR("Can only autoload from symbols"))));
- }
- else
- {
- VALUE autoload = VCDR(aload_def);
- if(CONSP(autoload))
- {
- /* trash the autoload defn, this way I make sure
- that we don't keep trying to autoload a function
- indefinitely. */
- GCVAL gcv_fun;
- VALUE tmp;
- PUSHGC(gcv_fun, fun);
- VCAR(aload_def) = sym_nil;
- tmp = cmd_load(VCAR(autoload), sym_t, sym_nil, sym_nil);
- POPGC;
- if(tmp && !NILP(tmp))
- return(cmd_symbol_function(fun, sym_nil));
- }
- return(cmd_signal(sym_invalid_autoload, LIST_1(fun)));
- }
- }
-
- static VALUE
- eval(VALUE obj)
- {
- VALUE result = NULL;
- GCVAL gcv_obj;
- #ifdef MINSTACK
- if(STK_SIZE <= MINSTACK)
- {
- STK_WARN("eval");
- return(cmd_signal(sym_stack_error, sym_nil));
- }
- #endif
- if(++lisp_depth > max_lisp_depth)
- {
- cmd_signal(sym_error, LIST_1(MKSTR("max-lisp-depth exceeded, possible infite recursion?")));
- }
- else if(obj)
- {
- switch(VTYPE(obj))
- {
- VALUE funcobj, arglist;
- int type;
- case V_Symbol:
- result = cmd_symbol_value(obj, sym_nil);
- break;
-
- case V_Cons:
- again:
- funcobj = VCAR(obj);
- arglist = VCDR(obj);
- if(SYMBOLP(funcobj))
- {
- if(VSYM(funcobj)->sym_Flags & SF_DEBUG)
- single_step_flag = TRUE;
- funcobj = cmd_symbol_function(funcobj, sym_nil);
- if(!funcobj)
- goto end;
- }
- switch(type = VTYPE(funcobj))
- {
- VALUE alist, car, args[5];
- GCVALN gcvn_args;
- int i, nargs;
- case V_Subr0:
- result = VSUBR0FUN(funcobj)();
- break;
-
- case V_SubrN:
- PUSHGC(gcv_obj, obj);
- alist = eval_list(arglist);
- if(alist)
- result = VSUBRNFUN(funcobj)(alist);
- POPGC;
- break;
-
- case V_Subr1:
- nargs = 1;
- args[0] = sym_nil;
- goto do_subr;
-
- case V_Subr2:
- nargs = 2;
- args[0] = args[1] = sym_nil;
- goto do_subr;
-
- case V_Subr3:
- nargs = 3;
- args[0] = args[1] = args[2] = sym_nil;
- goto do_subr;
-
- case V_Subr4:
- nargs = 4;
- args[0] = args[1] = args[2] = args[3] = sym_nil;
- goto do_subr;
-
- case V_Subr5:
- nargs = 5;
- args[0] = args[1] = args[2] = args[3] = args[4] = sym_nil;
- do_subr:
- PUSHGCN(gcvn_args, args, nargs);
- PUSHGC(gcv_obj, obj);
- for(i = 0; i < nargs; i++)
- {
- if(CONSP(arglist))
- {
- if(!(args[i] = cmd_eval(VCAR(arglist))))
- {
- POPGC; POPGCN;
- goto end;
- }
- arglist = VCDR(arglist);
- }
- else
- break;
- }
- POPGC; POPGCN;
- switch(type)
- {
- case V_Subr1:
- result = VSUBR1FUN(funcobj)(args[0]);
- break;
- case V_Subr2:
- result = VSUBR2FUN(funcobj)(args[0], args[1]);
- break;
- case V_Subr3:
- result = VSUBR3FUN(funcobj)(args[0], args[1], args[2]);
- break;
- case V_Subr4:
- result = VSUBR4FUN(funcobj)(args[0], args[1],
- args[2], args[3]);
- break;
- case V_Subr5:
- result = VSUBR5FUN(funcobj)(args[0], args[1], args[2],
- args[3], args[4]);
- break;
- }
- break;
-
- case V_SF:
- result = VSFFUN(funcobj)(arglist);
- break;
-
- case V_Cons:
- car = VCAR(funcobj);
- if(car == sym_lambda)
- {
- struct LispCall lc;
- lc.lc_Next = lisp_call_stack;
- lc.lc_Fun = VCAR(obj);
- lc.lc_Args = arglist;
- lc.lc_ArgsEvalledP = sym_nil;
- lisp_call_stack = &lc;
- if(!(result = eval_lambda(funcobj, arglist, TRUE))
- && throw_value && (VCAR(throw_value) == sym_defun))
- {
- result = VCDR(throw_value);
- throw_value = NULL;
- }
- lisp_call_stack = lc.lc_Next;
- }
- else if(car == sym_macro)
- {
- funcobj = VCDR(funcobj);
- if(CONSP(funcobj) && (VCAR(funcobj) == sym_lambda))
- {
- VALUE form = eval_lambda(funcobj, arglist, FALSE);
- if(form)
- result = cmd_eval(form);
- }
- else
- cmd_signal(sym_invalid_macro, LIST_1(VCAR(obj)));
- }
- else if(car == sym_autoload)
- {
- PUSHGC(gcv_obj, obj);
- result = load_autoload(VCAR(obj), funcobj);
- POPGC;
- if(result)
- {
- result = NULL;
- goto again;
- }
- }
- else
- cmd_signal(sym_invalid_function, LIST_1(VCAR(obj)));
- break;
-
- default:
- cmd_signal(sym_invalid_function, LIST_1(VCAR(obj)));
- break;
- }
- break;
-
- case V_Var:
- if(!(result = VVARFUN(obj)(NULL)))
- cmd_signal(sym_void_value, LIST_1(obj));
- break;
-
- default:
- result = obj;
- break;
- }
- }
- else
- cmd_signal(sym_error, LIST_1(MKSTR("Void object to `eval'")));
- /* In case I missed a non-local exit somewhere. */
- if(result && throw_value)
- result = NULL;
- end:
- lisp_depth--;
- return(result);
- }
-
- _PR VALUE cmd_eval(VALUE);
- DEFUN("eval", cmd_eval, subr_eval, (VALUE obj), V_Subr1, DOC_eval) /*
- ::doc:eval::
- eval FORM
-
- Evaluates FORM and returns its value.
- ::end:: */
- {
- static int DbDepth;
- bool newssflag = TRUE;
- VALUE result;
-
- TEST_INT;
- if(INT_P || !curr_vw)
- return(NULL);
-
- if((data_after_gc >= gc_threshold) && !gc_inhibit)
- {
- GCVAL gcv_obj;
- PUSHGC(gcv_obj, obj);
- cmd_garbage_collect(sym_t);
- POPGC;
- }
-
- if(!single_step_flag)
- return(eval(obj));
-
- DbDepth++;
- result = NULL;
- if(VSYM(sym_debug_entry)->sym_Function)
- {
- VALUE dbres;
- VALUE dbargs = cmd_cons(obj, cmd_cons(make_number(DbDepth), sym_nil));
- if(dbargs)
- {
- GCVAL gcv_dbargs;
- PUSHGC(gcv_dbargs, dbargs);
- single_step_flag = FALSE;
- if((dbres = funcall(sym_debug_entry, dbargs)) && CONSP(dbres))
- {
- switch(VNUM(VCAR(dbres)))
- {
- case 1:
- /* single step cdr and following stuff */
- single_step_flag = TRUE;
- result = eval(VCDR(dbres));
- single_step_flag = FALSE;
- break;
- case 2:
- /* run through cdr and step following */
- result = eval(VCDR(dbres));
- break;
- case 3:
- /* run cdr and following */
- result = eval(VCDR(dbres));
- newssflag = FALSE;
- break;
- case 4:
- /* result = cdr */
- single_step_flag = TRUE;
- result = VCDR(dbres);
- single_step_flag = FALSE;
- break;
- }
- if(result)
- {
- if(VSYM(sym_debug_exit)->sym_Function)
- {
- VCAR(dbargs) = result;
- if(!(dbres = funcall(sym_debug_exit, dbargs)))
- result = NULL;
- }
- }
- }
- POPGC;
- }
- }
- else
- {
- cmd_signal(sym_error, LIST_1(MKSTR("No debugger installed")));
- newssflag = FALSE;
- result = NULL;
- }
- DbDepth--;
- single_step_flag = newssflag;
- return(result);
- }
-
- VALUE
- funcall(VALUE fun, VALUE arglist)
- {
- int type;
- VALUE result = NULL, origfun = fun;
- GCVAL gcv_origfun, gcv_arglist;
-
- TEST_INT;
- if(INT_P || !curr_vw)
- return(NULL);
-
- #ifdef MINSTACK
- if(STK_SIZE <= MINSTACK)
- {
- STK_WARN("funcall");
- return(cmd_signal(sym_stack_error, sym_nil));
- }
- #endif
-
- if(++lisp_depth > max_lisp_depth)
- {
- lisp_depth--;
- return(cmd_signal(sym_error, LIST_1(MKSTR("max-lisp-depth exceeded, possible infite recursion?"))));
- }
-
- if((data_after_gc >= gc_threshold) && !gc_inhibit)
- {
- PUSHGC(gcv_origfun, origfun);
- PUSHGC(gcv_arglist, arglist);
- cmd_garbage_collect(sym_t);
- POPGC; POPGC;
- }
-
- again:
- if(SYMBOLP(fun))
- {
- if(VSYM(fun)->sym_Flags & SF_DEBUG)
- single_step_flag = TRUE;
- fun = cmd_symbol_function(fun, sym_nil);
- if(!fun)
- goto end;
- }
- switch(type = VTYPE(fun))
- {
- int i, nargs;
- VALUE car, argv[5];
- case V_SubrN:
- result = VSUBRNFUN(fun)(arglist);
- break;
-
- case V_Subr0:
- result = VSUBR0FUN(fun)();
- break;
-
- case V_Subr1:
- nargs = 1;
- argv[0] = sym_nil;
- goto do_subr;
-
- case V_Subr2:
- nargs = 2;
- argv[0] = argv[1] = sym_nil;
- goto do_subr;
-
- case V_Subr3:
- nargs = 3;
- argv[0] = argv[1] = argv[2] = sym_nil;
- goto do_subr;
-
- case V_Subr4:
- nargs = 4;
- argv[0] = argv[1] = argv[2] = argv[3] = sym_nil;
- goto do_subr;
-
- case V_Subr5:
- nargs = 5;
- argv[0] = argv[1] = argv[2] = argv[3] = argv[4] = sym_nil;
- do_subr:
- for(i = 0; i < nargs; i++)
- {
- if(CONSP(arglist))
- {
- argv[i] = VCAR(arglist);
- arglist = VCDR(arglist);
- }
- else
- break;
- }
- switch(type)
- {
- case V_Subr1:
- result = VSUBR1FUN(fun)(argv[0]);
- break;
- case V_Subr2:
- result = VSUBR2FUN(fun)(argv[0], argv[1]);
- break;
- case V_Subr3:
- result = VSUBR3FUN(fun)(argv[0], argv[1], argv[2]);
- break;
- case V_Subr4:
- result = VSUBR4FUN(fun)(argv[0], argv[1], argv[2], argv[3]);
- break;
- case V_Subr5:
- result = VSUBR5FUN(fun)(argv[0], argv[1], argv[2],
- argv[3], argv[4]);
- break;
- }
- break;
-
- case V_Cons:
- car = VCAR(fun);
- if(car == sym_lambda)
- {
- struct LispCall lc;
- lc.lc_Next = lisp_call_stack;
- lc.lc_Fun = origfun;
- lc.lc_Args = arglist;
- lc.lc_ArgsEvalledP = sym_t;
- lisp_call_stack = &lc;
- if(!(result = eval_lambda(fun, arglist, FALSE))
- && throw_value && (VCAR(throw_value) == sym_defun))
- {
- result = VCDR(throw_value);
- throw_value = NULL;
- }
- lisp_call_stack = lc.lc_Next;
- }
- else if(car == sym_autoload)
- {
- PUSHGC(gcv_origfun, origfun);
- PUSHGC(gcv_arglist, arglist);
- car = load_autoload(origfun, fun);
- POPGC; POPGC;
- if(car)
- {
- fun = origfun;
- goto again;
- }
- }
- else
- cmd_signal(sym_invalid_function, LIST_1(fun));
- break;
- default:
- cmd_signal(sym_invalid_function, LIST_1(fun));
- }
- /* In case I missed a non-local exit somewhere. */
- if(result && throw_value)
- result = NULL;
- end:
- lisp_depth--;
- return(result);
- }
-
- _PR VALUE cmd_funcall(VALUE);
- DEFUN("funcall", cmd_funcall, subr_funcall, (VALUE args), V_SubrN, DOC_funcall) /*
- ::doc:funcall::
- funcall FUNCTION ARGS...
-
- Calls FUNCTION with arguments ARGS... and returns its result.
- ::end:: */
- {
- if(!CONSP(args))
- return(cmd_signal(sym_bad_arg, list_2(sym_nil, make_number(1))));
- return(funcall(VCAR(args), VCDR(args)));
- }
-
- _PR VALUE cmd_progn(VALUE);
- DEFUN("progn", cmd_progn, subr_progn, (VALUE args), V_SF, DOC_progn) /*
- ::doc:progn::
- progn FORMS...
-
- Eval's each of the FORMS in order returning the value of the last
- one.
- ::end:: */
- {
- VALUE result = sym_nil;
- GCVAL gcv_args;
- PUSHGC(gcv_args, args);
- while(CONSP(args))
- {
- result = cmd_eval(VCAR(args));
- args = VCDR(args);
- TEST_INT;
- if(!result || INT_P)
- break;
- }
- if(result && !NILP(args))
- result = cmd_eval(args);
- POPGC;
- return(result);
- }
-
- VALUE
- eval_string(u_char *str, bool isValString)
- {
- VALUE res = sym_nil;
- VALUE stream = cmd_cons(make_number(0), sym_nil);
- if(stream)
- {
- VALUE obj;
- int c;
- GCVAL gcv_stream;
- if(isValString)
- VCDR(stream) = VAL(STRING_HDR(str));
- else
- {
- if(!(VCDR(stream) = string_dup(str)))
- return(NULL);
- }
- PUSHGC(gcv_stream, stream);
- obj = sym_nil;
- c = stream_getc(stream);
- while(res && (c != EOF) && (obj = readl(stream, &c)))
- {
- res = cmd_eval(obj);
- TEST_INT;
- if(INT_P)
- res = NULL;
- }
- POPGC;
- }
- return(res);
- }
-
- VALUE
- call_lisp0(VALUE function)
- {
- return(funcall(function, sym_nil));
- }
-
- VALUE
- call_lisp1(VALUE function, VALUE arg1)
- {
- return(funcall(function, LIST_1(arg1)));
- }
-
- VALUE
- call_lisp2(VALUE function, VALUE arg1, VALUE arg2)
- {
- return(funcall(function, LIST_2(arg1, arg2)));
- }
-
- void
- lisp_prin(VALUE strm, VALUE obj)
- {
- switch(VTYPE(obj))
- {
- u_char tbuf[40];
- int j;
-
- case V_Number:
- sprintf(tbuf, "%ld", VNUM(obj));
- stream_puts(strm, tbuf, -1, FALSE);
- break;
-
- case V_Cons:
- stream_putc(strm, '\(');
- while(CONSP(VCDR(obj)))
- {
- print_val(strm, VCAR(obj));
- obj = VCDR(obj);
- stream_putc(strm, ' ');
- TEST_INT;
- if(INT_P)
- return;
- }
- print_val(strm, VCAR(obj));
- if(!NILP(VCDR(obj)))
- {
- stream_puts(strm, " . ", -1, FALSE);
- print_val(strm, VCDR(obj));
- }
- stream_putc(strm, ')');
- break;
-
- case V_Vector:
- stream_putc(strm, '\[');
- for(j = 0; j < VVECT(obj)->vc_Size; j++)
- {
- if(VVECT(obj)->vc_Array[j])
- print_val(strm, VVECT(obj)->vc_Array[j]);
- else
- stream_puts(strm, "#<void>", -1, FALSE);
- if(j != (VVECT(obj)->vc_Size - 1))
- stream_putc(strm, ' ');
- }
- stream_putc(strm, ']');
- break;
-
- case V_Subr0:
- case V_Subr1:
- case V_Subr2:
- case V_Subr3:
- case V_Subr4:
- case V_Subr5:
- case V_SubrN:
- sprintf(tbuf, "#<subr %s>", VSTR(VXSUBR(obj)->subr_Name));
- stream_puts(strm, tbuf, -1, FALSE);
- break;
-
- case V_SF:
- sprintf(tbuf, "#<special-form %s>", VSTR(VXSUBR(obj)->subr_Name));
- stream_puts(strm, tbuf, -1, FALSE);
- break;
-
- case V_Var:
- sprintf(tbuf, "#<var %s>", VSTR(VXSUBR(obj)->subr_Name));
- stream_puts(strm, tbuf, -1, FALSE);
- break;
-
- #ifndef HAVE_SUBPROCESSES
- case V_Process:
- stream_puts(strm, "#<process>", -1, FALSE);
- break;
- #endif
-
- case V_Void:
- stream_puts(strm, "#<void>", -1, FALSE);
- break;
-
- default:
- stream_puts(strm, "#<unknown object type>", -1, FALSE);
- }
- }
-
- void
- string_princ(VALUE strm, VALUE obj)
- {
- stream_puts(strm, VSTR(obj), -1, TRUE);
- }
-
- void
- string_print(VALUE strm, VALUE obj)
- {
- int len = STRING_LEN(obj);
- u_char *s = VSTR(obj);
- u_char c;
- stream_putc(strm, '\"');
- while(len-- > 0)
- {
- switch(c = *s++)
- {
- #ifdef PRINT_ESCAPE_TAB_NL
- case '\t':
- stream_puts(strm, "\\t", 2, FALSE);
- break;
- case '\n':
- stream_puts(strm, "\\n", 2, FALSE);
- break;
- #endif
- case '\\':
- stream_puts(strm, "\\\\", 2, FALSE);
- break;
- case '"':
- stream_puts(strm, "\\\"", 2, FALSE);
- break;
- default:
- stream_putc(strm, (int)c);
- }
- }
- stream_putc(strm, '\"');
- }
-
- VALUE
- find_member_by_index(VALUE list, int index)
- {
- while((--index) && CONSP(list))
- {
- list = VCDR(list);
- TEST_INT;
- if(INT_P)
- return(sym_nil);
- }
- if(CONSP(list))
- return(VCAR(list));
- return(sym_nil);
- }
-
- VALUE
- move_down_list(VALUE list, int nodes)
- {
- while((nodes--) && CONSP(list))
- {
- list = VCDR(list);
- TEST_INT;
- if(INT_P)
- return(NULL);
- }
- return(list);
- }
-
- int
- list_length(VALUE list)
- {
- int i = 0;
- while(CONSP(list))
- {
- i++;
- list = VCDR(list);
- TEST_INT;
- if(INT_P)
- return(i);
- }
- return(i);
- }
-
- VALUE
- copy_list(VALUE list)
- {
- VALUE result;
- VALUE *last = &result;
- while(CONSP(list))
- {
- if(!(*last = cmd_cons(VCAR(list), sym_nil)))
- return(NULL);
- list = VCDR(list);
- last = &VCDR(*last);
- TEST_INT;
- if(INT_P)
- return(NULL);
- }
- *last = list;
- return(result);
- }
-
- /*
- * Used for easy handling of `var' objects
- */
- VALUE
- handle_var_int(VALUE val, long *data)
- {
- if(val)
- {
- if(NUMBERP(val))
- *data = VNUM(val);
- return(NULL);
- }
- return(make_number(*data));
- }
-
- _PR VALUE cmd_break(void);
- DEFUN("break", cmd_break, subr_break, (void), V_Subr0, DOC_break) /*
- ::doc:break::
- break
-
- The next form to be evaluated will be done so through the Lisp debugger.
- ::end:: */
- {
- single_step_flag = TRUE;
- return(sym_t);
- }
-
- _PR VALUE cmd_step(VALUE);
- DEFUN_INT("step", cmd_step, subr_step, (VALUE form), V_Subr1, DOC_step, "xForm to step through") /*
- ::doc:step::
- step FORM
-
- Use the Lisp debugger to evaluate FORM.
- ::end:: */
- {
- VALUE res;
- bool oldssf = single_step_flag;
- single_step_flag = TRUE;
- res = cmd_eval(form);
- single_step_flag = oldssf;
- return(res);
- }
-
- _PR VALUE cmd_macroexpand(VALUE, VALUE);
- DEFUN("macroexpand", cmd_macroexpand, subr_macroexpand, (VALUE form, VALUE env), V_Subr2, DOC_macroexpand) /*
- ::doc:macroexpand::
- macroexpand FORM [ENVIRONMENT]
-
- If FORM is a macro call, expand it until it isn't. If ENVIRONMENT is
- specified it is an alist of `(MACRO-NAME . DEFINITION)'.
- ::end:: */
- {
- VALUE car;
- GCVAL gcv_form, gcv_env, gcv_car;
- PUSHGC(gcv_form, form);
- PUSHGC(gcv_env, env);
- PUSHGC(gcv_car, car);
- top:
- if(CONSP(form))
- {
- car = VCAR(form);
- if(SYMBOLP(car))
- {
- VALUE tmp;
- if(!NILP(env) && (tmp = cmd_assq(car, env)) && CONSP(tmp))
- {
- car = VCDR(tmp);
- form = eval_lambda(car, VCDR(form), FALSE);
- if(form)
- goto top;
- }
- else
- {
- car = cmd_symbol_function(car, sym_t);
- if(VOIDP(car) || NILP(car))
- goto end;
- if(CONSP(car) && (VCAR(car) == sym_macro)
- && (VCAR(VCDR(car)) == sym_lambda))
- {
- form = eval_lambda(VCDR(car), VCDR(form), FALSE);
- if(form)
- goto top;
- }
- }
- }
- }
- end:
- POPGC; POPGC; POPGC;
- return(form);
- }
-
- _PR VALUE cmd_get_doc_string(VALUE idx);
- DEFUN("get-doc-string", cmd_get_doc_string, subr_get_doc_string, (VALUE idx), V_Subr1, DOC_get_doc_string) /*
- ::doc:get_doc_string::
- get-doc-string INDEX
-
- Returns the document-string number INDEX.
- ::end:: */
- {
- DECLARE1(idx, NUMBERP);
- return(cmd_read_file_from_to(MKSTR(DOC_FILE), idx, make_number((int)'\f')));
- }
-
- _PR VALUE cmd_add_doc_string(VALUE str);
- DEFUN("add-doc-string", cmd_add_doc_string, subr_add_doc_string, (VALUE str), V_Subr1, DOC_add_doc_string) /*
- ::doc:add_doc_string::
- add-doc-string STRING
-
- Appends STRING to the end of the doc-file and returns the index position of
- it's first character (a number).
- ::end:: */
- {
- FILE *docs;
- DECLARE1(str, STRINGP);
- docs = fopen(DOC_FILE, "a");
- if(docs)
- {
- int len = STRING_LEN(str);
- VALUE idx = make_number(ftell(docs));
- if(fwrite(VSTR(str), 1, len, docs) != len)
- {
- return(cmd_signal(sym_file_error,
- LIST_1(MKSTR("Can't append to doc-file"))));
- }
- putc('\f', docs);
- fclose(docs);
- return(idx);
- }
- return(cmd_signal(sym_file_error,
- list_2(MKSTR("Can't open doc-file"), MKSTR(DOC_FILE))));
- }
-
- _PR VALUE var_debug_on_error(VALUE val);
- DEFUN("debug-on-error", var_debug_on_error, subr_debug_on_error, (VALUE val), V_Var, DOC_debug_on_error) /*
- ::doc:debug_on_error::
- When an error is signalled this variable controls whether or not to enter the
- Lisp debugger immediately. If the variable's value is t or a list of symbols
- - one of which is the signalled error symbol - the debugger is entered.
- See `signal'.
- ::end:: */
- {
- if(val)
- debug_on_error = val;
- return(debug_on_error);
- }
-
- _PR VALUE cmd_signal(VALUE error, VALUE data);
- DEFUN("signal", cmd_signal, subr_signal, (VALUE error, VALUE data), V_Subr2, DOC_signal) /*
- ::doc:signal::
- signal ERROR-SYMBOL DATA
-
- Signal that an error has happened. ERROR-SYMBOL is the name of a symbol
- classifying the type of error, it should have a property `error-message' (a
- string) with a short description of the error message.
- DATA is a list of objects which are relevant to the error -- they will
- be made available to any error-handler or printed by the default error
- -handler.
- ::end:: */
- {
- VALUE tmp, errlist;
- /* Can only have one error at once. */
- if(throw_value)
- return(NULL);
- DECLARE1(error, SYMBOLP);
-
- errlist = cmd_cons(error, data);
-
- if(((debug_on_error == sym_t)
- || (CONSP(debug_on_error) && (tmp = cmd_memq(error, debug_on_error))
- && !NILP(tmp)))
- && VSYM(sym_debug_error_entry)->sym_Function)
- {
- /* Enter debugger. */
- VALUE old_debug_on_error = debug_on_error;
- GCVAL gcv_odoe;
- bool oldssflag = single_step_flag;
- debug_on_error = sym_nil;
- single_step_flag = FALSE;
- PUSHGC(gcv_odoe, old_debug_on_error);
- tmp = funcall(sym_debug_error_entry, cmd_cons(errlist, sym_nil));
- POPGC;
- debug_on_error = old_debug_on_error;
- if(tmp && (tmp == sym_t))
- single_step_flag = TRUE;
- else
- single_step_flag = oldssflag;
- }
- throw_value = cmd_cons(sym_error, errlist);
- return(NULL);
- }
-
- _PR VALUE cmd_error_protect(VALUE args);
- DEFUN("error-protect", cmd_error_protect, subr_error_protect, (VALUE args), V_SF, DOC_error_protect) /*
- ::doc:error_protect::
- error-protect FORM HANDLERS...
-
- Evaluates FORM with error-handlers in place, if no errors occur return the
- value returned by FORM, else the value of whichever handler's body was
- evaluated.
- Each HANDLER is a list looking like `(ERROR-SYMBOL BODY...)'. If an error
- of type ERROR-SYMBOL occurs BODY is evaluated with the symbol `error-info'
- temporarily set to `(ERROR-SYMBOL . DATA)' (these were the arguments given to
- the `signal' which caused the error).
- ::end:: */
- {
- VALUE res;
- GCVAL gcv_args;
- if(!CONSP(args))
- return(cmd_signal(sym_bad_arg, list_2(sym_nil, make_number(1))));
- PUSHGC(gcv_args, args);
- if(!(res = cmd_eval(VCAR(args))) && throw_value
- && (VCAR(throw_value) == sym_error))
- {
- /* an error. */
- VALUE errorsym = VCAR(VCDR(throw_value)), handlers = VCDR(args);
- while(CONSP(handlers) && CONSP(VCAR(handlers)))
- {
- VALUE handler = VCAR(handlers);
- if((VCAR(handler) == errorsym) || (VCAR(handler) == sym_error))
- {
- VALUE bindlist = sym_nil;
- GCVAL gcv_bindlist;
- bindlist = bind_symbol(sym_nil, sym_error_info, VCDR(throw_value));
- throw_value = NULL;
- PUSHGC(gcv_bindlist, bindlist);
- res = cmd_progn(VCDR(handler));
- POPGC;
- unbind_symbols(bindlist);
- break;
- }
- handlers = VCDR(handlers);
- TEST_INT;
- if(INT_P)
- {
- res = NULL;
- break;
- }
- }
- }
- POPGC;
- return(res);
- }
-
- void
- handle_error(VALUE error, VALUE data)
- {
- VALUE errstr;
- cursor(curr_vw, CURS_OFF);
- cmd_beep();
- if(!(errstr = cmd_get(error, sym_error_message)) || !STRINGP(errstr))
- errstr = MKSTR("Unknown error");
- switch(list_length(data))
- {
- case 0:
- cmd_format(list_3(sym_t, MKSTR("%s"), errstr));
- break;
- case 1:
- cmd_format(list_4(sym_t, MKSTR("%s: %s"), errstr, VCAR(data)));
- break;
- case 2:
- cmd_format(list_5(sym_t, MKSTR("%s: %s, %s"), errstr,
- VCAR(data), VCAR(VCDR(data))));
- break;
- case 3:
- cmd_format(cmd_cons(sym_t, list_5(MKSTR("%s: %s, %s, %s"), errstr,
- VCAR(data), VCAR(VCDR(data)), VCAR(VCDR(VCDR(data))))));
- break;
- default:
- cmd_format(list_3(sym_t, MKSTR("%s: ..."), errstr));
- }
- refresh_world();
- cursor(curr_vw, CURS_ON);
- }
-
- VALUE
- signal_arg_error(VALUE obj, int argNum)
- {
- return(cmd_signal(sym_bad_arg, list_2(obj, make_number(argNum))));
- }
-
- VALUE
- mem_error(void)
- {
- return(cmd_signal(sym_no_memory, sym_nil));
- }
-
- _PR VALUE cmd_backtrace(VALUE strm);
- DEFUN("backtrace", cmd_backtrace, subr_backtrace, (VALUE strm), V_Subr1, DOC_backtrace) /*
- ::doc:backtrace::
- backtrace [STREAM]
-
- Prints a backtrace of the current Lisp call stack to STREAM (or to
- `standard-output').
- The format is something like:
- FUNCTION (ARGLIST) ARGS-EVALLED-P
- where ARGS-EVALLED-P is either `t' or `nil', depending on whether or not
- ARGLIST had been evaluated or not before being put into the stack.
- ::end:: */
- {
- struct LispCall *lc;
- if(NILP(strm)
- && !(strm = cmd_symbol_value(sym_standard_output, sym_nil)))
- {
- return(cmd_signal(sym_bad_arg, list_2(strm, make_number(1))));
- }
- lc = lisp_call_stack;
- while(lc)
- {
- stream_putc(strm, '\n');
- print_val(strm, lc->lc_Fun);
- stream_putc(strm, ' ');
- print_val(strm, lc->lc_Args);
- stream_putc(strm, ' ');
- print_val(strm, lc->lc_ArgsEvalledP);
- lc = lc->lc_Next;
- }
- return(sym_t);
- }
-
- _PR VALUE var_max_lisp_depth(VALUE val);
- DEFUN("max-lisp-depth", var_max_lisp_depth, subr_max_lisp_depth, (VALUE val), V_Var, DOC_max_lisp_depth) /*
- ::doc:max_lisp_depth::
- The maximum number of times that eval and funcall can be called recursively.
- This is intended to stop infinite recursion, if the default value of 250 is
- too small (you get errors in normal use) set it to something larger.
- ::end:: */
- {
- return(handle_var_int(val, &max_lisp_depth));
- }
-
- void
- lisp_init(void)
- {
- INTERN(sym_quote, "quote");
- INTERN(sym_lambda, "lambda");
- INTERN(sym_macro, "macro");
- INTERN(sym_autoload, "autoload");
- INTERN(sym_function, "function");
- INTERN(sym_standard_input, "standard-input");
- INTERN(sym_standard_output, "standard-output");
- INTERN(sym_defun, "defun");
- INTERN(sym_debug_entry, "debug-entry");
- INTERN(sym_debug_exit, "debug-exit");
- INTERN(sym_debug_error_entry, "debug-error-entry");
- INTERN(sym_amp_optional, "&optional");
- INTERN(sym_amp_rest, "&rest");
- INTERN(sym_amp_aux, "&aux");
- mark_static(&throw_value);
- ADD_SUBR(subr_eval);
- ADD_SUBR(subr_funcall);
- ADD_SUBR(subr_progn);
- ADD_SUBR(subr_break);
- ADD_SUBR(subr_step);
- ADD_SUBR(subr_macroexpand);
- ADD_SUBR(subr_get_doc_string);
- ADD_SUBR(subr_add_doc_string);
- ADD_SUBR(subr_debug_on_error);
- ADD_SUBR(subr_signal);
- ADD_SUBR(subr_error_protect);
- ADD_SUBR(subr_backtrace);
- ADD_SUBR(subr_max_lisp_depth);
-
- /* Stuff for error-handling */
- debug_on_error = sym_nil;
- INTERN(sym_error_message, "error-message");
- INTERN(sym_error, "error");
- cmd_put(sym_error, sym_error_message, MKSTR("Error"));
- INTERN(sym_invalid_function, "invalid-function");
- cmd_put(sym_invalid_function, sym_error_message, MKSTR("Invalid function"));
- INTERN(sym_void_function, "void-function");
- cmd_put(sym_void_function, sym_error_message, MKSTR("Function value is void"));
- INTERN(sym_void_value, "void-value");
- cmd_put(sym_void_value, sym_error_message, MKSTR("Value as variable is void"));
- INTERN(sym_bad_arg, "bad-arg");
- cmd_put(sym_bad_arg, sym_error_message, MKSTR("Bad argument"));
- INTERN(sym_invalid_read_syntax, "invalid-read-syntax");
- cmd_put(sym_invalid_read_syntax, sym_error_message, MKSTR("Invalid read syntax"));
- INTERN(sym_end_of_stream, "end-of-stream");
- cmd_put(sym_end_of_stream, sym_error_message, MKSTR("Premature end of stream"));
- INTERN(sym_invalid_lambda_list, "invalid-lambda-list");
- cmd_put(sym_invalid_lambda_list, sym_error_message, MKSTR("Invalid lambda-list"));
- INTERN(sym_missing_arg, "missing-arg");
- cmd_put(sym_missing_arg, sym_error_message, MKSTR("Required argument missing"));
- INTERN(sym_invalid_macro, "invalid-macro");
- cmd_put(sym_invalid_macro, sym_error_message, MKSTR("Invalid macro definition"));
- INTERN(sym_invalid_autoload, "invalid-autoload");
- cmd_put(sym_invalid_autoload, sym_error_message, MKSTR("Invalid autoload definition"));
- INTERN(sym_no_catcher, "no-catcher");
- cmd_put(sym_no_catcher, sym_error_message, MKSTR("No catch'er for throw"));
- INTERN(sym_buffer_read_only, "buffer-read-only");
- cmd_put(sym_buffer_read_only, sym_error_message, MKSTR("Buffer is read-only"));
- INTERN(sym_bad_event_desc, "bad_event_desc");
- cmd_put(sym_bad_event_desc, sym_error_message, MKSTR("Invalid event description"));
- INTERN(sym_file_error, "file-error");
- cmd_put(sym_file_error, sym_error_message, MKSTR("File error"));
- INTERN(sym_invalid_stream, "invalid-stream");
- cmd_put(sym_invalid_stream, sym_error_message, MKSTR("Invalid stream"));
- INTERN(sym_setting_constant, "setting-constant");
- cmd_put(sym_setting_constant, sym_error_message, MKSTR("Attempt to set value of constant"));
- INTERN(sym_process_error, "process-error");
- cmd_put(sym_process_error, sym_error_message, MKSTR("Process error"));
- INTERN(sym_invalid_area, "invalid-area");
- cmd_put(sym_invalid_area, sym_error_message, MKSTR("Invalid area"));
- #ifdef MINSTACK
- INTERN(sym_stack_error, "stack-error");
- cmd_put(sym_stack_error, sym_error_message, MKSTR("Stack overflow"));
- #endif
- INTERN(sym_no_memory, "no-memory");
- cmd_put(sym_no_memory, sym_error_message, MKSTR("No free memory"));
- INTERN(sym_user_interrupt, "user-interrupt");
- cmd_put(sym_user_interrupt, sym_error_message, MKSTR("User interrupt!"));
- INTERN(sym_error_info, "error-info");
-
- int_cell = cmd_cons(sym_user_interrupt, sym_nil);
- mark_static(&int_cell);
- }
-
-