123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- /* error handling common to all routines. */
- /*
- Copyright (C) 2004, 2005, 2006 John E. Davis
- This file is part of the S-Lang Library.
- The S-Lang Library 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 of the
- License, or (at your option) any later version.
- The S-Lang Library 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 this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA.
- */
- #include "slinclud.h"
- #include "slang.h"
- #include "_slang.h"
- void (*_pSLinterpreter_Error_Hook) (int);
- void (*SLang_VMessage_Hook) (char *, va_list);
- void (*SLang_Error_Hook)(char *);
- void (*SLang_Exit_Error_Hook)(char *, va_list);
- void (*SLang_Dump_Routine)(char *);
- volatile int _pSLang_Error = 0;
- volatile int SLKeyBoard_Quit = 0;
- typedef struct _Exception_Type Exception_Type;
- struct _Exception_Type
- {
- int error_code;
- char *name;
- char *description;
- Exception_Type *subclasses;
- Exception_Type *next;
- Exception_Type *parent;
- };
- static Exception_Type *Exception_Root;
- static Exception_Type Exception_Root_Buf =
- {
- -1, "AnyError", "All Errors", NULL, NULL, NULL
- };
- /* Built-in error codes */
- /* These values should correspond to the values produced by _pSLerr_init.
- * Some apps may not use the interpreter, and as such _pSLerr_init will not
- * get called.
- */
- int SL_Any_Error = -1;
- int SL_Unknown_Error = 6;
- int SL_Internal_Error = 5;
- int SL_OS_Error = 1;
- int SL_Malloc_Error = 2;
- int SL_Import_Error = 7;
- int SL_RunTime_Error = 3;
- int SL_InvalidParm_Error = 4;
- int SL_TypeMismatch_Error = 8;
- int SL_UserBreak_Error = 9;
- int SL_Stack_Error = 10;
- int SL_StackOverflow_Error = 12;
- int SL_StackUnderflow_Error = 11;
- int SL_ReadOnly_Error = 13;
- int SL_VariableUninitialized_Error = 14;
- int SL_NumArgs_Error = 15;
- int SL_Index_Error = 16;
- int SL_Usage_Error = 17;
- int SL_Application_Error = 18;
- int SL_NotImplemented_Error = 19;
- int SL_LimitExceeded_Error = 20;
- int SL_Forbidden_Error = 21;
- int SL_Math_Error = 22;
- int SL_DivideByZero_Error = 23;
- int SL_ArithOverflow_Error = 24;
- int SL_ArithUnderflow_Error = 25;
- int SL_Domain_Error = 26;
- int SL_IO_Error = 27;
- int SL_Write_Error = 28;
- int SL_Read_Error = 29;
- int SL_Open_Error = 30;
- int SL_Data_Error = 31;
- int SL_Unicode_Error = 32;
- int SL_InvalidUTF8_Error = 33;
- int SL_Namespace_Error = 34;
- int SL_Parse_Error = 35;
- int SL_Syntax_Error = 36;
- int SL_DuplicateDefinition_Error = 37;
- int SL_UndefinedName_Error = 38;
- typedef struct
- {
- int *errcode_ptr;
- char *name;
- char *description;
- int *base_class_ptr;
- }
- BuiltIn_Exception_Table_Type;
- static SLCONST BuiltIn_Exception_Table_Type BuiltIn_Exception_Table[] =
- {
- /* Define MallocError and InvalidParmError ASAP */
- {&SL_OS_Error, "OSError", "OS Error", &SL_Any_Error},
- {&SL_Malloc_Error, "MallocError", "Not enough memory", &SL_OS_Error},
- {&SL_RunTime_Error, "RunTimeError", "Run-Time Error", &SL_Any_Error},
- {&SL_InvalidParm_Error, "InvalidParmError", "Invalid Parameter", &SL_RunTime_Error},
- {&SL_Internal_Error, "InternalError", "Internal Error", &SL_Any_Error},
- {&SL_Unknown_Error, "UnknownError", "Unknown Error", &SL_Any_Error},
- /* Rest of OSErrors */
- {&SL_Import_Error, "ImportError", "Import Error", &SL_OS_Error},
- /* Rest of RunTimeErrors */
- {&SL_TypeMismatch_Error, "TypeMismatchError", "Type Mismatch", &SL_RunTime_Error},
- {&SL_UserBreak_Error, "UserBreakError", "User Break", &SL_RunTime_Error},
- {&SL_Stack_Error, "StackError", "Stack Error", &SL_RunTime_Error},
- {&SL_StackUnderflow_Error, "StackUnderflowError", "Stack Underflow Error", &SL_Stack_Error},
- {&SL_StackOverflow_Error, "StackOverflowError", "Stack Overflow Error", &SL_Stack_Error},
- {&SL_ReadOnly_Error, "ReadOnlyError", "Read-Only Error", &SL_RunTime_Error},
- {&SL_VariableUninitialized_Error, "VariableUninitializedError", "Variable Uninitialized Error", &SL_RunTime_Error},
- {&SL_NumArgs_Error, "NumArgsError", "Invalid Number of Arguments", &SL_RunTime_Error},
- {&SL_Index_Error, "IndexError", "Invalid Index", &SL_RunTime_Error},
- {&SL_Usage_Error, "UsageError", "Illegal Usage", &SL_RunTime_Error},
- {&SL_Application_Error, "ApplicationError", "Application Error", &SL_RunTime_Error},
- {&SL_NotImplemented_Error, "NotImplementedError", "Not Implemented", &SL_RunTime_Error},
- {&SL_LimitExceeded_Error, "LimitExceededError", "Limit Exceeded", &SL_RunTime_Error},
- {&SL_Forbidden_Error, "ForbiddenError", "Operation Forbidden", &SL_RunTime_Error},
- {&SL_Math_Error, "MathError", "Math Error", &SL_RunTime_Error},
- {&SL_DivideByZero_Error, "DivideByZeroError", "Divide by Zero", &SL_Math_Error},
- {&SL_ArithOverflow_Error, "ArithOverflowError", "Arithmetic Overflow", &SL_Math_Error},
- {&SL_ArithUnderflow_Error, "ArithUnderflowError", "Arithmetic Underflow", &SL_Math_Error},
- {&SL_Domain_Error, "DomainError", "Domain Error", &SL_Math_Error},
- {&SL_IO_Error, "IOError", "I/O Error", &SL_RunTime_Error},
- {&SL_Write_Error, "WriteError", "Write failed", &SL_IO_Error},
- {&SL_Read_Error, "ReadError", "Read failed", &SL_IO_Error},
- {&SL_Open_Error, "OpenError", "Open failed", &SL_IO_Error},
- {&SL_Data_Error, "DataError", "Data Error", &SL_RunTime_Error},
- {&SL_Unicode_Error, "UnicodeError", "Unicode Error", &SL_RunTime_Error},
- {&SL_InvalidUTF8_Error, "UTF8Error", "Invalid UTF8", &SL_Unicode_Error},
- {&SL_Namespace_Error, "NamespaceError", "Namespace Error", &SL_RunTime_Error},
- /* Parse Errors */
- {&SL_Parse_Error, "ParseError", "Parse Error", &SL_Any_Error},
- {&SL_Syntax_Error, "SyntaxError", "Syntax Error", &SL_Parse_Error},
- {&SL_DuplicateDefinition_Error, "DuplicateDefinitionError", "Duplicate Definition", &SL_Parse_Error},
- {&SL_UndefinedName_Error, "UndefinedNameError", "Undefined Name", &SL_Parse_Error},
- {NULL, NULL, NULL, NULL}
- };
- static Exception_Type *find_exception (Exception_Type *root, int error_code)
- {
- Exception_Type *e;
- while (root != NULL)
- {
- if (error_code == root->error_code)
- return root;
- if (root->subclasses != NULL)
- {
- e = find_exception (root->subclasses, error_code);
- if (e != NULL)
- return e;
- }
- root = root->next;
- }
- return root;
- }
- static int is_exception_ancestor (int a, int b)
- {
- Exception_Type *e;
- if (a == b)
- return 1;
- if (NULL == (e = find_exception (Exception_Root, a)))
- return 0;
-
- while (e->parent != NULL)
- {
- e = e->parent;
- if (e->error_code == b)
- return 1;
- }
- return 0;
- }
- int SLerr_exception_eqs (int a, int b)
- {
- if (is_exception_ancestor (a, b))
- return 1;
-
- return 0;
- }
- static void free_this_exception (Exception_Type *e)
- {
- if (e == NULL)
- return;
-
- if (e->name != NULL)
- SLang_free_slstring (e->name);
- if (e->description != NULL)
- SLang_free_slstring (e->description);
- SLfree ((char *)e);
- }
-
- static int Next_Exception_Code;
- /* The whole point of this nonsense involving the _pSLerr_New_Exception_Hook
- * is to provide a mechanism to avoid linking in the interpreter for apps
- * that just want the other facilities.
- */
- int (*_pSLerr_New_Exception_Hook)(char *name, char *desc, int error_code);
- int _pSLerr_init_interp_exceptions (void)
- {
- SLCONST BuiltIn_Exception_Table_Type *b;
- Exception_Type *e;
- if (_pSLerr_New_Exception_Hook == NULL)
- return 0;
-
- e = &Exception_Root_Buf;
- if (-1 == (*_pSLerr_New_Exception_Hook)(e->name, e->description, e->error_code))
- return -1;
- b = BuiltIn_Exception_Table;
- while (b->errcode_ptr != NULL)
- {
- if (-1 == (*_pSLerr_New_Exception_Hook)(b->name, b->description, *b->errcode_ptr))
- return -1;
-
- b++;
- }
- return 0;
- }
- int SLerr_new_exception (int baseclass, char *name, char *descript)
- {
- Exception_Type *base;
- Exception_Type *e;
- if (-1 == _pSLerr_init ())
- return -1;
- base = find_exception (Exception_Root, baseclass);
- if (base == NULL)
- {
- SLang_verror (SL_InvalidParm_Error,
- "Base class for new exception not found");
- return -1;
- }
-
- e = (Exception_Type *) SLcalloc (1, sizeof (Exception_Type));
- if (e == NULL)
- return -1;
-
- if ((NULL == (e->name = SLang_create_slstring (name)))
- || (NULL == (e->description = SLang_create_slstring (descript))))
- {
- free_this_exception (e);
- return -1;
- }
-
- e->error_code = Next_Exception_Code;
- if ((_pSLerr_New_Exception_Hook != NULL)
- && (-1 == (*_pSLerr_New_Exception_Hook) (e->name, e->description, e->error_code)))
- {
- free_this_exception (e);
- return -1;
- }
- e->parent = base;
- e->next = base->subclasses;
- base->subclasses = e;
- Next_Exception_Code++;
- return e->error_code;
- }
- static int init_exceptions (void)
- {
- SLCONST BuiltIn_Exception_Table_Type *b;
- if (Exception_Root != NULL)
- return 0;
- Exception_Root = &Exception_Root_Buf;
- Next_Exception_Code = 1;
- b = BuiltIn_Exception_Table;
- while (b->errcode_ptr != NULL)
- {
- int err_code;
-
- err_code = SLerr_new_exception (*b->base_class_ptr, b->name, b->description);
- if (err_code == -1)
- return -1;
- *b->errcode_ptr = err_code;
- b++;
- }
-
- return 0;
- }
- static void free_exceptions (Exception_Type *root)
- {
- while (root != NULL)
- {
- Exception_Type *next;
- if (root->subclasses != NULL)
- free_exceptions (root->subclasses);
-
- next = root->next;
- free_this_exception (root);
- root = next;
- }
- }
-
- static void deinit_exceptions (void)
- {
- Exception_Type *root = Exception_Root;
-
- if (root != NULL)
- free_exceptions (root->subclasses);
-
- Exception_Root = NULL;
- Next_Exception_Code = 0;
- }
- char *SLerr_strerror (int err_code)
- {
- Exception_Type *e;
- if (err_code == 0)
- err_code = _pSLang_Error;
- if (-1 == _pSLerr_init ())
- return "Unable to initialize SLerr module";
- if (NULL == (e = find_exception (Exception_Root, err_code)))
- return "Invalid/Unknown Error Code";
-
- return e->description;
- }
- /* Error Queue Functions
- * SLang_verror (int errcode, fmt, args)
- * Add an error message to the queue.
- * SLerr_delete_queue ()
- * Removes messages from the error queue
- * SLerr_print_queue ()
- * Prints all messages from the queue, deletes the queue
- */
- typedef struct _Error_Message_Type
- {
- char *msg; /* SLstring, may be NULL */
- int msg_type;
- #define _SLERR_MSG_ERROR 1
- #define _SLERR_MSG_WARNING 2
- #define _SLERR_MSG_TRACEBACK 4
- struct _Error_Message_Type *next;
- }
- Error_Message_Type;
- typedef struct
- {
- Error_Message_Type *head;
- Error_Message_Type *tail;
- }
- Error_Queue_Type;
- static Error_Queue_Type *Default_Error_Queue;
- static void free_error_msg (Error_Message_Type *m)
- {
- if (m == NULL)
- return;
- if (m->msg != NULL)
- SLang_free_slstring (m->msg);
- SLfree ((char *)m);
- }
-
- static Error_Message_Type *allocate_error_msg (char *msg, int msg_type)
- {
- Error_Message_Type *m;
- if (NULL == (m = (Error_Message_Type*) SLcalloc (1, sizeof (Error_Message_Type))))
- return NULL;
-
- if ((NULL != msg) && (NULL == (m->msg = SLang_create_slstring (msg))))
- {
- free_error_msg (m);
- return NULL;
- }
- m->msg_type = msg_type;
- return m;
- }
- static void free_queued_messages (Error_Queue_Type *q)
- {
- Error_Message_Type *m;
- if (q == NULL)
- return;
- m = q->head;
- while (m != NULL)
- {
- Error_Message_Type *m1 = m->next;
- free_error_msg (m);
- m = m1;
- }
- q->head = NULL;
- q->tail = NULL;
- }
- static void delete_msg_queue (Error_Queue_Type *q)
- {
- if (q == NULL)
- return;
-
- free_queued_messages (q);
- SLfree ((char *)q);
- }
-
- static Error_Queue_Type *create_msg_queue (void)
- {
- Error_Queue_Type *q;
- if (NULL == (q = (Error_Queue_Type *)SLcalloc (1, sizeof(Error_Queue_Type))))
- return NULL;
-
- return q;
- }
- static int queue_message (Error_Queue_Type *q, char *msg, int msg_type)
- {
- Error_Message_Type *m;
-
- if (NULL == (m = allocate_error_msg (msg, msg_type)))
- return -1;
-
- if (q->tail != NULL)
- q->tail->next = m;
- if (q->head == NULL)
- q->head = m;
- q->tail = m;
-
- return 0;
- }
- static void print_error (int msg_type, char *err)
- {
- unsigned int len;
- switch (msg_type)
- {
- case _SLERR_MSG_ERROR:
- if (SLang_Error_Hook != NULL)
- {
- (*SLang_Error_Hook)(err);
- return;
- }
- break;
- case _SLERR_MSG_TRACEBACK:
- case _SLERR_MSG_WARNING:
- if (SLang_Dump_Routine != NULL)
- {
- (*SLang_Dump_Routine)(err);
- return;
- }
- break;
- }
-
- len = strlen (err);
- if (len == 0)
- return;
- fputs (err, stderr);
- if ((err[len-1] != '\n')
- && (msg_type != _SLERR_MSG_TRACEBACK))
- fputs("\n", stderr);
- fflush (stderr);
- }
- static void print_queue (void)
- {
- if (-1 == _pSLerr_init ())
- print_error (_SLERR_MSG_ERROR, "Unable to initialize SLerr module");
-
- if (_pSLang_Error == 0)
- return;
- if (Default_Error_Queue != NULL)
- {
- Error_Queue_Type *q = Default_Error_Queue;
- Error_Message_Type *m = q->head;
- while (m != NULL)
- {
- Error_Message_Type *m_next = m->next;
- if (m->msg != NULL)
- print_error (m->msg_type, m->msg);
- m = m_next;
- }
-
- free_queued_messages (q);
- }
- #if 0
- if (_pSLang_Error != SL_Usage_Error)
- {
- print_error (_SLERR_MSG_ERROR, SLerr_strerror (_pSLang_Error));
- }
- #endif
- }
- /* This function returns a pointer to the first error message in the queue.
- * Make no attempts to free the returned pointer.
- */
- char *_pSLerr_get_error_from_queue (void)
- {
- Error_Queue_Type *q;
- Error_Message_Type *m;
- unsigned int len;
- char *err, *err1, *err_max;
- if (NULL == (q = Default_Error_Queue))
- return NULL;
- len = 0;
- m = q->head;
- while (m != NULL)
- {
- if (m->msg_type == _SLERR_MSG_ERROR)
- len += 1 + strlen (m->msg);
- m = m->next;
- }
-
- if (len)
- len--; /* last \n not needed */
- if (NULL == (err = _pSLallocate_slstring (len)))
- return NULL;
-
- err_max = err + len;
- err1 = err;
- m = q->head;
- while (m != NULL)
- {
- if (m->msg_type == _SLERR_MSG_ERROR)
- {
- unsigned int dlen = strlen (m->msg);
- strcpy (err1, m->msg);
- err1 += dlen;
- if (err1 != err_max)
- *err1++ = '\n';
- }
- m = m->next;
- }
- *err1 = 0;
-
- return _pSLcreate_via_alloced_slstring (err, len);
- }
- void _pSLerr_print_message_queue (void)
- {
- print_queue ();
- }
- static volatile int Suspend_Error_Messages = 0;
- int _pSLerr_resume_messages (void)
- {
- if (Suspend_Error_Messages == 0)
- return 0;
-
- Suspend_Error_Messages--;
- if (Suspend_Error_Messages == 0)
- print_queue ();
- return 0;
- }
- int _pSLerr_suspend_messages (void)
- {
- Suspend_Error_Messages++;
- return 0;
- }
- void _pSLerr_free_queued_messages (void)
- {
- free_queued_messages (Default_Error_Queue);
- }
- void SLang_verror (int err_code, char *fmt, ...)
- {
- va_list ap;
- char err [4096];
- if (-1 == _pSLerr_init ())
- {
- print_queue ();
- return;
- }
- if (err_code == 0)
- err_code = SL_INTRINSIC_ERROR;
- if (_pSLang_Error == 0)
- SLang_set_error (err_code);
- if (fmt == NULL)
- return;
- va_start(ap, fmt);
- (void) SLvsnprintf (err, sizeof (err), fmt, ap);
- va_end(ap);
- if (Suspend_Error_Messages)
- (void) queue_message (Default_Error_Queue, err, _SLERR_MSG_ERROR);
- else
- print_error (_SLERR_MSG_ERROR, err);
- }
- int _pSLerr_traceback_msg (char *fmt, ...)
- {
- va_list ap;
- char msg [4096];
- va_start(ap, fmt);
- (void) SLvsnprintf (msg, sizeof (msg), fmt, ap);
- va_end(ap);
- return queue_message (Default_Error_Queue, msg, _SLERR_MSG_TRACEBACK);
- }
- void SLang_exit_error (char *fmt, ...)
- {
- va_list ap;
- print_queue ();
- va_start (ap, fmt);
- if (SLang_Exit_Error_Hook != NULL)
- {
- (*SLang_Exit_Error_Hook) (fmt, ap);
- exit (1);
- }
- if (fmt != NULL)
- {
- vfprintf (stderr, fmt, ap);
- fputs ("\n", stderr);
- fflush (stderr);
- }
- va_end (ap);
- exit (1);
- }
- int SLang_set_error (int error)
- {
- /* Only allow an error to be cleared (error==0), but not changed
- * if there already is an error.
- */
- if ((error == 0)
- || (_pSLang_Error == 0))
- _pSLang_Error = error;
- if (_pSLinterpreter_Error_Hook != NULL)
- (*_pSLinterpreter_Error_Hook) (_pSLang_Error);
-
- return 0;
- }
- int SLang_get_error (void)
- {
- return _pSLang_Error;
- }
- void SLang_vmessage (char *fmt, ...)
- {
- va_list ap;
- if (fmt == NULL)
- return;
- va_start (ap, fmt);
- if (SLang_VMessage_Hook != NULL)
- (*SLang_VMessage_Hook) (fmt, ap);
- else
- {
- vfprintf (stdout, fmt, ap);
- fputs ("\n", stdout);
- }
- va_end (ap);
- }
- /* This routine does not queue messages. It is used for tracing, etc. */
- void _pSLerr_dump_msg (char *fmt, ...)
- {
- char buf[1024];
- va_list ap;
- va_start (ap, fmt);
- if (SLang_Dump_Routine != NULL)
- {
- (void) SLvsnprintf (buf, sizeof (buf), fmt, ap);
- (*SLang_Dump_Routine) (buf);
- }
- else
- {
- vfprintf (stderr, fmt, ap);
- fflush (stderr);
- }
- va_end (ap);
- }
- int _pSLerr_init (void)
- {
- if (Default_Error_Queue == NULL)
- {
- Suspend_Error_Messages = 0;
- if (NULL == (Default_Error_Queue = create_msg_queue ()))
- return -1;
- }
- if (-1 == init_exceptions ())
- return -1;
-
- return 0;
- }
- void _pSLerr_deinit (void)
- {
- deinit_exceptions ();
- delete_msg_queue (Default_Error_Queue);
- Suspend_Error_Messages = 0;
- Default_Error_Queue = NULL;
- }
|