mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
767 lines
18 KiB
C
767 lines
18 KiB
C
/* 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;
|
|
}
|
|
|