2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
gbx_class_native.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-13 09:04:11 +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-13 09:04:11 +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-13 09:04:11 +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 __GBX_CLASS_NATIVE_C
|
|
|
|
|
|
|
|
#include "gb_common.h"
|
|
|
|
#include "gb_common_buffer.h"
|
|
|
|
#include "gb_alloc.h"
|
|
|
|
#include "gb_error.h"
|
|
|
|
#include "gb_limit.h"
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include "gb_buffer.h"
|
|
|
|
#include "gb_file.h"
|
|
|
|
#include "gbx_type.h"
|
|
|
|
#include "gbx_exec.h"
|
|
|
|
#include "gbx_debug.h"
|
|
|
|
#include "gb_magic.h"
|
|
|
|
#include "gbx_stream.h"
|
|
|
|
|
|
|
|
#include "gbx_string.h"
|
|
|
|
#include "gbx_object.h"
|
|
|
|
#include "gbx_variant.h"
|
|
|
|
#include "gbx_number.h"
|
|
|
|
|
|
|
|
#include "gambas.h"
|
|
|
|
#include "gbx_api.h"
|
|
|
|
|
|
|
|
#include "gbx_class.h"
|
|
|
|
|
|
|
|
//extern long total;
|
|
|
|
|
|
|
|
BEGIN_PROPERTY(class_self_property)
|
|
|
|
|
2008-02-21 15:13:47 +01:00
|
|
|
GB_ReturnSelf(_object);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
CLASS *CLASS_register_class(GB_DESC *ptr, CLASS *class)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2012-01-13 09:04:11 +01:00
|
|
|
int i, n_desc;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_DESC *desc;
|
|
|
|
CLASS_DESC *start;
|
|
|
|
CLASS_DESC_GAMBAS *gambas = (CLASS_DESC_GAMBAS *)ptr;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_EVENT *event;
|
|
|
|
const char *ptype;
|
|
|
|
//const char *type;
|
|
|
|
int first_event, nsign;
|
|
|
|
TYPE *sign;
|
|
|
|
int first;
|
|
|
|
int size_dynamic;
|
2012-02-01 02:51:29 +01:00
|
|
|
VALUE value;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
#if DEBUG_LOAD
|
2011-11-06 01:26:37 +01:00
|
|
|
fprintf(stderr, "Registering native class %s (%p)...\n", class->name, class);
|
2012-01-13 09:04:11 +01:00
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
if (gambas->type != GB_VERSION)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (class->error)
|
2012-10-19 23:00:35 +02:00
|
|
|
THROW_CLASS(class, "Loading has already failed", "");
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-01-01 15:46:02 +01:00
|
|
|
class->error = TRUE;
|
|
|
|
|
2009-01-01 14:42:17 +01:00
|
|
|
class->is_native = TRUE;
|
2012-01-13 09:04:11 +01:00
|
|
|
class->load = NULL;
|
|
|
|
class->data = NULL;
|
|
|
|
class->component = COMPONENT_current;
|
|
|
|
|
|
|
|
#if DEBUG_COMP
|
|
|
|
if (class->component)
|
|
|
|
fprintf(stderr, "class %s -> component %s\n", class->name, class->component->name);
|
|
|
|
else
|
|
|
|
fprintf(stderr, "class %s -> no component\n", class->name);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
class->is_virtual = *class->name == '.';
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-12-24 03:02:05 +01:00
|
|
|
#ifdef OS_64BITS
|
2012-01-13 09:04:11 +01:00
|
|
|
size_dynamic = (gambas->val1 + 7) & ~7;
|
2009-12-24 03:02:05 +01:00
|
|
|
#else
|
2012-01-13 09:04:11 +01:00
|
|
|
size_dynamic = (gambas->val1 + 3) & ~3;
|
2009-12-24 03:02:05 +01:00
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
class->n_desc = 0;
|
|
|
|
class->n_event = 0;
|
|
|
|
nsign = 0;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Read the class global information at the beginning of the description */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
desc = (CLASS_DESC *)&gambas[1];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
for (start = NULL; start == NULL; desc++)
|
|
|
|
{
|
|
|
|
if (desc->gambas.name == NULL)
|
|
|
|
{
|
|
|
|
start = desc;
|
|
|
|
break;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
switch ((intptr_t)desc->gambas.name)
|
|
|
|
{
|
|
|
|
case (intptr_t)GB_INHERITS_ID:
|
2018-08-14 16:46:55 +02:00
|
|
|
CLASS_inheritance(class, CLASS_find((const char *)desc->gambas.type));
|
2012-01-13 09:04:11 +01:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case (intptr_t)GB_AUTO_CREATABLE_ID:
|
|
|
|
class->auto_create = TRUE;
|
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case (intptr_t)GB_NOT_CREATABLE_ID:
|
2014-09-06 18:53:40 +02:00
|
|
|
class->no_create = TRUE;
|
|
|
|
break;
|
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case (intptr_t)GB_VIRTUAL_CLASS_ID:
|
|
|
|
class->no_create = TRUE;
|
2014-09-06 17:38:40 +02:00
|
|
|
class->is_virtual = TRUE;
|
2012-01-13 09:04:11 +01:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case (intptr_t)GB_HOOK_CHECK_ID:
|
|
|
|
class->check = (int (*)())(desc->hook.func);
|
2010-06-05 01:48:53 +02:00
|
|
|
class->must_check = TRUE;
|
2012-01-13 09:04:11 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
start = desc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/* If there is a parent class, and if the size is zero, then inherits the size */
|
2008-08-31 02:32:21 +02:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
if (class->parent && size_dynamic == 0)
|
|
|
|
size_dynamic = class->parent->size;
|
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Compute the number of symbol description */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
for(desc = start, n_desc = 0; desc->gambas.name != NULL; desc++, n_desc++);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Description analysis */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
for (i = 0; i < n_desc; i++)
|
|
|
|
{
|
|
|
|
desc = &start[i];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-08-20 02:33:36 +02:00
|
|
|
ptype = (char *)desc->gambas.type;
|
|
|
|
desc->gambas.type = TYPE_from_string(&ptype);
|
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
switch (CLASS_DESC_get_type(desc))
|
|
|
|
{
|
|
|
|
case CD_CONSTANT:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
if (desc->constant.type == T_STRING)
|
|
|
|
desc->constant.type = T_CSTRING;
|
2012-02-01 02:51:29 +01:00
|
|
|
else if (desc->constant.type == T_FLOAT || desc->constant.type == T_SINGLE)
|
|
|
|
{
|
2012-07-16 18:30:55 +02:00
|
|
|
if (desc->gambas.val1 == 0)
|
|
|
|
{
|
2012-07-17 21:36:11 +02:00
|
|
|
value._float.value = desc->gambas.val3._double;
|
2012-07-16 18:30:55 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (NUMBER_from_string(NB_READ_FLOAT, desc->constant.value._string, strlen(desc->constant.value._string), &value))
|
2012-10-19 23:00:35 +02:00
|
|
|
THROW_CLASS(class, "Bad constant", "");
|
2012-07-16 18:30:55 +02:00
|
|
|
}
|
|
|
|
|
2012-02-01 02:51:29 +01:00
|
|
|
if (desc->constant.type == T_SINGLE)
|
|
|
|
desc->constant.value._single = (float)value._float.value;
|
|
|
|
else
|
|
|
|
desc->constant.value._float = value._float.value;
|
|
|
|
}
|
2012-01-13 09:04:11 +01:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case CD_PROPERTY:
|
|
|
|
case CD_STATIC_PROPERTY:
|
|
|
|
case CD_PROPERTY_READ:
|
|
|
|
case CD_STATIC_PROPERTY_READ:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
if ((intptr_t)desc->property.read == CLASS_DESC_SELF)
|
|
|
|
desc->property.read = (void (*)())class_self_property;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
desc->property.write = desc->property.read;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
desc->property.native = TRUE;
|
|
|
|
//desc->property.help = (char *)type;
|
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case CD_METHOD:
|
|
|
|
case CD_STATIC_METHOD:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
//desc->method.help = (char *)desc->method.signature;
|
|
|
|
desc->method.native = TRUE;
|
2011-09-08 18:01:36 +02:00
|
|
|
desc->method.subr = desc->gambas.name[1] == '!';
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
if (desc->method.signature)
|
|
|
|
{
|
|
|
|
TYPE_signature_length((char *)desc->method.signature, &desc->method.npmin, &desc->method.npmax, &desc->method.npvar);
|
|
|
|
nsign += desc->method.npmax;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
case CD_EVENT:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
class->n_event++;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
//desc->event.help = (char *)desc->event.signature;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
if (desc->event.signature)
|
|
|
|
{
|
|
|
|
TYPE_signature_length((char *)desc->event.signature, &desc->event.npmin, &desc->event.npmax, &desc->method.npvar);
|
|
|
|
desc->event.npmin = desc->event.npmax;
|
|
|
|
nsign += desc->event.npmax;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
break;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
desc->method.class = class;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_calc_info(class, class->n_event, size_dynamic, TRUE, 0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-08-20 02:33:36 +02:00
|
|
|
// Inheritance
|
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_make_description(class, start, n_desc, &first);
|
2011-08-20 02:33:36 +02:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_make_event(class, &first_event);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
// Transfer events and signatures
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
if (nsign)
|
|
|
|
{
|
2013-03-30 00:33:01 +01:00
|
|
|
ALLOC(&class->signature, sizeof(TYPE) * nsign);
|
2012-01-13 09:04:11 +01:00
|
|
|
sign = class->signature;
|
2011-11-06 01:26:37 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
for (i = first; i < class->n_desc; i++)
|
2012-01-13 09:04:11 +01:00
|
|
|
{
|
2012-12-05 04:36:44 +01:00
|
|
|
desc = class->table[i].desc;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
//fprintf(stderr, "[%.*s]\n", class->table[i].len, class->table[i].name);
|
|
|
|
|
|
|
|
switch (CLASS_DESC_get_type(desc))
|
|
|
|
{
|
|
|
|
case CD_METHOD:
|
|
|
|
case CD_STATIC_METHOD:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
if (desc->method.npmax)
|
|
|
|
{
|
|
|
|
desc->method.signature =
|
|
|
|
TYPE_transform_signature(&sign, (char *)desc->method.signature, desc->method.npmax);
|
|
|
|
}
|
|
|
|
break;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
case CD_EVENT:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
if (desc->event.npmax)
|
|
|
|
{
|
|
|
|
desc->event.signature =
|
|
|
|
TYPE_transform_signature(&sign, (char *)desc->event.signature, desc->event.npmax);
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (class->n_event && (!class->parent || class->n_event > class->parent->n_event))
|
|
|
|
{
|
|
|
|
for (i = first; i < class->n_desc; i++)
|
|
|
|
{
|
|
|
|
desc = class->table[i].desc;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
switch (CLASS_DESC_get_type(desc))
|
|
|
|
{
|
|
|
|
case CD_EVENT:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-12-05 04:36:44 +01:00
|
|
|
event = &class->event[first_event];
|
|
|
|
event->name = class->table[i].name;
|
|
|
|
if (desc->event.index)
|
|
|
|
*((int *)desc->event.index) = first_event;
|
|
|
|
desc->event.index = first_event;
|
|
|
|
|
|
|
|
event->type = desc->event.type;
|
|
|
|
event->param = (CLASS_PARAM *)desc->event.signature;
|
|
|
|
event->n_param = desc->event.npmax;
|
|
|
|
|
|
|
|
first_event++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2012-01-13 09:04:11 +01:00
|
|
|
}
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Sort the class description */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_sort(class);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Search for special methods */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
CLASS_search_special(class);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Class is loaded */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2014-07-28 07:35:58 +02:00
|
|
|
class->loaded = TRUE;
|
2009-01-01 15:46:02 +01:00
|
|
|
class->error = FALSE;
|
2012-01-13 09:04:11 +01:00
|
|
|
|
|
|
|
/* Run the static initializer */
|
2008-08-31 02:32:21 +02:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
EXEC_public(class, NULL, "_init", 0);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
/* Class is ready */
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
class->ready = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
//total += MEMORY_size - alloc;
|
|
|
|
//printf("%s: %d TOTAL = %d\n", class->name, MEMORY_size - alloc, total);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-01-13 09:04:11 +01:00
|
|
|
return class;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
CLASS *CLASS_register(GB_DESC *ptr)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2014-07-28 07:35:58 +02:00
|
|
|
const char *name = ((CLASS_DESC_GAMBAS *)ptr)->name;
|
|
|
|
return CLASS_register_class(ptr, CLASS_check_global(CLASS_find_global(name)));
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|