/* xldebug - xlisp debugging support */
/* Copyright (c) 1989, by David Michael Betz. */
/* You may give out copies of this software; for conditions see the file */
/* COPYING included with this distribution. */
#include "xlisp.h"
/* forward declarations */
LOCAL VOID breakloop P5H(char *, char *, char *, LVAL, int);
#ifdef CONDITIONS
LOCAL VOID conditionhook P3H(char *, char *, LVAL);
#endif /* CONDITIONS */
/* xlabort - xlisp serious error handler */
VOID xlabort P1C(char *, emsg)
{
xlsignal(emsg,s_unbound);
xlerrprint("error",NULL,emsg,s_unbound);
xlbrklevel();
}
/* xlbreak - enter a break loop */
VOID xlbreak P2C(char *, emsg, LVAL, arg)
{
breakloop("break","return from BREAK",emsg,arg,TRUE);
}
/* xlfail - xlisp error handler */
VOID xlfail P1C(char *, emsg)
{
xlerror(emsg,s_unbound);
}
/* xlerror - handle a fatal error */
LVAL xlerror P2C(char *, emsg, LVAL, arg)
{
/** This is an incredible hack. If an error occurs in
initialization we are in big trouble. The most common reason is
that on this hardware division by zero causes a SIGFPE. This
really needs to be dealt with in configure. **/
if (s_breakenable == NULL) {
if (strcmp(emsg, "floating point error")==0)
xoserror("floating point error, probably in computing IEEE infinity"
"--check how to prevent floating point division by zero"
" from raising a SIGFPE on your system");
else xoserror(emsg);
exit(1);
}
#ifdef CONDITIONS
if (s_condition_hook != NULL && getvalue(s_condition_hook) != NIL)
conditionhook(NULL, emsg, arg);
else
#endif /* CONDITIONS */
if (!null(getvalue(s_breakenable)))
breakloop("error",NULL,emsg,arg,FALSE);
else {
xlsignal(emsg,arg);
xlerrprint("error",NULL,emsg,arg);
xlbrklevel();
}
return NIL; /* actually doesn't return */
}
/* xlcerror - handle a recoverable error */
VOID xlcerror P3C(char *, cmsg, char *, emsg, LVAL, arg)
{
#ifdef CONDITIONS
if (s_condition_hook != NULL && getvalue(s_condition_hook) != NIL)
conditionhook(cmsg, emsg, arg);
else
#endif /* CONDITIONS */
if (!null(getvalue(s_breakenable)))
breakloop("error",cmsg,emsg,arg,TRUE);
else {
xlsignal(emsg,arg);
xlerrprint("error",NULL,emsg,arg);
xlbrklevel();
}
}
/* xlerrprint - print an error message */
VOID xlerrprint P4C(char *, hdr, char *, cmsg, char *, emsg, LVAL, arg)
{
/* TAA MOD -- start error message on a fresh line */
xlfreshline(getvalue(s_stderr));
/* print the error message */
sprintf(buf,"%s: %s",hdr,emsg);
errputstr(buf);
/* print the argument */
if (arg != s_unbound) {
errputstr(" - ");
errprint(arg);
}
/* no argument, just end the line */
else
errputstr("\n");
/* print the continuation message */
if (cmsg != NULL) {
sprintf(buf,"if continued: %s\n",cmsg);
errputstr(buf);
}
}
#ifdef NEED_TO_REPLACE_BREAKLOOP
/* $putpatch.c$: "MODULE_XLDBUG_C_BREAKLOOP_REPLACEMENT" */
#else
/* breakloop - the debug read-eval-print loop */
LOCAL VOID breakloop P5C(char *, hdr, char *, cmsg, char *, emsg, LVAL, arg, int, cflag)
{
LVAL expr,val;
CONTEXT cntxt;
int type;
/* print the error message */
xlerrprint(hdr,cmsg,emsg,arg);
/* handle running in batch mode */
if (batchmode) xlfatal("uncaught error");
/* flush the input buffer */
xlflush();
/* do the back trace */
if (!null(getvalue(s_tracenable))) {
val = getvalue(s_tlimit);
xlbaktrace(fixp(val) ? (int)getfixnum(val) : -1);
}
/* protect some pointers */
xlsave1(expr);
/* increment the debug level */
++xldebug;
/* debug command processing loop */
xlbegin(&cntxt, CF_BRKLEVEL|CF_CLEANUP|CF_CONTINUE, s_true);
for (type = 0; type == 0; ) {
/* setup the continue trap */
#ifdef CRAYCC
type = XL_SETJMP(cntxt.c_jmpbuf);
if (type != 0)
#else
if ((type = XL_SETJMP(cntxt.c_jmpbuf)) != 0)
#endif /* CRAYCC */
switch (type) {
case CF_CLEANUP:
continue;
case CF_BRKLEVEL:
type = 0;
break;
case CF_CONTINUE:
if (cflag) {
dbgputstr("[ continue from break loop ]\n");
continue;
}
else xlabort("this error can't be continued");
}
/* print a prompt */
#ifdef PACKAGES
{
LVAL pack = getvalue(s_package);
if (pack != xluserpack && goodpackagep(pack)) {
dbgputstr(getstring(xlpackagename(pack)));
dbgputstr(" ");
}
}
#endif /* PACKAGES */
sprintf(buf,"%d> ",xldebug);
dbgputstr(buf);
/* read an expression and check for eof */
if (!xlread(getvalue(s_debugio),&expr, FALSE, FALSE)) {
type = CF_CLEANUP;
break;
}
/* save the input expression */
xlrdsave(expr);
/* evaluate the expression */
expr = xleval(expr);
/* save the result */
xlevsave(expr);
/* Show result on a new line -- TAA MOD to improve display */
xlfreshline(getvalue(s_debugio));
/* print it */
#ifdef MULVALS
{
int i;
for (i = 0; i < xlnumresults; i++)
dbgprint(xlresults[i]);
}
#else
dbgprint(expr);
#endif /* MULVALS */
}
xlend(&cntxt);
/* decrement the debug level */
--xldebug;
/* restore the stack */
xlpop();
/* check for aborting to the previous level */
if (type == CF_CLEANUP)
xlbrklevel();
}
#endif
/* baktrace - do a back trace */
VOID xlbaktrace P1C(int, n)
{
FRAMEP fp, p;
int argc;
for (fp = xlfp; (n < 0 || n--) && !null(*fp); fp = fp - (int)getfixnum(*fp)) {
p = fp + 1;
errputstr("Function: ");
errprint(*p++);
if (getvalue(s_baktraceprargs) != NIL) {
if ((argc = (int)getfixnum(*p++)) != 0)
errputstr("Arguments:\n");
while (--argc >= 0) {
errputstr(" ");
errprint(*p++);
}
}
}
}
/* xldinit - debug initialization routine */
VOID xldinit(V)
{
xlsample = 0;
xldebug = 0;
}
VOID xlsigint(V)
{
FRAMEP newfp;
if (boundp(s_intaction) && !null(getvalue(s_intaction))) {
newfp = xlsp;
pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
pusharg(getvalue(s_intaction));
pusharg(cvfixnum((FIXTYPE)0));
xlfp = newfp;
xlapply(0);
}
}
#ifdef CONDITIONS
LOCAL VOID conditionhook P3C(char *, cmsg, char *, emsg, LVAL, arg)
{
FRAMEP newfp;
LVAL olddenv,val,hook;
int argc;
/* rebind the hook functions to nil */
hook = getvalue(s_condition_hook);
olddenv = xldenv;
xldbind(s_condition_hook,NIL);
/* compute argument count */
argc = cmsg == NULL ? 4 : 5;
if (arg != s_unbound) argc++;
/* create the new call frame */
newfp = xlsp;
pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
pusharg(hook);
pusharg(cvfixnum((FIXTYPE) argc));
pusharg(cmsg == NULL ? s_error : s_cerror);
pusharg(null(xlfp[0]) ? NIL : cvfixnum((FIXTYPE) (xlfp - xlargstkbase)));
pusharg(cons(xlenv,xlfenv));
if (cmsg != NULL) pusharg(cvstring(cmsg));
if (arg != s_unbound) {
strcpy(buf, emsg);
strcat(buf, " - ~S");
pusharg(cvstring(buf));
}
else
pusharg(cvstring(emsg));
if (arg != s_unbound) pusharg(arg);
xlfp = newfp;
/* call the hook function */
val = xlapply(argc);
/* unbind the symbols */
xlunbind(olddenv);
if (cmsg == NULL)
xlabort("condition hook function should not have returned");
}
#endif /* CONDITIONS */
syntax highlighted by Code2HTML, v. 0.9.1