2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
2011-12-31 03:39:20 +01:00
|
|
|
gbx_exec_loop.c
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-12-31 03:39:20 +01:00
|
|
|
(c) 2000-2012 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-12-31 03:39:20 +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
|
|
|
|
2011-12-31 03:39:20 +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
|
|
|
|
2011-12-31 03:39:20 +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_EXEC_LOOP_C
|
|
|
|
|
|
|
|
#include "gb_common.h"
|
2012-03-04 00:57:36 +01:00
|
|
|
#include "gb_common_check.h"
|
2007-12-30 17:41:49 +01:00
|
|
|
#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"
|
2008-01-27 15:00:04 +01:00
|
|
|
#include "gbx_subr.h"
|
|
|
|
#include "gbx_math.h"
|
2010-06-05 01:48:53 +02:00
|
|
|
#include "gbx_c_array.h"
|
|
|
|
#include "gbx_struct.h"
|
2010-06-13 14:03:29 +02:00
|
|
|
#include "gbx_variant.h"
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
//#define DEBUG_PCODE 1
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
#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)
|
2010-06-05 01:48:53 +02:00
|
|
|
#define GET_XX() ((signed char)code)
|
|
|
|
#define GET_UX() ((unsigned char)code)
|
2007-12-30 17:41:49 +01:00
|
|
|
#define GET_3X() (code & 0x3F)
|
2011-09-08 22:08:33 +02:00
|
|
|
#define TEST_XX() (code & 1)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
static void my_VALUE_class_read(CLASS *class, VALUE *value, char *addr, CTYPE ctype, void *ref);
|
|
|
|
static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind);
|
2011-09-07 14:38:29 +02:00
|
|
|
//static void _SUBR_comp(ushort code);
|
2010-06-09 01:08:04 +02:00
|
|
|
static void _SUBR_compn(ushort code);
|
2012-05-24 02:31:57 +02:00
|
|
|
static void _SUBR_compi(ushort code);
|
2012-05-24 01:39:02 +02:00
|
|
|
static void _SUBR_add(ushort code);
|
|
|
|
static void _SUBR_sub(ushort code);
|
|
|
|
static void _SUBR_mul(ushort code);
|
2010-06-09 01:08:04 +02:00
|
|
|
static void _SUBR_div(ushort code);
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
static void *SubrTable[] =
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2012-05-24 02:31:57 +02:00
|
|
|
/* 28 */ NULL, _SUBR_compn, _SUBR_compi, _SUBR_compi,
|
|
|
|
/* 2C */ _SUBR_compi, _SUBR_compi, SUBR_near, SUBR_case,
|
2012-05-24 01:39:02 +02:00
|
|
|
/* 30 */ _SUBR_add, _SUBR_sub, _SUBR_mul, _SUBR_div,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 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 40 */
|
|
|
|
NULL, /* 01 41 */
|
|
|
|
NULL, /* 02 42 */
|
|
|
|
NULL, /* 03 43 */
|
|
|
|
SUBR_space, /* 04 44 */
|
|
|
|
SUBR_string, /* 05 45 */
|
|
|
|
SUBR_trim, /* 06 46 */
|
|
|
|
SUBR_upper, /* 07 47 */
|
|
|
|
SUBR_lower, /* 08 48 */
|
|
|
|
SUBR_chr, /* 09 49 */
|
|
|
|
SUBR_asc, /* 10 4A */
|
|
|
|
SUBR_instr, /* 11 4B */
|
|
|
|
SUBR_instr, /* 12 4C */
|
|
|
|
SUBR_subst, /* 13 4D */
|
|
|
|
SUBR_replace, /* 14 4E */
|
|
|
|
SUBR_split, /* 15 4F */
|
|
|
|
SUBR_scan, /* 16 50 */
|
|
|
|
SUBR_strcomp, /* 17 51 */
|
|
|
|
SUBR_iconv, /* 18 52 */
|
|
|
|
SUBR_sconv, /* 19 53 */
|
|
|
|
SUBR_abs, /* 20 54 */
|
|
|
|
SUBR_int, /* 21 55 */
|
|
|
|
SUBR_fix, /* 22 56 */
|
|
|
|
SUBR_sgn, /* 23 57 */
|
|
|
|
SUBR_math, /* 24 58 */
|
|
|
|
SUBR_pi, /* 25 59 */
|
|
|
|
SUBR_round, /* 26 5A */
|
|
|
|
SUBR_randomize, /* 27 5B */
|
|
|
|
SUBR_rnd, /* 28 5C */
|
|
|
|
SUBR_min_max, /* 29 5D */
|
|
|
|
SUBR_min_max, /* 30 5E */
|
|
|
|
SUBR_if, /* 31 5F */
|
|
|
|
SUBR_choose, /* 32 60 */
|
|
|
|
SUBR_array, /* 33 61 */
|
|
|
|
SUBR_math2, /* 34 62 */
|
|
|
|
SUBR_is_chr, /* 35 63 */
|
|
|
|
SUBR_bit, /* 36 64 */
|
|
|
|
SUBR_is_type, /* 37 65 */
|
|
|
|
SUBR_type, /* 38 66 */
|
|
|
|
SUBR_conv, /* 39 67 */
|
|
|
|
SUBR_hex_bin, /* 40 68 */
|
|
|
|
SUBR_hex_bin, /* 41 69 */
|
|
|
|
SUBR_val, /* 42 6A */
|
|
|
|
SUBR_str, /* 43 6B */
|
|
|
|
SUBR_format, /* 44 6C */
|
|
|
|
SUBR_timer, /* 45 6D */
|
|
|
|
SUBR_now, /* 46 6E */
|
|
|
|
SUBR_year, /* 47 6F */
|
|
|
|
SUBR_week, /* 48 70 */
|
|
|
|
SUBR_date, /* 49 71 */
|
|
|
|
SUBR_time, /* 50 72 */
|
|
|
|
SUBR_date_op, /* 51 73 */
|
|
|
|
SUBR_eval, /* 52 74 */
|
|
|
|
SUBR_error, /* 53 75 */
|
|
|
|
SUBR_debug, /* 54 76 */
|
|
|
|
SUBR_wait, /* 55 77 */
|
|
|
|
SUBR_open, /* 56 78 */
|
|
|
|
SUBR_close, /* 57 79 */
|
|
|
|
SUBR_input, /* 58 7A */
|
|
|
|
SUBR_linput, /* 59 7B */
|
|
|
|
SUBR_print, /* 60 7C */
|
|
|
|
SUBR_read, /* 61 7D */
|
|
|
|
SUBR_write, /* 62 7E */
|
|
|
|
SUBR_flush, /* 63 7F */
|
|
|
|
SUBR_lock, /* 64 80 */
|
|
|
|
SUBR_inp_out, /* 65 81 */
|
|
|
|
SUBR_eof, /* 66 82 */
|
|
|
|
SUBR_lof, /* 67 83 */
|
|
|
|
SUBR_seek, /* 68 84 */
|
|
|
|
SUBR_kill, /* 69 85 */
|
2012-04-11 02:27:18 +02:00
|
|
|
SUBR_mkdir, /* 70 86 */ // deprecated -> Even() & Odd()
|
2012-01-15 09:54:57 +01:00
|
|
|
SUBR_rmdir, /* 71 87 */ // deprecated
|
|
|
|
SUBR_move, /* 72 88 */
|
2012-01-31 03:33:01 +01:00
|
|
|
SUBR_swap, /* 73 89 */ // support for Copy()
|
|
|
|
SUBR_link, /* 74 8A */ // deprecated -> IsNan() & IsInf()
|
2011-06-11 03:46:42 +02:00
|
|
|
SUBR_exist, /* 75 8B */
|
|
|
|
SUBR_access, /* 76 8C */
|
|
|
|
SUBR_stat, /* 77 8D */
|
|
|
|
SUBR_dfree, /* 78 8E */
|
|
|
|
SUBR_temp, /* 79 8F */
|
|
|
|
SUBR_isdir, /* 80 90 */
|
|
|
|
SUBR_dir, /* 81 91 */
|
|
|
|
SUBR_rdir, /* 82 92 */
|
|
|
|
SUBR_exec, /* 83 93 */
|
|
|
|
SUBR_alloc, /* 84 94 */
|
|
|
|
SUBR_free, /* 85 95 */
|
|
|
|
SUBR_realloc, /* 86 96 */
|
|
|
|
SUBR_strptr, /* 87 97 */
|
|
|
|
SUBR_sleep, /* 88 98 */
|
|
|
|
SUBR_varptr, /* 89 99 */
|
|
|
|
SUBR_collection, /* 90 9A */
|
|
|
|
SUBR_tr, /* 91 9B */
|
|
|
|
SUBR_quote, /* 92 9C */
|
|
|
|
SUBR_unquote, /* 93 9D */
|
2012-01-31 03:33:01 +01:00
|
|
|
SUBR_make, /* 94 9E */
|
2010-07-14 18:33:29 +02:00
|
|
|
SUBR_ptr, /* 95 9F */
|
2007-12-30 17:41:49 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-01-17 22:39:26 +01:00
|
|
|
void EXEC_loop(void)
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
2011-06-11 03:46:42 +02:00
|
|
|
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 TRY */ &&_TRY,
|
|
|
|
/* 17 END TRY */ &&_END_TRY,
|
|
|
|
/* 18 CATCH */ &&_CATCH,
|
|
|
|
/* 19 DUP */ &&_DUP,
|
|
|
|
/* 1A DROP */ &&_DROP,
|
|
|
|
/* 1B NEW */ &&_NEW,
|
|
|
|
/* 1C CALL */ &&_CALL,
|
|
|
|
/* 1D CALL QUICK */ &&_CALL_QUICK,
|
|
|
|
/* 1E CALL EASY */ &&_CALL_SLOW,
|
2012-05-21 03:09:35 +02:00
|
|
|
/* 1F ON */ &&_ON_GOTO_GOSUB,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 20 JUMP */ &&_JUMP,
|
|
|
|
/* 21 JUMP IF TRUE */ &&_JUMP_IF_TRUE,
|
|
|
|
/* 22 JUMP IF FALSE */ &&_JUMP_IF_FALSE,
|
2012-03-04 00:57:36 +01:00
|
|
|
/* 23 GOSUB */ &&_GOSUB,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 24 JUMP FIRST */ &&_JUMP_FIRST,
|
|
|
|
/* 25 JUMP NEXT */ &&_JUMP_NEXT,
|
|
|
|
/* 26 FIRST */ &&_ENUM_FIRST,
|
|
|
|
/* 27 NEXT */ &&_ENUM_NEXT,
|
2011-09-07 14:38:29 +02:00
|
|
|
/* 28 = */ &&_SUBR_COMP,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 29 <> */ &&_SUBR_CODE,
|
|
|
|
/* 2A > */ &&_SUBR_CODE,
|
|
|
|
/* 2B <= */ &&_SUBR_CODE,
|
|
|
|
/* 2C < */ &&_SUBR_CODE,
|
|
|
|
/* 2D >= */ &&_SUBR_CODE,
|
|
|
|
/* 2E == */ &&_SUBR,
|
|
|
|
/* 2F CASE */ &&_SUBR_CODE,
|
|
|
|
/* 30 + */ &&_SUBR_CODE,
|
|
|
|
/* 31 - */ &&_SUBR_CODE,
|
|
|
|
/* 32 * */ &&_SUBR_CODE,
|
|
|
|
/* 33 / */ &&_SUBR_CODE,
|
|
|
|
/* 34 NEG */ &&_SUBR_CODE,
|
|
|
|
/* 35 \ */ &&_SUBR_CODE,
|
|
|
|
/* 36 MOD */ &&_SUBR_CODE,
|
|
|
|
/* 37 ^ */ &&_SUBR,
|
|
|
|
/* 38 AND */ &&_SUBR_CODE,
|
|
|
|
/* 39 OR */ &&_SUBR_CODE,
|
|
|
|
/* 3A XOR */ &&_SUBR_CODE,
|
|
|
|
/* 3B NOT */ &&_SUBR_CODE,
|
|
|
|
/* 3C & */ &&_SUBR_CODE,
|
|
|
|
/* 3D LIKE */ &&_SUBR_CODE,
|
|
|
|
/* 3E &/ */ &&_SUBR_CODE,
|
|
|
|
/* 3F Is */ &&_SUBR_CODE,
|
|
|
|
/* 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_CODE,
|
|
|
|
/* 47 UCase$ */ &&_SUBR_CODE,
|
|
|
|
/* 48 LCase$ */ &&_SUBR,
|
|
|
|
/* 49 Chr$ */ &&_SUBR,
|
|
|
|
/* 4A Asc */ &&_SUBR_CODE,
|
|
|
|
/* 4B InStr */ &&_SUBR_CODE,
|
|
|
|
/* 4C RInStr */ &&_SUBR_CODE,
|
|
|
|
/* 4D Subst$ */ &&_SUBR_CODE,
|
|
|
|
/* 4E Replace$ */ &&_SUBR_CODE,
|
|
|
|
/* 4F Split */ &&_SUBR_CODE,
|
|
|
|
/* 50 Scan */ &&_SUBR,
|
|
|
|
/* 51 Comp */ &&_SUBR_CODE,
|
|
|
|
/* 52 Conv */ &&_SUBR,
|
|
|
|
/* 53 DConv */ &&_SUBR_CODE,
|
|
|
|
/* 54 Abs */ &&_SUBR_CODE,
|
|
|
|
/* 55 Int */ &&_SUBR_CODE,
|
|
|
|
/* 56 Fix */ &&_SUBR_CODE,
|
|
|
|
/* 57 Sgn */ &&_SUBR_CODE,
|
|
|
|
/* 58 Frac... */ &&_SUBR_CODE,
|
|
|
|
/* 59 Pi */ &&_SUBR_CODE,
|
|
|
|
/* 5A Round */ &&_SUBR_CODE,
|
|
|
|
/* 5B Randomize */ &&_SUBR_CODE,
|
|
|
|
/* 5C Rnd */ &&_SUBR_CODE,
|
|
|
|
/* 5D Min */ &&_SUBR_CODE,
|
|
|
|
/* 5E Max */ &&_SUBR_CODE,
|
|
|
|
/* 5F IIf */ &&_SUBR_CODE,
|
|
|
|
/* 60 Choose */ &&_SUBR_CODE,
|
|
|
|
/* 61 Array */ &&_SUBR_CODE,
|
|
|
|
/* 62 ATan2... */ &&_SUBR_CODE,
|
|
|
|
/* 63 IsAscii... */ &&_SUBR_CODE,
|
|
|
|
/* 64 BClr... */ &&_SUBR_CODE,
|
|
|
|
/* 65 IsBoolean... */ &&_SUBR_CODE,
|
|
|
|
/* 66 TypeOf */ &&_SUBR_CODE,
|
|
|
|
/* 67 CBool... */ &&_SUBR_CODE,
|
|
|
|
/* 68 Bin$ */ &&_SUBR_CODE,
|
|
|
|
/* 69 Hex$ */ &&_SUBR_CODE,
|
|
|
|
/* 6A Val */ &&_SUBR,
|
|
|
|
/* 6B Str */ &&_SUBR,
|
|
|
|
/* 6C Format */ &&_SUBR_CODE,
|
|
|
|
/* 6D Timer */ &&_SUBR,
|
|
|
|
/* 6E Now */ &&_SUBR,
|
|
|
|
/* 6F Year... */ &&_SUBR_CODE,
|
|
|
|
/* 70 Week */ &&_SUBR_CODE,
|
|
|
|
/* 71 Date */ &&_SUBR_CODE,
|
|
|
|
/* 72 Time... */ &&_SUBR_CODE,
|
|
|
|
/* 73 DateAdd... */ &&_SUBR_CODE,
|
|
|
|
/* 74 Eval */ &&_SUBR_CODE,
|
|
|
|
/* 75 Error */ &&_SUBR,
|
|
|
|
/* 76 Debug */ &&_SUBR,
|
|
|
|
/* 77 Wait */ &&_SUBR_CODE,
|
|
|
|
/* 78 Open */ &&_SUBR_CODE,
|
|
|
|
/* 79 Close */ &&_SUBR,
|
|
|
|
/* 7A Input */ &&_SUBR_CODE,
|
|
|
|
/* 7B LineInput */ &&_SUBR,
|
|
|
|
/* 7C Print */ &&_SUBR_CODE,
|
|
|
|
/* 7D Read */ &&_SUBR_CODE,
|
|
|
|
/* 7E Write */ &&_SUBR_CODE,
|
|
|
|
/* 7F Flush */ &&_SUBR,
|
|
|
|
/* 80 Lock... */ &&_SUBR_CODE,
|
|
|
|
/* 81 InputFrom... */ &&_SUBR_CODE,
|
|
|
|
/* 82 Eof */ &&_SUBR_CODE,
|
|
|
|
/* 83 Lof */ &&_SUBR_CODE,
|
|
|
|
/* 84 Seek */ &&_SUBR_CODE,
|
2012-01-15 09:54:57 +01:00
|
|
|
/* 85 Kill */ &&_SUBR_CODE,
|
2012-04-11 02:27:18 +02:00
|
|
|
/* 86 Mkdir */ &&_SUBR_CODE,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 87 Rmdir */ &&_SUBR,
|
2012-01-15 09:54:57 +01:00
|
|
|
/* 88 Move */ &&_SUBR_CODE,
|
2012-01-31 03:33:01 +01:00
|
|
|
/* 89 Copy */ &&_SUBR_CODE,
|
|
|
|
/* 8A Link */ &&_SUBR_CODE,
|
2011-07-17 12:57:55 +02:00
|
|
|
/* 8B Exist */ &&_SUBR_CODE,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 8C Access */ &&_SUBR_CODE,
|
|
|
|
/* 8D Stat */ &&_SUBR_CODE,
|
|
|
|
/* 8E Dfree */ &&_SUBR,
|
|
|
|
/* 8F Temp$ */ &&_SUBR_CODE,
|
|
|
|
/* 90 IsDir */ &&_SUBR,
|
|
|
|
/* 91 Dir */ &&_SUBR_CODE,
|
|
|
|
/* 92 RDir */ &&_SUBR_CODE,
|
|
|
|
/* 93 Exec... */ &&_SUBR_CODE,
|
|
|
|
/* 94 Alloc */ &&_SUBR_CODE,
|
|
|
|
/* 95 Free */ &&_SUBR,
|
|
|
|
/* 96 Realloc */ &&_SUBR_CODE,
|
|
|
|
/* 97 StrPtr */ &&_SUBR_CODE,
|
|
|
|
/* 98 Sleep */ &&_SUBR,
|
|
|
|
/* 99 VarPtr */ &&_SUBR,
|
|
|
|
/* 9A Collection */ &&_SUBR_CODE,
|
|
|
|
/* 9B Tr$ */ &&_SUBR,
|
|
|
|
/* 9C Quote$... */ &&_SUBR_CODE,
|
2012-05-19 23:35:26 +02:00
|
|
|
/* 9D Unquote$... */ &&_SUBR_CODE,
|
2011-06-11 03:46:42 +02:00
|
|
|
/* 9E MkInt$... */ &&_SUBR_CODE,
|
|
|
|
/* 9F Byte@... */ &&_SUBR_CODE,
|
|
|
|
/* 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_EX,
|
|
|
|
/* 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
|
|
|
|
};
|
|
|
|
|
|
|
|
int NO_WARNING(ind);
|
|
|
|
ushort code;
|
|
|
|
|
|
|
|
void _pop_ctrl(int ind)
|
|
|
|
{
|
|
|
|
VALUE *val = &BP[ind];
|
|
|
|
RELEASE(val);
|
|
|
|
SP--;
|
|
|
|
*val = *SP;
|
|
|
|
}
|
|
|
|
|
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_MAIN:
|
|
|
|
|
2012-03-28 23:55:19 +02:00
|
|
|
#if 0
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
f = fopen("/var/log/thttpd/pcode.log", "a");
|
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
fprintf(f, "%s: ", DEBUG_get_current_position());
|
|
|
|
if (*PC >> 8)
|
|
|
|
PCODE_dump(f, PC - FP->code, PC);
|
|
|
|
else
|
|
|
|
fprintf(f, "\n");
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
#if DEBUG_PCODE
|
2011-06-11 03:46:42 +02:00
|
|
|
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);
|
2007-12-30 17:41:49 +01:00
|
|
|
#endif
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
code = *PC;
|
|
|
|
goto *jump_table[code >> 8];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2010-06-15 08:54:38 +02:00
|
|
|
_SUBR_CODE:
|
|
|
|
|
2011-12-11 20:14:04 +01:00
|
|
|
//fprintf(stderr, "gbx3: %02X: %s\n", (code >> 8), DEBUG_get_current_position());
|
2011-06-11 03:46:42 +02:00
|
|
|
(*(EXEC_FUNC_CODE)SubrTable[(code >> 8) - 0x28])(code);
|
2010-06-15 08:54:38 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//if (UNLIKELY(PCODE_is_void(code)))
|
|
|
|
// POP();
|
2010-06-15 08:54:38 +02:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_NEXT:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
code = *(++PC);
|
2011-01-16 23:04:17 +01:00
|
|
|
|
2012-03-28 23:55:19 +02:00
|
|
|
#if 0
|
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
|
|
|
|
f = fopen("/var/log/thttpd/pcode.log", "a");
|
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
fprintf(f, "%s: ", DEBUG_get_current_position());
|
|
|
|
if (*PC >> 8)
|
|
|
|
PCODE_dump(f, PC - FP->code, PC);
|
|
|
|
else
|
|
|
|
fprintf(f, "\n");
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-01-16 23:04:17 +01:00
|
|
|
#if DEBUG_PCODE
|
2011-06-11 03:46:42 +02:00
|
|
|
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);
|
2011-01-16 23:04:17 +01:00
|
|
|
#endif
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto *jump_table[code >> 8];
|
2010-06-15 08:54:38 +02:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
_SUBR:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
(*(EXEC_FUNC)SubrTable[(code >> 8) - 0x28])();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_LOCAL:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
*SP = BP[GET_XX()];
|
|
|
|
PUSH();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_PARAM:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
*SP = PP[GET_XX()];
|
|
|
|
PUSH();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_ARRAY:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_push_array(code);
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_UNKNOWN:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_push_unknown(code);
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
/*_PUSH_SPECIAL:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_push_special();
|
|
|
|
goto _NEXT;*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_EVENT:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
/*
|
|
|
|
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.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
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.
|
|
|
|
*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
ind = GET_UX();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (CP->parent)
|
|
|
|
ind += CP->parent->n_event;
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_FUNCTION;
|
2007-12-30 17:41:49 +01:00
|
|
|
SP->_function.kind = FUNCTION_EVENT;
|
|
|
|
SP->_function.index = ind;
|
|
|
|
SP->_function.defined = FALSE;
|
|
|
|
SP->_function.class = NULL;
|
|
|
|
SP->_function.object = NULL;
|
2011-06-11 03:46:42 +02:00
|
|
|
SP++;
|
|
|
|
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_POP_LOCAL:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
VALUE *val = &BP[GET_XX()];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv(&SP[-1], val->type);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
RELEASE(val);
|
|
|
|
SP--;
|
|
|
|
*val = *SP;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_POP_PARAM:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
VALUE *val = &PP[GET_XX()];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv(&SP[-1], val->type);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
RELEASE(val);
|
|
|
|
SP--;
|
|
|
|
*val = *SP;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_POP_CTRL:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
_pop_ctrl(GET_XX());
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_POP_ARRAY:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_pop_array(code);
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_POP_UNKNOWN:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_pop_unknown();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_POP_OPTIONAL:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
2011-10-28 03:54:10 +02:00
|
|
|
VALUE *val = &PP[GET_XX()];
|
2011-06-11 03:46:42 +02:00
|
|
|
|
|
|
|
if (LIKELY(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);
|
2011-10-28 03:54:10 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP--;
|
|
|
|
*val = *SP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
POP();
|
|
|
|
}
|
|
|
|
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_SHORT:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_INTEGER;
|
|
|
|
PC++;
|
|
|
|
SP->_integer.value = *((short *)PC);
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_INTEGER:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_INTEGER;
|
|
|
|
PC++;
|
|
|
|
SP->_integer.value = PC[0] | ((uint)PC[1] << 16);
|
|
|
|
SP++;
|
2010-06-05 01:48:53 +02:00
|
|
|
PC += 2;
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_CHAR:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
STRING_char_value(SP, (char)GET_UX());
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_ME:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(GET_UX() & 1))
|
|
|
|
{
|
2011-07-14 20:30:12 +02:00
|
|
|
if (DEBUG_info)
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
2011-07-14 20:30:12 +02:00
|
|
|
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;
|
|
|
|
}
|
2011-06-11 03:46:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
SP->type = T_NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (LIKELY(OP != NULL))
|
|
|
|
{
|
|
|
|
SP->_object.class = CP;
|
|
|
|
SP->_object.object = OP;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SP->type = T_CLASS;
|
|
|
|
SP->_class.class = CP;
|
|
|
|
}
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
if (UNLIKELY(GET_UX() & 2))
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
// The used class must be in the stack, because it is tested by exec_push && exec_pop
|
2010-05-19 22:18:23 +02:00
|
|
|
if (LIKELY(OP != NULL))
|
2008-12-28 20:01:39 +01:00
|
|
|
{
|
|
|
|
SP->_object.class = SP->_object.class->parent;
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->_object.super = EXEC_super;
|
2008-12-28 20:01:39 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SP->_class.class = SP->_class.class->parent;
|
|
|
|
SP->_class.super = EXEC_super;
|
|
|
|
}
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_super = SP;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
PUSH();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_MISC:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
static const void *_jump[] =
|
2012-01-31 03:33:01 +01:00
|
|
|
{ &&__PUSH_NULL, &&__PUSH_VOID, &&__PUSH_FALSE, &&__PUSH_TRUE, &&__PUSH_LAST, &&__PUSH_STRING, &&__PUSH_PINF, &&__PUSH_MINF }; //, &&__POP_LAST };
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto *_jump[GET_UX()];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__PUSH_NULL:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_NULL;
|
|
|
|
//SP->_integer.value = 0;
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__PUSH_VOID:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_VOID;
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__PUSH_FALSE:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_BOOLEAN;
|
|
|
|
SP->_integer.value = 0;
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__PUSH_TRUE:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_BOOLEAN;
|
|
|
|
SP->_integer.value = -1;
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__PUSH_LAST:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_OBJECT;
|
|
|
|
SP->_object.object = EVENT_Last;
|
2010-12-21 15:05:42 +01:00
|
|
|
OBJECT_REF(EVENT_Last, "EXEC_loop");
|
2011-06-11 03:46:42 +02:00
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2009-09-17 22:58:27 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__PUSH_STRING:
|
|
|
|
|
2009-09-17 22:58:27 +02:00
|
|
|
SP->type = T_STRING;
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->_string.addr = NULL;
|
2009-09-17 22:58:27 +02:00
|
|
|
SP->_string.start = SP->_string.len = 0;
|
2011-06-11 03:46:42 +02:00
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2010-12-21 15:05:42 +01:00
|
|
|
|
2012-01-31 03:33:01 +01:00
|
|
|
__PUSH_PINF:
|
|
|
|
|
|
|
|
SP->type = T_FLOAT;
|
|
|
|
SP->_float.value = INFINITY;
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
|
|
|
|
|
|
|
__PUSH_MINF:
|
|
|
|
|
|
|
|
SP->type = T_FLOAT;
|
|
|
|
SP->_float.value = -INFINITY;
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
|
|
|
|
2010-12-21 15:05:42 +01:00
|
|
|
/*__POP_LAST:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv(&SP[-1], T_OBJECT);
|
2010-12-21 15:05:42 +01:00
|
|
|
OBJECT_UNREF(EVENT_Last, "EXEC_loop");
|
2011-06-11 03:46:42 +02:00
|
|
|
SP--;
|
|
|
|
EVENT_Last = SP->_object.object;
|
2010-12-21 15:05:42 +01:00
|
|
|
goto _NEXT;*/
|
2009-09-17 22:58:27 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
_PUSH_RETURN:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
*SP++ = *RP;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_DUP:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
*SP = SP[-1];
|
|
|
|
PUSH();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_DROP:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
POP();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_NEW:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_new();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2012-05-21 03:09:35 +02:00
|
|
|
_ON_GOTO_GOSUB:
|
|
|
|
|
|
|
|
{
|
|
|
|
int n, m;
|
|
|
|
|
|
|
|
m = GET_XX();
|
|
|
|
SP--;
|
|
|
|
VALUE_conv_integer(SP);
|
|
|
|
n = SP->_integer.value;
|
|
|
|
if (n < 0 || n >= m)
|
|
|
|
PC += m + 3;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PC[m + 2] = PC[n + 1] - (m - n) - 2;
|
|
|
|
PC += m + 1;
|
|
|
|
}
|
|
|
|
goto _MAIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2012-03-04 00:57:36 +01:00
|
|
|
_GOSUB:
|
|
|
|
|
|
|
|
{
|
2012-03-05 00:43:07 +01:00
|
|
|
STACK_GOSUB *gp;
|
|
|
|
VALUE *ctrl;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!GP)
|
|
|
|
ARRAY_create(&GP);
|
2012-03-04 00:57:36 +01:00
|
|
|
|
2012-03-05 00:43:07 +01:00
|
|
|
gp = ARRAY_add(&GP);
|
|
|
|
gp->pc = PC - FP->code;
|
|
|
|
if (FP->n_ctrl)
|
|
|
|
{
|
|
|
|
ALLOC(&gp->ctrl, sizeof(VALUE) * FP->n_ctrl, "EXEC_loop._GOSUB");
|
|
|
|
ctrl = &BP[FP->n_local];
|
|
|
|
for (i = 0; i < FP->n_ctrl; i++)
|
|
|
|
{
|
|
|
|
gp->ctrl[i] = ctrl[i];
|
|
|
|
ctrl[i].type = T_NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
gp->ctrl = NULL;
|
2012-03-04 00:57:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
_JUMP:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
PC += (signed short)PC[1] + 2;
|
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_JUMP_IF_TRUE:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv_boolean(&SP[-1]);
|
|
|
|
SP--;
|
2011-09-08 22:08:33 +02:00
|
|
|
if (UNLIKELY(SP->_boolean.value & 1))
|
2011-06-11 03:46:42 +02:00
|
|
|
PC += (signed short)PC[1];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
PC += 2;
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_JUMP_IF_FALSE:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv_boolean(&SP[-1]);
|
|
|
|
SP--;
|
2011-09-08 22:08:33 +02:00
|
|
|
if (!UNLIKELY(SP->_boolean.value & 1))
|
2011-06-11 03:46:42 +02:00
|
|
|
PC += (signed short)PC[1];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
PC += 2;
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_RETURN:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
2012-03-04 00:57:36 +01:00
|
|
|
static const void *return_jump[] = { &&__RETURN_GOSUB, &&__RETURN_VALUE, &&__RETURN_VOID };
|
|
|
|
|
|
|
|
TYPE type;
|
2012-03-05 00:43:07 +01:00
|
|
|
STACK_GOSUB *gp;
|
|
|
|
VALUE *ctrl;
|
|
|
|
int i, n;
|
2012-03-04 00:57:36 +01:00
|
|
|
|
|
|
|
goto *return_jump[GET_UX()];
|
|
|
|
|
|
|
|
__RETURN_GOSUB:
|
|
|
|
|
|
|
|
if (!GP)
|
|
|
|
goto __RETURN_VOID;
|
2012-03-05 00:43:07 +01:00
|
|
|
|
|
|
|
n = ARRAY_count(GP);
|
|
|
|
if (n == 0)
|
|
|
|
goto __RETURN_VOID;
|
2012-03-04 00:57:36 +01:00
|
|
|
|
2012-03-05 00:43:07 +01:00
|
|
|
gp = &GP[n - 1];
|
|
|
|
PC = FP->code + gp->pc + 2;
|
|
|
|
if (FP->n_ctrl)
|
2010-04-26 11:36:47 +02:00
|
|
|
{
|
2012-03-05 00:43:07 +01:00
|
|
|
ctrl = &BP[FP->n_local];
|
|
|
|
for (i = 0; i < FP->n_ctrl; i++)
|
|
|
|
{
|
|
|
|
RELEASE(&ctrl[i]);
|
|
|
|
ctrl[i] = gp->ctrl[i];
|
|
|
|
}
|
|
|
|
FREE(&gp->ctrl, "EXEC_loop._RETURN");
|
2010-04-26 11:36:47 +02:00
|
|
|
}
|
2012-03-05 00:43:07 +01:00
|
|
|
|
|
|
|
if (n == 1)
|
|
|
|
ARRAY_delete(&GP);
|
|
|
|
else
|
|
|
|
ARRAY_remove_last(&GP);
|
|
|
|
|
2012-03-04 00:57:36 +01:00
|
|
|
goto _MAIN;
|
|
|
|
|
|
|
|
__RETURN_VALUE:
|
|
|
|
|
|
|
|
type = FP->type;
|
|
|
|
if (TYPE_is_pure_object(type) && ((CLASS *)type)->override)
|
|
|
|
type = (TYPE)(((CLASS *)type)->override);
|
2010-04-26 11:36:47 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv(&SP[-1], type);
|
|
|
|
SP--;
|
|
|
|
*RP = *SP;
|
2012-03-04 00:57:36 +01:00
|
|
|
|
|
|
|
goto __RETURN_LEAVE;
|
|
|
|
|
|
|
|
__RETURN_VOID:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_default(RP, FP->type);
|
2012-03-04 00:57:36 +01:00
|
|
|
|
|
|
|
__RETURN_LEAVE:
|
|
|
|
|
2011-09-09 03:50:57 +02:00
|
|
|
EXEC_leave_keep();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-05-23 21:26:15 +02:00
|
|
|
if (PC == NULL || FP->fast)
|
2012-03-04 00:57:36 +01:00
|
|
|
return;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-03-04 00:57:36 +01:00
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_CALL:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
2011-09-08 18:01:36 +02:00
|
|
|
static const void *call_jump[] =
|
|
|
|
{
|
|
|
|
&&__CALL_NULL, &&__CALL_NATIVE, &&__CALL_PRIVATE, &&__CALL_PUBLIC,
|
|
|
|
&&__CALL_EVENT, &&__CALL_EXTERN, &&__CALL_UNKNOWN, &&__CALL_CALL,
|
|
|
|
&&__CALL_SUBR
|
|
|
|
};
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE * NO_WARNING(val);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
ind = GET_3X();
|
|
|
|
val = &SP[-(ind + 1)];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(!TYPE_is_function(val->type)))
|
|
|
|
{
|
2010-05-28 08:24:14 +02:00
|
|
|
bool defined = EXEC_object(val, &EXEC.class, (OBJECT **)&EXEC.object);
|
2011-06-11 03:46:42 +02:00
|
|
|
|
2010-05-28 08:24:14 +02:00
|
|
|
val->type = T_FUNCTION;
|
2011-06-11 03:46:42 +02:00
|
|
|
val->_function.kind = FUNCTION_CALL;
|
|
|
|
val->_function.defined = defined;
|
|
|
|
val->_function.class = EXEC.class;
|
|
|
|
val->_function.object = EXEC.object;
|
|
|
|
//goto _CALL;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
EXEC.class = val->_function.class;
|
|
|
|
EXEC.object = val->_function.object;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXEC.nparam = ind;
|
|
|
|
EXEC.use_stack = TRUE;
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(!val->_function.defined))
|
2007-12-30 17:41:49 +01:00
|
|
|
*PC |= CODE_CALL_VARIANT;
|
|
|
|
|
|
|
|
goto *call_jump[(int)val->_function.kind];
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_NULL:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
while (ind > 0)
|
|
|
|
{
|
|
|
|
POP();
|
|
|
|
ind--;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
POP();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//if (!PCODE_is_void(code))
|
|
|
|
{
|
|
|
|
/*VALUE_default(SP, (TYPE)(val->_function.function));*/
|
|
|
|
SP->type = T_NULL;
|
|
|
|
SP++;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_NATIVE:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.native = TRUE;
|
|
|
|
EXEC.index = val->_function.index;
|
|
|
|
EXEC.desc = &EXEC.class->table[EXEC.index].desc->method;
|
|
|
|
//EXEC.use_stack = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __EXEC_NATIVE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PRIVATE:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.native = FALSE;
|
|
|
|
EXEC.index = val->_function.index;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __EXEC_ENTER;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PUBLIC:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
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;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __EXEC_ENTER;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__EXEC_ENTER:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_enter_check(val->_function.defined);
|
2012-05-23 21:26:15 +02:00
|
|
|
if (FP->fast)
|
|
|
|
{
|
|
|
|
(*CP->jit_functions[EXEC.index])();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__EXEC_NATIVE:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_native_check(val->_function.defined);
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_EVENT:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-01-16 23:04:17 +01:00
|
|
|
//if (OP && !strcmp(OBJECT_class(OP)->name, "Workspace"))
|
|
|
|
// BREAKPOINT();
|
2007-12-30 17:41:49 +01:00
|
|
|
ind = GB_Raise(OP, val->_function.index, (-EXEC.nparam));
|
|
|
|
|
|
|
|
POP(); // function
|
|
|
|
|
2010-06-18 02:14:53 +02:00
|
|
|
//if (!PCODE_is_void(code))
|
2007-12-30 17:41:49 +01:00
|
|
|
{
|
|
|
|
SP->type = T_BOOLEAN;
|
|
|
|
SP->_boolean.value = ind ? -1 : 0;
|
|
|
|
SP++;
|
|
|
|
}
|
|
|
|
|
|
|
|
//EVENT_Last = old_last;
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_UNKNOWN:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_unknown_name = CP->load->unknown[val->_function.index];
|
|
|
|
EXEC.desc = CLASS_get_special_desc(EXEC.class, SPEC_UNKNOWN);
|
|
|
|
//EXEC.use_stack = TRUE;
|
|
|
|
goto __CALL_SPEC;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_CALL:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.desc = CLASS_get_special_desc(EXEC.class, SPEC_CALL);
|
|
|
|
if (UNLIKELY(!EXEC.desc && !EXEC.object && EXEC.nparam == 1 && !EXEC.class->is_virtual))
|
|
|
|
{
|
|
|
|
SP[-2] = SP[-1];
|
|
|
|
SP--;
|
2010-06-05 01:48:53 +02:00
|
|
|
VALUE_conv_object(SP - 1, (TYPE)EXEC.class);
|
2007-12-30 17:41:49 +01:00
|
|
|
goto _NEXT;
|
2011-06-11 03:46:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
goto __CALL_SPEC;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_SPEC:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(!EXEC.desc))
|
|
|
|
THROW(E_NFUNC);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.native = FUNCTION_is_native(EXEC.desc);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (EXEC.native)
|
|
|
|
{
|
|
|
|
EXEC_native();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EXEC.index = (int)(intptr_t)(EXEC.desc->exec);
|
|
|
|
EXEC.class = EXEC.desc->class;
|
|
|
|
EXEC_enter();
|
2012-05-23 21:26:15 +02:00
|
|
|
if (FP->fast)
|
|
|
|
{
|
|
|
|
(*CP->jit_functions[EXEC.index])();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _MAIN;
|
2011-06-11 03:46:42 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_EXTERN:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.index = val->_function.index;
|
|
|
|
EXTERN_call();
|
|
|
|
goto _NEXT;
|
2011-09-08 18:01:36 +02:00
|
|
|
|
|
|
|
__CALL_SUBR:
|
|
|
|
|
|
|
|
((EXEC_FUNC_CODE)(EXEC.class->table[val->_function.index].desc->method.exec))(code);
|
|
|
|
SP[-2] = SP[-1];
|
|
|
|
SP--;
|
|
|
|
goto _NEXT;
|
2011-06-11 03:46:42 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_CALL_QUICK:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
static const void *call_jump[] =
|
|
|
|
{ &&__CALL_NULL, &&__CALL_NATIVE_Q, &&__CALL_PRIVATE_Q, &&__CALL_PUBLIC_Q };
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE * NO_WARNING(val);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
ind = GET_3X();
|
|
|
|
val = &SP[-(ind + 1)];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.class = val->_function.class;
|
|
|
|
EXEC.object = val->_function.object;
|
|
|
|
EXEC.nparam = ind;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(!val->_function.defined))
|
|
|
|
*PC |= CODE_CALL_VARIANT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//if (call_jump[(int)val->_function.kind] == 0)
|
|
|
|
// fprintf(stderr, "val->_function.kind = %d ?\n", val->_function.kind);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto *call_jump[(int)val->_function.kind];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PRIVATE_Q:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.native = FALSE;
|
|
|
|
EXEC.index = val->_function.index;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __EXEC_ENTER_Q;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PUBLIC_Q:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
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;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__EXEC_ENTER_Q:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_enter_quick();
|
2012-05-23 21:26:15 +02:00
|
|
|
if (FP->fast)
|
|
|
|
{
|
|
|
|
(*CP->jit_functions[EXEC.index])();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _MAIN;
|
2011-06-11 03:46:42 +02:00
|
|
|
|
|
|
|
__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;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2010-06-18 02:14:53 +02:00
|
|
|
#if 0
|
2010-12-18 05:27:59 +01:00
|
|
|
_CALL_EASY:
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
static const void *call_jump[] =
|
|
|
|
{ &&__CALL_NULL, &&__CALL_NATIVE_E, &&__CALL_PRIVATE_E, &&__CALL_PUBLIC_E };
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE * NO_WARNING(val);
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
ind = GET_3X();
|
|
|
|
val = &SP[-(ind + 1)];
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.class = val->_function.class;
|
|
|
|
EXEC.object = val->_function.object;
|
|
|
|
EXEC.nparam = ind;
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(!val->_function.defined))
|
|
|
|
*PC |= CODE_CALL_VARIANT;
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//if (call_jump[(int)val->_function.kind] == 0)
|
|
|
|
// fprintf(stderr, "val->_function.kind = %d ?\n", val->_function.kind);
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto *call_jump[(int)val->_function.kind];
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PRIVATE_E:
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.native = FALSE;
|
|
|
|
EXEC.index = val->_function.index;
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __EXEC_ENTER_E;
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PUBLIC_E:
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
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;
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__EXEC_ENTER_E:
|
2010-06-18 02:14:53 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_enter_easy();
|
|
|
|
goto _MAIN;
|
|
|
|
|
|
|
|
__CALL_NATIVE_E:
|
|
|
|
|
|
|
|
EXEC.native = TRUE;
|
|
|
|
EXEC.index = val->_function.index;
|
|
|
|
EXEC.desc = &EXEC.class->table[EXEC.index].desc->method;
|
|
|
|
|
|
|
|
EXEC_native_easy();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
2010-06-18 02:14:53 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_CALL_SLOW:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
static const void *call_jump[] =
|
|
|
|
{ &&__CALL_NULL, &&__CALL_NATIVE_S, &&__CALL_PRIVATE_S, &&__CALL_PUBLIC_S };
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE * NO_WARNING(val);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
ind = GET_3X();
|
|
|
|
val = &SP[-(ind + 1)];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.class = val->_function.class;
|
|
|
|
EXEC.object = val->_function.object;
|
|
|
|
EXEC.nparam = ind;
|
|
|
|
EXEC.use_stack = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(!val->_function.defined))
|
|
|
|
*PC |= CODE_CALL_VARIANT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto *call_jump[(int)val->_function.kind];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PRIVATE_S:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC.native = FALSE;
|
|
|
|
EXEC.index = val->_function.index;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __EXEC_ENTER_S;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__CALL_PUBLIC_S:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
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;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
__EXEC_ENTER_S:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EXEC_enter();
|
2012-05-23 21:26:15 +02:00
|
|
|
if (FP->fast)
|
|
|
|
{
|
|
|
|
(*CP->jit_functions[EXEC.index])();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _MAIN;
|
2011-06-11 03:46:42 +02:00
|
|
|
|
|
|
|
__CALL_NATIVE_S:
|
|
|
|
|
|
|
|
EXEC.native = TRUE;
|
|
|
|
EXEC.index = val->_function.index;
|
|
|
|
EXEC.desc = &EXEC.class->table[EXEC.index].desc->method;
|
|
|
|
|
|
|
|
EXEC_native();
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_JUMP_FIRST:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
PC[1] &= 0xFF00;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2011-09-01 01:42:46 +02:00
|
|
|
#define MUST_CONTINUE_32(_x, _y) (!(_x) || (((_x) ^ (_y)) >> 31) & 1)
|
|
|
|
#define MUST_CONTINUE_64(_x, _y) (!(_x) || (((_x) ^ (_y)) >> 63) & 1)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-09-01 01:42:46 +02:00
|
|
|
_JUMP_NEXT:
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
2011-09-01 02:39:54 +02:00
|
|
|
static const void *jn_jump[] =
|
2011-10-20 02:03:25 +02:00
|
|
|
{
|
2011-10-23 19:13:48 +02:00
|
|
|
&&_JN_START, NULL, &&_JN_BYTE, &&_JN_SHORT, &&_JN_INTEGER, &&_JN_LONG, &&_JN_SINGLE, &&_JN_FLOAT
|
2011-10-20 02:03:25 +02:00
|
|
|
};
|
2011-10-23 19:13:48 +02:00
|
|
|
|
2011-09-01 02:39:54 +02:00
|
|
|
static const void *jn_test[] =
|
2011-10-20 02:03:25 +02:00
|
|
|
{
|
2011-10-23 19:13:48 +02:00
|
|
|
NULL, NULL, &&_JN_INTEGER_TEST, &&_JN_INTEGER_TEST, &&_JN_INTEGER_TEST,
|
|
|
|
&&_JN_LONG_TEST, &&_JN_SINGLE_TEST, &&_JN_FLOAT_TEST
|
2011-10-20 02:03:25 +02:00
|
|
|
};
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-03-04 00:57:36 +01:00
|
|
|
TYPE type;
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE * NO_WARNING(end);
|
|
|
|
VALUE * NO_WARNING(inc);
|
|
|
|
VALUE * NO_WARNING(val);
|
|
|
|
|
|
|
|
end = &BP[PC[-1] & 0xFF];
|
|
|
|
inc = end + 1;
|
|
|
|
val = &BP[PC[2] & 0xFF];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto *jn_jump[GET_UX()];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
_JN_START:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
type = val->type;
|
2011-09-01 02:39:54 +02:00
|
|
|
|
|
|
|
if (type < T_BYTE || type > T_FLOAT)
|
2011-10-25 01:58:41 +02:00
|
|
|
THROW(E_TYPE, "Number", TYPE_get_name(type));
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
// The step value must stay negative, even if the loop variable is a byte
|
|
|
|
|
2011-10-20 02:03:25 +02:00
|
|
|
if (TYPE_is_integer(type))
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
VALUE_conv_integer(&SP[-1]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
VALUE_conv(&SP[-1], type);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_conv(&SP[-2], type);
|
|
|
|
|
|
|
|
ind = PC[-1] & 0xFF;
|
|
|
|
|
|
|
|
_pop_ctrl(ind + 1); /* modifie val ! */
|
|
|
|
_pop_ctrl(ind);
|
|
|
|
|
|
|
|
val = &BP[PC[2] & 0xFF];
|
2011-09-01 01:42:46 +02:00
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
*PC |= type;
|
|
|
|
goto *jn_test[type];
|
2011-10-20 02:03:25 +02:00
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_BYTE:
|
2011-10-20 02:03:25 +02:00
|
|
|
val->_integer.value = (unsigned char)(val->_integer.value + inc->_integer.value);
|
2011-10-23 19:13:48 +02:00
|
|
|
goto _JN_INTEGER_TEST;
|
2011-10-20 02:03:25 +02:00
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_SHORT:
|
2011-10-20 02:03:25 +02:00
|
|
|
val->_integer.value = (short)(val->_integer.value + inc->_integer.value);
|
2011-10-23 19:13:48 +02:00
|
|
|
goto _JN_INTEGER_TEST;
|
2011-09-01 01:42:46 +02:00
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_INTEGER:
|
2011-10-20 02:03:25 +02:00
|
|
|
val->_integer.value += inc->_integer.value;
|
2011-09-01 01:42:46 +02:00
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_INTEGER_TEST:
|
|
|
|
if ((inc->_integer.value > 0 && val->_integer.value <= end->_integer.value)
|
|
|
|
|| (inc->_integer.value < 0 && val->_integer.value >= end->_integer.value))
|
2011-10-20 02:03:25 +02:00
|
|
|
{
|
|
|
|
PC += 3;
|
|
|
|
goto _MAIN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _JN_END;
|
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_LONG:
|
2011-09-01 01:42:46 +02:00
|
|
|
val->_long.value += inc->_long.value;
|
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_LONG_TEST:
|
|
|
|
if ((inc->_long.value > 0 && val->_long.value <= end->_long.value)
|
|
|
|
|| (inc->_long.value < 0 && val->_long.value >= end->_long.value))
|
2011-10-20 02:03:25 +02:00
|
|
|
{
|
|
|
|
PC += 3;
|
|
|
|
goto _MAIN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _JN_END;
|
2011-09-01 01:42:46 +02:00
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_SINGLE:
|
2011-10-20 02:03:25 +02:00
|
|
|
val->_single.value += inc->_single.value;
|
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_SINGLE_TEST:
|
|
|
|
if ((inc->_single.value > 0 && val->_single.value <= end->_single.value)
|
|
|
|
|| (inc->_single.value < 0 && val->_single.value >= end->_single.value))
|
2011-09-01 13:46:32 +02:00
|
|
|
{
|
2011-10-20 02:03:25 +02:00
|
|
|
PC += 3;
|
|
|
|
goto _MAIN;
|
2011-09-01 13:46:32 +02:00
|
|
|
}
|
2011-10-20 02:03:25 +02:00
|
|
|
else
|
|
|
|
goto _JN_END;
|
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_FLOAT:
|
2011-10-20 02:03:25 +02:00
|
|
|
val->_float.value += inc->_float.value;
|
|
|
|
|
2011-10-23 19:13:48 +02:00
|
|
|
_JN_FLOAT_TEST:
|
|
|
|
if ((inc->_float.value > 0 && val->_float.value <= end->_float.value)
|
|
|
|
|| (inc->_float.value < 0 && val->_float.value >= end->_float.value))
|
2011-10-20 02:03:25 +02:00
|
|
|
{
|
|
|
|
PC += 3;
|
|
|
|
goto _MAIN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto _JN_END;
|
2011-09-01 13:46:32 +02:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
_JN_END:
|
|
|
|
PC += (signed short)PC[1] + 2;
|
2011-09-01 01:42:46 +02:00
|
|
|
goto _MAIN;
|
2011-06-11 03:46:42 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_ENUM_FIRST:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
_pop_ctrl(GET_XX());
|
|
|
|
EXEC_enum_first(code);
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_ENUM_NEXT:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(EXEC_enum_next(code)))
|
|
|
|
goto _JUMP;
|
|
|
|
else
|
2010-06-05 01:48:53 +02:00
|
|
|
{
|
|
|
|
PC += 2;
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _MAIN;
|
2010-06-05 01:48:53 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_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++;
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//fprintf(stderr, "PUSH CLASS: %s in %s\n", SP->_class.class->name, SP->_class.class->component ? SP->_class.class->component->name : NULL);
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_FUNCTION:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
/*ind = GET_7XX();*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
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;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
OBJECT_REF(OP, "exec_loop._PUSH_FUNCTION (FUNCTION)");
|
|
|
|
SP++;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_EXTERN:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
/*ind = GET_7XX();*/
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_FUNCTION;
|
|
|
|
SP->_function.class = CP;
|
|
|
|
SP->_function.object = NULL;
|
|
|
|
SP->_function.kind = FUNCTION_EXTERN;
|
|
|
|
SP->_function.index = GET_UX();
|
|
|
|
SP->_function.defined = TRUE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//OBJECT_REF(OP, "exec_loop._PUSH_FUNCTION (FUNCTION)");
|
|
|
|
SP++;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
{
|
|
|
|
CLASS_VAR *var;
|
|
|
|
char *addr;
|
2010-05-19 14:43:57 +02:00
|
|
|
void *ref;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_PUSH_DYNAMIC:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
var = &CP->load->dyn[GET_7XX()];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//if (UNLIKELY(OP == NULL))
|
|
|
|
// THROW_ILLEGAL();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-05-19 14:43:57 +02:00
|
|
|
ref = OP;
|
2011-06-11 03:46:42 +02:00
|
|
|
addr = &OP[var->pos];
|
|
|
|
goto __READ;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_PUSH_STATIC:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
var = &CP->load->stat[GET_7XX()];
|
|
|
|
addr = (char *)CP->stat + var->pos;
|
2010-05-19 14:43:57 +02:00
|
|
|
ref = CP;
|
2011-06-11 03:46:42 +02:00
|
|
|
goto __READ;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
__READ:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
my_VALUE_class_read(CP, SP, addr, var->type, ref);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
PUSH();
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
_POP_DYNAMIC:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
var = &CP->load->dyn[GET_7XX()];
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
//if (UNLIKELY(OP == NULL))
|
|
|
|
// THROW_ILLEGAL();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
addr = &OP[var->pos];
|
|
|
|
goto __WRITE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_POP_STATIC:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
var = &CP->load->stat[GET_7XX()];
|
|
|
|
addr = (char *)CP->stat + var->pos;
|
|
|
|
goto __WRITE;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
__WRITE:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
VALUE_class_write(CP, &SP[-1], addr, var->type);
|
|
|
|
POP();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_CONST:
|
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
ind = GET_UXX();
|
2011-06-11 03:46:42 +02:00
|
|
|
my_VALUE_class_constant(CP, SP, ind);
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
|
2010-12-20 04:56:43 +01:00
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_CONST_EX:
|
|
|
|
|
|
|
|
PC++;
|
2011-06-11 03:46:42 +02:00
|
|
|
my_VALUE_class_constant(CP, SP, *PC);
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2010-12-20 04:56:43 +01:00
|
|
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_PUSH_QUICK:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
SP->type = T_INTEGER;
|
|
|
|
SP->_integer.value = GET_XXX();
|
|
|
|
SP++;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_ADD_QUICK:
|
|
|
|
|
2008-04-17 12:18:25 +02:00
|
|
|
{
|
|
|
|
static void *_aq_jump[] = {
|
2012-01-11 02:49:57 +01:00
|
|
|
&&__AQ_VOID, &&__AQ_BOOLEAN, &&__AQ_BYTE, &&__AQ_SHORT, &&__AQ_INTEGER, &&__AQ_LONG, &&__AQ_SINGLE, &&__AQ_FLOAT,
|
2011-01-10 23:56:30 +01:00
|
|
|
&&__AQ_DATE, &&__AQ_STRING, &&__AQ_STRING, &&__AQ_POINTER
|
2008-04-17 12:18:25 +02:00
|
|
|
};
|
|
|
|
|
2008-05-12 18:09:33 +02:00
|
|
|
TYPE NO_WARNING(type);
|
2008-04-17 12:18:25 +02:00
|
|
|
int NO_WARNING(value);
|
|
|
|
VALUE * NO_WARNING(P1);
|
|
|
|
void * NO_WARNING(jump_end);
|
|
|
|
|
|
|
|
P1 = SP - 1;
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(TYPE_is_variant(P1->type)))
|
2008-04-17 12:18:25 +02:00
|
|
|
{
|
|
|
|
jump_end = &&__AQ_VARIANT_END;
|
|
|
|
VARIANT_undo(P1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
jump_end = &&__AQ_END;
|
|
|
|
|
|
|
|
type = P1->type;
|
|
|
|
value = GET_XXX();
|
|
|
|
|
2011-01-10 23:56:30 +01:00
|
|
|
if (LIKELY(type <= T_POINTER))
|
2008-04-17 12:18:25 +02:00
|
|
|
goto *_aq_jump[type];
|
2012-01-11 02:49:57 +01:00
|
|
|
|
|
|
|
__AQ_VOID:
|
|
|
|
|
|
|
|
THROW(E_NRETURN);
|
2008-04-17 12:18:25 +02:00
|
|
|
|
|
|
|
__AQ_BOOLEAN:
|
|
|
|
|
2011-09-13 02:04:40 +02:00
|
|
|
THROW(E_TYPE, "Number", TYPE_get_name(type));
|
2008-04-17 12:18:25 +02:00
|
|
|
|
|
|
|
__AQ_BYTE:
|
2009-01-30 02:16:03 +01:00
|
|
|
|
|
|
|
P1->_integer.value = (unsigned char)(P1->_integer.value + value);
|
|
|
|
goto *jump_end;
|
|
|
|
|
2008-04-17 12:18:25 +02:00
|
|
|
__AQ_SHORT:
|
2009-01-30 02:16:03 +01:00
|
|
|
|
|
|
|
P1->_integer.value = (short)(P1->_integer.value + value);
|
|
|
|
goto *jump_end;
|
|
|
|
|
2008-04-17 12:18:25 +02:00
|
|
|
__AQ_INTEGER:
|
|
|
|
|
|
|
|
P1->_integer.value += value;
|
|
|
|
goto *jump_end;
|
|
|
|
|
|
|
|
__AQ_LONG:
|
|
|
|
|
|
|
|
P1->_long.value += (int64_t)value;
|
|
|
|
goto *jump_end;
|
|
|
|
|
2010-11-16 02:49:18 +01:00
|
|
|
__AQ_SINGLE:
|
|
|
|
|
|
|
|
P1->_single.value += (float)value;
|
|
|
|
goto *jump_end;
|
|
|
|
|
2010-11-22 11:10:56 +01:00
|
|
|
__AQ_DATE:
|
|
|
|
__AQ_STRING:
|
|
|
|
|
|
|
|
VALUE_conv_float(P1);
|
|
|
|
|
2008-04-17 12:18:25 +02:00
|
|
|
__AQ_FLOAT:
|
|
|
|
|
|
|
|
P1->_float.value += (double)value;
|
|
|
|
goto *jump_end;
|
|
|
|
|
2011-01-10 23:56:30 +01:00
|
|
|
__AQ_POINTER:
|
|
|
|
|
|
|
|
P1->_pointer.value += value;
|
|
|
|
goto *jump_end;
|
|
|
|
|
2008-04-17 12:18:25 +02:00
|
|
|
__AQ_VARIANT_END:
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
VALUE_conv_variant(P1);
|
2008-04-17 12:18:25 +02:00
|
|
|
|
|
|
|
__AQ_END:
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2008-04-17 12:18:25 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_TRY:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
EP = SP;
|
|
|
|
ET = EC;
|
|
|
|
EC = PC + (signed short)PC[1] + 2;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
#if DEBUG_ERROR
|
|
|
|
fprintf(stderr, "exec TRY %p\n", EC);
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
PC += 2;
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _MAIN;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_END_TRY:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
#if DEBUG_ERROR
|
|
|
|
fprintf(stderr, "exec END TRY %p\n", PC);
|
|
|
|
#endif
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
// If EP was reset to null, then an error occurred
|
|
|
|
EXEC_got_error = (EP == NULL);
|
|
|
|
EP = NULL;
|
|
|
|
EC = ET;
|
|
|
|
ET = NULL;
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_CATCH:
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (UNLIKELY(EC == NULL))
|
|
|
|
goto _NEXT;
|
|
|
|
else
|
2012-03-04 00:57:36 +01:00
|
|
|
goto __RETURN_VOID;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_BREAK:
|
|
|
|
|
2012-02-26 19:31:54 +01:00
|
|
|
//DEBUG_where(); fputc('\n', stderr);
|
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (EXEC_debug && CP && CP->component == COMPONENT_main)
|
|
|
|
{
|
|
|
|
//TRACE.ec = PC + 1;
|
|
|
|
//TRACE.ep = SP;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
TC = PC + 1;
|
|
|
|
TP = SP;
|
2012-05-19 04:55:05 +02:00
|
|
|
|
2012-05-23 23:35:58 +02:00
|
|
|
if (EXEC_profile_instr)
|
2012-05-19 04:55:05 +02:00
|
|
|
DEBUG.Profile.Add(CP, FP, PC);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
ind = GET_UX();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
if (ind == 0)
|
|
|
|
{
|
|
|
|
if (!DEBUG_info->stop)
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
// Return from (void stack)
|
2007-12-30 17:41:49 +01:00
|
|
|
if (DEBUG_info->leave)
|
|
|
|
{
|
|
|
|
if (STACK_get_current()->pc)
|
|
|
|
goto _NEXT;
|
|
|
|
if (FP == DEBUG_info->fp)
|
|
|
|
goto _NEXT;
|
2011-06-11 03:46:42 +02:00
|
|
|
if (BP > DEBUG_info->bp)
|
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
// Forward or Return From
|
2011-06-11 03:46:42 +02:00
|
|
|
else if (DEBUG_info->fp != NULL)
|
|
|
|
{
|
|
|
|
if (BP > DEBUG_info->bp)
|
|
|
|
goto _NEXT;
|
|
|
|
}
|
|
|
|
// otherwise, Next
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
DEBUG.Breakpoint(ind);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*PC = C_NOP;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_QUIT:
|
|
|
|
|
2010-06-18 02:14:53 +02:00
|
|
|
switch(GET_UX())
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
EXEC_quit();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
2010-12-27 15:28:59 +01:00
|
|
|
if (EXEC_debug && CP) // && CP->component == COMPONENT_main)
|
2010-06-18 02:14:53 +02:00
|
|
|
DEBUG.Breakpoint(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
default:
|
|
|
|
GAMBAS_StopEvent = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-06-11 03:46:42 +02:00
|
|
|
goto _NEXT;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
_BYREF:
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (LIKELY(PC == FP->code))
|
2008-02-24 17:29:02 +01:00
|
|
|
{
|
2010-06-05 01:48:53 +02:00
|
|
|
PC += GET_UX() + 2;
|
|
|
|
goto _MAIN;
|
2008-02-24 17:29:02 +01:00
|
|
|
}
|
|
|
|
|
2008-01-19 18:52:05 +01:00
|
|
|
THROW(E_BYREF);
|
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2012-05-21 03:09:35 +02:00
|
|
|
/*_ILLEGAL:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2012-05-21 03:09:35 +02:00
|
|
|
THROW_ILLEGAL();*/
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
#define EXEC_code code
|
|
|
|
|
|
|
|
_SUBR_LEFT:
|
|
|
|
|
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
|
|
|
SUBR_ENTER();
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (LIKELY(!SUBR_check_string(PARAM)))
|
2008-01-27 15:00:04 +01:00
|
|
|
{
|
|
|
|
if (NPARAM == 1)
|
|
|
|
val = 1;
|
|
|
|
else
|
|
|
|
{
|
2010-06-03 01:23:50 +02:00
|
|
|
VALUE_conv_integer(&PARAM[1]);
|
2008-01-27 15:00:04 +01:00
|
|
|
val = PARAM[1]._integer.value;
|
|
|
|
}
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(val < 0))
|
2008-01-27 15:00:04 +01:00
|
|
|
val += PARAM->_string.len;
|
|
|
|
|
|
|
|
PARAM->_string.len = MinMax(val, 0, PARAM->_string.len);
|
|
|
|
}
|
|
|
|
|
|
|
|
SP -= NPARAM;
|
|
|
|
SP++;
|
|
|
|
}
|
2010-06-18 02:14:53 +02:00
|
|
|
goto _NEXT;
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_SUBR_RIGHT:
|
|
|
|
|
|
|
|
{
|
|
|
|
int val;
|
|
|
|
int new_len;
|
|
|
|
|
|
|
|
SUBR_ENTER();
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (LIKELY(!SUBR_check_string(PARAM)))
|
2008-01-27 15:00:04 +01:00
|
|
|
{
|
|
|
|
if (NPARAM == 1)
|
|
|
|
val = 1;
|
|
|
|
else
|
|
|
|
{
|
2010-06-03 01:23:50 +02:00
|
|
|
VALUE_conv_integer(&PARAM[1]);
|
2008-01-27 15:00:04 +01:00
|
|
|
val = PARAM[1]._integer.value;
|
|
|
|
}
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(val < 0))
|
2008-01-27 15:00:04 +01:00
|
|
|
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++;
|
|
|
|
}
|
2010-06-18 02:14:53 +02:00
|
|
|
goto _NEXT;
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_SUBR_MID:
|
|
|
|
{
|
|
|
|
int start;
|
|
|
|
int len;
|
2008-03-13 22:38:43 +01:00
|
|
|
bool null;
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
SUBR_ENTER();
|
|
|
|
|
2008-03-13 22:38:43 +01:00
|
|
|
null = SUBR_check_string(PARAM);
|
2008-01-27 15:00:04 +01:00
|
|
|
|
2010-06-03 01:23:50 +02:00
|
|
|
VALUE_conv_integer(&PARAM[1]);
|
2008-01-27 15:00:04 +01:00
|
|
|
start = PARAM[1]._integer.value - 1;
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(start < 0))
|
2008-01-27 15:00:04 +01:00
|
|
|
THROW(E_ARG);
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(null))
|
2008-03-13 22:38:43 +01:00
|
|
|
goto _SUBR_MID_FIN;
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(start >= PARAM->_string.len))
|
2008-01-27 15:00:04 +01:00
|
|
|
{
|
2011-09-06 22:47:26 +02:00
|
|
|
VOID_STRING(PARAM);
|
2008-01-27 15:00:04 +01:00
|
|
|
goto _SUBR_MID_FIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NPARAM == 2)
|
|
|
|
len = PARAM->_string.len;
|
|
|
|
else
|
|
|
|
{
|
2010-06-03 01:23:50 +02:00
|
|
|
VALUE_conv_integer(&PARAM[2]);
|
2008-01-27 15:00:04 +01:00
|
|
|
len = PARAM[2]._integer.value;
|
|
|
|
}
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(len < 0))
|
2008-01-27 15:00:04 +01:00
|
|
|
len = Max(0, PARAM->_string.len - start + len);
|
|
|
|
|
|
|
|
len = MinMax(len, 0, PARAM->_string.len - start);
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(len == 0))
|
2008-01-27 15:00:04 +01:00
|
|
|
{
|
2010-06-09 01:08:04 +02:00
|
|
|
RELEASE_STRING(PARAM);
|
2008-01-27 15:00:04 +01:00
|
|
|
PARAM->_string.addr = NULL;
|
|
|
|
PARAM->_string.start = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
PARAM->_string.start += start;
|
|
|
|
|
|
|
|
PARAM->_string.len = len;
|
|
|
|
|
|
|
|
_SUBR_MID_FIN:
|
|
|
|
|
|
|
|
SP -= NPARAM;
|
|
|
|
SP++;
|
|
|
|
}
|
2010-06-18 02:14:53 +02:00
|
|
|
goto _NEXT;
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
|
|
|
_SUBR_LEN:
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
SUBR_GET_PARAM(1);
|
|
|
|
|
2010-05-19 22:18:23 +02:00
|
|
|
if (UNLIKELY(SUBR_check_string(PARAM)))
|
2008-01-27 15:00:04 +01:00
|
|
|
len = 0;
|
|
|
|
else
|
|
|
|
len = PARAM->_string.len;
|
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
RELEASE_STRING(PARAM);
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
PARAM->type = T_INTEGER;
|
|
|
|
PARAM->_integer.value = len;
|
|
|
|
}
|
2010-06-18 02:14:53 +02:00
|
|
|
goto _NEXT;
|
2008-01-27 15:00:04 +01:00
|
|
|
|
|
|
|
/*-----------------------------------------------*/
|
|
|
|
|
2010-05-22 20:02:34 +02:00
|
|
|
_SUBR_COMP:
|
|
|
|
{
|
|
|
|
static void *jump[17] = {
|
|
|
|
&&__SC_VARIANT, &&__SC_BOOLEAN, &&__SC_BYTE, &&__SC_SHORT, &&__SC_INTEGER, &&__SC_LONG, &&__SC_SINGLE, &&__SC_FLOAT, &&__SC_DATE,
|
|
|
|
&&__SC_STRING, &&__SC_STRING, &&__SC_POINTER, &&__SC_ERROR, &&__SC_ERROR, &&__SC_ERROR, &&__SC_NULL, &&__SC_OBJECT
|
|
|
|
};
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
char NO_WARNING(result);
|
|
|
|
VALUE *NO_WARNING(P1);
|
|
|
|
VALUE *NO_WARNING(P2);
|
|
|
|
|
2010-05-22 20:02:34 +02:00
|
|
|
P1 = SP - 2;
|
2011-09-07 14:38:29 +02:00
|
|
|
P2 = SP - 1;
|
2010-05-22 20:02:34 +02:00
|
|
|
|
|
|
|
goto *jump[code & 0x1F];
|
|
|
|
|
|
|
|
__SC_BOOLEAN:
|
|
|
|
__SC_BYTE:
|
|
|
|
__SC_SHORT:
|
|
|
|
__SC_INTEGER:
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
result = P1->_integer.value == P2->_integer.value;
|
|
|
|
goto __SC_END;
|
2010-05-22 20:02:34 +02:00
|
|
|
|
|
|
|
__SC_LONG:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_LONG);
|
|
|
|
VALUE_conv(P2, T_LONG);
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
result = P1->_long.value == P2->_long.value;
|
2010-05-22 20:02:34 +02:00
|
|
|
goto __SC_END;
|
|
|
|
|
|
|
|
__SC_DATE:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_DATE);
|
|
|
|
VALUE_conv(P2, T_DATE);
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
result = DATE_comp_value(P1, P2) == 0;
|
2010-05-22 20:02:34 +02:00
|
|
|
goto __SC_END;
|
|
|
|
|
|
|
|
__SC_NULL:
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
if (P2->type == T_NULL)
|
2010-05-22 20:02:34 +02:00
|
|
|
{
|
2011-09-07 14:38:29 +02:00
|
|
|
result = VALUE_is_null(P1);
|
|
|
|
goto __SC_END_RELEASE;
|
|
|
|
}
|
|
|
|
else if (P1->type == T_NULL)
|
|
|
|
{
|
|
|
|
result = VALUE_is_null(P2);
|
|
|
|
goto __SC_END_RELEASE;
|
2010-05-22 20:02:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
__SC_STRING:
|
|
|
|
|
|
|
|
VALUE_conv_string(P1);
|
|
|
|
VALUE_conv_string(P2);
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
if (P1->_string.len != P2->_string.len)
|
|
|
|
result = 0;
|
2010-05-22 20:02:34 +02:00
|
|
|
else
|
2011-09-07 14:38:29 +02:00
|
|
|
result = STRING_equal_same(P1->_string.addr + P1->_string.start, P2->_string.addr + P2->_string.start, P1->_string.len);
|
|
|
|
|
|
|
|
RELEASE_STRING(P1);
|
|
|
|
RELEASE_STRING(P2);
|
|
|
|
goto __SC_END;
|
2010-05-22 20:02:34 +02:00
|
|
|
|
|
|
|
__SC_SINGLE:
|
2011-09-07 14:38:29 +02:00
|
|
|
|
|
|
|
VALUE_conv(P1, T_SINGLE);
|
|
|
|
VALUE_conv(P2, T_SINGLE);
|
|
|
|
|
|
|
|
result = P1->_single.value == P2->_single.value;
|
|
|
|
goto __SC_END;
|
|
|
|
|
2010-05-22 20:02:34 +02:00
|
|
|
__SC_FLOAT:
|
|
|
|
|
2010-06-03 01:23:50 +02:00
|
|
|
VALUE_conv_float(P1);
|
|
|
|
VALUE_conv_float(P2);
|
2010-05-22 20:02:34 +02:00
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
result = P1->_float.value == P2->_float.value;
|
2010-05-22 20:02:34 +02:00
|
|
|
goto __SC_END;
|
|
|
|
|
|
|
|
__SC_POINTER:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_POINTER);
|
|
|
|
VALUE_conv(P2, T_POINTER);
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
result = P1->_pointer.value == P2->_pointer.value;
|
2010-05-22 20:02:34 +02:00
|
|
|
goto __SC_END;
|
|
|
|
|
|
|
|
__SC_OBJECT:
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
result = OBJECT_comp_value(P1, P2) == 0;
|
|
|
|
//RELEASE_OBJECT(P1);
|
|
|
|
//RELEASE_OBJECT(P2);
|
2010-05-22 20:02:34 +02:00
|
|
|
goto __SC_END_RELEASE;
|
|
|
|
|
|
|
|
__SC_VARIANT:
|
|
|
|
|
|
|
|
{
|
|
|
|
bool variant = FALSE;
|
2011-09-07 14:38:29 +02:00
|
|
|
TYPE type;
|
2010-05-22 20:02:34 +02:00
|
|
|
|
|
|
|
if (TYPE_is_variant(P1->type))
|
|
|
|
{
|
|
|
|
VARIANT_undo(P1);
|
|
|
|
variant = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TYPE_is_variant(P2->type))
|
|
|
|
{
|
|
|
|
VARIANT_undo(P2);
|
|
|
|
variant = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = Max(P1->type, P2->type);
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
if (TYPE_is_object_null(P1->type) && TYPE_is_object_null(P2->type))
|
|
|
|
type = T_OBJECT;
|
|
|
|
else if (TYPE_is_object(type))
|
|
|
|
THROW(E_TYPE, "Object", TYPE_get_name(Min(P1->type, P2->type)));
|
2012-01-11 02:49:57 +01:00
|
|
|
else if (TYPE_is_void(type))
|
|
|
|
THROW(E_NRETURN);
|
2010-05-22 20:02:34 +02:00
|
|
|
|
|
|
|
if (!variant)
|
|
|
|
*PC |= type;
|
|
|
|
|
|
|
|
goto *jump[type];
|
|
|
|
}
|
|
|
|
|
|
|
|
__SC_ERROR:
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
THROW(E_TYPE, "Number, Date or String", TYPE_get_name(code & 0x1F));
|
2010-05-22 20:02:34 +02:00
|
|
|
|
|
|
|
__SC_END_RELEASE:
|
|
|
|
|
|
|
|
RELEASE(P1);
|
|
|
|
RELEASE(P2);
|
|
|
|
|
|
|
|
__SC_END:
|
|
|
|
|
|
|
|
P1->type = T_BOOLEAN;
|
|
|
|
SP--;
|
2011-09-07 14:38:29 +02:00
|
|
|
P1->_boolean.value = -result;
|
|
|
|
goto _NEXT;
|
2010-05-22 20:02:34 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
}
|
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
|
|
|
|
static void my_VALUE_class_read(CLASS *class, VALUE *value, char *addr, CTYPE ctype, void *ref)
|
|
|
|
{
|
|
|
|
VALUE_class_read_inline(class, value, addr, ctype, ref);
|
|
|
|
}
|
|
|
|
|
2011-09-07 14:38:29 +02:00
|
|
|
#if 0
|
2010-06-09 01:08:04 +02:00
|
|
|
static void _SUBR_comp(ushort code)
|
|
|
|
{
|
|
|
|
static void *jump[17] = {
|
|
|
|
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE,
|
|
|
|
&&__STRING, &&__STRING, &&__POINTER, &&__ERROR, &&__ERROR, &&__ERROR, &&__NULL, &&__OBJECT
|
|
|
|
};
|
|
|
|
|
|
|
|
//static void *test[] = { &&__EQ, &&__NE, &&__GT, &&__LE, &&__LT, &&__GE };
|
|
|
|
|
|
|
|
char NO_WARNING(result);
|
|
|
|
VALUE *P1;
|
|
|
|
VALUE *P2;
|
|
|
|
|
|
|
|
P1 = SP - 2;
|
|
|
|
P2 = P1 + 1;
|
|
|
|
|
|
|
|
goto *jump[code & 0x1F];
|
|
|
|
|
|
|
|
__BOOLEAN:
|
|
|
|
__BYTE:
|
|
|
|
__SHORT:
|
|
|
|
__INTEGER:
|
|
|
|
|
|
|
|
result = P1->_integer.value == P2->_integer.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__LONG:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_LONG);
|
|
|
|
VALUE_conv(P2, T_LONG);
|
|
|
|
|
|
|
|
result = P1->_long.value == P2->_long.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__DATE:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_DATE);
|
|
|
|
VALUE_conv(P2, T_DATE);
|
|
|
|
|
|
|
|
result = DATE_comp_value(P1, P2) == 0;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__NULL:
|
|
|
|
|
|
|
|
if (P2->type == T_NULL)
|
|
|
|
{
|
|
|
|
result = VALUE_is_null(P1);
|
|
|
|
goto __END_RELEASE;
|
|
|
|
}
|
|
|
|
else if (P1->type == T_NULL)
|
|
|
|
{
|
|
|
|
result = VALUE_is_null(P2);
|
|
|
|
goto __END_RELEASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
__STRING:
|
|
|
|
|
|
|
|
VALUE_conv_string(P1);
|
|
|
|
VALUE_conv_string(P2);
|
|
|
|
|
|
|
|
if (P1->_string.len != P2->_string.len)
|
|
|
|
result = 0;
|
|
|
|
else
|
|
|
|
result = STRING_equal_same(P1->_string.addr + P1->_string.start, P2->_string.addr + P2->_string.start, P1->_string.len);
|
|
|
|
|
|
|
|
RELEASE_STRING(P1);
|
|
|
|
RELEASE_STRING(P2);
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__SINGLE:
|
2010-11-16 02:49:18 +01:00
|
|
|
|
|
|
|
VALUE_conv(P1, T_SINGLE);
|
|
|
|
VALUE_conv(P2, T_SINGLE);
|
|
|
|
|
|
|
|
result = P1->_single.value == P2->_single.value;
|
|
|
|
goto __END;
|
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
__FLOAT:
|
|
|
|
|
|
|
|
VALUE_conv_float(P1);
|
|
|
|
VALUE_conv_float(P2);
|
|
|
|
|
|
|
|
result = P1->_float.value == P2->_float.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__POINTER:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_POINTER);
|
|
|
|
VALUE_conv(P2, T_POINTER);
|
|
|
|
|
|
|
|
result = P1->_pointer.value == P2->_pointer.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__OBJECT:
|
|
|
|
|
|
|
|
result = OBJECT_comp_value(P1, P2) == 0;
|
|
|
|
//RELEASE_OBJECT(P1);
|
|
|
|
//RELEASE_OBJECT(P2);
|
|
|
|
goto __END_RELEASE;
|
|
|
|
|
|
|
|
__VARIANT:
|
|
|
|
|
|
|
|
{
|
|
|
|
bool variant = FALSE;
|
|
|
|
TYPE type;
|
|
|
|
|
|
|
|
if (TYPE_is_variant(P1->type))
|
|
|
|
{
|
|
|
|
VARIANT_undo(P1);
|
|
|
|
variant = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TYPE_is_variant(P2->type))
|
|
|
|
{
|
|
|
|
VARIANT_undo(P2);
|
|
|
|
variant = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = Max(P1->type, P2->type);
|
|
|
|
|
|
|
|
if (TYPE_is_object_null(P1->type) && TYPE_is_object_null(P2->type))
|
|
|
|
type = T_OBJECT;
|
|
|
|
else if (TYPE_is_object(type))
|
|
|
|
THROW(E_TYPE, "Object", TYPE_get_name(Min(P1->type, P2->type)));
|
|
|
|
|
|
|
|
if (!variant)
|
|
|
|
*PC |= type;
|
|
|
|
|
|
|
|
goto *jump[type];
|
|
|
|
}
|
|
|
|
|
|
|
|
__ERROR:
|
|
|
|
|
|
|
|
THROW(E_TYPE, "Number, Date or String", TYPE_get_name(code & 0x1F));
|
|
|
|
|
|
|
|
__END_RELEASE:
|
|
|
|
|
|
|
|
RELEASE(P1);
|
|
|
|
RELEASE(P2);
|
|
|
|
|
|
|
|
__END:
|
|
|
|
|
|
|
|
P1->type = T_BOOLEAN;
|
|
|
|
SP--;
|
|
|
|
P1->_boolean.value = -result;
|
|
|
|
}
|
2011-09-07 14:38:29 +02:00
|
|
|
#endif
|
2010-06-09 01:08:04 +02:00
|
|
|
|
|
|
|
static void _SUBR_compn(ushort code)
|
|
|
|
{
|
|
|
|
static void *jump[17] = {
|
|
|
|
&&__VARIANT, &&__BOOLEAN, &&__BYTE, &&__SHORT, &&__INTEGER, &&__LONG, &&__SINGLE, &&__FLOAT, &&__DATE,
|
|
|
|
&&__STRING, &&__STRING, &&__POINTER, &&__ERROR, &&__ERROR, &&__ERROR, &&__NULL, &&__OBJECT
|
|
|
|
};
|
|
|
|
|
|
|
|
//static void *test[] = { &&__EQ, &&__NE, &&__GT, &&__LE, &&__LT, &&__GE };
|
|
|
|
|
|
|
|
char NO_WARNING(result);
|
|
|
|
VALUE *P1;
|
|
|
|
VALUE *P2;
|
|
|
|
|
|
|
|
P1 = SP - 2;
|
|
|
|
P2 = P1 + 1;
|
|
|
|
|
|
|
|
goto *jump[code & 0x1F];
|
|
|
|
|
|
|
|
__BOOLEAN:
|
|
|
|
__BYTE:
|
|
|
|
__SHORT:
|
|
|
|
__INTEGER:
|
|
|
|
|
|
|
|
result = P1->_integer.value == P2->_integer.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__LONG:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_LONG);
|
|
|
|
VALUE_conv(P2, T_LONG);
|
|
|
|
|
|
|
|
result = P1->_long.value == P2->_long.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__DATE:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_DATE);
|
|
|
|
VALUE_conv(P2, T_DATE);
|
|
|
|
|
|
|
|
result = DATE_comp_value(P1, P2) == 0;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__NULL:
|
|
|
|
|
|
|
|
if (P2->type == T_NULL)
|
|
|
|
{
|
|
|
|
result = VALUE_is_null(P1);
|
|
|
|
goto __END_RELEASE;
|
|
|
|
}
|
|
|
|
else if (P1->type == T_NULL)
|
|
|
|
{
|
|
|
|
result = VALUE_is_null(P2);
|
|
|
|
goto __END_RELEASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
__STRING:
|
|
|
|
|
|
|
|
VALUE_conv_string(P1);
|
|
|
|
VALUE_conv_string(P2);
|
|
|
|
|
|
|
|
if (P1->_string.len != P2->_string.len)
|
|
|
|
result = 0;
|
|
|
|
else
|
|
|
|
result = STRING_equal_same(P1->_string.addr + P1->_string.start, P2->_string.addr + P2->_string.start, P1->_string.len);
|
|
|
|
|
|
|
|
RELEASE_STRING(P1);
|
|
|
|
RELEASE_STRING(P2);
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__SINGLE:
|
2010-11-16 02:49:18 +01:00
|
|
|
|
|
|
|
VALUE_conv(P1, T_SINGLE);
|
|
|
|
VALUE_conv(P2, T_SINGLE);
|
|
|
|
|
|
|
|
result = P1->_single.value == P2->_single.value;
|
|
|
|
goto __END;
|
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
__FLOAT:
|
|
|
|
|
|
|
|
VALUE_conv_float(P1);
|
|
|
|
VALUE_conv_float(P2);
|
|
|
|
|
|
|
|
result = P1->_float.value == P2->_float.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__POINTER:
|
|
|
|
|
|
|
|
VALUE_conv(P1, T_POINTER);
|
|
|
|
VALUE_conv(P2, T_POINTER);
|
|
|
|
|
|
|
|
result = P1->_pointer.value == P2->_pointer.value;
|
|
|
|
goto __END;
|
|
|
|
|
|
|
|
__OBJECT:
|
|
|
|
|
|
|
|
result = OBJECT_comp_value(P1, P2) == 0;
|
|
|
|
//RELEASE_OBJECT(P1);
|
|
|
|
//RELEASE_OBJECT(P2);
|
|
|
|
goto __END_RELEASE;
|
|
|
|
|
|
|
|
__VARIANT:
|
|
|
|
|
|
|
|
{
|
|
|
|
bool variant = FALSE;
|
|
|
|
TYPE type;
|
|
|
|
|
|
|
|
if (TYPE_is_variant(P1->type))
|
|
|
|
{
|
|
|
|
VARIANT_undo(P1);
|
|
|
|
variant = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TYPE_is_variant(P2->type))
|
|
|
|
{
|
|
|
|
VARIANT_undo(P2);
|
|
|
|
variant = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
type = Max(P1->type, P2->type);
|
|
|
|
|
|
|
|
if (TYPE_is_object_null(P1->type) && TYPE_is_object_null(P2->type))
|
|
|
|
type = T_OBJECT;
|
|
|
|
else if (TYPE_is_object(type))
|
|
|
|
THROW(E_TYPE, "Object", TYPE_get_name(Min(P1->type, P2->type)));
|
2012-01-11 02:49:57 +01:00
|
|
|
else if (TYPE_is_void(type))
|
|
|
|
THROW(E_NRETURN);
|
2010-06-09 01:08:04 +02:00
|
|
|
|
|
|
|
if (!variant)
|
|
|
|
*PC |= type;
|
|
|
|
|
|
|
|
goto *jump[type];
|
|
|
|
}
|
|
|
|
|
|
|
|
__ERROR:
|
|
|
|
|
|
|
|
THROW(E_TYPE, "Number, Date or String", TYPE_get_name(code & 0x1F));
|
|
|
|
|
|
|
|
__END_RELEASE:
|
|
|
|
|
|
|
|
RELEASE(P1);
|
|
|
|
RELEASE(P2);
|
|
|
|
|
|
|
|
__END:
|
|
|
|
|
|
|
|
P1->type = T_BOOLEAN;
|
|
|
|
SP--;
|
|
|
|
|
|
|
|
P1->_boolean.value = result - 1; // ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
2011-09-09 03:50:57 +02:00
|
|
|
#define sgn(_x) \
|
|
|
|
({ \
|
|
|
|
int x = _x; \
|
|
|
|
int minusOne = x >> 31; \
|
|
|
|
unsigned int negateX = (unsigned int) -x; \
|
|
|
|
int plusOne = (int)(negateX >> 31); \
|
|
|
|
int result = minusOne | plusOne; \
|
|
|
|
result; \
|
|
|
|
})
|
|
|
|
|
2010-06-09 01:08:04 +02:00
|
|
|
static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind)
|
|
|
|
{
|
|
|
|
VALUE_class_constant_inline(class, value, ind);
|
|
|
|
}
|
|
|
|
|
2012-05-24 01:39:02 +02:00
|
|
|
#define STATIC_SUBR
|
|
|
|
#include "gbx_subr_common.h"
|
2012-05-24 02:31:57 +02:00
|
|
|
|