/*************************************************************************** exec_push.c Instructions that push symbols, special functions and arrays on the stack. (c) 2000-2007 Benoit Minisini 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" 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; int 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); 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; *((int *)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 = (int)(intptr_t)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 = (int)&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 = (int)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 ���ras� Il faut donc le d���encer nous-m�e. Sauf si c'est un appel de m�hode statique (cf. plus haut) */ OBJECT_UNREF(object, "EXEC_push_unknown"); _FIN: PC++; } void EXEC_push_array(void) { CLASS *class; OBJECT *object; GET_NPARAM(np); int dim[MAX_ARRAY_DIM]; int i; void *data; boolean defined; VALUE *val; ARRAY_DESC *desc; 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; desc = (ARRAY_DESC *)SP->_array.class->load->array[SP->_array.index]; data = ARRAY_get_address(desc, SP->_array.addr, np, dim); VALUE_read(SP, data, CLASS_ctype_to_type(SP->_array.class, desc->type)); PUSH(); } else { EXEC_object(val, &class, &object, &defined); /*RELEASE(SP);*/ /* Ex�ution de la m�hode sp�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); } }