[EXAMPLES]

* BUG: The Scripting example was fixed.

[INTERPRETER]
* NEW: The error management was redesigned.

[GB.DB]
* NEW: Database driver can declare a set of character that are allowed in a
  database name.
  
[GB.DB.SQLITE2]
* NEW: '.' is allowed in database names now.

[GB.DB.SQLITE3]
* NEW: '.' is allowed in database names now.



git-svn-id: svn://localhost/gambas/trunk@1038 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2008-01-25 15:01:02 +00:00
parent 7cc9986bda
commit 9f4ee9e75e
17 changed files with 173 additions and 142 deletions

9
TODO
View File

@ -31,7 +31,6 @@ Do it asap:
- Structure support
- Callback support
- Sorting two or more arrays at the same time.
- Creates error objects for each error and not one for all.
DEVELOPMENT ENVIRONMENT
-----------------------
@ -67,19 +66,12 @@ DATABASE COMPONENT
- Copy a result line into another one.
- Use SAVEPOINT in postgresql to simulate nested transactions.
DOCUMENTATION WIKI
------------------
- Mass rename command.
- Fix last changes: only those in one language.
64 BITS
-------
- X11 Window datatype is a long => Control.Id should return a pointer
OTHER
-----
@ -89,5 +81,4 @@ COMPONENTS
----------
- gb.corba ?
- gb.v4l ?

View File

@ -612,6 +612,8 @@ static int open_database(DB_DESC *desc, DB_DATABASE *db)
db->flags.no_blob = TRUE;
db->flags.no_nest = TRUE;
db->db_name_char = ".";
db->handle = conn;
return FALSE;
}

View File

@ -711,6 +711,8 @@ static int open_database(DB_DESC * desc, DB_DATABASE * db)
db->flags.no_table_type = TRUE;
db->flags.no_nest = TRUE;
db->db_name_char = ".";
db->handle = conn;
return FALSE;
}

View File

