📄 gbx_exec.c
字号:
/*************************************************************************** exec.c Subroutines for the interpreter : executing methods, native methods, the NEW operator, the casting operator, etc. (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_EXEC_C#include "gb_common.h"#include "gb_error.h"#include "gbx_type.h"#include <unistd.h>#include <sys/time.h>#include "gb_limit.h"#include "gbx_subr.h"#include "gbx_stack.h"#include "gbx_trace.h"#include "gbx_string.h"#include "gbx_date.h"#include "gbx_array.h"#include "gbx_c_collection.h"#include "gbx_api.h"#include "gbx_exec.h"PUBLIC STACK_CONTEXT EXEC_current = { 0 }; /* Contexte �sauvegarder */PUBLIC PCODE EXEC_code; /* Opcode de l'instruction en cours */PUBLIC VALUE *SP = NULL; /* Pointeur de pile */PUBLIC VALUE TEMP; /* Stockage temporaire */PUBLIC VALUE RET; /* Valeur de retour de la fonction */PUBLIC bool EXEC_debug = FALSE; /* Mode d�ogage */PUBLIC boolean EXEC_enum_stop = FALSE; /* Indique la fin d'une �um�ation */PUBLIC void *EXEC_enum_data; /* Etat de l'�um�ation en cours */PUBLIC bool EXEC_arch = FALSE; /* Ex�ution d'une archive */PUBLIC bool EXEC_fifo = FALSE; /* D�ogage par fifo */PUBLIC EXEC_HOOK EXEC_Hook = { NULL };PUBLIC bool EXEC_big_endian;PUBLIC EXEC_FUNCTION EXEC;PUBLIC void EXEC_init(void){ char test[4]; PC = NULL; BP = NULL; OP = NULL; CP = NULL; RP->type = T_VOID; test[0] = 0xAA; test[1] = 0xBB; test[2] = 0xCC; test[3] = 0xDD; EXEC_big_endian = *((ulong *)test) == 0xAABBCCDDL; /*printf("%s endian\n", EXEC_big_endian ? "big" : "little");*/ DATE_init();}PUBLIC void BORROW(VALUE *value){ static void *jump[16] = { &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__STRING, &&__NONE, &&__VARIANT, &&__NONE, &&__NONE, &&__FUNCTION, &&__NONE, &&__NONE }; TYPE type = value->type; if (TYPE_is_object(type)) goto __OBJECT; else goto *jump[type];__STRING: STRING_ref(value->_string.addr); return;__OBJECT: OBJECT_REF(value->_object.object, "BORROW"); return;__VARIANT: if (value->_variant.vtype == T_STRING) STRING_ref((*(char **)value->_variant.value)); else if (TYPE_is_object(value->_variant.vtype)) OBJECT_REF(*((void **)value->_variant.value), "BORROW"); return;__FUNCTION: OBJECT_REF(value->_function.object, "BORROW"); return;__NONE: return;}PUBLIC void UNBORROW(VALUE *value){ static void *jump[16] = { &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__STRING, &&__NONE, &&__VARIANT, &&__NONE, &&__NONE, &&__FUNCTION, &&__NONE, &&__NONE }; TYPE type = value->type; if (TYPE_is_object(type)) goto __OBJECT; else goto *jump[type];__STRING: STRING_unref_keep(&value->_string.addr); return;__OBJECT: OBJECT_UNREF_KEEP(&value->_object.object, "UNBORROW"); return;__VARIANT: if (value->_variant.vtype == T_STRING) STRING_unref_keep((char **)value->_variant.value); else if (TYPE_is_object(value->_variant.vtype)) OBJECT_UNREF_KEEP((void **)value->_variant.value, "UNBORROW"); return;__FUNCTION: OBJECT_UNREF_KEEP(&value->_function.object, "UNBORROW"); return;__NONE: return;}PUBLIC void RELEASE(VALUE *value){ static void *jump[16] = { &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__STRING, &&__NONE, &&__VARIANT, &&__ARRAY, &&__NONE, &&__FUNCTION, &&__NONE, &&__NONE }; TYPE type = value->type; if (TYPE_is_object(type)) goto __OBJECT; else goto *jump[type];__STRING: STRING_unref(&value->_string.addr); return;__OBJECT: OBJECT_UNREF(&value->_object.object, "RELEASE"); return;__VARIANT: if (value->_variant.vtype == T_STRING) STRING_unref((char **)value->_variant.value); else if (TYPE_is_object(value->_variant.vtype)) OBJECT_UNREF(value->_variant.value, "RELEASE"); return;__FUNCTION: OBJECT_UNREF(&value->_function.object, "RELEASE"); return;__ARRAY: if (!value->_array.keep) ARRAY_free(&value->_array.addr, value->_array.desc); return;__NONE: return;}#if 0PUBLIC void DUMP(VALUE *value){ static void *jump[16] = { &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__NONE, &&__STRING, &&__NONE, &&__VARIANT, &&__ARRAY, &&__NONE, &&__FUNCTION, &&__NONE, &&__NONE }; TYPE type = value->type; printf("type = %p / ", (void *)type); if (TYPE_is_object(type)) goto __OBJECT; else goto *jump[type];__STRING: printf("STRING %p\n", value->_string.addr); return;__OBJECT: if (value->_object.object) { printf("OBJECT (%p)\n", value->_object.object); printf("-> %s\n", OBJECT_class(value->_object.object)->name); } else printf("OBJECT (NULL)\n"); return;__VARIANT: if (value->_variant.vtype == T_STRING) printf("STRING %p\n", *((char **)value->_variant.value)); else if (TYPE_is_object(value->_variant.vtype)) printf("OBJECT (%s %p)\n", OBJECT_class(*((void **)value->_variant.value))->name, *((void **)value->_variant.value)); return;__FUNCTION: printf("FUNCTION %s (%s %p)\n", value->_function.class->name, OBJECT_class(value->_function.object)->name, value->_function.object); return;__ARRAY: printf("ARRAY\n"); return;__NONE: printf("\n"); return;}#endifPUBLIC void EXEC_release_return_value(void){ RELEASE(RP); RP->type = T_VOID;}#define print_register() \ printf("| SP = %d BP = %d FP = %p PC = %p EC = %p\n", SP - (VALUE *)STACK_base, BP - (VALUE *)STACK_base, FP, PC, EC)PUBLIC void EXEC_enter(void){ int i; FUNCTION *func; // = EXEC.func; int nparam = EXEC.nparam; void *object = EXEC.object; CLASS *class = EXEC.class; #if DEBUG_STACK printf("\n| >> EXEC_enter(%s, %ld, %d)\n", EXEC.class->name, EXEC.index, nparam); print_register(); #endif /* func_id = value->index; if (value->kind & FUNCTION_PUBLIC) func_id = (int)(class->table[func_id].desc.method->exec; */ func = &class->load->func[EXEC.index]; #if DEBUG_STACK if (func->debug) printf(" | >> %s\n", func->debug->name); #endif /* v�ification des param�res */ if (nparam < func->npmin) THROW(E_NEPARAM); else if (nparam > func->n_param) THROW(E_TMPARAM); /* param�res obligatoires et r�ervation */ for (i = 0; i < func->npmin; i++) { VALUE_conv(SP - nparam + i, func->param[i].type); /*BORROW(SP - nparam + i);*/ } if (func->npmin < func->n_param) { /* param�res facultatifs, mais pass� �la fonction */ for (i = func->npmin; i < nparam; i++) { if (SP[- nparam + i].type == T_VOID) SP[- nparam + i]._void.ptype = func->param[i].type; else { VALUE_conv(SP - nparam + i, func->param[i].type); /*BORROW(SP - nparam + i);*/ } } /* param�res facultatifs non pass� �la fonction */ if (nparam < func->n_param) { STACK_check(func->n_param - nparam); for (i = nparam; i < func->n_param; i++) { SP->type = T_VOID; SP->_void.ptype = func->param[i].type; SP++; } } } /* sauvegarde du contexte */ STACK_push_frame(&EXEC_current); /* V�ification de la pile */ STACK_check(func->stack_usage); /* entr� de fonction */ BP = SP; FP = func; PC = func->code; OP = object; CP = class; EP = NULL; if (func->error) { #if DEBUG_ERROR printf("EXEC_enter: EC = PC + %d\n", func->error); #endif EC = PC + func->error; } else EC = NULL; /* On r��ence l'objet pour qu'il ne soit pas d�ruit pendant l'ex�ution de la m�hode */ OBJECT_REF(OP, "EXEC_enter"); /*printf("PC = %p nparam = %d\n", PC, FP->n_param);*/ /* Initialisation des variables locales */ if (func->n_local) { for (i = 0; i < func->n_local; i++) { VALUE_class_default(class, SP, func->local[i].type); SP++; } } /* Initialisation des variables de controles */ if (func->n_ctrl) { for (i = 0; i < func->n_ctrl; i++) { SP->type = T_VOID; SP++; } } /*printf("EXEC_enter: nparam = %d nlocal = %d nctrl = %d\n", func->n_param, func->n_local, func->n_ctrl);*/ RP->type = T_VOID; #if DEBUG_STACK printf("| << EXEC_enter()\n"); print_register(); #endif}PUBLIC void EXEC_leave(bool keep_ret_value){ int i, n; boolean drop; VALUE ret;#if DEBUG_STACK printf("| >> EXEC_leave\n"); print_register();#endif /* Je garde cette bourde en commentaires. La honte... for (i = 0; i < (SP - BP); i++) { SP--; #if 1 printf("Release local %p (0x%08lX)\n", SP, (ulong)SP->type); #endif RELEASE(SP); } */ /* Sauvegarde de la valeur de retour. Car elle peut �re �ras� par un _free() g���par un OBJECT_UNREF */ ret = *RP; /* Lib�ation des variables locales et de controle */ n = FP->n_param + (SP - BP); for (i = 0; i < n; i++) POP(); /* On lib�e l'objet reserv�dans EXEC_enter() */ OBJECT_UNREF(&OP, "EXEC_leave"); /* restitution du contexte */ STACK_pop_frame(&EXEC_current); /*printf("PC = %p nparam = %d\n", PC, nparam);*/ if (PC) { drop = PCODE_is_void(*PC); if (SP[-1].type != T_FUNCTION) { printf("EXEC_leave: type != T_FUNCTION\n"); POP(); /* description de la fonction ? */ } else { SP--; OBJECT_UNREF(&SP->_function.object, "EXEC_leave"); } /*output = PCODE_is_output(*PC);*/ } else { drop = TRUE; keep_ret_value = TRUE; } /* lib�ation de la pile utilis� */ /* Attention ! le RELEASE(RP) conjugu�au UNBORROW(RP) peut faire descendre le compteur de r��ence d'un objet �-1 ! */ /* NOTE: les param�res input-output ont le m�e probl�e que la valeur de retour. Ils peuvent contenir des r��ences d�allou�s ! A CORRIGER ! En attendant, ils sont d�activ�. */#if DEBUG_REF printf("EXEC_leave: return\n");#endif if (!drop) { *SP = ret; RP->type = T_VOID; if (PCODE_is_variant(*PC)) VALUE_conv(SP, T_VARIANT); SP++; } else if (!keep_ret_value) EXEC_release_return_value();/* output = TRUE } else { if (!drop) { UNBORROW(RP); SP[-(nparam + 1)] = *RP; RP->type = T_VOID; } else RELEASE(RP); } } }*/#if DEBUG_STACK printf("| << EXEC_leave()\n"); print_register(); printf("\n");#endif}PUBLIC void EXEC_function_real(bool keep_ret_value){ /*PCODE *save = PC;*/ boolean retry; /* n�essaire, car *PC est examin�par EXEC_leave pour savoir si on attend une valeur de retour */ STACK_push_frame(&EXEC_current); PC = NULL; TRY { EXEC_enter(); } CATCH { STACK_pop_frame(&EXEC_current); PROPAGATE(); } END_TRY if (PC != NULL) { do { TRY { EXEC_loop(); retry = FALSE; } CATCH { if (ERROR_info.code == E_UNKNOWN) { while (PC != NULL) EXEC_leave(FALSE); PROPAGATE(); } else if (EP != NULL) { #if DEBUG_ERROR printf("#1 EP = %d SP = %d\n", EP - STACK_base, SP - STACK_base); #endif while (SP > EP) POP(); PC = EC; retry = TRUE; /* On va directement sur le END TRY */ } else if (EC != NULL) { #if DEBUG_ERROR printf("#2 EC = %p\n", EC); #endif PC = EC; EC = NULL; retry = TRUE; } else { #if DEBUG_ERROR printf("#3\n"); #endif if (EXEC_debug && !STACK_has_error_handler()) { while (SP > TRACE.ep) POP(); PC = TRACE.ec; TRACE_main(TRUE); retry = TRUE; } else { while (PC != NULL && EC == NULL) EXEC_leave(FALSE); if (PC == NULL) { /*printf("try to propagate\n");*/ STACK_pop_frame(&EXEC_current); PROPAGATE(); /*ERROR_print(); exit(1);*/ /*retry = FALSE;*/ } PC = EC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -