a282449a85
* BUG: Arguments passed by reference do not crash randomly anymore. git-svn-id: svn://localhost/gambas/trunk@1964 867c0c6c-44f3-4631-809d-bfa615b0a4ec
1815 lines
38 KiB
C
1815 lines
38 KiB
C
/***************************************************************************
|
||
|
||
exec_loop.c
|
||
|
||
The interpreter main loop
|
||
|
||
(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.
|
||
|
||
***************************************************************************/
|
||
|
||
#define __GBX_EXEC_LOOP_C
|
||
|
||
#include "gb_common.h"
|
||
#include "gb_error.h"
|
||
#include "gbx_type.h"
|
||
#include "gbx_debug.h"
|
||
|
||
#include "gbx_subr.h"
|
||
#include "gb_pcode.h"
|
||
#include "gbx_stack.h"
|
||
#include "gbx_event.h"
|
||
#include "gbx_value.h"
|
||
#include "gbx_local.h"
|
||
#include "gbx_string.h"
|
||
#include "gbx_api.h"
|
||
#include "gbx_archive.h"
|
||
#include "gbx_extern.h"
|
||
#include "gbx_exec.h"
|
||
#include "gbx_subr.h"
|
||
#include "gbx_math.h"
|
||
|
||
//#define DEBUG_PCODE 1
|
||
|
||
#if DEBUG_PCODE
|
||
#define PROJECT_EXEC
|
||
#include "gb_pcode_temp.h"
|
||
#endif
|
||
|
||
#define SUBR_beep EXEC_ILLEGAL
|
||
|
||
|
||
#define GET_XXX() (((signed short)(code << 4)) >> 4)
|
||
#define GET_UXX() (code & 0xFFF)
|
||
#define GET_7XX() (code & 0x7FF)
|
||
#define GET_XX() ((signed char)(code & 0xFF))
|
||
#define GET_3X() (code & 0x3F)
|
||
|
||
|
||
static EXEC_FUNC SubrTable[] =
|
||
{
|
||
/* 28 */ SUBR_comp, SUBR_comp, SUBR_comp, SUBR_comp,
|
||
/* 2C */ SUBR_comp, SUBR_comp, SUBR_near, SUBR_case,
|
||
/* 30 */ SUBR_add_, SUBR_add_, SUBR_add_, SUBR_add_,
|
||
/* 34 */ SUBR_neg_, SUBR_quo, SUBR_rem, SUBR_pow,
|
||
/* 38 */ SUBR_and_, SUBR_and_, SUBR_and_, SUBR_not,
|
||
/* 3C */ SUBR_cat, SUBR_like, SUBR_file, SUBR_is,
|
||
|
||
NULL, /* 00 */
|
||
NULL, /* 01 */
|
||
NULL, /* 02 */
|
||
NULL, /* 03 */
|
||
SUBR_space, /* 04 */
|
||
SUBR_string, /* 05 */
|
||
SUBR_trim, /* 06 */
|
||
SUBR_upper, /* 07 */
|
||
SUBR_lower, /* 08 */
|
||
SUBR_chr, /* 09 */
|
||
SUBR_asc, /* 10 */
|
||
SUBR_instr, /* 11 */
|
||
SUBR_instr, /* 12 */
|
||
SUBR_subst, /* 13 */
|
||
SUBR_replace, /* 14 */
|
||
SUBR_split, /* 15 */
|
||
SUBR_scan, /* 16 */
|
||
SUBR_strcomp, /* 17 */
|
||
SUBR_iconv, /* 18 */
|
||
SUBR_sconv, /* 19 */
|
||
SUBR_neg_, /* 20 */
|
||
SUBR_neg_, /* 21 */
|
||
SUBR_neg_, /* 22 */
|
||
SUBR_sgn, /* 23 */
|
||
SUBR_math, /* 24 */
|
||
SUBR_pi, /* 25 */
|
||
SUBR_round, /* 26 */
|
||
SUBR_randomize, /* 27 */
|
||
SUBR_rnd, /* 28 */
|
||
SUBR_min_max, /* 29 */
|
||
SUBR_min_max, /* 30 */
|
||
SUBR_if, /* 31 */
|
||
SUBR_choose, /* 32 */
|
||
SUBR_array, /* 33 */
|
||
SUBR_math2, /* 34 */
|
||
SUBR_is_chr, /* 35 */
|
||
SUBR_bit, /* 36 */
|
||
SUBR_is_type, /* 37 */
|
||
SUBR_type, /* 38 */
|
||
SUBR_conv, /* 39 */
|
||
SUBR_bin, /* 40 */
|
||
SUBR_hex, /* 41 */
|
||
SUBR_val, /* 42 */
|
||
SUBR_str, /* 43 */
|
||
SUBR_format, /* 44 */
|
||
SUBR_timer, /* 45 */
|
||
SUBR_now, /* 46 */
|
||
SUBR_year, /* 47 */
|
||
SUBR_week, /* 48 */
|
||
SUBR_date, /* 49 */
|
||
SUBR_time, /* 50 */
|
||
SUBR_date_op, /* 51 */
|
||
SUBR_eval, /* 52 */
|
||
SUBR_error, /* 53 */
|
||
SUBR_debug, /* 54 */
|
||
SUBR_wait, /* 55 */
|
||
SUBR_open, /* 56 */
|
||
SUBR_close, /* 57 */
|
||
SUBR_input, /* 58 */
|
||
SUBR_linput, /* 59 */
|
||
SUBR_print, /* 60 */
|
||
SUBR_read, /* 61 */
|
||
SUBR_write, /* 62 */
|
||
SUBR_flush, /* 63 */
|
||
SUBR_lock, /* 64 */
|
||
SUBR_inp_out, /* 65 */
|
||
SUBR_eof, /* 66 */
|
||
SUBR_lof, /* 67 */
|
||
SUBR_seek, /* 68 */
|
||
SUBR_kill, /* 69 */
|
||
SUBR_mkdir, /* 70 */
|
||
SUBR_rmdir, /* 71 */
|
||
SUBR_rename, /* 72 */
|
||
SUBR_copy, /* 73 */
|
||
SUBR_link, /* 74 */
|
||
SUBR_exist, /* 75 */
|
||
SUBR_access, /* 76 */
|
||
SUBR_stat, /* 77 */
|
||
SUBR_dfree, /* 78 */
|
||
SUBR_temp, /* 79 */
|
||
SUBR_isdir, /* 80 */
|
||
SUBR_dir, /* 81 */
|
||
SUBR_rdir, /* 82 */
|
||
SUBR_exec, /* 83 */
|
||
SUBR_alloc, /* 84 */
|
||
SUBR_free, /* 85 */
|
||
SUBR_realloc, /* 86 */
|
||
SUBR_strptr, /* 87 */
|
||
SUBR_sleep, /* 88 */
|
||
SUBR_varptr, /* 89 */
|
||
SUBR_collection, /* 90 */
|
||
SUBR_tr, /* 91 */
|
||
SUBR_quote, /* 92 */
|
||
SUBR_unquote /* 93 */
|
||
/* -> 95 */
|
||
};
|
||
|
||
|
||
void EXEC_loop(void)
|
||
{
|
||
static const void *jump_table[256] =
|
||
{
|
||
/* 00 NOP */ &&_NEXT,
|
||
/* 01 PUSH LOCAL */ &&_PUSH_LOCAL,
|
||
/* 02 PUSH PARAM */ &&_PUSH_PARAM,
|
||
/* 03 PUSH ARRAY */ &&_PUSH_ARRAY,
|
||
/* 04 PUSH UNKNOWN */ &&_PUSH_UNKNOWN,
|
||
/* 05 PUSH EXTERN */ &&_PUSH_EXTERN,
|
||
/* 06 BYREF */ &&_BYREF,
|
||
/* 07 PUSH EVENT */ &&_PUSH_EVENT,
|
||
/* 08 QUIT */ &&_QUIT,
|
||
/* 09 POP LOCAL */ &&_POP_LOCAL,
|
||
/* 0A POP PARAM */ &&_POP_PARAM,
|
||
/* 0B POP ARRAY */ &&_POP_ARRAY,
|
||
/* 0C POP UNKNOWN */ &&_POP_UNKNOWN,
|
||
/* 0D POP OPTIONAL */ &&_POP_OPTIONAL,
|
||
/* 0E POP CTRL */ &&_POP_CTRL,
|
||
/* 0F BREAK */ &&_BREAK,
|
||
/* 10 RETURN */ &&_RETURN,
|
||
/* 11 PUSH SHORT */ &&_PUSH_SHORT,
|
||
/* 12 PUSH INTEGER */ &&_PUSH_INTEGER,
|
||
/* 13 PUSH CHAR */ &&_PUSH_CHAR,
|
||
/* 14 PUSH MISC */ &&_PUSH_MISC,
|
||
/* 15 PUSH ME */ &&_PUSH_ME,
|
||
/* 16 EVENT */ &&_EVENT,
|
||
/* 17 TRY */ &&_TRY,
|
||
/* 18 END TRY */ &&_END_TRY,
|
||
/* 19 CATCH */ &&_CATCH,
|
||
/* 1A DUP */ &&_DUP,
|
||
/* 1B DROP */ &&_DROP,
|
||
/* 1C NEW */ &&_NEW,
|
||
/* 1D CALL */ &&_CALL,
|
||
/* 1E CALL QUICK */ &&_CALL_QUICK,
|
||
/* 1F CALL NORM */ &&_CALL_NORM,
|
||
/* 20 JUMP */ &&_JUMP,
|
||
/* 21 JUMP IF TRUE */ &&_JUMP_IF_TRUE,
|
||
/* 22 JUMP IF FALSE */ &&_JUMP_IF_FALSE,
|
||
/* 23 */ &&_ILLEGAL,
|
||
/* 24 JUMP FIRST */ &&_JUMP_FIRST,
|
||
/* 25 JUMP NEXT */ &&_JUMP_NEXT,
|
||
/* 26 FIRST */ &&_ENUM_FIRST,
|
||
/* 27 NEXT */ &&_ENUM_NEXT,
|
||
/* 28 = */ &&_SUBR,
|
||
/* 29 <> */ &&_SUBR,
|
||
/* 2A > */ &&_SUBR,
|
||
/* 2B <= */ &&_SUBR,
|
||
/* 2C < */ &&_SUBR,
|
||
/* 2D >= */ &&_SUBR,
|
||
/* 2E == */ &&_SUBR,
|
||
/* 2F CASE */ &&_SUBR,
|
||
/* 30 + */ &&_SUBR,
|
||
/* 31 - */ &&_SUBR,
|
||
/* 32 * */ &&_SUBR,
|
||
/* 33 / */ &&_SUBR,
|
||
/* 34 NEG */ &&_SUBR,
|
||
/* 35 \ */ &&_SUBR,
|
||
/* 36 MOD */ &&_SUBR,
|
||
/* 37 ^ */ &&_SUBR,
|
||
/* 38 AND */ &&_SUBR,
|
||
/* 39 OR */ &&_SUBR,
|
||
/* 3A XOR */ &&_SUBR,
|
||
/* 3B NOT */ &&_SUBR,
|
||
/* 3C & */ &&_SUBR,
|
||
/* 3D LIKE */ &&_SUBR,
|
||
/* 3E &/ */ &&_SUBR,
|
||
/* 3F */ &&_SUBR,
|
||
/* 40 Left$ */ &&_SUBR_LEFT,
|
||
/* 41 Mid$ */ &&_SUBR_MID,
|
||
/* 42 Right$ */ &&_SUBR_RIGHT,
|
||
/* 43 Len */ &&_SUBR_LEN,
|
||
/* 44 Space$ */ &&_SUBR,
|
||
/* 45 String$ */ &&_SUBR,
|
||
/* 46 Trim$ */ &&_SUBR,
|
||
/* 47 UCase$ */ &&_SUBR,
|
||
/* 48 LCase$ */ &&_SUBR,
|
||
/* 49 Chr$ */ &&_SUBR,
|
||
/* 4A Asc */ &&_SUBR,
|
||
/* 4B InStr */ &&_SUBR,
|
||
/* 4C RInStr */ &&_SUBR,
|
||
/* 4D Subst$ */ &&_SUBR,
|
||
/* 4E Replace$ */ &&_SUBR,
|
||
/* 4F Split */ &&_SUBR,
|
||
/* 50 Scan */ &&_SUBR,
|
||
/* 51 Comp */ &&_SUBR,
|
||
/* 52 Conv */ &&_SUBR,
|
||
/* 53 DConv */ &&_SUBR,
|
||
/* 54 Abs */ &&_SUBR,
|
||
/* 55 Int */ &&_SUBR,
|
||
/* 56 Fix */ &&_SUBR,
|
||
/* 57 Sgn */ &&_SUBR,
|
||
/* 58 Frac... */ &&_SUBR,
|
||
/* 59 Pi */ &&_SUBR,
|
||
/* 5A Round */ &&_SUBR,
|
||
/* 5B Randomize */ &&_SUBR,
|
||
/* 5C Rnd */ &&_SUBR,
|
||
/* 5D Min */ &&_SUBR,
|
||
/* 5E Max */ &&_SUBR,
|
||
/* 5F IIf */ &&_SUBR,
|
||
/* 60 Choose */ &&_SUBR,
|
||
/* 61 Array */ &&_SUBR,
|
||
/* 62 ATan2... */ &&_SUBR,
|
||
/* 63 IsAscii... */ &&_SUBR,
|
||
/* 64 BClr... */ &&_SUBR,
|
||
/* 65 IsBoolean... */ &&_SUBR,
|
||
/* 66 TypeOf */ &&_SUBR,
|
||
/* 67 CBool... */ &&_SUBR,
|
||
/* 68 Bin$ */ &&_SUBR,
|
||
/* 69 Hex$ */ &&_SUBR,
|
||
/* 6A Val */ &&_SUBR,
|
||
/* 6B Str */ &&_SUBR,
|
||
/* 6C Format */ &&_SUBR,
|
||
/* 6D Timer */ &&_SUBR,
|
||
/* 6E Now */ &&_SUBR,
|
||
/* 6F Year... */ &&_SUBR,
|
||
/* 70 Date */ &&_SUBR,
|
||
/* 71 Time... */ &&_SUBR,
|
||
/* 72 DateAdd... */ &&_SUBR,
|
||
/* 73 Eval */ &&_SUBR,
|
||
/* 74 Error */ &&_SUBR,
|
||
/* 75 Debug */ &&_SUBR,
|
||
/* 76 Wait */ &&_SUBR,
|
||
/* 77 Open */ &&_SUBR,
|
||
/* 78 Close */ &&_SUBR,
|
||
/* 79 Input */ &&_SUBR,
|
||
/* 7A LineInput */ &&_SUBR,
|
||
/* 7B Print */ &&_SUBR,
|
||
/* 7C Read */ &&_SUBR,
|
||
/* 7D Write */ &&_SUBR,
|
||
/* 7E Flush */ &&_SUBR,
|
||
/* 7F Lock... */ &&_SUBR,
|
||
/* 80 InputFrom... */ &&_SUBR,
|
||
/* 81 Eof */ &&_SUBR,
|
||
/* 82 Lof */ &&_SUBR,
|
||
/* 83 Seek */ &&_SUBR,
|
||
/* 84 Kill */ &&_SUBR,
|
||
/* 85 Mkdir */ &&_SUBR,
|
||
/* 86 Rmdir */ &&_SUBR,
|
||
/* 87 Move */ &&_SUBR,
|
||
/* 88 Copy */ &&_SUBR,
|
||
/* 89 Link */ &&_SUBR,
|
||
/* 8A Exist */ &&_SUBR,
|
||
/* 8B Access */ &&_SUBR,
|
||
/* 8C Stat */ &&_SUBR,
|
||
/* 8D Dfree */ &&_SUBR,
|
||
/* 8E Temp$ */ &&_SUBR,
|
||
/* 8F IsDir */ &&_SUBR,
|
||
/* 90 Dir */ &&_SUBR,
|
||
/* 91 RDir */ &&_SUBR,
|
||
/* 92 Exec... */ &&_SUBR,
|
||
/* 93 Alloc */ &&_SUBR,
|
||
/* 94 Free */ &&_SUBR,
|
||
/* 95 Realloc */ &&_SUBR,
|
||
/* 96 StrPtr */ &&_SUBR,
|
||
/* 97 Sleep */ &&_SUBR,
|
||
/* 98 VarPtr */ &&_SUBR,
|
||
/* 99 Collection */ &&_SUBR,
|
||
/* 9A Tr$ */ &&_SUBR,
|
||
/* 9B Quote$... */ &&_SUBR,
|
||
/* 9C Unquote$ */ &&_SUBR,
|
||
/* 9D */ &&_SUBR,
|
||
/* 9E */ &&_SUBR,
|
||
/* 9F */ &&_SUBR,
|
||
/* A0 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A1 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A2 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A3 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A4 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A5 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A6 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A7 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A8 ADD QUICK */ &&_ADD_QUICK,
|
||
/* A9 ADD QUICK */ &&_ADD_QUICK,
|
||
/* AA ADD QUICK */ &&_ADD_QUICK,
|
||
/* AB ADD QUICK */ &&_ADD_QUICK,
|
||
/* AC ADD QUICK */ &&_ADD_QUICK,
|
||
/* AD ADD QUICK */ &&_ADD_QUICK,
|
||
/* AE ADD QUICK */ &&_ADD_QUICK,
|
||
/* AF ADD QUICK */ &&_ADD_QUICK,
|
||
/* B0 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B1 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B2 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B3 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B4 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B5 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B6 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B7 PUSH CLASS */ &&_PUSH_CLASS,
|
||
/* B8 PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* B9 PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* BA PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* BB PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* BC PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* BD PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* BE PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* BF PUSH FUNCTION */ &&_PUSH_FUNCTION,
|
||
/* C0 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C1 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C2 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C3 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C4 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C5 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C6 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C7 PUSH DYNAMIC */ &&_PUSH_DYNAMIC,
|
||
/* C8 PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* C9 PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* CA PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* CB PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* CC PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* CD PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* CE PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* CF PUSH STATIC */ &&_PUSH_STATIC,
|
||
/* D0 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D1 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D2 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D3 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D4 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D5 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D6 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D7 POP DYNAMIC */ &&_POP_DYNAMIC,
|
||
/* D8 POP STATIC */ &&_POP_STATIC,
|
||
/* D9 POP STATIC */ &&_POP_STATIC,
|
||
/* DA POP STATIC */ &&_POP_STATIC,
|
||
/* DB POP STATIC */ &&_POP_STATIC,
|
||
/* DC POP STATIC */ &&_POP_STATIC,
|
||
/* DD POP STATIC */ &&_POP_STATIC,
|
||
/* DE POP STATIC */ &&_POP_STATIC,
|
||
/* DF POP STATIC */ &&_POP_STATIC,
|
||
/* E0 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E1 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E2 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E3 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E4 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E5 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E6 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E7 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E8 PUSH CONST */ &&_PUSH_CONST,
|
||
/* E9 PUSH CONST */ &&_PUSH_CONST,
|
||
/* EA PUSH CONST */ &&_PUSH_CONST,
|
||
/* EB PUSH CONST */ &&_PUSH_CONST,
|
||
/* EC PUSH CONST */ &&_PUSH_CONST,
|
||
/* ED PUSH CONST */ &&_PUSH_CONST,
|
||
/* EE PUSH CONST */ &&_PUSH_CONST,
|
||
/* EF PUSH CONST */ &&_PUSH_CONST,
|
||
/* F0 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F1 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F2 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F3 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F4 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F5 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F6 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F7 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F8 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* F9 PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* FA PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* FB PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* FC PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* FD PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* FE PUSH QUICK */ &&_PUSH_QUICK,
|
||
/* FF PUSH QUICK */ &&_PUSH_QUICK
|
||
};
|
||
|
||
register int NO_WARNING(ind);
|
||
register ushort code;
|
||
/*ushort uind;*/
|
||
TYPE type;
|
||
|
||
void _pop_ctrl(int ind)
|
||
{
|
||
register VALUE *val = &BP[ind];
|
||
RELEASE(val);
|
||
SP--;
|
||
*val = *SP;
|
||
}
|
||
|
||
goto _MAIN;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_NEXT3:
|
||
|
||
PC++;
|
||
|
||
_NEXT2:
|
||
|
||
PC++;
|
||
|
||
_NEXT:
|
||
|
||
PC++;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_MAIN:
|
||
|
||
#if DEBUG_PCODE
|
||
DEBUG_where();
|
||
fprintf(stderr, "[%4d] ", (int)(intptr_t)(SP - (VALUE *)STACK_base));
|
||
if (*PC >> 8)
|
||
PCODE_dump(stderr, PC - FP->code, PC);
|
||
else
|
||
fprintf(stderr, "\n");
|
||
fflush(stderr);
|
||
#endif
|
||
|
||
code = *PC;
|
||
goto *jump_table[code >> 8];
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_SUBR:
|
||
|
||
EXEC_code = code;
|
||
|
||
(*SubrTable[(code >> 8) - 0x28])();
|
||
|
||
_SUBR_END:
|
||
|
||
if (PCODE_is_void(code))
|
||
POP();
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_LOCAL:
|
||
|
||
*SP = BP[GET_XX()];
|
||
PUSH();
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_PARAM:
|
||
|
||
*SP = PP[GET_XX()];
|
||
PUSH();
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_ARRAY:
|
||
|
||
EXEC_push_array(code);
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_UNKNOWN:
|
||
|
||
EXEC_push_unknown(code);
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
/*_PUSH_SPECIAL:
|
||
|
||
EXEC_push_special();
|
||
goto _NEXT;*/
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_EVENT:
|
||
|
||
/*
|
||
The function called by raising an event is different at each call,
|
||
but the signature remains the same, so optimizing the next CALL
|
||
instruction with CALL QUICK is safe.
|
||
|
||
The only problem is when pushing a 'NULL' function, i.e. a function
|
||
that does nothing, because there is no handler for this event.
|
||
Then CALL QUICK must know how to handle these functions.
|
||
*/
|
||
|
||
ind = GET_XX();
|
||
|
||
if (CP->parent)
|
||
ind += CP->parent->n_event;
|
||
|
||
SP->type = T_FUNCTION;
|
||
SP->_function.kind = FUNCTION_EVENT;
|
||
SP->_function.index = ind;
|
||
SP->_function.defined = FALSE;
|
||
SP->_function.class = NULL;
|
||
SP->_function.object = NULL;
|
||
SP++;
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_POP_LOCAL:
|
||
|
||
{
|
||
register VALUE *val = &BP[GET_XX()];
|
||
|
||
VALUE_conv(&SP[-1], val->type);
|
||
|
||
RELEASE(val);
|
||
SP--;
|
||
*val = *SP;
|
||
}
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_POP_PARAM:
|
||
|
||
{
|
||
register VALUE *val = &PP[GET_XX()];
|
||
|
||
VALUE_conv(&SP[-1], val->type);
|
||
|
||
RELEASE(val);
|
||
SP--;
|
||
*val = *SP;
|
||
}
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_POP_CTRL:
|
||
|
||
_pop_ctrl(GET_XX());
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_POP_ARRAY:
|
||
|
||
EXEC_pop_array(code);
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_POP_UNKNOWN:
|
||
|
||
EXEC_pop_unknown();
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_POP_OPTIONAL:
|
||
|
||
/*
|
||
if (ind >= 0)
|
||
val = &BP[ind];
|
||
else
|
||
val = &PP[ind];
|
||
*/
|
||
|
||
{
|
||
register VALUE *val = &BP[GET_XX()];
|
||
|
||
if (val->type == T_VOID)
|
||
{
|
||
if (SP[-1].type == T_VOID)
|
||
VALUE_default(&SP[-1], val->_void.ptype);
|
||
else
|
||
VALUE_conv(&SP[-1], val->_void.ptype);
|
||
/* RELEASE(val); Pas n<>essaire */
|
||
SP--;
|
||
*val = *SP;
|
||
}
|
||
else
|
||
POP();
|
||
}
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_SHORT:
|
||
|
||
SP->type = T_INTEGER;
|
||
PC++;
|
||
SP->_integer.value = *((short *)PC);
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_INTEGER:
|
||
|
||
SP->type = T_INTEGER;
|
||
PC++;
|
||
SP->_integer.value = PC[0] | ((uint)PC[1] << 16);
|
||
SP++;
|
||
goto _NEXT2;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_CHAR:
|
||
|
||
STRING_char_value(SP, (char)GET_XX());
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_ME:
|
||
|
||
if (GET_XX() & 1)
|
||
{
|
||
if (DEBUG_info->op)
|
||
{
|
||
SP->_object.class = DEBUG_info->cp;
|
||
SP->_object.object = DEBUG_info->op;
|
||
}
|
||
else if (DEBUG_info->cp)
|
||
{
|
||
SP->type = T_CLASS;
|
||
SP->_class.class = DEBUG_info->cp;
|
||
}
|
||
else
|
||
SP->type = T_NULL;
|
||
}
|
||
else
|
||
{
|
||
if (OP)
|
||
{
|
||
SP->_object.class = CP;
|
||
SP->_object.object = OP;
|
||
}
|
||
else
|
||
{
|
||
SP->type = T_CLASS;
|
||
SP->_class.class = CP;
|
||
}
|
||
}
|
||
|
||
if (GET_XX() & 2)
|
||
{
|
||
// The used class must be in the stack, because it is tested by exec_push && exec_pop
|
||
if (OP)
|
||
{
|
||
SP->_object.class = SP->_object.class->parent;
|
||
SP->_object.super = EXEC_super;
|
||
}
|
||
else
|
||
{
|
||
SP->_class.class = SP->_class.class->parent;
|
||
SP->_class.super = EXEC_super;
|
||
}
|
||
|
||
EXEC_super = SP;
|
||
}
|
||
|
||
PUSH();
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_MISC:
|
||
|
||
{
|
||
static const void *_jump[] =
|
||
{ &&__PUSH_NULL, &&__PUSH_VOID, &&__PUSH_FALSE, &&__PUSH_TRUE, &&__PUSH_LAST };
|
||
|
||
goto *_jump[GET_XX()];
|
||
|
||
__PUSH_NULL:
|
||
|
||
SP->type = T_NULL;
|
||
SP->_integer.value = 0;
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
__PUSH_VOID:
|
||
|
||
SP->type = T_VOID;
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
__PUSH_FALSE:
|
||
|
||
SP->type = T_BOOLEAN;
|
||
SP->_integer.value = 0;
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
__PUSH_TRUE:
|
||
|
||
SP->type = T_BOOLEAN;
|
||
SP->_integer.value = -1;
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
__PUSH_LAST:
|
||
|
||
SP->type = T_OBJECT;
|
||
SP->_object.object = EVENT_Last;
|
||
PUSH();
|
||
goto _NEXT;
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_EVENT:
|
||
|
||
GAMBAS_StopEvent = TRUE;
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
/*
|
||
_PUSH_RETURN:
|
||
|
||
*SP++ = *RP;
|
||
goto _NEXT;
|
||
*/
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_DUP:
|
||
|
||
*SP = SP[-1];
|
||
PUSH();
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_DROP:
|
||
|
||
ind = GET_3X();
|
||
|
||
while (ind > 0)
|
||
{
|
||
POP();
|
||
ind--;
|
||
}
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_NEW:
|
||
|
||
EXEC_new();
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_JUMP:
|
||
|
||
PC += (signed short)PC[1] + 2;
|
||
goto _MAIN;
|
||
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_JUMP_IF_TRUE:
|
||
|
||
VALUE_conv(&SP[-1], T_BOOLEAN);
|
||
SP--;
|
||
if (SP->_boolean.value)
|
||
{
|
||
PC += (signed short)PC[1] + 2;
|
||
goto _MAIN;
|
||
}
|
||
|
||
goto _NEXT2;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_JUMP_IF_FALSE:
|
||
|
||
VALUE_conv(&SP[-1], T_BOOLEAN);
|
||
SP--;
|
||
if (SP->_boolean.value == 0)
|
||
{
|
||
PC += (signed short)PC[1] + 2;
|
||
goto _MAIN;
|
||
}
|
||
|
||
goto _NEXT2;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_RETURN:
|
||
|
||
if (GET_XX())
|
||
{
|
||
VALUE_conv(&SP[-1], FP->type);
|
||
SP--;
|
||
*RP = *SP;
|
||
//ERROR_clear();
|
||
EXEC_leave(FALSE);
|
||
}
|
||
else
|
||
{
|
||
VALUE_default(RP, FP->type);
|
||
//ERROR_clear();
|
||
EXEC_leave(FALSE);
|
||
}
|
||
|
||
if (PC == NULL)
|
||
return;
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_CALL:
|
||
|
||
{
|
||
static const void *call_jump[] =
|
||
{ &&__CALL_NULL, &&__CALL_NATIVE, &&__CALL_PRIVATE, &&__CALL_PUBLIC,
|
||
&&__CALL_EVENT, &&__CALL_EXTERN, &&__CALL_UNKNOWN, &&__CALL_CALL };
|
||
|
||
register VALUE * NO_WARNING(val);
|
||
|
||
ind = GET_3X();
|
||
val = &SP[-(ind + 1)];
|
||
|
||
if (!TYPE_is_function(val->type))
|
||
{
|
||
bool defined;
|
||
|
||
EXEC_object(val, &EXEC.class, (OBJECT **)&EXEC.object, &defined);
|
||
val->type = T_FUNCTION;
|
||
val->_function.kind = FUNCTION_CALL;
|
||
val->_function.defined = defined;
|
||
val->_function.class = EXEC.class;
|
||
val->_function.object = EXEC.object;
|
||
//goto _CALL;
|
||
}
|
||
else
|
||
{
|
||
EXEC.class = val->_function.class;
|
||
EXEC.object = val->_function.object;
|
||
}
|
||
|
||
EXEC.drop = PCODE_is_void(code);
|
||
EXEC.nparam = ind;
|
||
EXEC.use_stack = TRUE;
|
||
|
||
if (!val->_function.defined)
|
||
*PC |= CODE_CALL_VARIANT;
|
||
|
||
goto *call_jump[(int)val->_function.kind];
|
||
|
||
__CALL_NULL:
|
||
|
||
while (ind > 0)
|
||
{
|
||
POP();
|
||
ind--;
|
||
}
|
||
|
||
POP();
|
||
|
||
if (!PCODE_is_void(code))
|
||
{
|
||
/*VALUE_default(SP, (TYPE)(val->_function.function));*/
|
||
SP->type = T_NULL;
|
||
SP++;
|
||
}
|
||
|
||
goto _NEXT;
|
||
|
||
__CALL_NATIVE:
|
||
|
||
EXEC.native = TRUE;
|
||
EXEC.index = val->_function.index;
|
||
EXEC.desc = &EXEC.class->table[EXEC.index].desc->method;
|
||
//EXEC.use_stack = TRUE;
|
||
|
||
goto __EXEC_NATIVE;
|
||
|
||
__CALL_PRIVATE:
|
||
|
||
EXEC.native = FALSE;
|
||
EXEC.index = val->_function.index;
|
||
|
||
goto __EXEC_ENTER;
|
||
|
||
__CALL_PUBLIC:
|
||
|
||
EXEC.native = FALSE;
|
||
EXEC.desc = &EXEC.class->table[val->_function.index].desc->method;
|
||
EXEC.index = (int)(intptr_t)(EXEC.desc->exec);
|
||
EXEC.class = EXEC.desc->class;
|
||
|
||
goto __EXEC_ENTER;
|
||
|
||
__EXEC_ENTER:
|
||
|
||
EXEC_enter_check(val->_function.defined);
|
||
goto _MAIN;
|
||
|
||
__EXEC_NATIVE:
|
||
|
||
EXEC_native_check(val->_function.defined);
|
||
goto _NEXT;
|
||
|
||
__CALL_EVENT:
|
||
|
||
ind = GB_Raise(OP, val->_function.index, (-EXEC.nparam));
|
||
|
||
#if 0
|
||
EXEC.desc = &EXEC.class->table[val->_function.index].desc->method;
|
||
EXEC.class = EXEC.desc->class;
|
||
EXEC.native = FUNCTION_is_native(EXEC.desc);
|
||
|
||
old_last = EVENT_Last;
|
||
EVENT_Last = OP;
|
||
|
||
if (EXEC.native)
|
||
{
|
||
//EXEC.use_stack = TRUE;
|
||
EXEC_native();
|
||
}
|
||
else
|
||
{
|
||
EXEC.index = (int)(EXEC.desc->exec);
|
||
EXEC_function();
|
||
}
|
||
|
||
ind = GAMBAS_StopEvent ? -1 : 0;
|
||
#endif
|
||
|
||
POP(); // function
|
||
|
||
if (!PCODE_is_void(code))
|
||
{
|
||
SP->type = T_BOOLEAN;
|
||
SP->_boolean.value = ind ? -1 : 0;
|
||
SP++;
|
||
}
|
||
|
||
//EVENT_Last = old_last;
|
||
|
||
goto _NEXT;
|
||
|
||
__CALL_UNKNOWN:
|
||
|
||
EXEC.property = FALSE;
|
||
EXEC.unknown = CP->load->unknown[val->_function.index];
|
||
EXEC.desc = CLASS_get_special_desc(EXEC.class, SPEC_UNKNOWN);
|
||
//EXEC.use_stack = TRUE;
|
||
goto __CALL_SPEC;
|
||
|
||
__CALL_CALL:
|
||
|
||
EXEC.desc = CLASS_get_special_desc(EXEC.class, SPEC_CALL);
|
||
if (!EXEC.desc && !EXEC.object && EXEC.nparam == 1 && !EXEC.class->is_virtual)
|
||
{
|
||
SP[-2] = SP[-1];
|
||
SP--;
|
||
VALUE_conv(SP - 1, (TYPE)EXEC.class);
|
||
goto _NEXT;
|
||
}
|
||
|
||
goto __CALL_SPEC;
|
||
|
||
__CALL_SPEC:
|
||
|
||
if (!EXEC.desc)
|
||
THROW(E_NFUNC);
|
||
|
||
EXEC.native = FUNCTION_is_native(EXEC.desc);
|
||
|
||
if (EXEC.native)
|
||
{
|
||
EXEC_native();
|
||
goto _NEXT;
|
||
}
|
||
else
|
||
{
|
||
EXEC.index = (int)(intptr_t)(EXEC.desc->exec);
|
||
EXEC.class = EXEC.desc->class;
|
||
EXEC_enter();
|
||
goto _MAIN;
|
||
}
|
||
|
||
__CALL_EXTERN:
|
||
|
||
EXEC.index = val->_function.index;
|
||
EXTERN_call();
|
||
goto _NEXT;
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_CALL_QUICK:
|
||
|
||
{
|
||
static const void *call_jump[] =
|
||
{ &&__CALL_NULL, &&__CALL_NATIVE_Q, &&__CALL_PRIVATE_Q, &&__CALL_PUBLIC_Q };
|
||
|
||
register VALUE * NO_WARNING(val);
|
||
|
||
ind = GET_3X();
|
||
val = &SP[-(ind + 1)];
|
||
|
||
EXEC.class = val->_function.class;
|
||
EXEC.object = val->_function.object;
|
||
EXEC.drop = PCODE_is_void(code);
|
||
EXEC.nparam = ind;
|
||
|
||
if (!val->_function.defined)
|
||
*PC |= CODE_CALL_VARIANT;
|
||
|
||
//if (call_jump[(int)val->_function.kind] == 0)
|
||
// fprintf(stderr, "val->_function.kind = %d ?\n", val->_function.kind);
|
||
|
||
goto *call_jump[(int)val->_function.kind];
|
||
|
||
__CALL_PRIVATE_Q:
|
||
|
||
EXEC.native = FALSE;
|
||
EXEC.index = val->_function.index;
|
||
|
||
goto __EXEC_ENTER_Q;
|
||
|
||
__CALL_PUBLIC_Q:
|
||
|
||
EXEC.native = FALSE;
|
||
EXEC.desc = &EXEC.class->table[val->_function.index].desc->method;
|
||
EXEC.index = (int)(intptr_t)(EXEC.desc->exec);
|
||
EXEC.class = EXEC.desc->class;
|
||
|
||
__EXEC_ENTER_Q:
|
||
|
||
EXEC_enter_quick();
|
||
goto _MAIN;
|
||
|
||
__CALL_NATIVE_Q:
|
||
|
||
EXEC.native = TRUE;
|
||
EXEC.index = val->_function.index;
|
||
EXEC.desc = &EXEC.class->table[EXEC.index].desc->method;
|
||
|
||
EXEC_native_quick();
|
||
goto _NEXT;
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_CALL_NORM:
|
||
|
||
{
|
||
static const void *call_jump[] =
|
||
{ &&__CALL_NULL, &&__CALL_NATIVE_N, &&__CALL_PRIVATE_N, &&__CALL_PUBLIC_N };
|
||
|
||
register VALUE * NO_WARNING(val);
|
||
|
||
ind = GET_3X();
|
||
val = &SP[-(ind + 1)];
|
||
|
||
EXEC.class = val->_function.class;
|
||
EXEC.object = val->_function.object;
|
||
EXEC.drop = PCODE_is_void(code);
|
||
EXEC.nparam = ind;
|
||
EXEC.use_stack = TRUE;
|
||
|
||
if (!val->_function.defined)
|
||
*PC |= CODE_CALL_VARIANT;
|
||
|
||
goto *call_jump[(int)val->_function.kind];
|
||
|
||
__CALL_PRIVATE_N:
|
||
|
||
EXEC.native = FALSE;
|
||
EXEC.index = val->_function.index;
|
||
|
||
goto __EXEC_ENTER_N;
|
||
|
||
__CALL_PUBLIC_N:
|
||
|
||
EXEC.native = FALSE;
|
||
EXEC.desc = &EXEC.class->table[val->_function.index].desc->method;
|
||
EXEC.index = (int)(intptr_t)(EXEC.desc->exec);
|
||
EXEC.class = EXEC.desc->class;
|
||
|
||
__EXEC_ENTER_N:
|
||
|
||
EXEC_enter();
|
||
goto _MAIN;
|
||
|
||
__CALL_NATIVE_N:
|
||
|
||
EXEC.native = TRUE;
|
||
EXEC.index = val->_function.index;
|
||
EXEC.desc = &EXEC.class->table[EXEC.index].desc->method;
|
||
|
||
EXEC_native();
|
||
goto _NEXT;
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_JUMP_FIRST:
|
||
|
||
PC[1] &= 0xFF00;
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_JUMP_NEXT:
|
||
|
||
{
|
||
static const void *jn_jump[] = { &&_JN_START, &&_JN_NEXT_1, &&_JN_NEXT_2, &&_JN_NEXT_3, &&_JN_NEXT_4, &&_JN_NEXT_5, &&_JN_NEXT_6 };
|
||
|
||
VALUE * NO_WARNING(end);
|
||
VALUE * NO_WARNING(inc);
|
||
register VALUE * NO_WARNING(val);
|
||
|
||
end = &BP[PC[-1] & 0xFF];
|
||
inc = end + 1;
|
||
val = &BP[PC[2] & 0xFF];
|
||
|
||
goto *jn_jump[GET_XX()];
|
||
|
||
_JN_START:
|
||
|
||
type = val->type;
|
||
|
||
// The step value must stay negative, even if the loop variable is a byte
|
||
|
||
if (TYPE_is_integer(type))
|
||
{
|
||
VALUE_conv(&SP[-1], T_INTEGER);
|
||
}
|
||
else
|
||
{
|
||
VALUE_conv(&SP[-1], type);
|
||
}
|
||
|
||
VALUE_conv(&SP[-2], type);
|
||
|
||
ind = PC[-1] & 0xFF;
|
||
|
||
_pop_ctrl(ind + 1); /* modifie val ! */
|
||
_pop_ctrl(ind);
|
||
|
||
val = &BP[PC[2] & 0xFF];
|
||
|
||
if (TYPE_is_integer(type))
|
||
{
|
||
if (inc->_integer.value > 0)
|
||
{
|
||
*PC |= 1;
|
||
goto _JN_TEST_1;
|
||
}
|
||
else
|
||
{
|
||
*PC |= 2;
|
||
goto _JN_TEST_2;
|
||
}
|
||
}
|
||
else if (TYPE_is_float(type))
|
||
{
|
||
if (inc->_float.value > 0)
|
||
{
|
||
*PC |= 3;
|
||
goto _JN_TEST_3;
|
||
}
|
||
else
|
||
{
|
||
*PC |= 4;
|
||
goto _JN_TEST_4;
|
||
}
|
||
}
|
||
else if (TYPE_is_long(type))
|
||
{
|
||
if (inc->_long.value > 0)
|
||
{
|
||
*PC |= 5;
|
||
goto _JN_TEST_5;
|
||
}
|
||
else
|
||
{
|
||
*PC |= 6;
|
||
goto _JN_TEST_6;
|
||
}
|
||
}
|
||
else
|
||
THROW(E_TYPE, "Number", TYPE_get_name(type));
|
||
|
||
_JN_NEXT_1:
|
||
|
||
val->_integer.value += inc->_integer.value;
|
||
|
||
_JN_TEST_1:
|
||
|
||
if (val->_integer.value <= end->_integer.value)
|
||
goto _NEXT3;
|
||
|
||
goto _JN_END;
|
||
|
||
_JN_NEXT_2:
|
||
|
||
val->_integer.value += inc->_integer.value;
|
||
|
||
_JN_TEST_2:
|
||
|
||
if (val->_integer.value >= end->_integer.value)
|
||
goto _NEXT3;
|
||
|
||
goto _JN_END;
|
||
|
||
_JN_NEXT_3:
|
||
|
||
val->_float.value += inc->_float.value;
|
||
|
||
_JN_TEST_3:
|
||
|
||
if (val->_float.value <= end->_float.value)
|
||
goto _NEXT3;
|
||
|
||
goto _JN_END;
|
||
|
||
_JN_NEXT_4:
|
||
|
||
val->_float.value += inc->_float.value;
|
||
|
||
_JN_TEST_4:
|
||
|
||
if (val->_float.value >= end->_float.value)
|
||
goto _NEXT3;
|
||
|
||
goto _JN_END;
|
||
|
||
_JN_NEXT_5:
|
||
|
||
val->_long.value += inc->_long.value;
|
||
|
||
_JN_TEST_5:
|
||
|
||
if (val->_long.value <= end->_long.value)
|
||
goto _NEXT3;
|
||
|
||
goto _JN_END;
|
||
|
||
_JN_NEXT_6:
|
||
|
||
val->_long.value += inc->_long.value;
|
||
|
||
_JN_TEST_6:
|
||
|
||
if (val->_long.value >= end->_long.value)
|
||
goto _NEXT3;
|
||
|
||
goto _JN_END;
|
||
|
||
_JN_END:
|
||
|
||
PC += (signed short)PC[1] + 2;
|
||
goto _MAIN;
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_ENUM_FIRST:
|
||
|
||
_pop_ctrl(GET_XX());
|
||
EXEC_enum_first(code);
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_ENUM_NEXT:
|
||
|
||
if (EXEC_enum_next(code))
|
||
goto _JUMP;
|
||
else
|
||
goto _NEXT2;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_CLASS:
|
||
|
||
{
|
||
CLASS *class = CP->load->class_ref[GET_7XX()];
|
||
|
||
//CLASS_load(class);
|
||
//fprintf(stderr, "PUSH CLASS: %s %s\n", class->name, class->auto_create ? "AUTO CREATE" : "");
|
||
|
||
SP->type = T_CLASS;
|
||
SP->_class.class = class;
|
||
SP++;
|
||
|
||
//fprintf(stderr, "PUSH CLASS: %s in %s\n", SP->_class.class->name, SP->_class.class->component ? SP->_class.class->component->name : NULL);
|
||
}
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_FUNCTION:
|
||
|
||
/*ind = GET_7XX();*/
|
||
|
||
SP->type = T_FUNCTION;
|
||
SP->_function.class = CP;
|
||
SP->_function.object = OP;
|
||
SP->_function.kind = FUNCTION_PRIVATE;
|
||
SP->_function.index = GET_7XX();
|
||
SP->_function.defined = TRUE;
|
||
|
||
OBJECT_REF(OP, "exec_loop._PUSH_FUNCTION (FUNCTION)");
|
||
SP++;
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_EXTERN:
|
||
|
||
/*ind = GET_7XX();*/
|
||
|
||
SP->type = T_FUNCTION;
|
||
SP->_function.class = CP;
|
||
SP->_function.object = NULL;
|
||
SP->_function.kind = FUNCTION_EXTERN;
|
||
SP->_function.index = GET_XX();
|
||
SP->_function.defined = TRUE;
|
||
|
||
//OBJECT_REF(OP, "exec_loop._PUSH_FUNCTION (FUNCTION)");
|
||
SP++;
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
{
|
||
CLASS_VAR *var;
|
||
char *addr;
|
||
|
||
_PUSH_DYNAMIC:
|
||
|
||
var = &CP->load->dyn[GET_7XX()];
|
||
|
||
if (OP == NULL)
|
||
THROW(E_ILLEGAL);
|
||
|
||
addr = &OP[var->pos];
|
||
goto __READ;
|
||
|
||
_PUSH_STATIC:
|
||
|
||
var = &CP->load->stat[GET_7XX()];
|
||
addr = (char *)CP->stat + var->pos;
|
||
goto __READ;
|
||
|
||
__READ:
|
||
|
||
VALUE_class_read(CP, SP, addr, var->type);
|
||
|
||
PUSH();
|
||
goto _NEXT;
|
||
|
||
|
||
_POP_DYNAMIC:
|
||
|
||
var = &CP->load->dyn[GET_7XX()];
|
||
|
||
if (OP == NULL)
|
||
THROW(E_ILLEGAL);
|
||
|
||
addr = &OP[var->pos];
|
||
goto __WRITE;
|
||
|
||
_POP_STATIC:
|
||
|
||
var = &CP->load->stat[GET_7XX()];
|
||
addr = (char *)CP->stat + var->pos;
|
||
goto __WRITE;
|
||
|
||
__WRITE:
|
||
|
||
VALUE_class_write(CP, &SP[-1], addr, var->type);
|
||
POP();
|
||
|
||
goto _NEXT;
|
||
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_CONST:
|
||
|
||
VALUE_class_constant(CP, SP, GET_UXX());
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_PUSH_QUICK:
|
||
|
||
SP->type = T_INTEGER;
|
||
SP->_integer.value = GET_XXX();
|
||
SP++;
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_ADD_QUICK:
|
||
|
||
{
|
||
static void *_aq_jump[] = {
|
||
NULL, &&__AQ_BOOLEAN, &&__AQ_BYTE, &&__AQ_SHORT, &&__AQ_INTEGER, &&__AQ_LONG, &&__AQ_FLOAT, &&__AQ_FLOAT, &&__AQ_DATE, &&__AQ_STRING, &&__AQ_STRING
|
||
};
|
||
|
||
TYPE NO_WARNING(type);
|
||
int NO_WARNING(value);
|
||
VALUE * NO_WARNING(P1);
|
||
void * NO_WARNING(jump_end);
|
||
|
||
P1 = SP - 1;
|
||
|
||
if (TYPE_is_variant(P1->type))
|
||
{
|
||
jump_end = &&__AQ_VARIANT_END;
|
||
VARIANT_undo(P1);
|
||
}
|
||
else
|
||
jump_end = &&__AQ_END;
|
||
|
||
type = P1->type;
|
||
value = GET_XXX();
|
||
|
||
if (type <= T_CSTRING)
|
||
goto *_aq_jump[type];
|
||
|
||
THROW(E_TYPE, "Number", TYPE_get_name(type));
|
||
|
||
__AQ_BOOLEAN:
|
||
|
||
fprintf(stderr, "warning: ");
|
||
DEBUG_where();
|
||
fprintf(stderr, "ADD QUICK with Boolean\n");
|
||
|
||
P1->_integer.value ^= (value & 1) ? -1 : 0;
|
||
goto *jump_end;
|
||
|
||
__AQ_BYTE:
|
||
|
||
P1->_integer.value = (unsigned char)(P1->_integer.value + value);
|
||
goto *jump_end;
|
||
|
||
__AQ_SHORT:
|
||
|
||
P1->_integer.value = (short)(P1->_integer.value + value);
|
||
goto *jump_end;
|
||
|
||
__AQ_INTEGER:
|
||
|
||
P1->_integer.value += value;
|
||
goto *jump_end;
|
||
|
||
__AQ_LONG:
|
||
|
||
P1->_long.value += (int64_t)value;
|
||
goto *jump_end;
|
||
|
||
__AQ_DATE:
|
||
__AQ_STRING:
|
||
|
||
VALUE_conv(P1, T_FLOAT);
|
||
|
||
__AQ_FLOAT:
|
||
|
||
P1->_float.value += (double)value;
|
||
goto *jump_end;
|
||
|
||
__AQ_VARIANT_END:
|
||
|
||
VALUE_conv(P1, T_VARIANT);
|
||
|
||
__AQ_END:
|
||
goto _NEXT;
|
||
}
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_TRY:
|
||
|
||
EP = SP;
|
||
ET = EC;
|
||
EC = PC + (signed short)PC[1] + 2;
|
||
|
||
#if DEBUG_ERROR
|
||
fprintf(stderr, "exec TRY %p\n", EC);
|
||
#endif
|
||
|
||
goto _NEXT2;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_END_TRY:
|
||
|
||
#if DEBUG_ERROR
|
||
fprintf(stderr, "exec END TRY %p\n", PC);
|
||
#endif
|
||
|
||
/* If EP was reset to null, then there was an error */
|
||
EXEC_got_error = (EP == NULL);
|
||
EP = NULL;
|
||
EC = ET;
|
||
ET = NULL;
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_CATCH:
|
||
|
||
if (EC == NULL)
|
||
goto _NEXT;
|
||
else
|
||
goto _RETURN;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_BREAK:
|
||
|
||
if (EXEC_debug && CP && CP->component == COMPONENT_main)
|
||
{
|
||
//TRACE.ec = PC + 1;
|
||
//TRACE.ep = SP;
|
||
|
||
TC = PC + 1;
|
||
TP = SP;
|
||
|
||
ind = GET_XX();
|
||
|
||
if (ind == 0)
|
||
{
|
||
if (!DEBUG_info->stop)
|
||
goto _NEXT;
|
||
|
||
// Return from (void stack)
|
||
if (DEBUG_info->leave)
|
||
{
|
||
if (STACK_get_current()->pc)
|
||
goto _NEXT;
|
||
if (FP == DEBUG_info->fp)
|
||
goto _NEXT;
|
||
if (BP > DEBUG_info->bp)
|
||
goto _NEXT;
|
||
}
|
||
// Forward or Return From
|
||
else if (DEBUG_info->fp != NULL)
|
||
{
|
||
if (BP > DEBUG_info->bp)
|
||
goto _NEXT;
|
||
}
|
||
// otherwise, Next
|
||
}
|
||
|
||
DEBUG.Breakpoint(ind);
|
||
}
|
||
else
|
||
*PC = C_NOP;
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_QUIT:
|
||
|
||
if (GET_XX() == 0)
|
||
EXEC_quit();
|
||
|
||
if (EXEC_debug && CP && CP->component == COMPONENT_main)
|
||
DEBUG.Breakpoint(0);
|
||
//else
|
||
// TRACE_backtrace(stderr);
|
||
|
||
goto _NEXT;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_BYREF:
|
||
|
||
if (PC == FP->code)
|
||
{
|
||
PC += GET_XX();
|
||
goto _NEXT2;
|
||
}
|
||
|
||
THROW(E_BYREF);
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_ILLEGAL:
|
||
|
||
THROW(E_ILLEGAL);
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
#define EXEC_code code
|
||
|
||
_SUBR_LEFT:
|
||
|
||
{
|
||
int val;
|
||
|
||
SUBR_ENTER();
|
||
|
||
if (!SUBR_check_string(PARAM))
|
||
{
|
||
if (NPARAM == 1)
|
||
val = 1;
|
||
else
|
||
{
|
||
VALUE_conv(&PARAM[1], T_INTEGER);
|
||
val = PARAM[1]._integer.value;
|
||
}
|
||
|
||
if (val < 0)
|
||
val += PARAM->_string.len;
|
||
|
||
PARAM->_string.len = MinMax(val, 0, PARAM->_string.len);
|
||
}
|
||
|
||
SP -= NPARAM;
|
||
SP++;
|
||
}
|
||
goto _SUBR_END;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_SUBR_RIGHT:
|
||
|
||
{
|
||
int val;
|
||
int new_len;
|
||
|
||
SUBR_ENTER();
|
||
|
||
if (!SUBR_check_string(PARAM))
|
||
{
|
||
if (NPARAM == 1)
|
||
val = 1;
|
||
else
|
||
{
|
||
VALUE_conv(&PARAM[1], T_INTEGER);
|
||
val = PARAM[1]._integer.value;
|
||
}
|
||
|
||
if (val < 0)
|
||
val += PARAM->_string.len;
|
||
|
||
new_len = MinMax(val, 0, PARAM->_string.len);
|
||
|
||
PARAM->_string.start += PARAM->_string.len - new_len;
|
||
PARAM->_string.len = new_len;
|
||
}
|
||
|
||
SP -= NPARAM;
|
||
SP++;
|
||
}
|
||
goto _SUBR_END;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_SUBR_MID:
|
||
{
|
||
int start;
|
||
int len;
|
||
bool null;
|
||
|
||
SUBR_ENTER();
|
||
|
||
null = SUBR_check_string(PARAM);
|
||
|
||
VALUE_conv(&PARAM[1], T_INTEGER);
|
||
start = PARAM[1]._integer.value - 1;
|
||
|
||
if (start < 0)
|
||
THROW(E_ARG);
|
||
|
||
if (null)
|
||
goto _SUBR_MID_FIN;
|
||
|
||
if (start >= PARAM->_string.len)
|
||
{
|
||
RELEASE(PARAM);
|
||
STRING_void_value(PARAM);
|
||
goto _SUBR_MID_FIN;
|
||
}
|
||
|
||
if (NPARAM == 2)
|
||
len = PARAM->_string.len;
|
||
else
|
||
{
|
||
VALUE_conv(&PARAM[2], T_INTEGER);
|
||
len = PARAM[2]._integer.value;
|
||
}
|
||
|
||
if (len < 0)
|
||
len = Max(0, PARAM->_string.len - start + len);
|
||
|
||
len = MinMax(len, 0, PARAM->_string.len - start);
|
||
|
||
if (len == 0)
|
||
{
|
||
RELEASE(PARAM);
|
||
PARAM->_string.addr = NULL;
|
||
PARAM->_string.start = 0;
|
||
}
|
||
else
|
||
PARAM->_string.start += start;
|
||
|
||
PARAM->_string.len = len;
|
||
|
||
_SUBR_MID_FIN:
|
||
|
||
SP -= NPARAM;
|
||
SP++;
|
||
}
|
||
goto _SUBR_END;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
_SUBR_LEN:
|
||
{
|
||
int len;
|
||
|
||
SUBR_GET_PARAM(1);
|
||
|
||
if (SUBR_check_string(PARAM))
|
||
len = 0;
|
||
else
|
||
len = PARAM->_string.len;
|
||
|
||
RELEASE(PARAM);
|
||
|
||
PARAM->type = T_INTEGER;
|
||
PARAM->_integer.value = len;
|
||
}
|
||
goto _SUBR_END;
|
||
|
||
/*-----------------------------------------------*/
|
||
|
||
}
|
||
|