/* * * e r r o r . c -- The error procedure * * Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI * * * 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); }