2007-12-30 17:41:49 +01:00
/***************************************************************************
2012-01-15 09:54:57 +01:00
gb_error . c
2007-12-30 17:41:49 +01:00
2018-02-12 02:53:46 +01:00
( c ) 2000 - 2017 Benoît Minisini < g4mba5 @ gmail . com >
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
This program 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 , or ( at your option )
any later version .
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
This program 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 .
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston ,
MA 02110 - 1301 , USA .
2007-12-30 17:41:49 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define __GB_ERROR_C
# include "gb_common.h"
# include <stdarg.h>
# include <ctype.h>
# include "gb_buffer.h"
# include "gbx_debug.h"
# include "gbx_exec.h"
# include "gbx_api.h"
2011-08-31 04:28:48 +02:00
# include "gbx_stack.h"
2013-05-25 16:00:40 +02:00
# include "gbx_project.h"
2019-09-17 10:07:59 +02:00
# include "gbx.h"
2010-01-20 02:37:45 +01:00
# include "gb_error.h"
2007-12-30 17:41:49 +01:00
2008-02-02 11:54:13 +01:00
//#define DEBUG_ERROR 1
2007-12-30 17:41:49 +01:00
2008-01-25 16:01:02 +01:00
ERROR_CONTEXT * ERROR_current = NULL ;
2008-01-27 15:00:04 +01:00
ERROR_INFO ERROR_last = { 0 } ;
2011-08-31 04:28:48 +02:00
void * ERROR_backtrace = NULL ;
2010-06-18 02:14:53 +02:00
ERROR_HANDLER * ERROR_handler = NULL ;
2010-08-29 22:51:10 +02:00
# if DEBUG_ERROR
int ERROR_depth = 0 ;
# endif
2008-01-25 16:01:02 +01:00
2007-12-30 17:41:49 +01:00
static int _lock = 0 ;
2018-08-10 14:22:49 +02:00
static char * _print_prefix = NULL ;
2007-12-30 17:41:49 +01:00
2020-01-04 22:11:29 +01:00
static const char * const _message [ 77 ] =
2007-12-30 17:41:49 +01:00
{
2018-03-17 23:33:02 +01:00
/* 0 E_UNKNOWN */ " Unknown error " ,
/* 1 E_MEMORY */ " Out of memory " ,
/* 2 E_CLASS */ " .3Cannot load class '&1': &2&3 " ,
/* 3 E_STACK */ " Stack overflow " ,
/* 4 E_NEPARAM */ " Not enough arguments " ,
/* 5 E_TMPARAM */ " Too many arguments " ,
/* 6 E_TYPE */ " .2Type mismatch: wanted &1, got &2 instead " ,
/* 7 E_OVERFLOW */ " Overflow " ,
/* 8 E_ILLEGAL */ " Illegal instruction " ,
/* 9 E_NFUNC */ " Not a function " ,
/* 10 E_CSTATIC */ " .1Class '&1' is not creatable " ,
/* 11 E_NSYMBOL */ " .2Unknown symbol '&2' in class '&1' " ,
/* 12 E_NOBJECT */ " Not an object " ,
/* 13 E_NULL */ " Null object " ,
/* 14 E_STATIC */ " .2'&1.&2' is static " ,
/* 15 E_NREAD */ " .2'&1.&2' is write only " ,
/* 16 E_NWRITE */ " .2'&1.&2' is read only " ,
/* 17 E_NPROPERTY */ " .2'&1.&2' is not a property " ,
/* 18 E_NRETURN */ " No return value " ,
/* 19 E_MATH */ " Mathematic error " ,
/* 20 E_ARG */ " Bad argument " ,
/* 21 E_BOUND */ " Out of bounds " ,
/* 22 E_NDIM */ " Bad number of dimensions " ,
/* 23 E_NARRAY */ " Not an array " ,
/* 24 E_MAIN */ " No startup method " ,
/* 25 E_NNEW */ " No instantiation method " ,
/* 26 E_ZERO */ " Division by zero " ,
/* 27 E_LIBRARY */ " .2Cannot load component '&1': &2 " ,
/* 28 E_EVENT */ " .3Bad event handler in &1.&2(): &3 " ,
/* 29 E_IOBJECT */ " Invalid object " ,
/* 30 E_ENUM */ " Not an enumeration " ,
/* 31 E_UCONV */ " Unsupported string conversion " ,
/* 32 E_CONV */ " Bad string conversion " ,
/* 33 E_DATE */ " Invalid date " ,
/* 34 E_BADPATH */ " Invalid path " ,
/* 35 E_OPEN */ " .2Cannot open file '&1': &2 " ,
/* 36 E_PROJECT */ " .2Bad project file: line &1: &2 " ,
/* 37 E_FULL */ " Device is full " ,
/* 38 E_EXIST */ " File already exists " , /* &1 */
/* 39 E_EOF */ " End of file " ,
/* 40 E_FORMAT */ " Bad format string " ,
/* 41 E_DYNAMIC */ " .2'&1.&2' is not static " ,
/* 42 E_SYSTEM */ " .2System error #&1: &2 " ,
/* 43 E_ACCESS */ " Access forbidden " ,
/* 44 E_TOOLONG */ " File name is too long " ,
/* 45 E_NEXIST */ " File or directory does not exist " , /* &1 */
/* 46 E_DIR */ " File is a directory " , /* &1 */
/* 47 E_READ */ " Read error " ,
/* 48 E_WRITE */ " Write error " ,
/* 49 E_NDIR */ " .1Not a directory: &1 " ,
/* 50 E_REGEXP */ " .1Bad regular expression: &1 " ,
/* 51 E_ARCH */ " .2Bad archive: &1: &2 " ,
/* 52 E_REGISTER */ " .1Cannot register class '&1' " ,
/* 53 E_CLOSED */ " Stream is closed " ,
/* 54 E_VIRTUAL */ " Bad use of virtual class " ,
/* 55 E_STOP */ " STOP instruction encountered " ,
/* 56 E_STRING */ " Too many simultaneous new strings " ,
/* 57 E_EVAL */ " .1Bad expression: &1 " ,
/* 58 E_LOCK */ " File is locked " ,
/* 59 E_PARENT */ " No parent class " ,
/* 60 E_EXTLIB */ " .2Cannot find dynamic library '&1': &2 " ,
/* 61 E_EXTSYM */ " .2Cannot find symbol '&2' in dynamic library '&1' " ,
/* 62 E_BYREF */ " Argument cannot be passed by reference " ,
/* 63 E_OVERRIDE */ " .3'&1.&2' is incorrectly overridden in class '&3' " ,
/* 64 E_NKEY */ " Void key " ,
2019-07-31 00:20:13 +02:00
/* 65 E_SARRAY */ " Read-only array " ,
2018-03-17 23:33:02 +01:00
/* 66 E_EXTCB */ " .1Cannot create callback: &1 " ,
/* 67 E_SERIAL */ " Serialization error " ,
/* 68 E_CHILD */ " .2Cannot run child process: &1&2 " ,
/* 69 E_USER */ " Unknown user or group " ,
/* 70 E_NEMPTY */ " Directory is not empty " ,
/* 71 E_UTYPE */ " Unsupported datatype " ,
2018-12-16 00:35:46 +01:00
/* 72 E_FREEREF */ " Free object referenced " ,
2019-08-24 01:57:16 +02:00
/* 73 E_ASSERT */ " Assertion failed " ,
2019-07-31 00:20:13 +02:00
/* 74 E_MARRAY */ " Multidimensional array " ,
2020-01-04 22:11:29 +01:00
/* 75 E_UCLASS */ " .1Unknown class '&1' " ,
2020-01-06 23:02:33 +01:00
/* 76 E_SPEC */ " .2Incorrect declaration of symbol '&1' in class '&2' "
2007-12-30 17:41:49 +01:00
} ;
2010-08-29 22:51:10 +02:00
# if DEBUG_ERROR
void ERROR_debug ( const char * msg , . . . )
{
int i ;
2012-01-15 09:54:57 +01:00
va_list args ;
2011-01-16 23:04:17 +01:00
ERROR_CONTEXT * err ;
2010-08-29 22:51:10 +02:00
2012-01-15 09:54:57 +01:00
va_start ( args , msg ) ;
2007-12-30 17:41:49 +01:00
2010-08-29 22:51:10 +02:00
for ( i = 0 ; i < ERROR_depth ; i + + )
fprintf ( stderr , " - " ) ;
2012-01-15 09:54:57 +01:00
vfprintf ( stderr , msg , args ) ;
2015-11-18 02:29:28 +01:00
2011-01-16 23:04:17 +01:00
fprintf ( stderr , " \t \t \t \t \t \t \t \t \t " ) ;
DEBUG_where ( ) ;
err = ERROR_current ;
while ( err )
{
fprintf ( stderr , " [%p] -> " , err ) ;
err = err - > prev ;
}
fprintf ( stderr , " NULL \n " ) ;
2015-11-18 02:29:28 +01:00
2013-01-06 17:13:31 +01:00
va_end ( args ) ;
2010-08-29 22:51:10 +02:00
}
# endif
2007-12-30 17:41:49 +01:00
2008-01-17 22:39:26 +01:00
void ERROR_lock ( )
2007-12-30 17:41:49 +01:00
{
_lock + + ;
}
2008-01-17 22:39:26 +01:00
void ERROR_unlock ( )
2007-12-30 17:41:49 +01:00
{
_lock - - ;
}
2008-01-27 15:00:04 +01:00
void ERROR_reset ( ERROR_INFO * info )
2007-12-30 17:41:49 +01:00
{
2010-05-22 20:02:34 +02:00
if ( ! info - > code )
return ;
2015-11-18 02:29:28 +01:00
2008-01-27 15:00:04 +01:00
info - > code = 0 ;
if ( info - > free )
2008-01-25 16:01:02 +01:00
{
2008-02-02 11:54:13 +01:00
STRING_unref ( & info - > msg ) ;
2008-01-27 15:00:04 +01:00
info - > free = FALSE ;
2008-01-25 16:01:02 +01:00
}
2008-02-02 11:54:13 +01:00
info - > msg = NULL ;
2007-12-30 17:41:49 +01:00
}
2016-07-07 10:50:33 +02:00
static void ERROR_clear ( )
2007-12-30 17:41:49 +01:00
{
if ( _lock )
2009-02-04 23:51:20 +01:00
{
# if DEBUG_ERROR
2010-08-29 22:51:10 +02:00
ERROR_debug ( " ERROR_clear: (%p) *LOCKED* \n " , ERROR_current ) ;
2009-02-04 23:51:20 +01:00
# endif
2007-12-30 17:41:49 +01:00
return ;
2009-02-04 23:51:20 +01:00
}
2015-11-18 02:29:28 +01:00
2009-02-04 23:51:20 +01:00
# if DEBUG_ERROR
fprintf ( stderr , " ERROR_clear: (%p) \n " , ERROR_current ) ;
# endif
2008-01-27 15:00:04 +01:00
ERROR_reset ( & ERROR_current - > info ) ;
2016-07-07 10:50:33 +02:00
STACK_free_backtrace ( & ERROR_backtrace ) ;
2007-12-30 17:41:49 +01:00
}
2010-05-22 20:02:34 +02:00
#if 0
2008-01-17 22:39:26 +01:00
void ERROR_enter ( ERROR_CONTEXT * err )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
err - > prev = ERROR_current ;
err - > info . code = 0 ;
//err->info.free = FALSE;
//err->info.msg = NULL;
//err->info.backtrace = NULL;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
ERROR_current = err ;
2008-01-25 16:01:02 +01:00
# if DEBUG_ERROR
2009-02-04 23:51:20 +01:00
fprintf ( stderr , " ERROR_enter: (%p) \n " , ERROR_current ) ;
2008-01-25 16:01:02 +01:00
fprintf ( stderr , " >> ERROR_enter " ) ;
{
ERROR_CONTEXT * e = err ;
while ( e )
{
fprintf ( stderr , " -> %p " , e ) ;
e = e - > prev ;
}
fprintf ( stderr , " \n " ) ;
}
2012-01-15 09:54:57 +01:00
# endif
2007-12-30 17:41:49 +01:00
}
2010-05-22 20:02:34 +02:00
# endif
2007-12-30 17:41:49 +01:00
2010-05-22 20:02:34 +02:00
#if 0
2008-01-17 22:39:26 +01:00
void ERROR_leave ( ERROR_CONTEXT * err )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
if ( err - > prev = = ERROR_LEAVE_DONE )
return ;
2015-11-18 02:29:28 +01:00
2008-01-25 16:01:02 +01:00
# if DEBUG_ERROR
fprintf ( stderr , " << ERROR_leave " ) ;
{
ERROR_CONTEXT * e = err ;
while ( e )
{
fprintf ( stderr , " -> %p " , e ) ;
e = e - > prev ;
}
2008-02-02 11:54:13 +01:00
fprintf ( stderr , " : %d %s \n " , err - > info . code , err - > info . msg ) ;
2008-01-25 16:01:02 +01:00
}
# endif
2015-11-18 02:29:28 +01:00
2008-01-25 16:01:02 +01:00
//if (!err->prev)
// BREAKPOINT();
2015-11-18 02:29:28 +01:00
2008-01-25 16:01:02 +01:00
ERROR_current = err - > prev ;
2015-11-18 02:29:28 +01:00
2008-01-25 16:01:02 +01:00
if ( ERROR_current )
{
2009-02-04 23:51:20 +01:00
# if DEBUG_ERROR
fprintf ( stderr , " ERROR_leave: (%p) \n " , ERROR_current ) ;
# endif
2010-01-27 04:28:06 +01:00
if ( err - > info . code )
{
ERROR_reset ( & ERROR_current - > info ) ;
ERROR_current - > info = err - > info ;
}
2008-01-25 16:01:02 +01:00
}
2009-02-04 23:51:20 +01:00
else
ERROR_reset ( & err - > info ) ;
2008-01-25 16:01:02 +01:00
err - > prev = ERROR_LEAVE_DONE ;
2012-01-15 09:54:57 +01:00
//ERROR_reset(err);
2008-01-25 16:01:02 +01:00
}
2010-05-22 20:02:34 +02:00
# endif
2008-01-25 16:01:02 +01:00
void ERROR_propagate ( )
{
2012-05-19 04:55:05 +02:00
ERROR_HANDLER * ph , * prev ;
2008-02-02 11:54:13 +01:00
# if DEBUG_ERROR
2010-08-29 22:51:10 +02:00
ERROR_debug ( " ERROR_propagate: %p %d %s (ret = %d) \n " , ERROR_current , ERROR_current - > info . code , ERROR_current - > info . msg , ERROR_current - > ret ) ;
2008-02-02 11:54:13 +01:00
# endif
2015-11-18 02:29:28 +01:00
2010-08-03 13:00:42 +02:00
//fprintf(stderr, "ERROR_propagate: %p\n", ERROR_handler);
2010-08-29 22:51:10 +02:00
if ( ERROR_in_catch ( ERROR_current ) )
2010-08-03 13:00:42 +02:00
ERROR_leave ( ERROR_current ) ;
2015-11-18 02:29:28 +01:00
2010-06-18 02:14:53 +02:00
while ( ERROR_handler )
{
2010-08-03 13:00:42 +02:00
ph = ERROR_handler ;
if ( ERROR_current & & ERROR_current - > handler = = ph )
2010-06-18 02:14:53 +02:00
break ;
2015-11-18 02:29:28 +01:00
2010-08-03 13:00:42 +02:00
//fprintf(stderr, "ERROR_propagate: %p @ %p (%p)\n", ERROR_handler, ERROR_handler->context, ERROR_current);
2012-05-19 04:55:05 +02:00
prev = ph - > prev ;
2012-09-09 19:24:54 +02:00
( * ph - > handler ) ( ph - > arg1 , ph - > arg2 ) ;
2012-05-19 04:55:05 +02:00
ERROR_handler = prev ;
2010-06-18 02:14:53 +02:00
}
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
longjmp ( ERROR_current - > env , 1 ) ;
2007-12-30 17:41:49 +01:00
}
2008-01-25 16:01:02 +01:00
2008-01-17 22:39:26 +01:00
const char * ERROR_get ( void )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
/*
if ( code > 0 & & code < 256 )
return strerror ( code ) ;
else
return ERROR_Message [ code - 256 ] ;
*/
return strerror ( errno ) ;
2007-12-30 17:41:49 +01:00
}
2009-09-23 00:10:38 +02:00
static int get_message_length ( const char * pattern , char * arg [ ] , int narg )
2008-03-11 14:29:47 +01:00
{
2009-09-23 00:10:38 +02:00
int len ;
int i ;
2015-11-18 02:29:28 +01:00
2009-09-23 00:10:38 +02:00
len = strlen ( pattern ) + narg ;
for ( i = 0 ; i < narg ; i + + )
2019-02-06 23:23:18 +01:00
{
if ( arg [ i ] )
len + = strlen ( arg [ i ] ) ;
}
2015-11-18 02:29:28 +01:00
2009-09-23 00:10:38 +02:00
if ( ! EXEC_debug )
len - = narg * 3 ;
2008-03-11 14:29:47 +01:00
return len ;
}
2007-12-30 17:41:49 +01:00
2008-01-17 22:39:26 +01:00
void ERROR_define ( const char * pattern , char * arg [ ] )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
uchar c ;
char * msg = NULL ;
int len ;
2009-09-23 00:10:38 +02:00
int narg = 0 ;
2007-12-30 17:41:49 +01:00
ERROR_clear ( ) ;
2012-01-15 09:54:57 +01:00
if ( ( intptr_t ) pattern > = 0 & & ( intptr_t ) pattern < 256 )
{
ERROR_current - > info . code = ( int ) ( intptr_t ) pattern ;
pattern = _message [ ( int ) ( intptr_t ) pattern ] ;
if ( * pattern = = ' . ' )
2009-09-23 00:10:38 +02:00
{
narg = pattern [ 1 ] - ' 0 ' ;
pattern + = 2 ;
}
2012-01-15 09:54:57 +01:00
}
else if ( ( intptr_t ) pattern = = E_ABORT )
{
ERROR_current - > info . code = E_ABORT ;
pattern = " " ;
2007-12-30 17:41:49 +01:00
}
else
2009-09-23 00:10:38 +02:00
{
2012-01-15 09:54:57 +01:00
ERROR_current - > info . code = E_CUSTOM ;
2015-11-18 02:29:28 +01:00
2009-09-25 21:56:26 +02:00
if ( arg )
2009-09-23 00:10:38 +02:00
{
2009-09-25 21:56:26 +02:00
msg = ( char * ) pattern ;
for ( ; ; )
2009-09-23 00:10:38 +02:00
{
2009-09-25 21:56:26 +02:00
c = * msg + + ;
if ( c = = 0 )
break ;
2015-11-18 02:29:28 +01:00
2009-09-25 21:56:26 +02:00
if ( c = = ' & ' )
2009-09-23 00:10:38 +02:00
{
2009-09-25 21:56:26 +02:00
c = * msg + + ;
if ( c > = ' 1 ' & & c < = ' 4 ' )
{
2009-09-27 11:28:52 +02:00
c - = ' 0 ' ;
2009-09-25 21:56:26 +02:00
if ( c > narg )
narg = c ;
}
2009-09-23 00:10:38 +02:00
}
}
}
}
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
if ( narg )
{
2009-09-23 00:10:38 +02:00
len = get_message_length ( pattern , arg , narg ) ;
2012-01-15 09:54:57 +01:00
if ( len )
{
2010-06-05 01:48:53 +02:00
msg = STRING_new ( NULL , len ) ;
2009-01-04 12:55:37 +01:00
ERROR_current - > info . msg = msg ;
2012-01-15 09:54:57 +01:00
ERROR_current - > info . free = TRUE ;
2015-11-18 02:29:28 +01:00
2009-09-23 00:10:38 +02:00
if ( EXEC_debug )
2009-01-04 12:55:37 +01:00
{
2009-09-23 00:10:38 +02:00
int i ;
strcpy ( msg , pattern ) ;
msg + = strlen ( pattern ) ;
for ( i = 0 ; i < narg ; i + + )
{
* msg + + = ' | ' ;
if ( arg [ i ] )
{
strcpy ( msg , arg [ i ] ) ;
msg + = strlen ( arg [ i ] ) ;
}
}
}
else
{
for ( ; ; )
2009-01-04 12:55:37 +01:00
{
c = * pattern + + ;
2009-09-23 00:10:38 +02:00
if ( c = = 0 )
break ;
2015-11-18 02:29:28 +01:00
2009-09-23 00:10:38 +02:00
if ( c = = ' & ' )
2009-01-04 12:55:37 +01:00
{
2009-09-23 00:10:38 +02:00
c = * pattern + + ;
if ( c > = ' 1 ' & & c < = ' 4 ' )
2009-07-12 23:49:13 +02:00
{
2009-09-23 00:10:38 +02:00
c - = ' 1 ' ;
if ( arg [ c ] )
{
len = strlen ( arg [ c ] ) ;
memcpy ( msg , arg [ c ] , len ) ;
msg + = len ;
}
2009-07-12 23:49:13 +02:00
}
2009-01-04 12:55:37 +01:00
}
2009-09-23 00:10:38 +02:00
else
* msg + + = c ;
2009-01-04 12:55:37 +01:00
}
2015-11-18 02:29:28 +01:00
2009-09-23 00:10:38 +02:00
* msg = 0 ;
2009-01-04 12:55:37 +01:00
}
2014-07-14 19:23:05 +02:00
/*fprintf(stderr, "msg: %s\n", ERROR_current->info.msg);
if ( strcmp ( ERROR_current - > info . msg , " Type mismatch: wanted WebView, got Function instead " ) = = 0 )
{
BREAKPOINT ( ) ;
STRING_watch = ERROR_current - > info . msg ;
} */
2009-01-04 12:55:37 +01:00
}
2012-01-15 09:54:57 +01:00
}
else if ( ERROR_current - > info . code = = E_CUSTOM )
2009-09-25 21:56:26 +02:00
{
2011-02-02 00:26:08 +01:00
if ( pattern & & * pattern )
{
ERROR_current - > info . msg = STRING_new_zero ( pattern ) ;
ERROR_current - > info . free = TRUE ;
}
else
{
2014-07-14 19:23:05 +02:00
ERROR_current - > info . msg = ( char * ) _message [ E_UNKNOWN ] ;
ERROR_current - > info . free = FALSE ;
2011-02-02 00:26:08 +01:00
}
2009-09-25 21:56:26 +02:00
}
else
2012-01-15 09:54:57 +01:00
{
ERROR_current - > info . msg = ( char * ) pattern ;
ERROR_current - > info . free = FALSE ;
}
2007-12-30 17:41:49 +01:00
2009-09-25 21:56:26 +02:00
//fprintf(stderr, "ERROR_define: %p %d '%s'\n", ERROR_current, ERROR_current->info.code, ERROR_current->info.msg);
2008-01-27 15:00:04 +01:00
//STRING_add_char(&ERROR_current->info.msg, 0);
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
ERROR_current - > info . cp = CP ;
ERROR_current - > info . fp = FP ;
ERROR_current - > info . pc = PC ;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
# if DEBUG_ERROR
2010-08-29 22:51:10 +02:00
ERROR_debug ( " ERROR_define: %s \n " , ERROR_current - > info . msg ) ;
2012-01-15 09:54:57 +01:00
# endif
2007-12-30 17:41:49 +01:00
}
2008-01-17 22:39:26 +01:00
void THROW ( int code , . . . )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
va_list args ;
int i ;
char * arg [ 4 ] ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
va_start ( args , code ) ;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
for ( i = 0 ; i < 4 ; i + + )
arg [ i ] = va_arg ( args , char * ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
ERROR_define ( ( char * ) ( intptr_t ) code , arg ) ;
2009-11-30 05:25:48 +01:00
2013-01-06 17:13:31 +01:00
va_end ( args ) ;
2018-08-22 09:30:27 +02:00
2009-11-30 05:25:48 +01:00
PROPAGATE ( ) ;
2007-12-30 17:41:49 +01:00
}
2016-03-20 02:27:31 +01:00
void THROW_NULL ( void )
{
THROW ( E_NULL ) ;
}
2012-10-19 23:00:35 +02:00
void THROW_CLASS ( void * class , char * arg1 , char * arg2 )
{
THROW ( E_CLASS , CLASS_get_name ( ( CLASS * ) class ) , arg1 , arg2 ) ;
}
2016-03-20 02:27:31 +01:00
void THROW_ILLEGAL ( void )
2010-05-27 00:01:28 +02:00
{
THROW ( E_ILLEGAL ) ;
}
2007-12-30 17:41:49 +01:00
2016-03-20 02:27:31 +01:00
void THROW_STACK ( void )
2012-03-06 02:50:41 +01:00
{
2013-01-01 12:55:40 +01:00
# if DEBUG_STACK
fprintf ( stderr , " THROW STACK! \n " ) ;
# endif
2012-03-06 02:50:41 +01:00
THROW ( E_STACK ) ;
}
2008-01-17 22:39:26 +01:00
void THROW_SYSTEM ( int err , const char * path )
2007-12-30 17:41:49 +01:00
{
2008-10-30 01:54:18 +01:00
char buf [ 6 ] ;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
switch ( err )
{
case ENOENT :
THROW ( E_NEXIST , path ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case EISDIR :
THROW ( E_DIR , path ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case ENOTDIR :
THROW ( E_NDIR , path ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case ENOMEM :
THROW ( E_MEMORY ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case EACCES :
THROW ( E_ACCESS ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case ENAMETOOLONG :
THROW ( E_TOOLONG ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case ENOSPC :
THROW ( E_FULL ) ;
2007-12-30 17:41:49 +01:00
2012-01-15 09:54:57 +01:00
case EEXIST :
THROW ( E_EXIST , path ) ;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
default :
sprintf ( buf , " %d " , err ) ;
THROW ( E_SYSTEM , buf , strerror ( err ) ) ;
}
2007-12-30 17:41:49 +01:00
}
2018-08-11 14:05:09 +02:00
2012-12-15 03:27:42 +01:00
void ERROR_fatal ( const char * error , . . . )
{
va_list args ;
va_start ( args , error ) ;
fputs ( EXEC_arch ? " gbr " GAMBAS_VERSION_STRING : " gbx " GAMBAS_VERSION_STRING , stderr ) ;
fputs ( " : " , stderr ) ;
vfprintf ( stderr , error , args ) ;
va_end ( args ) ;
putc ( ' \n ' , stderr ) ;
_exit ( 1 ) ;
}
2008-01-17 22:39:26 +01:00
void ERROR_panic ( const char * error , . . . )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
va_list args ;
va_start ( args , error ) ;
fflush ( NULL ) ;
2018-08-10 13:26:54 +02:00
fprintf ( stderr , " \n ** \n ** OOPS! INTERNAL ERROR. Program aborting, sorry! :-( \n ** " ) ;
2012-01-15 09:54:57 +01:00
vfprintf ( stderr , error , args ) ;
2015-11-18 02:29:28 +01:00
2013-01-06 17:13:31 +01:00
va_end ( args ) ;
2018-08-10 14:22:49 +02:00
fputc ( ' \n ' , stderr ) ;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
if ( ERROR_current - > info . code )
{
2018-08-10 14:22:49 +02:00
fprintf ( stderr , " ** \n " ) ;
_print_prefix = " ** " ;
2019-09-17 10:07:59 +02:00
ERROR_print ( FALSE ) ;
2018-08-10 14:22:49 +02:00
_print_prefix = NULL ;
2012-01-15 09:54:57 +01:00
}
2018-08-10 14:22:49 +02:00
fprintf ( stderr , " ** \n ** Please send a bug report to the gambas bugtracker [1] or to the gambas mailing-list [2]. \n ** [1] http://gambaswiki.org/bugtracker \n ** [2] https://lists.gambas-basic.org/listinfo/user \n ** \n \n " ) ;
2012-01-15 09:54:57 +01:00
_exit ( 1 ) ;
2007-12-30 17:41:49 +01:00
}
2018-08-10 14:22:49 +02:00
static void print_prefix ( FILE * where )
{
if ( _print_prefix ) fputs ( _print_prefix , where ) ;
}
2008-01-17 22:39:26 +01:00
void ERROR_print_at ( FILE * where , bool msgonly , bool newline )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
if ( ! ERROR_current - > info . code )
return ;
2007-12-30 17:41:49 +01:00
2018-08-10 14:22:49 +02:00
print_prefix ( where ) ;
2007-12-30 17:41:49 +01:00
if ( ! msgonly )
{
2008-01-25 16:01:02 +01:00
if ( ERROR_current - > info . cp & & ERROR_current - > info . fp & & ERROR_current - > info . pc )
fprintf ( where , " %s: " , DEBUG_get_position ( ERROR_current - > info . cp , ERROR_current - > info . fp , ERROR_current - > info . pc ) ) ;
2007-12-30 17:41:49 +01:00
else
fprintf ( where , " ERROR: " ) ;
2008-01-25 16:01:02 +01:00
/*if (ERROR_current->info.code > 0 && ERROR_current->info.code < 256)
fprintf ( where , " %ld: " , ERROR_current - > info . code ) ; */
if ( ERROR_current - > info . code > 0 )
fprintf ( where , " #%d: " , ERROR_current - > info . code ) ;
2011-02-02 00:26:08 +01:00
if ( ERROR_current - > info . msg )
fprintf ( where , " %s " , ERROR_current - > info . msg ) ;
2010-01-24 15:23:51 +01:00
}
else
{
char * p = ERROR_current - > info . msg ;
2010-09-16 13:27:51 +02:00
unsigned char c ;
2015-11-18 02:29:28 +01:00
2011-02-02 00:26:08 +01:00
if ( p )
2010-01-24 15:23:51 +01:00
{
2011-02-02 00:26:08 +01:00
while ( ( c = * p + + ) )
{
if ( c < ' ' ) c = ' ' ;
fputc ( c , where ) ;
}
2010-01-24 15:23:51 +01:00
}
2007-12-30 17:41:49 +01:00
}
2012-01-15 09:54:57 +01:00
if ( newline )
fputc ( ' \n ' , where ) ;
2007-12-30 17:41:49 +01:00
}
2019-09-17 10:07:59 +02:00
bool ERROR_print ( bool can_ignore )
2007-12-30 17:41:49 +01:00
{
2012-01-15 09:54:57 +01:00
static bool lock = FALSE ;
2019-09-17 10:07:59 +02:00
bool ignore = FALSE ;
2012-04-14 00:11:51 +02:00
ERROR_print_at ( stderr , FALSE , TRUE ) ;
2015-11-18 02:29:28 +01:00
2012-04-14 00:11:51 +02:00
if ( ERROR_backtrace )
2018-08-10 14:22:49 +02:00
{
print_prefix ( stderr ) ;
2012-04-14 00:11:51 +02:00
DEBUG_print_backtrace ( ERROR_backtrace ) ;
2018-08-10 14:22:49 +02:00
}
2019-09-17 10:07:59 +02:00
if ( EXEC_main_hook_done & & ! EXEC_debug & & EXEC_Hook . error & & ! lock )
{
lock = TRUE ;
GAMBAS_DoNotRaiseEvent = TRUE ;
ignore = HOOK ( error ) ( ERROR_current - > info . code , ERROR_current - > info . msg , DEBUG_get_position ( ERROR_current - > info . cp , ERROR_current - > info . fp , ERROR_current - > info . pc ) , can_ignore ) ;
GAMBAS_DoNotRaiseEvent = ! ignore ;
lock = FALSE ;
}
return ignore ;
2007-12-30 17:41:49 +01:00
}
2013-05-28 22:48:43 +02:00
static void ERROR_copy ( ERROR_INFO * save , ERROR_INFO * last )
2007-12-30 17:41:49 +01:00
{
2008-01-27 15:00:04 +01:00
ERROR_reset ( save ) ;
2008-01-25 16:01:02 +01:00
* save = ERROR_current - > info ;
2011-07-24 11:45:44 +02:00
2011-08-05 18:03:59 +02:00
if ( last )
{
ERROR_reset ( last ) ;
* last = ERROR_last ;
}
2007-12-30 17:41:49 +01:00
}
2013-05-28 22:48:43 +02:00
void ERROR_save ( ERROR_INFO * save , ERROR_INFO * last )
{
ERROR_copy ( save , last ) ;
CLEAR ( & ERROR_current - > info ) ;
if ( last )
CLEAR ( & ERROR_last ) ;
}
2011-07-24 11:45:44 +02:00
void ERROR_restore ( ERROR_INFO * save , ERROR_INFO * last )
2007-12-30 17:41:49 +01:00
{
2008-01-27 15:00:04 +01:00
ERROR_reset ( & ERROR_current - > info ) ;
2008-01-25 16:01:02 +01:00
ERROR_current - > info = * save ;
2008-01-27 15:00:04 +01:00
CLEAR ( save ) ;
2011-07-24 11:45:44 +02:00
2011-08-05 18:03:59 +02:00
if ( last )
{
ERROR_reset ( & ERROR_last ) ;
ERROR_last = * last ;
CLEAR ( last ) ;
}
2007-12-30 17:41:49 +01:00
}
2008-02-02 11:54:13 +01:00
2011-08-31 04:28:48 +02:00
void ERROR_set_last ( bool bt )
2008-02-02 11:54:13 +01:00
{
ERROR_reset ( & ERROR_last ) ;
ERROR_last = ERROR_current - > info ;
if ( ERROR_last . free )
STRING_ref ( ERROR_last . msg ) ;
2016-07-07 10:50:33 +02:00
if ( bt & & ! ERROR_backtrace )
2011-08-31 04:28:48 +02:00
ERROR_backtrace = STACK_get_backtrace ( ) ;
2008-03-11 14:29:47 +01:00
}
2010-01-25 18:53:58 +01:00
2012-07-29 17:50:27 +02:00
void ERROR_define_last ( void )
{
ERROR_reset ( & ERROR_current - > info ) ;
ERROR_current - > info = ERROR_last ;
if ( ERROR_last . free )
STRING_ref ( ERROR_last . msg ) ;
}
2010-08-28 14:33:05 +02:00
void ERROR_warning ( const char * warning , . . . )
{
2012-01-15 09:54:57 +01:00
va_list args ;
2010-08-28 14:33:05 +02:00
2012-01-15 09:54:57 +01:00
va_start ( args , warning ) ;
2010-08-28 14:33:05 +02:00
2012-01-15 09:54:57 +01:00
fflush ( NULL ) ;
2010-08-28 14:33:05 +02:00
2012-01-15 09:54:57 +01:00
fprintf ( stderr , " gbx " GAMBAS_VERSION_STRING " : warning: " ) ;
vfprintf ( stderr , warning , args ) ;
2015-11-18 02:29:28 +01:00
2013-01-06 17:13:31 +01:00
va_end ( args ) ;
2015-11-18 02:29:28 +01:00
2012-01-15 09:54:57 +01:00
putc ( ' \n ' , stderr ) ;
2010-08-28 14:33:05 +02:00
}
2010-12-21 15:05:42 +01:00
2011-09-13 04:31:56 +02:00
/*void ERROR_deprecated(const char *msg)
2010-12-21 15:05:42 +01:00
{
ERROR_warning ( " %s: %s is deprecated. " , DEBUG_get_current_position ( ) , msg ) ;
2011-09-13 04:31:56 +02:00
} */
2010-12-21 15:05:42 +01:00
2011-08-31 04:28:48 +02:00
void ERROR_exit ( void )
{
ERROR_reset ( & ERROR_last ) ;
2011-09-09 00:04:52 +02:00
STACK_free_backtrace ( & ERROR_backtrace ) ;
2012-09-09 19:24:54 +02:00
}
2013-05-25 16:00:40 +02:00
void ERROR_hook ( void )
{
2013-05-26 13:18:55 +02:00
static bool no_rec = FALSE ;
2015-11-18 02:29:28 +01:00
2013-05-25 16:00:40 +02:00
ERROR_INFO save = { 0 } ;
ERROR_INFO last = { 0 } ;
2020-01-04 22:11:29 +01:00
STACK_BACKTRACE * save_bt = NULL ;
2013-05-26 13:18:55 +02:00
CLASS_DESC_METHOD * handle_error ;
2015-11-18 02:29:28 +01:00
2013-05-26 13:18:55 +02:00
if ( no_rec )
return ;
2015-11-18 02:29:28 +01:00
2014-07-28 07:35:58 +02:00
if ( PROJECT_class & & CLASS_is_loaded ( PROJECT_class ) )
2013-05-25 16:00:40 +02:00
{
2020-01-04 22:11:29 +01:00
handle_error = ( CLASS_DESC_METHOD * ) CLASS_get_symbol_desc_kind ( PROJECT_class , " Application_Error " , CD_STATIC_METHOD , 0 , T_VOID ) ;
2015-11-18 02:29:28 +01:00
2013-06-09 23:30:43 +02:00
if ( handle_error )
2013-05-25 16:00:40 +02:00
{
2013-06-09 23:30:43 +02:00
no_rec = TRUE ;
2020-01-04 22:11:29 +01:00
ERROR_copy ( & save , & last ) ;
if ( ERROR_backtrace ) save_bt = STACK_copy_backtrace ( ERROR_backtrace ) ;
2015-11-18 02:29:28 +01:00
2013-06-09 23:30:43 +02:00
TRY
{
EXEC_public_desc ( PROJECT_class , NULL , handle_error , 0 ) ;
}
CATCH
{
}
END_TRY
2013-05-25 16:00:40 +02:00
2013-06-09 23:30:43 +02:00
ERROR_restore ( & save , & last ) ;
2020-01-04 22:11:29 +01:00
STACK_free_backtrace ( & ERROR_backtrace ) ;
if ( save_bt )
ERROR_backtrace = save_bt ;
2013-06-09 23:30:43 +02:00
no_rec = FALSE ;
}
2013-05-25 16:00:40 +02:00
}
}