@ -38,8 +38,11 @@
#include "gbx_exec.h"
#include "gbx_api.h"
//#define DEBUG_ERROR
ERROR_INFO ERROR_info = { 0 };
ERROR_CONTEXT *ERROR_current = NULL;
//ERROR_current->info ERROR_current->info = { 0 };
static int _lock = 0;
static const char *_message[64] =
@ -110,7 +113,6 @@ static const char *_message[64] =
NULL
};
static ERROR_CONTEXT *_current = NULL;
void ERROR_lock()
@ -124,37 +126,89 @@ void ERROR_unlock()
_lock--;
}
static void ERROR_reset()
static void ERROR_reset(ERROR_CONTEXT *err)
{
ERROR_info.code = 0;
DEBUG_free_backtrace(&ERROR_info.backtrace);
err->info.code = 0;
if (err->info.free)
{
STRING_free(&err->info.msg);
err->info.free = FALSE;
}
else
err->info.msg = NULL;
DEBUG_free_backtrace(&err->info.backtrace);
}
void ERROR_clear()
{
if (_lock)
return;
ERROR_reset();
ERROR_reset(ERROR_current);
}
void ERROR_enter(ERROR_CONTEXT *err)
{
CLEAR(err);
err->prev = _current;
_current = err;
err->prev = ERROR_current;
ERROR_current = err;
#if DEBUG_ERROR
fprintf(stderr, ">> ERROR_enter");
{
ERROR_CONTEXT *e = err;
while (e)
{
fprintf(stderr, " -> %p", e);
e = e->prev;
}
fprintf(stderr, "\n");
}
#endif
}
void ERROR_leave(ERROR_CONTEXT *err)
{
if (err->prev != ERROR_LEAVE_DONE)
{
_current = err->prev;
err->prev = ERROR_LEAVE_DONE;
}
if (err->prev == ERROR_LEAVE_DONE)
return;
#if DEBUG_ERROR
fprintf(stderr, "<< ERROR_leave");
{
ERROR_CONTEXT *e = err;
while (e)
{
fprintf(stderr, " -> %p", e);
e = e->prev;
}
fprintf(stderr, "\n");
}
#endif
//if (!err->prev)
// BREAKPOINT();
ERROR_current = err->prev;
if (ERROR_current)
{
ERROR_reset(ERROR_current);
ERROR_current->info = err->info;
}
err->prev = ERROR_LEAVE_DONE;
//ERROR_reset(err);
}
void ERROR_propagate()
{
if (ERROR_current->ret)
ERROR_leave(ERROR_current);
longjmp(ERROR_current->env, 1);
}
const char *ERROR_get(void)
{
@ -170,54 +224,43 @@ const char *ERROR_get(void)
void ERROR_define(const char *pattern, char *arg[])
{
int n;
uchar c;
boolean subst;
void _add_char(uchar c)
{
if (n >= MAX_ERROR_MSG)
return;
if (c && c < ' ' && c != '\n')
c = ' ';
ERROR_info.msg[n++] = c;
STRING_add(&ERROR_current->info.msg, (char *)&c, 1);
}
void _add_string(const char *s)
{
if (!s)
s = "";
while (*s)
{
_add_char(*s);
s++;
}
STRING_add(&ERROR_current->info.msg, s, 0);
}
ERROR_clear();
if ((intptr_t)pattern >= 0 && (intptr_t)pattern < 256)
{
ERROR_info.code = (int)(intptr_t)pattern;
ERROR_current->info.code = (int)(intptr_t)pattern;
pattern = _message[(int)(intptr_t)pattern];
}
else if ((intptr_t)pattern == E_ABORT)
{
ERROR_info.code = E_ABORT;
ERROR_current->info.code = E_ABORT;
pattern = "";
}
else
ERROR_info.code = E_CUSTOM;
n = 0;
ERROR_current->info.code = E_CUSTOM;
if (arg)
{
subst = FALSE;
ERROR_current->info.free = TRUE;
for (;;)
{
c = *pattern++;
@ -246,45 +289,23 @@ void ERROR_define(const char *pattern, char *arg[])
}
else
{
_add_string(pattern);
ERROR_current->info.msg = (char *)pattern;
ERROR_current->info.free = FALSE;
}
_add_char(0);
ERROR_info.cp = CP;
ERROR_info.fp = FP;
ERROR_info.pc = PC;
ERROR_current->info.cp = CP;
ERROR_current->info.fp = FP;
ERROR_current->info.pc = PC;
if (EXEC_debug || (CP && CP->debug))
{
DEBUG_free_backtrace(&ERROR_info.backtrace);
ERROR_info.backtrace = DEBUG_backtrace();
//DEBUG_free_backtrace(&ERROR_current->info.backtrace);
ERROR_current->info.backtrace = DEBUG_backtrace();
}
}
void PROPAGATE()
{
ERROR_CONTEXT *err;
/*
if (_must_free_index)
{
for (i = 0; i < _must_free_index; i++)
OBJECT_UNREF(&_must_free[i], "PROPAGATE");
_must_free_index = 0;
}
*/
if (_current == NULL)
ERROR_panic("Cannot propagate error. No error handler.");
err = _current;
ERROR_leave(_current);
longjmp(err->env, 1);
}
void THROW(int code, ...)
{
va_list args;
@ -347,7 +368,7 @@ void ERROR_panic(const char *error, ...)
);
vfprintf(stderr, error, args);
fprintf(stderr, "\n");
if (ERROR_info.code)
if (ERROR_current->info.code)
{
fprintf(stderr, "\n");
ERROR_print();
@ -361,22 +382,22 @@ void ERROR_panic(const char *error, ...)
void ERROR_print_at(FILE *where, bool msgonly, bool newline)
{
if (!ERROR_info.code)
if (!ERROR_current->info.code)
return;
if (!msgonly)
{
if (ERROR_info.cp && ERROR_info.fp && ERROR_info.pc)
fprintf(where, "%s: ", DEBUG_get_position(ERROR_info.cp, ERROR_info.fp, ERROR_info.pc));
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));
else
fprintf(where, "ERROR: ");
/*if (ERROR_info.code > 0 && ERROR_info.code < 256)
fprintf(where, "%ld:", ERROR_info.code);*/
if (ERROR_info.code > 0)
fprintf(where, "#%d: ", ERROR_info.code);
/*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);
}
fprintf(where, "%s", ERROR_info.msg);
fprintf(where, "%s", ERROR_current->info.msg);
if (newline)
fputc('\n', where);
}
@ -385,7 +406,7 @@ void ERROR_print(void)
{
static bool lock = FALSE;
DEBUG_BACKTRACE *bt = ERROR_info.backtrace;
DEBUG_BACKTRACE *bt = ERROR_current->info.backtrace;
ERROR_print_at(stderr, FALSE, TRUE);
@ -401,33 +422,35 @@ void ERROR_print(void)
{
lock = TRUE;
GAMBAS_DoNotRaiseEvent = TRUE;
HOOK(error)(ERROR_info.code, ERROR_info.msg, DEBUG_get_position(ERROR_info.cp, ERROR_info.fp, ERROR_info.pc));
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));
lock = FALSE;
}
}
void ERROR_save(ERROR_INFO *save)
{
save->code = ERROR_info.code;
save->cp = ERROR_info.cp;
save->fp = ERROR_info.fp;
save->pc = ERROR_info.pc;
save->backtrace = ERROR_info.backtrace;
ERROR_info.backtrace = NULL;
strlcpy(save->msg, ERROR_info.msg, sizeof(ERROR_info.msg));
*save = ERROR_current->info;
ERROR_reset(ERROR_current);
// save->code = ERROR_current->info.code;
// save->cp = ERROR_current->info.cp;
// save->fp = ERROR_current->info.fp;
// save->pc = ERROR_current->info.pc;
// save->backtrace = ERROR_current->info.backtrace;
// ERROR_current->info.backtrace = NULL;
// strlcpy(save->msg, ERROR_current->info.msg, sizeof(ERROR_current->info.msg));
}
void ERROR_restore(ERROR_INFO *save)
{
ERROR_reset();
ERROR_info.code = save->code;
ERROR_info.cp = save->cp;
ERROR_info.cp = save->fp;
ERROR_info.pc = save->pc;
ERROR_info.backtrace = save->backtrace;
save->backtrace = NULL;
strlcpy(ERROR_info.msg, save->msg, sizeof(ERROR_info.msg));
ERROR_reset(ERROR_current);
ERROR_current->info = *save;
// ERROR_current->info.code = save->code;
// ERROR_current->info.cp = save->cp;
// ERROR_current->info.cp = save->fp;
// ERROR_current->info.pc = save->pc;
// ERROR_current->info.backtrace = save->backtrace;
// save->backtrace = NULL;
// strlcpy(ERROR_current->info.msg, save->msg, sizeof(ERROR_current->info.msg));
}

View File

@ -100,11 +100,13 @@ enum {
typedef
struct {
int code;
short code;
bool free;
void *cp;
void *fp;
void *pc;
char msg[MAX_ERROR_MSG + 1];
//char msg[MAX_ERROR_MSG + 1];
char *msg;
void *backtrace;
}
ERROR_INFO;
@ -112,16 +114,16 @@ typedef
typedef
struct _ERROR {
struct _ERROR *prev;
int code;
jmp_buf env;
int ret;
ERROR_INFO info;
}
ERROR_CONTEXT;
#ifndef __GB_ERROR_C
EXTERN ERROR_INFO ERROR_info;
EXTERN ERROR_CONTEXT *ERROR_current;
#endif
#define ERROR_LEAVE_DONE ((ERROR_CONTEXT *)-1)
#define TRY \
@ -129,27 +131,30 @@ EXTERN ERROR_INFO ERROR_info;
ERROR_CONTEXT __err_context; \
{ \
ERROR_CONTEXT *__err = &__err_context; \
/*fprintf(stderr, "TRY %s\n", __FUNCTION__);*/ \
ERROR_enter(__err); \
__err->code = setjmp(__err->env); \
if (__err->code == 0)
#define FINALLY
__err->ret = setjmp(__err->env); \
if (__err->ret == 0)
/*#define CATCH \
fprintf(stderr, "%p == %p ? %d\n", ERROR_current, __err, __err->ret); \
if (__err->ret != 0 && (__err->ret = 2))*/
#define CATCH \
if (__err->code != 0 && !(__err->code = 0))
#define CATCH_GET(get_it) \
if (__err->code != 0 && (get_it = __err->code) && !(__err->code = 0))
/*if (__err->ret) fprintf(stderr, "CATCH %p\n", __err); \
if (__err->ret)*/ \
else
#define END_TRY \
if (__err->code == 0) \
ERROR_leave(__err); \
else \
PROPAGATE(); \
ERROR_leave(__err); \
/*fprintf(stderr, "END TRY %s\n", __FUNCTION__);*/ \
} \
}
//PUBLIC void ERROR_clear(void);
#define ERROR __err
#define PROPAGATE() ERROR_propagate()
//#define PROPAGATE() fprintf(stderr, "PROPAGATE %s\n", __FUNCTION__), ERROR_propagate()
PUBLIC const char *ERROR_get(void);
PUBLIC void ERROR_enter(ERROR_CONTEXT *err);
@ -157,7 +162,7 @@ PUBLIC void ERROR_leave(ERROR_CONTEXT *err);
PUBLIC void ERROR_define(const char *pattern, char *arg[]);
PUBLIC void PROPAGATE() NORETURN;
PUBLIC void ERROR_propagate() NORETURN;
PUBLIC void THROW(int code, ...) NORETURN;
PUBLIC void THROW_SYSTEM(int err, const char *path);

View File

@ -113,7 +113,6 @@ static void main_exit()
EVENT_exit();
FILE_exit();
STRING_exit();
ERROR_clear();
STACK_exit();
}
@ -222,7 +221,7 @@ int main(int argc, char **argv)
}
CATCH
{
if (ERROR_info.code && ERROR_info.code != E_ABORT)
if (ERROR_current->info.code && ERROR_current->info.code != E_ABORT)
ERROR_print_at(stderr, TRUE, TRUE);
main_exit();
_exit(1);
@ -321,7 +320,7 @@ int main(int argc, char **argv)
}
else
{
if (ERROR_info.code && ERROR_info.code != E_ABORT)
if (ERROR->info.code && ERROR->info.code != E_ABORT)
ERROR_print();
main_exit();
_exit(1);
@ -358,7 +357,7 @@ int main(int argc, char **argv)
}
CATCH
{
if (ERROR_info.code && ERROR_info.code != E_ABORT)
if (ERROR->info.code && ERROR->info.code != E_ABORT)
{
if (EXEC_debug)
{
@ -376,7 +375,6 @@ int main(int argc, char **argv)
}
END_TRY
ERROR_info.code = 0;
main_exit();
if (MEMORY_count)

View File

@ -101,7 +101,7 @@ void *GAMBAS_Api[] =
(void *)GB_IsProperty,
(void *)GB_Error,
(void *)PROPAGATE,
(void *)ERROR_propagate,
(void *)GB_GetClass,
(void *)GB_GetClassName,

View File

@ -45,15 +45,15 @@
BEGIN_PROPERTY(CERROR_code)
GB_ReturnInt(ERROR_info.code);
GB_ReturnInt(ERROR_current->info.code);
END_PROPERTY
BEGIN_PROPERTY(CERROR_text)
if (ERROR_info.code)
GB_ReturnNewZeroString(ERROR_info.msg);
if (ERROR_current->info.code)
GB_ReturnNewZeroString(ERROR_current->info.msg);
else
GB_ReturnNull();
@ -62,8 +62,8 @@ END_PROPERTY
BEGIN_PROPERTY(CERROR_class)
if (ERROR_info.code)
GB_ReturnObject(ERROR_info.cp);
if (ERROR_current->info.code)
GB_ReturnObject(ERROR_current->info.cp);
else
GB_ReturnNull();
@ -72,8 +72,8 @@ END_PROPERTY
BEGIN_PROPERTY(CERROR_where)
if (ERROR_info.code)
GB_ReturnNewZeroString(DEBUG_get_position(ERROR_info.cp, ERROR_info.fp, ERROR_info.pc));
if (ERROR_current->info.code)
GB_ReturnNewZeroString(DEBUG_get_position(ERROR_current->info.cp, ERROR_current->info.fp, ERROR_current->info.pc));
else
GB_ReturnNull();
@ -97,7 +97,7 @@ END_METHOD
BEGIN_METHOD_VOID(CERROR_propagate)
if (ERROR_info.code)
if (ERROR_current->info.code)
GAMBAS_Error = TRUE;
END_METHOD
@ -105,7 +105,7 @@ END_METHOD
BEGIN_PROPERTY(CERROR_backtrace)
DEBUG_BACKTRACE *bt = (DEBUG_BACKTRACE *)ERROR_info.backtrace;
DEBUG_BACKTRACE *bt = (DEBUG_BACKTRACE *)ERROR_current->info.backtrace;
if (!bt)
GB_ReturnNull();

View File

@ -195,7 +195,7 @@ void CLASS_exit(void)
fprintf(stderr, "\n------------------- CLASS_exit -------------------\n\n");
#endif
in_error = ERROR_info.code > 0;
in_error = ERROR_current != NULL;
#if DEBUG_LOAD
fprintf(stderr, "Freeing auto-creatable objects...\n");
@ -258,7 +258,7 @@ void CLASS_exit(void)
#endif
/* On force la lib<69>ation de ce qui reste, tant pis */
/* ERROR_info.code != 0 if we are exiting just after an error */
/* ERROR_current->info.code != 0 if we are exiting just after an error */
if (n < nc)
{

View File

@ -93,7 +93,7 @@ static bool EVAL_exec()
//AP = ARCH_from_class(CP);
EXEC_debug = debug;
return (ERROR_info.code != 0);
return (ERROR_current->info.code != 0);
}

View File

@ -72,6 +72,7 @@ EXEC_HOOK EXEC_Hook = { NULL };
EXEC_FUNCTION EXEC;
bool EXEC_main_hook_done = FALSE;
int EXEC_return_value = 0;
bool EXEC_got_error = FALSE;
void EXEC_init(void)
{
@ -711,7 +712,7 @@ void EXEC_function_real(bool keep_ret_value)
CATCH
{
// QUIT was called
if (ERROR_info.code == E_ABORT)
if (ERROR->info.code == E_ABORT)
{
#if DEBUG_ERROR
printf("#0 QUIT\n");

View File

@ -98,7 +98,7 @@ EXTERN CENUM *EXEC_enum;
EXTERN bool EXEC_big_endian;
EXTERN bool EXEC_main_hook_done;
EXTERN int EXEC_return_value;
EXTERN bool EXEC_got_error;
/*EXTERN long EXEC_const[];*/
#endif

View File

@ -1535,11 +1535,8 @@ _END_TRY:
#endif
/* If EP was reset to null, then there was an error */
if (EP)
{
ERROR_clear();
EP = NULL;
}
EXEC_got_error = (EP == NULL);
EP = NULL;
EC = ET;
ET = NULL;
goto _NEXT;

View File

@ -59,7 +59,7 @@ static void init_eval()
void SUBR_error(void)
{
SP->type = T_BOOLEAN;
SP->_boolean.value = ERROR_info.code != 0 ? -1 : 0;
SP->_boolean.value = EXEC_got_error ? -1 : 0;
SP++;
}

View File

@ -165,7 +165,7 @@ BEGIN_METHOD(CDATABASE_add, GB_STRING name)
CCONNECTION *conn = GB.SubCollection.Container(THIS);
char *name = GB.ToZeroString(ARG(name));
if (DB_CheckName(name, "database"))
if (DB_CheckNameWith(name, "database", conn->db.db_name_char))
return;
if (check_database(conn, name, FALSE))

View File

@ -69,6 +69,7 @@ typedef
int pos; /* position of 'limit' keyword */
}
limit;
char *db_name_char; /* These characters are allowed in a database name */
}
DB_DATABASE;

View File

@ -143,6 +143,17 @@ typedef
#define Min(a, b) ({ int _a = (a), _b = (b); _a < _b ? _a : _b; })
#define MinMax(v, a, b) ({ int _v = (v), _a = (a), _b = (b); _v < _a ? _a : (_v > _b ? _b : _v); })
#if (defined (__i386__) || defined (__x86_64__)) && defined (__GNUC__) && __GNUC__ >= 2
# define BREAKPOINT() { __asm__ __volatile__ ("int $03"); }
#elif (defined (_MSC_VER) || defined (__DMC__)) && defined (_M_IX86)
# define BREAKPOINT() { __asm int 3h }G_STMT_END
#elif defined (__alpha__) && !defined(__osf__) && defined (__GNUC__) && __GNUC__ >= 2
# define BREAKPOINT() { __asm__ __volatile__ ("bpt"); }
#else /* !__i386__ && !__alpha__ */
# define BREAKPOINT() { raise (SIGTRAP); }
#endif /* __i386__ */
#define COPYRIGHT "(c) 2000-2007 Benoit Minisini\n\n" \
"This program is free software; you can redistribute it and/or \n" \
"modify it under the terms of the GNU General Public License as \n" \