170 lines
4.9 KiB
C
170 lines
4.9 KiB
C
/*
|
|
*
|
|
* e r r o r . c -- The error procedure
|
|
*
|
|
* Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
|
|
*
|
|
*
|
|
* Permission to use, copy, modify, distribute,and license this
|
|
* software and its documentation for any purpose is hereby granted,
|
|
* provided that existing copyright notices are retained in all
|
|
* copies and that this notice is included verbatim in any
|
|
* distributions. No written agreement, license, or royalty fee is
|
|
* required for any of the authorized uses.
|
|
* This software is provided ``AS IS'' without express or implied
|
|
* warranty.
|
|
*
|
|
* Author: Erick Gallesio [eg@unice.fr]
|
|
* Creation date: 14-Nov-1993 14:58
|
|
* Last file update: 3-Sep-1999 20:19 (eg)
|
|
*/
|
|
|
|
#include "stk.h"
|
|
|
|
#ifdef DEBUG_STK
|
|
void print_error_handlers(void) /* For debug only */
|
|
{
|
|
struct error_handler *p;
|
|
|
|
Fprintf(STk_stderr, "\t**** Error handlers\n");
|
|
|
|
for (p = STk_err_handler; ; p = p->prev) {
|
|
Fprintf(STk_stderr, "\t\thandler(@%lx) = %02x =>",
|
|
(unsigned long) p, p->context);
|
|
|
|
if (p->context & ERR_FATAL) Fprintf(STk_stderr, "FATAL ");
|
|
if (p->context & ERR_OK) Fprintf(STk_stderr, "OK ");
|
|
if (p->context & ERR_READ_FROM_STRING) Fprintf(STk_stderr, "READ_FROM_STRING ");
|
|
if (p->context & ERR_IGNORED) Fprintf(STk_stderr, "IGNORED ");
|
|
if (p->context & ERR_TCL_BACKGROUND) Fprintf(STk_stderr, "TCL_BACKGROUND ");
|
|
if (p->context & ERR_IN_REPORT_ERROR) Fprintf(STk_stderr, "IN_REPORT_ERROR ");
|
|
if (p->context & ERR_IN_LOAD) Fprintf(STk_stderr, "IN_LOAD ");
|
|
Fprintf(STk_stderr, "\n");
|
|
if (!p->prev) break;
|
|
}
|
|
Flush(STk_stderr);
|
|
}
|
|
#endif
|
|
|
|
|
|
/***************************************************/
|
|
|
|
static void print_error_message(char *head, char *message, SCM who,
|
|
int uncode, int show_stack)
|
|
{
|
|
if (uncode) who = STk_uncode(who);
|
|
|
|
Fprintf(STk_curr_eport, "%s %s", head, message);
|
|
if (NNULLP(who)) {
|
|
Puts(": ", STk_curr_eport);
|
|
STk_print(who, STk_curr_eport, PANIC_MODE);
|
|
}
|
|
if (show_stack) STk_show_eval_stack(5, uncode);
|
|
}
|
|
|
|
|
|
|
|
static void recursive_error(char *head, char *message, SCM x)
|
|
{
|
|
Fprintf(STk_curr_eport,
|
|
"\n#### WARNING: error occurred while executing the body of %s!!\n",
|
|
REPORT_ERROR);
|
|
Fprintf(STk_curr_eport, "#### Error in %s was\n", REPORT_ERROR);
|
|
print_error_message("", message, x, FALSE, TRUE);
|
|
Fprintf(STk_curr_eport, "#### Going back to original error:\n");
|
|
longjmp(STk_err_handler->j, JMP_ERROR); /* Go back to previous call to error */
|
|
}
|
|
|
|
|
|
/*=============================================================================
|
|
*
|
|
* print-message
|
|
*
|
|
*=============================================================================*/
|
|
|
|
static void print_message(char *message, SCM x)
|
|
{
|
|
char head[MAX_PATH_LENGTH+50];
|
|
int context = STk_err_handler->context;
|
|
|
|
/*
|
|
* Determine what the header of the message will contain depending of context
|
|
*/
|
|
if (context & ERR_IN_REPORT_ERROR) {
|
|
/* We have a recursive error (i.e. the printing function is buggy) */
|
|
recursive_error(head, message, x);
|
|
} else if (context & ERR_READ_FROM_STRING)
|
|
strcpy(head,"*** Read from string error:\n");
|
|
#ifdef USE_TK
|
|
else if (context & ERR_TCL_BACKGROUND)
|
|
strcpy(head, "*** Background error:\n");
|
|
#endif
|
|
else {
|
|
/* ERR_FATAL or ERR_OK */
|
|
if (STk_current_filename==UNBOUND)
|
|
sprintf(head, "*** Error:\n");
|
|
else {
|
|
sprintf(head, "*** Error at line %d of file %s:\n",
|
|
STk_line_counter, CHARS(STk_current_filename));
|
|
STk_current_filename = UNBOUND;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Header is constituted, call the report-error user procedure for
|
|
* printing message (if available)
|
|
*/
|
|
PUSH_ERROR_HANDLER
|
|
{
|
|
SCM tmp = STk_lookup_variable(REPORT_ERROR, NIL);
|
|
|
|
STk_err_handler->context |= ERR_IN_REPORT_ERROR; /* for recursive errors */
|
|
|
|
if (STk_procedurep(tmp) == Truth)
|
|
Apply(tmp, LIST3(STk_makestring(head),
|
|
STk_makestring(message),
|
|
STk_uncode(x)));
|
|
else
|
|
print_error_message(head, message, x, TRUE, TRUE);
|
|
}
|
|
WHEN_ERROR
|
|
{
|
|
print_error_message(head, message, x, TRUE, FALSE);
|
|
Putc('\n', STk_curr_eport);
|
|
}
|
|
POP_ERROR_HANDLER;
|
|
|
|
Flush(STk_curr_oport); Flush(STk_curr_eport);
|
|
}
|
|
|
|
|
|
void STk_err(char *message, SCM x)
|
|
{
|
|
STk_reset_eval_hook();
|
|
|
|
/* Retain the arguments of this error in global Scheme variables */
|
|
STk_define_variable("*last-error-message*", STk_makestring(message), NIL);
|
|
STk_define_variable("*last-error-arg*", x, NIL);
|
|
|
|
/* Print a message if the error is not ignored */
|
|
if (!(STk_err_handler->context & ERR_IGNORED)) {
|
|
if (*message) print_message(message, x);
|
|
STk_reset_eval_stack();
|
|
}
|
|
|
|
/* Propage the error if we are not in a critical section */
|
|
if (STk_err_handler->context & ERR_FATAL)
|
|
panic("FATAL ERROR IN CRITICAL CODE SECTION.");
|
|
else
|
|
longjmp(STk_err_handler->j, JMP_ERROR);
|
|
}
|
|
|
|
|
|
void STk_procedure_error(char *procedure, char *message, SCM x)
|
|
{
|
|
char msg[200];
|
|
|
|
sprintf(msg, "%s: %s", procedure, message);
|
|
STk_err(msg, x);
|
|
}
|