📄 si_instr.c
字号:
/*
* Copyright (C) Ericsson Mobile Communications AB, 2000.
* Licensed to AU-System AB.
* All rights reserved.
*
* This software is covered by the license agreement between
* the end user and AU-System AB, and may be used and copied
* only in accordance with the terms of the said agreement.
*
* Neither Ericsson Mobile Communications AB nor AU-System AB
* assumes any responsibility or liability for any errors or inaccuracies in
* this software, or any consequential, incidental or indirect damage arising
* out of the use of the Generic WAP Client software.
*/
#include "si_instr.h"
#include "si_frame.h"
#include "si_libs.h"
#include "url.h"
typedef struct {
enumErrorCode (*func)( BYTE, pstructSI ); /* pointer to a function */
UINT16 timeCost;
} structInstr_S;
typedef struct {
enumErrorCode (*func)( pstructSI );
UINT16 timeCost;
} structInstr;
/* Global instruction arrays */
const structInstr_S array1XXPPPPP[4] =
{
{ Exec_JUMP_FW_S, 1},
{ Exec_JUMP_BW_S, 1},
{ Exec_TJUMP_FW_S, 1},
{ Exec_LOAD_VAR_S, 1}
};
const structInstr_S array010XPPPP[2] =
{
{ Exec_STORE_VAR_S, 1},
{ Exec_LOAD_CONST_S, 1}
};
const structInstr_S array011XXPPP[4] =
{
{ Exec_CALL_S, 1},
{ Exec_CALL_LIB_S, 1},
{ Exec_INCR_VAR_S, 1},
{ NULL, 0}
};
const structInstr array00XXXXXX[64] =
{
{ NULL, 0},
{ Exec_JUMP_FW, 1}, { Exec_JUMP_FW_W, 1}, { Exec_JUMP_BW, 1},
{ Exec_JUMP_BW_W, 1}, { Exec_TJUMP_FW, 1}, { Exec_TJUMP_FW_W, 1},
{ Exec_TJUMP_BW, 1}, { Exec_TJUMP_BW_W, 1}, { Exec_CALL, 1},
{ Exec_CALL_LIB, 1}, { Exec_CALL_LIB_W, 1}, { Exec_CALL_URL, 1},
{ Exec_CALL_URL_W, 1}, { Exec_LOAD_VAR, 1}, { Exec_STORE_VAR, 1},
{ Exec_INCR_VAR, 1}, { Exec_DECR_VAR, 1}, { Exec_LOAD_CONST, 1},
{ Exec_LOAD_CONST_W, 1},{ Exec_CONST_0, 1}, { Exec_CONST_1, 1},
{ Exec_CONST_M1, 1}, { Exec_CONST_ES, 1}, { Exec_CONST_INVALID, 1},
{ Exec_CONST_TRUE, 1}, { Exec_CONST_FALSE, 1}, { Exec_INCR, 1},
{ Exec_DECR, 1}, { Exec_ADD_ASG, 1}, { Exec_SUB_ASG, 1},
{ Exec_UMINUS, 1}, { Exec_ADD, 1}, { Exec_SUB, 1},
{ Exec_MUL, 1}, { Exec_DIV, 1}, { Exec_IDIV, 1},
{ Exec_REM, 1}, { Exec_B_AND, 1}, { Exec_B_OR, 1},
{ Exec_B_XOR, 1}, { Exec_B_NOT, 1}, { Exec_B_LSHIFT, 1},
{ Exec_B_RSSHIFT, 1}, { Exec_B_RSZSHIFT, 1}, { Exec_EQ, 1},
{ Exec_LE, 1}, { Exec_LT, 1}, { Exec_GE, 1},
{ Exec_GT, 1}, { Exec_NE, 1}, { Exec_NOT, 1},
{ Exec_SCAND, 1}, { Exec_SCOR, 1}, { Exec_TOBOOL, 1},
{ Exec_POP, 1}, { Exec_TYPEOF, 1}, { Exec_ISVALID, 1},
{ Exec_RETURN, 1}, { Exec_RETURN_ES, 1}, { Exec_DEBUG, 1},
{ NULL, 0}, { NULL, 0}, { NULL, 0}
};
enumErrorCode ExecBytecodeInstr( BYTE instr, pstructSI si )
{
UINT8 arrayIndex;
if ((instr != 0) && (si != NULL))
{
if ( (instr & 0x80) == 0x80 )
{
arrayIndex = (instr & 0x60) >> 5;
si->currTime += array1XXPPPPP[ arrayIndex ].timeCost;
if (array1XXPPPPP[ arrayIndex ].func != NULL)
{
return (array1XXPPPPP[ arrayIndex ].func)( instr, si );
}
else
{
return ERR_WAE_WMLS_VERIFICATION;
}
}
else if ( (instr & 0xE0) == 0x40 )
{
arrayIndex = (instr & 0x10) >> 4;
si->currTime += array010XPPPP[ arrayIndex ].timeCost;
if (array010XPPPP[ arrayIndex ].func != NULL)
{
return (array010XPPPP[ arrayIndex ].func)( instr, si );
}
else
{
return ERR_WAE_WMLS_VERIFICATION;
}
}
else if ( (instr & 0xE0) == 0x60 )
{
arrayIndex = (instr & 0x18) >> 3;
si->currTime += array011XXPPP[ arrayIndex ].timeCost;
if (array011XXPPP[ arrayIndex ].func != NULL)
{
return (array011XXPPP[ arrayIndex ].func)( instr, si );
}
else
{
return ERR_WAE_WMLS_VERIFICATION;
}
}
else if ( (instr & 0xC0) == 0x00 )
{
arrayIndex = instr & 0x3F;
si->currTime += array00XXXXXX[ arrayIndex ].timeCost;
if (array00XXXXXX[ arrayIndex ].func != NULL)
{
return (array00XXXXXX[ arrayIndex ].func)( si );
}
else
{
return ERR_WAE_WMLS_VERIFICATION;
}
}
else
{
return ERR_WAE_WMLS_VERIFICATION;
}
}
return ERR_WAE_WMLS_NULL;
}
/* Control flow instructions ***********************************************************/
enumErrorCode Exec_JUMP_FW_S( BYTE instr, pstructSI si )
{
UINT8 offset;
offset = Read5bFrom8b( instr );
if ( RE_Jump( si->RE, offset ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
enumErrorCode Exec_JUMP_FW( pstructSI si )
{
UINT8 offset;
if ( RE_Read8bOperand( si->RE, &offset ) &&
RE_Jump( si->RE, offset ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
return ERR_WAE_WMLS_VERIFICATION;
}
enumErrorCode Exec_JUMP_FW_W( pstructSI si )
{
UINT16 offset;
if ( RE_Read16bOperand( si->RE, &offset ) &&
RE_Jump( si->RE, offset ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
return ERR_WAE_WMLS_VERIFICATION;
}
enumErrorCode Exec_JUMP_BW_S( BYTE instr, pstructSI si )
{
UINT8 offset;
offset = Read5bFrom8b( instr );
if ( RE_Jump( si->RE, -((INT32)offset)-1 ) ) {
/* at the given offset from the address of this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
enumErrorCode Exec_JUMP_BW( pstructSI si )
{
UINT8 offset;
if ( RE_Read8bOperand( si->RE, &offset ) &&
RE_Jump( si->RE, -((INT32)offset)-2 ) ) {
/* at the given offset from the address of this instruction */
return ERR_WAE_WMLS_NONE;
}
return ERR_WAE_WMLS_VERIFICATION;
}
enumErrorCode Exec_JUMP_BW_W( pstructSI si )
{
UINT16 offset;
if ( RE_Read16bOperand( si->RE, &offset ) &&
RE_Jump( si->RE, -((INT32)offset)-3 ) ) {
/* at the given offset from the address of this instruction */
return ERR_WAE_WMLS_NONE;
}
return ERR_WAE_WMLS_VERIFICATION;
}
enumErrorCode Exec_TJUMP_FW_S( BYTE instr, pstructSI si )
{
UINT8 offset;
BOOL makeJump = TRUE;
pstructVar op1;
offset = Read5bFrom8b( instr );
op1 = RE_Pop( si->RE );
if (op1 == NULL)
return ERR_WAE_WMLS_STACK_UNDERFLOW;
if (Var_ConvertMethod( CONVERT_BOOLS, op1, NULL )) {
makeJump = ! (op1->val.theInt); /* theInt is also the placeholder of the bool value */
/* only jump on false or invalid */
}
/* if convert failed it is treated as invalid which leads to a jump */
Var_Delete( &op1 ); /* op1 is no longer needed */
if (makeJump) {
if ( RE_Jump( si->RE, offset ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
else {
return ERR_WAE_WMLS_NONE;
}
}
enumErrorCode Exec_TJUMP_FW( pstructSI si )
{
UINT8 offset;
BOOL makeJump = TRUE;
pstructVar op1;
if ( ! RE_Read8bOperand( si->RE, &offset )) {
return ERR_WAE_WMLS_VERIFICATION;
}
op1 = RE_Pop( si->RE );
if (op1 == NULL)
return ERR_WAE_WMLS_STACK_UNDERFLOW;
if (Var_ConvertMethod( CONVERT_BOOLS, op1, NULL )) {
makeJump = ! (op1->val.theInt); /* theInt is also the placeholder of the bool value */
/* only jump on false or invalid */
}
/* if convert failed it is treated as invalid which leads to a jump */
Var_Delete( &op1 ); /* op1 is no longer needed */
if (makeJump) {
if ( RE_Jump( si->RE, offset ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
else {
return ERR_WAE_WMLS_NONE;
}
}
enumErrorCode Exec_TJUMP_FW_W( pstructSI si )
{
UINT16 offset;
BOOL makeJump = TRUE;
pstructVar op1;
if ( ! RE_Read16bOperand( si->RE, &offset )) {
return ERR_WAE_WMLS_VERIFICATION;
}
op1 = RE_Pop( si->RE );
if (op1 == NULL)
return ERR_WAE_WMLS_STACK_UNDERFLOW;
if (Var_ConvertMethod( CONVERT_BOOLS, op1, NULL )) {
makeJump = ! (op1->val.theInt); /* theInt is also the placeholder of the bool value */
/* only jump on false or invalid */
}
/* if convert failed it is treated as invalid which leads to a jump */
Var_Delete( &op1 ); /* op1 is no longer needed */
if (makeJump) {
if ( RE_Jump( si->RE, offset ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
else {
return ERR_WAE_WMLS_NONE;
}
}
enumErrorCode Exec_TJUMP_BW( pstructSI si )
{
UINT8 offset;
BOOL makeJump = TRUE;
pstructVar op1;
if ( ! RE_Read8bOperand( si->RE, &offset )) {
return ERR_WAE_WMLS_VERIFICATION;
}
op1 = RE_Pop( si->RE );
if (op1 == NULL)
return ERR_WAE_WMLS_STACK_UNDERFLOW;
if (Var_ConvertMethod( CONVERT_BOOLS, op1, NULL )) {
makeJump = ! (op1->val.theInt); /* theInt is also the placeholder of the bool value */
/* only jump on false or invalid */
}
/* if convert failed it is treated as invalid which leads to a jump */
Var_Delete( &op1 ); /* op1 is no longer needed */
if (makeJump) {
if ( RE_Jump( si->RE, -((INT32)offset)-2 ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
else {
return ERR_WAE_WMLS_NONE;
}
}
enumErrorCode Exec_TJUMP_BW_W( pstructSI si )
{
UINT16 offset;
BOOL makeJump = TRUE;
pstructVar op1;
if ( ! RE_Read16bOperand( si->RE, &offset )) {
return ERR_WAE_WMLS_VERIFICATION;
}
op1 = RE_Pop( si->RE );
if (op1 == NULL) {
Var_Delete( &op1 );
return ERR_WAE_WMLS_STACK_UNDERFLOW;
}
if (Var_ConvertMethod( CONVERT_BOOLS, op1, NULL )) {
makeJump = ! (op1->val.theInt); /* theInt is also the placeholder of the bool value */
/* only jump on false or invalid */
}
/* if convert failed it is treated as invalid which leads to a jump */
Var_Delete( &op1 ); /* op1 is no longer needed */
if (makeJump) {
if ( RE_Jump( si->RE, -((INT32)offset)-3 ) ) {
/* at the given offset from the address of the
first byte following this instruction */
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
else {
return ERR_WAE_WMLS_NONE;
}
}
/* Function call instructions ******************************************************************/
enumErrorCode Exec_CALL_S( BYTE instr, pstructSI si )
/*
CORRECTION 990226 (KHN)
=======================
Added so that a local function call makes sure to
report the stack underflow error. This happens if
there are less operands on the stack than the function
has as number of arguments.
*/
{
UINT8 findex = 0;
findex = Read3bFrom8b( instr );
if (findex < si->RE->BPI->nbrOfFunctions) {
/* valid function index */
/* set the return IP*/
FS_Push( si->RE->FS, &(si->RE->currF), si->RE->IP );
si->RE->currF = Frame_New( findex, si->RE->BPI, si->RE->OpS );
if (si->RE->currF == NULL)
{ /* not enough operands on the OpS to match number of function arguments */
return ERR_WAE_WMLS_STACK_UNDERFLOW;
}
/* set the IP so the next instruction to be executed will be in the new function */
si->RE->IP = si->RE->BPI->functions[ findex ].startPos;
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
enumErrorCode Exec_CALL( pstructSI si )
/*
CORRECTION 990226 (KHN)
=======================
Added so that a local function call makes sure to
report the stack underflow error. This happens if
there are less operands on the stack than the function
has as number of arguments.
*/
{
UINT8 findex = 0;
if ( ! RE_Read8bOperand( si->RE, &findex )) {
return ERR_WAE_WMLS_VERIFICATION;
}
if (findex < si->RE->BPI->nbrOfFunctions) {
/* valid function index */
FS_Push( si->RE->FS, &(si->RE->currF), si->RE->IP );
si->RE->currF = Frame_New( findex, si->RE->BPI, si->RE->OpS );
/* set the IP so the next instruction to be executed will be in the new function */
si->RE->IP = si->RE->BPI->functions[ findex ].startPos;
if (si->RE->currF == NULL)
{ /* not enough operands on the OpS to match number of function arguments */
return ERR_WAE_WMLS_STACK_UNDERFLOW;
}
return ERR_WAE_WMLS_NONE;
}
else {
return ERR_WAE_WMLS_VERIFICATION;
}
}
enumErrorCode Exec_CALL_LIB_S( BYTE instr, pstructSI si )
{
UINT8 findex = 0,
lindex = 0;
findex = Read3bFrom8b( instr );
if ( ! RE_Read8bOperand( si->RE, &lindex )) {
return ERR_WAE_WMLS_VERIFICATION;
}
return CallLibraryFunction( si, lindex, findex );
}
enumErrorCode Exec_CALL_LIB( pstructSI si )
{
UINT8 findex = 0;
UINT8 lindex = 0;
if ( ! RE_Read8bOperand( si->RE, &findex )) {
return ERR_WAE_WMLS_VERIFICATION;
}
if ( ! RE_Read8bOperand( si->RE, &lindex )) {
return ERR_WAE_WMLS_VERIFICATION;
}
return CallLibraryFunction( si, lindex, findex );
}
enumErrorCode Exec_CALL_LIB_W( pstructSI si )
{
UINT8 findex = 0;
UINT16 lindex = 0;
if ( ! RE_Read8bOperand( si->RE, &findex )) {
return ERR_WAE_WMLS_VERIFICATION;
}
if ( ! RE_Read16bOperand( si->RE, &lindex )) {
return ERR_WAE_WMLS_VERIFICATION;
}
return CallLibraryFunction( si, lindex, findex );
}
enumErrorCode Exec_CALL_URL( pstructSI si )
{
UINT8 cindexURL = 0;
UINT8 cindexFUNC = 0;
UINT8 nbrOfArgs = 0;
pstructVar url = NULL;
WCHAR* resolvedUrl = NULL;
BYTE* utf8_funcName = NULL;
enumConstType constType;
enumErrorCode error = ERR_WAE_WMLS_VERIFICATION;
if ( ! RE_Read8bOperand( si->RE, &cindexURL )) {
return ERR_WAE_WMLS_VERIFICATION;
}
if ( ! RE_Read8bOperand( si->RE, &cindexFUNC )) {
return ERR_WAE_WMLS_VERIFICATION;
}
if ( ! RE_Read8bOperand( si->RE, &nbrOfArgs )) {
return ERR_WAE_WMLS_VERIFICATION;
}
if (BPI_GetConstantType( si->RE->BPI, cindexURL, &constType ))
{
utf8_funcName = BPI_GetRawUTF8Constant( si->RE->BPI, si->RE->BP, si->RE->BPend, cindexFUNC );
if ((constType >= CONST_TYPE_UTF8) && (constType <= CONST_TYPE_EXT_CHARSET) && (utf8_funcName != NULL) )
{
url = BPI_GetConstant( si->RE->BPI, si->RE->BP, si->RE->BPend, cindexURL );
if (url != NULL)
{
if (w_Resolve (si->baseURL, url->val.theString, &resolvedUrl))
{
si->returnInfo = SI_RETURN_EXTERNAL;
if ( SI_NewReturnParams( si ) )
{
/* the SIs returnparams struct is to be filled in */
si->returnParams->islibCall = FALSE;
si->returnParams->bpUrl = resolvedUrl;
resolvedUrl = NULL;
si->returnParams->funcName = utf8_funcName;
utf8_funcName = NULL;
si->returnParams->argOpS = OpS_NewFromOpS( si->RE->OpS, nbrOfArgs );
if (si->returnParams->argOpS != NULL)
{
error = ERR_WAE_WMLS_NONE;
}
else
{
error = ERR_WAE_WMLS_STACK_UNDERFLOW;
}
}
}
/* else ERR_WAE_WMLS_VERIFICATION (the init value of error) */
}
}
}
DEALLOC( &resolvedUrl );
Var_Delete( &url );
DEALLOC( &utf8_funcName );
return error;
}
enumErrorCode Exec_CALL_URL_W( pstructSI si )
{
UINT16 cindexURL = 0;
UINT16 cindexFUNC = 0;
UINT8 nbrOfArgs = 0;
pstructVar url = NULL;
WCHAR* resolvedUrl = NULL;
BYTE* utf8_funcName = NULL;
enumConstType constType;
enumErrorCode error = ERR_WAE_WMLS_VERIFICATION;
if ( ! RE_Read16bOperand( si->RE, &cindexURL )) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -