471 lines
8.8 KiB
C
471 lines
8.8 KiB
C
|
/***************************************************************************
|
|||
|
|
|||
|
exec_push.c
|
|||
|
|
|||
|
Instructions that push symbols, special functions and arrays on the
|
|||
|
stack.
|
|||
|
|
|||
|
(c) 2000-2007 Benoit 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.
|
|||
|
|
|||
|
***************************************************************************/
|
|||
|
|
|||
|
|
|||
|
#include "gb_common.h"
|
|||
|
#include "gb_limit.h"
|
|||
|
#include "gbx_exec.h"
|
|||
|
#include "gb_pcode.h"
|
|||
|
#include "gbx_api.h"
|
|||
|
|
|||
|
#include "gbx_string.h"
|
|||
|
#include "gbx_array.h"
|
|||
|
#include "gbx_c_collection.h"
|
|||
|
|
|||
|
|
|||
|
PUBLIC void EXEC_push_unknown(ushort code)
|
|||
|
{
|
|||
|
static void *jump[] = {
|
|||
|
/* 0 */ &&_PUSH_GENERIC,
|
|||
|
/* 1 */ &&_PUSH_CONSTANT,
|
|||
|
/* 2 */ &&_PUSH_VARIABLE,
|
|||
|
/* 3 */ &&_PUSH_STATIC_VARIABLE,
|
|||
|
/* 4 */ &&_PUSH_PROPERTY,
|
|||
|
/* 5 */ &&_PUSH_METHOD,
|
|||
|
/* 6 */ &&_PUSH_STATIC_METHOD,
|
|||
|
/* 7 */ &&_PUSH_VARIABLE_AUTO,
|
|||
|
/* 8 */ &&_PUSH_PROPERTY_AUTO,
|
|||
|
/* 9 */ &&_PUSH_METHOD_AUTO,
|
|||
|
/* 10 */ &&_PUSH_EXTERN
|
|||
|
};
|
|||
|
|
|||
|
const char *name;
|
|||
|
long index;
|
|||
|
CLASS_DESC *desc;
|
|||
|
CLASS *class;
|
|||
|
OBJECT *object;
|
|||
|
char *addr;
|
|||
|
bool defined;
|
|||
|
VALUE *val;
|
|||
|
|
|||
|
EXEC_object(&SP[-1], &class, &object, &defined);
|
|||
|
|
|||
|
goto *jump[code & 0xF];
|
|||
|
|
|||
|
|
|||
|
_PUSH_GENERIC:
|
|||
|
|
|||
|
name = CP->load->unknown[PC[1]];
|
|||
|
|
|||
|
// The first time we access a symbol, we must not be virtual to find it
|
|||
|
val = &SP[-1];
|
|||
|
if (defined && object && !VALUE_is_super(val))
|
|||
|
index = CLASS_find_symbol(val->_object.class, name);
|
|||
|
else
|
|||
|
index = CLASS_find_symbol(class, name);
|
|||
|
|
|||
|
/*FILE *file = fopen("/tmp/bug.log", "a");
|
|||
|
if (file)
|
|||
|
{
|
|||
|
fprintf(file, "EXEC_push: %s.%s\n", class->name, name);
|
|||
|
fclose(file);
|
|||
|
}*/
|
|||
|
|
|||
|
if (index == NO_SYMBOL)
|
|||
|
{
|
|||
|
//index = CLASS_find_symbol(class, name);
|
|||
|
|
|||
|
if (class->special[SPEC_UNKNOWN] == NO_SYMBOL)
|
|||
|
{
|
|||
|
if (defined && object && !VALUE_is_super(val))
|
|||
|
class = val->_object.class;
|
|||
|
THROW(E_NSYMBOL, name, class->name);
|
|||
|
}
|
|||
|
|
|||
|
goto _PUSH_UNKNOWN_METHOD;
|
|||
|
}
|
|||
|
|
|||
|
desc = class->table[index].desc;
|
|||
|
|
|||
|
switch (CLASS_DESC_get_type(desc))
|
|||
|
{
|
|||
|
case CD_CONSTANT:
|
|||
|
|
|||
|
if (defined)
|
|||
|
{
|
|||
|
if (TYPE_is_integer(desc->constant.type)
|
|||
|
&& ((PC[-1] & 0xF800) == C_PUSH_CLASS))
|
|||
|
{
|
|||
|
PC[-1] = C_PUSH_LONG;
|
|||
|
*((long *)PC) = desc->constant.value._integer;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*PC |= 1;
|
|||
|
PC[1] = index;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
goto _PUSH_CONSTANT_2;
|
|||
|
|
|||
|
case CD_VARIABLE:
|
|||
|
|
|||
|
if (object == NULL)
|
|||
|
{
|
|||
|
if (!class->auto_create)
|
|||
|
THROW(E_DYNAMIC, class->name, name);
|
|||
|
object = EXEC_auto_create(class, TRUE);
|
|||
|
*PC |= 7;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (defined) *PC |= 2;
|
|||
|
}
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_VARIABLE_2;
|
|||
|
|
|||
|
case CD_STATIC_VARIABLE:
|
|||
|
|
|||
|
if (object != NULL)
|
|||
|
THROW(E_STATIC, class->name, name);
|
|||
|
|
|||
|
if (defined) *PC |= 3;
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_STATIC_VARIABLE_2;
|
|||
|
|
|||
|
case CD_PROPERTY:
|
|||
|
case CD_PROPERTY_READ:
|
|||
|
|
|||
|
if (object == NULL)
|
|||
|
{
|
|||
|
if (!class->auto_create)
|
|||
|
THROW(E_DYNAMIC, class->name, name);
|
|||
|
object = EXEC_auto_create(class, TRUE);
|
|||
|
*PC |= 8;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (defined) *PC |= 4;
|
|||
|
}
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_PROPERTY_2;
|
|||
|
|
|||
|
case CD_STATIC_PROPERTY:
|
|||
|
case CD_STATIC_PROPERTY_READ:
|
|||
|
|
|||
|
if (object != NULL)
|
|||
|
THROW(E_STATIC, class->name, name);
|
|||
|
|
|||
|
if (defined) *PC |= 4;
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_PROPERTY_2;
|
|||
|
|
|||
|
case CD_METHOD:
|
|||
|
|
|||
|
if (object == NULL)
|
|||
|
{
|
|||
|
if (!class->auto_create)
|
|||
|
THROW(E_DYNAMIC, class->name, name);
|
|||
|
object = EXEC_auto_create(class, TRUE);
|
|||
|
*PC |= 9;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (defined) *PC |= 5;
|
|||
|
}
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_METHOD_2;
|
|||
|
|
|||
|
case CD_STATIC_METHOD:
|
|||
|
|
|||
|
if (object)
|
|||
|
{
|
|||
|
OBJECT_UNREF(&object, "EXEC_push_unknown");
|
|||
|
object = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (defined) *PC |= 6;
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_METHOD_2;
|
|||
|
|
|||
|
case CD_EXTERN:
|
|||
|
|
|||
|
if (object)
|
|||
|
{
|
|||
|
OBJECT_UNREF(&object, "EXEC_push_unknown");
|
|||
|
object = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (defined) *PC |= 10;
|
|||
|
|
|||
|
if (defined)
|
|||
|
PC[1] = index;
|
|||
|
|
|||
|
goto _PUSH_EXTERN_2;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
THROW(E_NSYMBOL, name, class->name);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
_PUSH_CONSTANT:
|
|||
|
|
|||
|
desc = class->table[PC[1]].desc;
|
|||
|
|
|||
|
_PUSH_CONSTANT_2:
|
|||
|
|
|||
|
VALUE_read(&SP[-1], (void *)&desc->constant.value, desc->constant.type);
|
|||
|
goto _FIN_DEFINED;
|
|||
|
|
|||
|
|
|||
|
_PUSH_VARIABLE_AUTO:
|
|||
|
|
|||
|
object = EXEC_auto_create(class, TRUE);
|
|||
|
|
|||
|
_PUSH_VARIABLE:
|
|||
|
|
|||
|
desc = class->table[PC[1]].desc;
|
|||
|
|
|||
|
_PUSH_VARIABLE_2:
|
|||
|
|
|||
|
addr = (char *)object + desc->variable.offset;
|
|||
|
goto _READ_PROPERTY;
|
|||
|
|
|||
|
|
|||
|
_PUSH_STATIC_VARIABLE:
|
|||
|
|
|||
|
desc = class->table[PC[1]].desc;
|
|||
|
|
|||
|
_PUSH_STATIC_VARIABLE_2:
|
|||
|
|
|||
|
addr = (char *)class->stat + desc->variable.offset;
|
|||
|
goto _READ_PROPERTY;
|
|||
|
|
|||
|
|
|||
|
_READ_PROPERTY:
|
|||
|
|
|||
|
VALUE_read(&SP[-1], (void *)addr, desc->property.type);
|
|||
|
goto _FIN_DEFINED;
|
|||
|
|
|||
|
|
|||
|
_PUSH_PROPERTY_AUTO:
|
|||
|
|
|||
|
object = EXEC_auto_create(class, TRUE);
|
|||
|
|
|||
|
_PUSH_PROPERTY:
|
|||
|
|
|||
|
desc = class->table[PC[1]].desc;
|
|||
|
|
|||
|
_PUSH_PROPERTY_2:
|
|||
|
|
|||
|
if (desc->property.native)
|
|||
|
{
|
|||
|
if (EXEC_call_native(desc->property.read, object, desc->property.type, NULL))
|
|||
|
PROPAGATE();
|
|||
|
|
|||
|
SP[-1] = TEMP;
|
|||
|
goto _FIN_DEFINED;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
EXEC.class = desc->property.class;
|
|||
|
EXEC.object = object;
|
|||
|
EXEC.drop = FALSE;
|
|||
|
EXEC.nparam = 0;
|
|||
|
EXEC.native = FALSE;
|
|||
|
EXEC.index = (long)desc->property.read;
|
|||
|
|
|||
|
EXEC_function_keep();
|
|||
|
|
|||
|
SP[-1] = *RP;
|
|||
|
RP->type = T_VOID;
|
|||
|
goto _FIN_DEFINED_NO_BORROW;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
_PUSH_STATIC_METHOD:
|
|||
|
|
|||
|
if (object)
|
|||
|
{
|
|||
|
OBJECT_UNREF(&object, "EXEC_push_unknown");
|
|||
|
object = NULL;
|
|||
|
}
|
|||
|
|
|||
|
goto _PUSH_METHOD;
|
|||
|
|
|||
|
_PUSH_METHOD_AUTO:
|
|||
|
|
|||
|
object = EXEC_auto_create(class, TRUE);
|
|||
|
|
|||
|
_PUSH_METHOD:
|
|||
|
|
|||
|
index = PC[1];
|
|||
|
desc = class->table[index].desc;
|
|||
|
|
|||
|
_PUSH_METHOD_2:
|
|||
|
|
|||
|
//printf("PUSH_METHOD: %d %s\n", index, desc->method.name);
|
|||
|
|
|||
|
SP--;
|
|||
|
SP->type = T_FUNCTION;
|
|||
|
SP->_function.class = class;
|
|||
|
SP->_function.object = object;
|
|||
|
/*SP->_function.function = (long)&desc->method;*/
|
|||
|
|
|||
|
if (FUNCTION_is_native(&desc->method))
|
|||
|
SP->_function.kind = FUNCTION_NATIVE;
|
|||
|
else
|
|||
|
SP->_function.kind = FUNCTION_PUBLIC;
|
|||
|
|
|||
|
SP->_function.index = index;
|
|||
|
|
|||
|
SP->_function.defined = defined;
|
|||
|
|
|||
|
SP++;
|
|||
|
|
|||
|
goto _FIN;
|
|||
|
|
|||
|
|
|||
|
_PUSH_EXTERN:
|
|||
|
|
|||
|
if (object)
|
|||
|
{
|
|||
|
OBJECT_UNREF(&object, "EXEC_push_unknown");
|
|||
|
object = NULL;
|
|||
|
}
|
|||
|
|
|||
|
index = PC[1];
|
|||
|
desc = class->table[index].desc;
|
|||
|
|
|||
|
_PUSH_EXTERN_2:
|
|||
|
|
|||
|
//printf("PUSH_METHOD: %d %s\n", index, desc->method.name);
|
|||
|
|
|||
|
SP--;
|
|||
|
SP->type = T_FUNCTION;
|
|||
|
SP->_function.class = class;
|
|||
|
SP->_function.object = object;
|
|||
|
SP->_function.kind = FUNCTION_EXTERN;
|
|||
|
SP->_function.index = (long)desc->ext.exec;
|
|||
|
SP->_function.defined = defined;
|
|||
|
SP++;
|
|||
|
|
|||
|
goto _FIN;
|
|||
|
|
|||
|
_PUSH_UNKNOWN_METHOD:
|
|||
|
|
|||
|
SP--;
|
|||
|
SP->type = T_FUNCTION;
|
|||
|
SP->_function.class = class;
|
|||
|
SP->_function.object = object;
|
|||
|
SP->_function.kind = FUNCTION_UNKNOWN;
|
|||
|
SP->_function.index = PC[1];
|
|||
|
SP->_function.defined = FALSE;
|
|||
|
SP++;
|
|||
|
|
|||
|
//OBJECT_REF(&object, "EXEC_push_unknown: UNKNOWN");
|
|||
|
|
|||
|
goto _FIN;
|
|||
|
|
|||
|
|
|||
|
_FIN_DEFINED:
|
|||
|
|
|||
|
BORROW(&SP[-1]);
|
|||
|
|
|||
|
_FIN_DEFINED_NO_BORROW:
|
|||
|
|
|||
|
if (!defined)
|
|||
|
VALUE_conv(&SP[-1], T_VARIANT);
|
|||
|
|
|||
|
/* sp[-1] contenait l'objet et a <20><><EFBFBD>ras<61> Il faut donc le d<><64><EFBFBD>encer
|
|||
|
nous-m<EFBFBD>e. Sauf si c'est un appel de m<EFBFBD>hode statique (cf. plus haut) */
|
|||
|
|
|||
|
OBJECT_UNREF(&object, "EXEC_push_unknown");
|
|||
|
|
|||
|
_FIN:
|
|||
|
|
|||
|
PC++;
|
|||
|
}
|
|||
|
|
|||
|
PUBLIC void EXEC_push_array(void)
|
|||
|
{
|
|||
|
CLASS *class;
|
|||
|
OBJECT *object;
|
|||
|
GET_NPARAM(np);
|
|||
|
long dim[MAX_ARRAY_DIM];
|
|||
|
int i;
|
|||
|
void *data;
|
|||
|
boolean defined;
|
|||
|
VALUE *val;
|
|||
|
|
|||
|
val = &SP[-np];
|
|||
|
np--;
|
|||
|
|
|||
|
|
|||
|
if (val->type == T_ARRAY)
|
|||
|
{
|
|||
|
for (i = 1; i <= np; i++)
|
|||
|
{
|
|||
|
VALUE_conv(&val[i], T_INTEGER);
|
|||
|
dim[i - 1] = val[i]._integer.value;
|
|||
|
}
|
|||
|
|
|||
|
SP -= np + 1;
|
|||
|
|
|||
|
data = ARRAY_get_address((ARRAY_DESC *)SP->_array.desc, SP->_array.addr, np, dim);
|
|||
|
|
|||
|
VALUE_read(SP, data, ((ARRAY_DESC *)SP->_array.desc)->type);
|
|||
|
|
|||
|
PUSH();
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
EXEC_object(val, &class, &object, &defined);
|
|||
|
/*RELEASE(SP);*/
|
|||
|
|
|||
|
/* Ex<45>ution de la m<>hode sp<73>iale _get */
|
|||
|
|
|||
|
if (EXEC_special(SPEC_GET, class, object, np, FALSE))
|
|||
|
THROW(E_NARRAY, class->name);
|
|||
|
|
|||
|
OBJECT_UNREF(&object, "EXEC_push_array");
|
|||
|
SP--;
|
|||
|
SP[-1] = SP[0];
|
|||
|
|
|||
|
if (!defined)
|
|||
|
VALUE_conv(&SP[-1], T_VARIANT);
|
|||
|
}
|
|||
|
}
|