📄 gbx_api.c
字号:
/*************************************************************************** gambas_api.c Gambas API for external libraries (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net> 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 1, or (at your option) any later version. 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. 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., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __GBX_API_C#include "gb_common.h"#include "gb_common_case.h"#include "gb_error.h"#include "gb_alloc.h"#include <stdarg.h>#include "gbx_class.h"#include "gbx_exec.h"#include "gbx_event.h"#include "gbx_stack.h"#include "gbx_stream.h"#include "gbx_library.h"#include "gbx_watch.h"#include "gbx_project.h"#include "gbx_eval.h"#include "gbx_local.h"#include "gbx_hash.h"#include "gb_file.h"#include "gbx_number.h"#include "gbx_object.h"#include "gbx_string.h"#include "gbx_date.h"#include "gambas.h"#include "gbx_api.h"typedef struct { OBJECT *object; CLASS_DESC_METHOD *desc; } GB_API_FUNCTION;PUBLIC void *GAMBAS_Api[] ={ (void *)GB_VERSION, (void *)GB_GetInterface, (void *)GB_Hook, (void *)GB_LoadComponent, (void *)GB_Push, (void *)GB_GetFunction, (void *)GB_Call, (void *)GB_Raise, (void *)GB_Post, (void *)EVENT_check_post, (void *)GB_CanRaise, (void *)GB_GetEvent, (void *)GB_NParam, (void *)GB_Conv, (void *)GB_GetUnknown, (void *)GB_IsProperty, (void *)GB_Error, (void *)PROPAGATE, (void *)GB_GetClass, (void *)GB_GetClassName, (void *)CLASS_look, (void *)CLASS_find, (void *)GB_Is, (void *)GB_Ref, (void *)GB_Unref, (void *)GB_UnrefKeep, (void *)GB_Detach, (void *)GB_Attach, (void *)GB_New, (void *)CLASS_auto_create, (void *)GB_CheckObject, (void *)GB_GetEnum, (void *)GB_StopEnum, (void *)GB_Return, (void *)GB_ReturnInt, (void *)GB_ReturnBoolean, (void *)GB_ReturnDate, (void *)GB_ReturnObject, (void *)GB_ReturnNull, (void *)GB_ReturnFloat, (void *)GB_ReturnPtr, (void *)GB_ReturnString, (void *)GB_ReturnConstString, (void *)GB_ReturnConstZeroString, (void *)GB_ReturnNewString, (void *)GB_ReturnNewZeroString, (void *)STRING_new, (void *)GB_FreeString, (void *)STRING_extend, (void *)STRING_add, (void *)GB_StringLength, (void *)GB_ToZeroString, (void *)NUMBER_from_string, (void *)GB_NumberToString, (void *)STRING_subst, (void *)SUBST_add, (void *)GB_ConvString, (void *)STRING_conv_file_name, (void *)GB_LoadFile, (void *)GB_ReleaseFile, (void *)FILE_exist, (void *)GB_GetTempDir, (void *)GB_Store, (void *)GB_StoreString, (void *)GB_StoreObject, (void *)GB_StoreVariant, (void *)DATE_split, (void *)DATE_make, (void *)DATE_from_time, (void *)DATE_timer, (void *)GB_Watch, (void *)GB_Eval, (void *)GB_Alloc, (void *)GB_Free, (void *)GB_Realloc, (void *)GB_NewArray, (void *)ARRAY_delete, (void *)ARRAY_count, (void *)GB_Add, (void *)GB_SubCollectionNew, (void *)GB_SubCollectionAdd, (void *)GB_SubCollectionRemove, (void *)GB_SubCollectionGet, (void *)GB_SubCollectionContainer, (void *)GB_tolower, (void *)GB_toupper, (void *)strcasecmp, (void *)strncasecmp, (void *)GB_AppName, (void *)GB_AppTitle, (void *)GB_AppVersion, (void *)GB_AppPath, (void *)GB_SystemCharset, (void *)LOCAL_get_lang, (void *)GB_ArrayNew, (void *)GB_ArrayCount, (void *)GB_ArrayAdd, (void *)GB_ArrayGet, (void *)GB_CollectionNew, (void *)GB_CollectionCount, (void *)GB_CollectionSet, (void *)GB_CollectionGet, (void *)GB_HashTableNew, (void *)HASH_TABLE_delete, (void *)HASH_TABLE_size, (void *)GB_HashTableAdd, (void *)GB_HashTableRemove, (void *)GB_HashTableGet, (void *)GB_HashTableEnum, (void *)GB_StreamInit, NULL};PUBLIC TYPE GAMBAS_ReturnType;PUBLIC bool GAMBAS_Error = FALSE;PUBLIC bool GAMBAS_DoNotRaiseEvent = FALSE;PUBLIC bool GAMBAS_StopEvent = FALSE;PUBLIC int GB_GetInterface(const char *name, long version, void *iface){ if (LIBRARY_get_interface_by_name(name, version, iface)) ERROR_panic("Cannot find interface of library '%s'", name); return FALSE;}PUBLIC void *GB_Hook(int type, void *hook){ void *old_hook; if ((type < GB_HOOK_MAIN) || (type > GB_HOOK_ERROR)) return NULL; type--; old_hook = ((void **)&EXEC_Hook)[type]; ((void **)&EXEC_Hook)[type] = hook; return old_hook;}PUBLIC int GB_LoadComponent(const char *name){ int ret = 0; TRY { LIBRARY *lib = LIBRARY_create(name); LIBRARY_load(lib); } CATCH { ret = 1; GAMBAS_Error = TRUE; } END_TRY return ret;}PRIVATE void push(int nval, va_list args){ TYPE type; STACK_check(nval); while (nval) { type = va_arg(args, TYPE); switch(type) { case T_INTEGER: case T_BOOLEAN: SP->type = type; SP->_integer.value = va_arg(args, long); break; case T_STRING: SP->type = T_CSTRING; SP->_string.addr = va_arg(args, char *); SP->_string.start = 0; SP->_string.len = va_arg(args, long); if (SP->_string.len <= 0 && SP->_string.addr) SP->_string.len = strlen(SP->_string.addr); break; case T_FLOAT: SP->type = type; SP->_float.value = va_arg(args, double); break; case T_OBJECT: SP->type = type; SP->_object.object = va_arg(args, void *); OBJECT_REF(SP->_object.object, "push"); break; default: ERROR_panic("GB.Push: unknown datatype = &1", type); break; } SP++; nval--; }}PUBLIC void GB_Push(int nval, ...){ va_list args; va_start(args, nval); push(nval, args); va_end(args);}PRIVATE void call_method(void *object, CLASS_DESC_METHOD *desc, int nparam){ if (OBJECT_is_class(object)) { EXEC.object = NULL; //EXEC.class = (CLASS *)object; } else { EXEC.object = object; //EXEC.class = OBJECT_class(object); } EXEC.class = desc->class; EXEC.nparam = nparam; /*desc->npmin;*/ EXEC.drop = FALSE; if (FUNCTION_is_native(desc)) { EXEC.native = TRUE; EXEC.use_stack = FALSE; EXEC.desc = desc; EXEC_native(); SP--; *RP = *SP; SP->type = T_VOID; } else { EXEC.native = FALSE; EXEC.index = (long)desc->exec; //EXEC.func = &class->load->func[(long)desc->exec]; EXEC_function_keep(); }}PUBLIC int GB_CanRaise(void *object, int event_id){ OBJECT *parent; ushort *event_tab; int func_id; if (object == NULL) return FALSE; event_tab = OBJECT_event(object)->event; parent = OBJECT_event(object)->parent; if (parent == NULL) return FALSE; func_id = event_tab[event_id]; if (func_id == 0) return FALSE; return TRUE;}PUBLIC int GB_Raise(void *object, int event_id, int nparam, ...){ OBJECT *parent; CLASS *class; int func_id; CLASS_DESC_METHOD *desc; ushort *event_tab; int result; va_list args; void *old_last; /*MEMORY_check_ptr(object);*/ if (GAMBAS_DoNotRaiseEvent) return FALSE; if (object == NULL) return FALSE; parent = OBJECT_event(object)->parent; if (parent == NULL || OBJECT_is_locked(object)) return FALSE; event_tab = OBJECT_event(object)->event; func_id = event_tab[event_id]; if (!func_id) return FALSE; class = OBJECT_class(object);#if DEBUG_EVENT printf("GB_Raise(%p, %d, %s, %p)\n", object, event_id, class->event[event_id].name, param); printf("func_id = %d parent = %p parent class = %p\n", func_id, parent, parent->class); fflush(NULL);#endif if ((*parent->class->check)(parent)) { OBJECT_detach(object); return FALSE; } func_id--; if (OBJECT_is_class(parent)) desc = &(((CLASS *)parent)->table[func_id].desc->method); else desc = &(parent->class->table[func_id].desc->method); old_last = EVENT_Last; EVENT_Last = object; OBJECT_REF(object, "GB_Raise"); va_start(args, nparam); push(nparam, args); va_end(args); call_method(parent, desc, nparam); if (RP->type == T_VOID) result = 0; else result = (RP->_boolean.value != 0 ? 1 : 0); if (GAMBAS_StopEvent) { GAMBAS_StopEvent = FALSE; result = 1; } EXEC_release_return_value(); OBJECT_UNREF(&object, "GB_Raise"); EVENT_Last = old_last; return result;}PUBLIC long GB_GetEvent(void *class, char *name){ CLASS_DESC_EVENT *cd; cd = CLASS_get_event_desc((CLASS *)class, name); if (!cd) return (-1); else return *cd->index;}PUBLIC void GB_Post(void (*func)(), long param){ EVENT_post(func, param);}PUBLIC int GB_NParam(void){ return EXEC.nparvar;}PUBLIC int GB_IsProperty(void){ return EXEC.property;}PUBLIC const char *GB_GetUnknown(void){ return CP->load->unknown[EXEC.index];}PUBLIC void GB_Error(const char *error, ...){ va_list args; char *arg[8]; int i; if (!error) { GAMBAS_Error = FALSE; return; } va_start(args, error); for (i = 0; i < 8; i++) arg[i] = va_arg(args, char *); ERROR_define(error, arg); GAMBAS_Error = TRUE;}PUBLIC void GB_Ref(void *object){ #if TRACE_MEMORY CLASS *save = CP; CP = NULL; #endif if (object) OBJECT_REF(object, "GB_Ref"); #if TRACE_MEMORY CP = save; #endif}PUBLIC void GB_Unref(void **object){ #if TRACE_MEMORY CLASS *save = CP; CP = NULL; #endif if (*object) OBJECT_UNREF(object, "GB_Unref"); #if TRACE_MEMORY CP = save; #endif}PUBLIC void GB_UnrefKeep(void **object, int delete){ #if TRACE_MEMORY CLASS *save = CP; CP = NULL; #endif if (*object != NULL) { if (delete) { OBJECT_UNREF(object, "GB_UnrefKeep"); } else { OBJECT_UNREF_KEEP(object, "GB_UnrefKeep"); } } #if TRACE_MEMORY CP = save; #endif}PUBLIC void GB_Detach(void *object){ if (object) OBJECT_detach(object);}PUBLIC void GB_Attach(void *object, void *parent, const char *name){ if (object) OBJECT_attach(object, parent, name);}PUBLIC void GB_StopEnum(void){ EXEC_enum_stop = TRUE; VALUE_default(&TEMP, GAMBAS_ReturnType);}PUBLIC void *GB_GetEnum(void){ return (void *)EXEC_enum_data;}PUBLIC void GB_Return(ulong type, ...){ static void *jump[16] = { &&__VOID, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__FLOAT, &&__DATE, &&__STRING, &&__STRING, &&__VARIANT, &&__ARRAY, &&__STRUCT, &&__FUNCTION, &&__CLASS, &&__NULL }; VALUE *ret = &TEMP; va_list args; va_start(args, type); ret->type = type; if (TYPE_is_object(type)) goto __OBJECT; else goto *jump[type];__BOOLEAN: ret->_integer.value = va_arg(args, int) ? (-1) : 0; goto __CONV;__BYTE: ret->_integer.value = va_arg(args, int); goto __CONV;__SHORT: ret->_integer.value = va_arg(args, int); goto __CONV;__INTEGER: ret->_integer.value = va_arg(args, long); goto __CONV;__FLOAT: ret->_float.value = va_arg(args, double); goto __CONV;__DATE: ret->_date.date = va_arg(args, long); ret->_date.time = va_arg(args, long); goto __CONV;__OBJECT: ret->_object.object = va_arg(args, void *); goto __CONV;__CLASS: ret->_class.class = va_arg(args, CLASS *); goto __CONV;__CONV: /*VALUE_conv(ret, GAMBAS_ReturnType); Laisser l'appelant faire la conversion */__STRING:__VOID:__LONG:__VARIANT:__ARRAY:__STRUCT:__FUNCTION:__NULL: return;}PUBLIC void GB_ReturnInt(long val){ GB_Return(T_INTEGER, val);}PUBLIC void GB_ReturnFloat(double val){ GB_Return(T_FLOAT, val);}PUBLIC void GB_ReturnDate(GB_DATE *date){ TEMP = *((VALUE *)date); TEMP.type = T_DATE;}PUBLIC void GB_ReturnBoolean(int val){ GB_Return(T_BOOLEAN, val);}PUBLIC void GB_ReturnObject(void *val){ if (val == NULL) GB_ReturnNull(); else if (GAMBAS_ReturnType == T_VARIANT) GB_Return(T_OBJECT, val); else GB_Return(GAMBAS_ReturnType, val);}PUBLIC void GB_ReturnPtr(ulong type, void *value){ if (type == T_VOID) return; VALUE_read(&TEMP, value, type); /*VALUE_conv(&TEMP, GAMBAS_ReturnType);*/}PUBLIC char *GB_ToZeroString(GB_STRING *src){ char *str; STRING_new_temp(&str, src->value.addr + src->value.start, src->value.len); if (str == NULL) return ""; else return str;}PUBLIC void GB_ReturnString(char *str){ TEMP.type = T_STRING; TEMP._string.addr = str; TEMP._string.start = 0; TEMP._string.len = STRING_length(str); if (TEMP._string.len == 0) TEMP._string.addr = 0;}PUBLIC void GB_ReturnConstString(const char *str, long len){ TEMP.type = T_CSTRING; TEMP._string.addr = (char *)str; TEMP._string.start = 0; TEMP._string.len = len; if (TEMP._string.len == 0) TEMP._string.addr = 0;}PUBLIC void GB_ReturnConstZeroString(const char *str){ long len; if (str) len = strlen(str); else len = 0; GB_ReturnConstString(str, len);}PUBLIC void GB_ReturnNewString(const char *src, long len){ char *str; STRING_new_temp(&str, src, len); GB_ReturnString(str);}PUBLIC void GB_ReturnNewZeroString(const char *src){ GB_ReturnNewString(src, 0);}PUBLIC void GB_ReturnNull(void){ TEMP.type = T_NULL;}PUBLIC void *GB_GetClass(void *object){ if (object) return OBJECT_class(object); else return EXEC.class;}PUBLIC char *GB_GetClassName(void *object){ CLASS *class = GB_GetClass(object); return class->name;}PUBLIC int GB_Is(void *object, void *class){ CLASS *ob_class; if (!object) return FALSE; ob_class = OBJECT_class(object); return ((ob_class == class) || CLASS_inherits(ob_class, class));}PUBLIC int GB_LoadFile(const char *path, long lenp, char **addr, long *len){ int ret = 0; TRY { *addr = 0; STREAM_load(STRING_conv_file_name(path, lenp), addr, len); } CATCH { if (*addr) GB_ReleaseFile(addr, *len); GAMBAS_Error = TRUE; ret = 1; } END_TRY return ret;}PUBLIC void GB_ReleaseFile(char **addr, long len){ FREE(addr, "GB_ReleaseFile");}PUBLIC void GB_Store(GB_TYPE type, GB_VALUE *src, void *dst){ if (src != NULL) { /* Ne marche que parce que value->type == type apr鑣 un VALUE_read() Sinon il y'aurait des probl鑝es de r閒閞ences - VALUE_write faisant appel
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -