From 0d7efa0ee3bf944b152935d9659b7af741d24f1f Mon Sep 17 00:00:00 2001 From: Kensuke Matsuzaki Date: Sat, 21 Oct 2023 00:33:57 +0900 Subject: [PATCH 1/5] =?UTF-8?q?float=E3=81=A8int64=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- makefile | 6 + makefile.emscripten | 4 + src/hsp3/hspvar_core.cpp | 5 + src/hsp3/hspvar_core.h | 6 +- src/hsp3/hspvar_double.cpp | 6 + src/hsp3/hspvar_float.cpp | 266 +++++++++++++++++++++++++++++ src/hsp3/hspvar_int.cpp | 6 + src/hsp3/hspvar_int64.cpp | 266 +++++++++++++++++++++++++++++ src/hsp3/hspvar_str.cpp | 10 ++ test/test_hspvars/Makefile | 3 + test/test_hspvars/test_hspvars.hsp | 38 +++++ 11 files changed, 614 insertions(+), 2 deletions(-) create mode 100644 src/hsp3/hspvar_float.cpp create mode 100644 src/hsp3/hspvar_int64.cpp create mode 100644 test/test_hspvars/Makefile create mode 100644 test/test_hspvars/test_hspvars.hsp diff --git a/makefile b/makefile index d27f7e47..0bc1daf8 100644 --- a/makefile +++ b/makefile @@ -27,6 +27,8 @@ OBJS = \ src/hsp3/hspvar_label.do \ src/hsp3/hspvar_str.do \ src/hsp3/hspvar_struct.do \ + src/hsp3/hspvar_float.do \ + src/hsp3/hspvar_int64.do \ src/hsp3dish/hspwnd_dish.do \ src/hsp3dish/hspwnd_obj.do \ src/hsp3dish/hspwnd_edit.do \ @@ -87,6 +89,8 @@ OBJS_CL = \ src/hsp3/hspvar_label.o \ src/hsp3/hspvar_str.o \ src/hsp3/hspvar_struct.o \ + src/hsp3/hspvar_float.o \ + src/hsp3/hspvar_int64.o \ src/hsp3/stack.o \ src/hsp3/strbuf.o \ src/hsp3/strnote.o \ @@ -119,6 +123,8 @@ OBJS_GP = \ src/hsp3/hspvar_label.gpo \ src/hsp3/hspvar_str.gpo \ src/hsp3/hspvar_struct.gpo \ + src/hsp3/hspvar_float.gpo \ + src/hsp3/hspvar_int64.gpo \ src/hsp3dish/hspwnd_dish.gpo \ src/hsp3dish/hspwnd_obj.gpo \ src/hsp3dish/hspwnd_edit.gpo \ diff --git a/makefile.emscripten b/makefile.emscripten index dfd7ce27..23977985 100644 --- a/makefile.emscripten +++ b/makefile.emscripten @@ -55,6 +55,8 @@ OBJS = \ src/hsp3/hspvar_label.js.o \ src/hsp3/hspvar_str.js.o \ src/hsp3/hspvar_struct.js.o \ + src/hsp3/hspvar_float.js.o \ + src/hsp3/hspvar_int64.js.o \ src/hsp3dish/hspwnd_dish.js.o \ src/hsp3dish/hspwnd_obj.js.o \ src/hsp3dish/hspwnd_edit.js.o \ @@ -98,6 +100,8 @@ OBJS_GP = \ src/hsp3/hspvar_label.g.o \ src/hsp3/hspvar_str.g.o \ src/hsp3/hspvar_struct.g.o \ + src/hsp3/hspvar_float.g.o \ + src/hsp3/hspvar_int64.g.o \ src/hsp3dish/hspwnd_dish.g.o \ src/hsp3dish/hspwnd_obj.g.o \ src/hsp3dish/hspwnd_edit.g.o \ diff --git a/src/hsp3/hspvar_core.cpp b/src/hsp3/hspvar_core.cpp index db072d3e..d9966e25 100644 --- a/src/hsp3/hspvar_core.cpp +++ b/src/hsp3/hspvar_core.cpp @@ -23,6 +23,8 @@ extern void HspVarInt_Init( HspVarProc *p ); extern void HspVarStr_Init( HspVarProc *p ); extern void HspVarDouble_Init( HspVarProc *p ); extern void HspVarStruct_Init( HspVarProc *p ); +extern void HspVarInt64_Init( HspVarProc *p ); +extern void HspVarFloat_Init( HspVarProc *p ); /*------------------------------------------------------------*/ /* @@ -85,6 +87,9 @@ void HspVarCoreResetVartype( int expand ) HspVarCoreRegisterType( HSPVAR_FLAG_DOUBLE, (HSPVAR_COREFUNC)HspVarDouble_Init ); HspVarCoreRegisterType( HSPVAR_FLAG_STRUCT, (HSPVAR_COREFUNC)HspVarStruct_Init ); HspVarCoreRegisterType( HSPVAR_FLAG_LABEL, (HSPVAR_COREFUNC)HspVarLabel_Init ); // ラベル型(3.1) + // 追加型 + HspVarCoreRegisterType( HSPVAR_FLAG_INT64, (HSPVAR_COREFUNC)HspVarInt64_Init ); + HspVarCoreRegisterType( HSPVAR_FLAG_FLOAT, (HSPVAR_COREFUNC)HspVarFloat_Init ); } diff --git a/src/hsp3/hspvar_core.h b/src/hsp3/hspvar_core.h index cf240f66..1eeaf901 100644 --- a/src/hsp3/hspvar_core.h +++ b/src/hsp3/hspvar_core.h @@ -15,8 +15,10 @@ // 7はVARIANTで予約済み -#define HSPVAR_FLAG_USERDEF 8 -#define HSPVAR_FLAG_MAX 8 +#define HSPVAR_FLAG_INT64 8 +#define HSPVAR_FLAG_FLOAT 9 +#define HSPVAR_FLAG_USERDEF 10 +#define HSPVAR_FLAG_MAX 10 #define HSPVAR_MODE_NONE -1 #define HSPVAR_MODE_MALLOC 1 diff --git a/src/hsp3/hspvar_double.cpp b/src/hsp3/hspvar_double.cpp index 50c6ca69..3e25be44 100644 --- a/src/hsp3/hspvar_double.cpp +++ b/src/hsp3/hspvar_double.cpp @@ -41,6 +41,12 @@ static void *HspVarDouble_Cnv( const void *buffer, int flag ) case HSPVAR_FLAG_INT: conv = (double)( *(int *)buffer ); return &conv; + case HSPVAR_FLAG_INT64: + conv = (double)( *(int64_t *)buffer ); + return &conv; + case HSPVAR_FLAG_FLOAT: + conv = (double)( *(float *)buffer ); + return &conv; case HSPVAR_FLAG_DOUBLE: break; default: diff --git a/src/hsp3/hspvar_float.cpp b/src/hsp3/hspvar_float.cpp new file mode 100644 index 00000000..1fbb8cb2 --- /dev/null +++ b/src/hsp3/hspvar_float.cpp @@ -0,0 +1,266 @@ + +// +// HSPVAR core module +// onion software/onitama 2003/4 +// +#include +#include +#include +#include +#include "hspvar_core.h" +#include "hsp3debug.h" +#include "strbuf.h" + +/*------------------------------------------------------------*/ +/* + HSPVAR core interface (float) +*/ +/*------------------------------------------------------------*/ + +#define GetPtr(pval) ((float *)pval) + +static float conv; +static short *aftertype; + +// Core +static PDAT *HspVarFloat_GetPtr( PVal *pval ) +{ + return (PDAT *)(( (float *)(pval->pt))+pval->offset); +} + +static void *HspVarFloat_Cnv( const void *buffer, int flag ) +{ + // リクエストされた型 -> 自分の型への変換を行なう + // (組み込み型にのみ対応でOK) + // (参照元のデータを破壊しないこと) + // + switch( flag ) { + case HSPVAR_FLAG_STR: + conv = (float)atof( (char *)buffer ); + return &conv; + case HSPVAR_FLAG_INT: + conv = (float)( *(int *)buffer ); + return &conv; + case HSPVAR_FLAG_DOUBLE: + conv = (float)( *(double *)buffer ); + break; + case HSPVAR_FLAG_INT64: + conv = (float)( *(int64_t *)buffer ); + return &conv; + case HSPVAR_FLAG_FLOAT: + break; + default: + throw HSPVAR_ERROR_TYPEMISS; + } + return (void *)buffer; +} + +/* +static void *HspVarFloat_CnvCustom( const void *buffer, int flag ) +{ + // (カスタムタイプのみ) + // 自分の型 -> リクエストされた型 への変換を行なう + // (組み込み型に対応させる) + // (参照元のデータを破壊しないこと) + // + return buffer; +} +*/ + +static int GetVarSize( PVal *pval ) +{ + // PVALポインタの変数が必要とするサイズを取得する + // (sizeフィールドに設定される) + // + return HspVarCoreCountElems(pval) * sizeof(float); +} + + +static void HspVarFloat_Free( PVal *pval ) +{ + // PVALポインタの変数メモリを解放する + // + if ( pval->mode == HSPVAR_MODE_MALLOC ) { sbFree( pval->pt ); } + pval->pt = NULL; + pval->mode = HSPVAR_MODE_NONE; +} + + +static void HspVarFloat_Alloc( PVal *pval, const PVal *pval2 ) +{ + HspVarCoreAllocPODArray(pval, pval2, sizeof(float)); +} + +/* +static void *HspVarFloat_ArrayObject( PVal *pval, int *mptype ) +{ + // 配列要素の指定 (文字列/連想配列用) + // + throw HSPERR_UNSUPPORTED_FUNCTION; + return NULL; +} +*/ + +// Size +static int HspVarFloat_GetSize( const PDAT *pval ) +{ + return sizeof(float); +} + +// Set +static void HspVarFloat_Set( PVal *pval, PDAT *pdat, const void *in ) +{ + //*GetPtr(pdat) = *((float *)(in)); + memcpy(pdat, in, sizeof(float)); +} + +// Add +static void HspVarFloat_AddI( PDAT *pval, const void *val ) +{ + *GetPtr(pval) += *((float *)(val)); + *aftertype = HSPVAR_FLAG_FLOAT; +} + +// Sub +static void HspVarFloat_SubI( PDAT *pval, const void *val ) +{ + *GetPtr(pval) -= *((float *)(val)); + *aftertype = HSPVAR_FLAG_FLOAT; +} + +// Mul +static void HspVarFloat_MulI( PDAT *pval, const void *val ) +{ + *GetPtr(pval) *= *((float *)(val)); + *aftertype = HSPVAR_FLAG_FLOAT; +} + +// Div +static void HspVarFloat_DivI( PDAT *pval, const void *val ) +{ + float p = *((float *)(val)); + if ( p == 0.0 ) throw( HSPVAR_ERROR_DIVZERO ); + *GetPtr(pval) /= p; + *aftertype = HSPVAR_FLAG_FLOAT; +} + +// Mod +static void HspVarFloat_ModI( PDAT *pval, const void *val ) +{ + float p = *((float *)(val)); + float dval; + if ( p == 0.0 ) throw( HSPVAR_ERROR_DIVZERO ); + dval = *GetPtr(pval); + *GetPtr(pval) = fmod( dval, p ); + *aftertype = HSPVAR_FLAG_FLOAT; +} + + +// Eq +static void HspVarFloat_EqI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) == *((float *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// Ne +static void HspVarFloat_NeI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) != *((float *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// Gt +static void HspVarFloat_GtI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) > *((float *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// Lt +static void HspVarFloat_LtI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) < *((float *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// GtEq +static void HspVarFloat_GtEqI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) >= *((float *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// LtEq +static void HspVarFloat_LtEqI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) <= *((float *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +/* +// INVALID +static void HspVarFloat_Invalid( PDAT *pval, const void *val ) +{ + throw( HSPVAR_ERROR_INVALID ); +} +*/ + +static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size ) +{ + *size = pval->size - ( ((char *)pdat) - pval->pt ); + return (pdat); +} + +static void AllocBlock( PVal *pval, PDAT *pdat, int size ) +{ +} + + +/*------------------------------------------------------------*/ + +void HspVarFloat_Init( HspVarProc *p ) +{ + aftertype = &p->aftertype; + + p->Set = HspVarFloat_Set; + p->Cnv = HspVarFloat_Cnv; + p->GetPtr = HspVarFloat_GetPtr; +// p->CnvCustom = HspVarFloat_CnvCustom; + p->GetSize = HspVarFloat_GetSize; + p->GetBlockSize = GetBlockSize; + p->AllocBlock = AllocBlock; + +// p->ArrayObject = HspVarFloat_ArrayObject; + p->Alloc = HspVarFloat_Alloc; + p->Free = HspVarFloat_Free; + + p->AddI = HspVarFloat_AddI; + p->SubI = HspVarFloat_SubI; + p->MulI = HspVarFloat_MulI; + p->DivI = HspVarFloat_DivI; + p->ModI = HspVarFloat_ModI; + +// p->AndI = HspVarFloat_Invalid; +// p->OrI = HspVarFloat_Invalid; +// p->XorI = HspVarFloat_Invalid; + + p->EqI = HspVarFloat_EqI; + p->NeI = HspVarFloat_NeI; + p->GtI = HspVarFloat_GtI; + p->LtI = HspVarFloat_LtI; + p->GtEqI = HspVarFloat_GtEqI; + p->LtEqI = HspVarFloat_LtEqI; + +// p->RrI = HspVarFloat_Invalid; +// p->LrI = HspVarFloat_Invalid; + + p->vartype_name = "float"; // タイプ名 + p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0) + p->support = HSPVAR_SUPPORT_STORAGE|HSPVAR_SUPPORT_FLEXARRAY; + // サポート状況フラグ(HSPVAR_SUPPORT_*) + p->basesize = sizeof(float); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1 +} + +/*------------------------------------------------------------*/ + diff --git a/src/hsp3/hspvar_int.cpp b/src/hsp3/hspvar_int.cpp index c75db475..239d911e 100644 --- a/src/hsp3/hspvar_int.cpp +++ b/src/hsp3/hspvar_int.cpp @@ -50,6 +50,12 @@ static void *HspVarInt_Cnv( const void *buffer, int flag ) case HSPVAR_FLAG_DOUBLE: conv = (int)( *(double *)buffer ); return &conv; + case HSPVAR_FLAG_INT64: + conv = (int)( *(int64_t *)buffer ); + return &conv; + case HSPVAR_FLAG_FLOAT: + conv = (int)( *(float *)buffer ); + return &conv; default: throw HSPVAR_ERROR_TYPEMISS; } diff --git a/src/hsp3/hspvar_int64.cpp b/src/hsp3/hspvar_int64.cpp new file mode 100644 index 00000000..a57aa09f --- /dev/null +++ b/src/hsp3/hspvar_int64.cpp @@ -0,0 +1,266 @@ + +// +// HSPVAR core module +// onion software/onitama 2003/4 +// +#include +#include +#include +#include +#include "hspvar_core.h" +#include "hsp3debug.h" +#include "strbuf.h" + +/*------------------------------------------------------------*/ +/* + HSPVAR core interface (int64_t) +*/ +/*------------------------------------------------------------*/ + +#define GetPtr(pval) ((int64_t *)pval) + +static int64_t conv; +static short *aftertype; + +// Core +static PDAT *HspVarInt64_GetPtr( PVal *pval ) +{ + return (PDAT *)(( (int64_t *)(pval->pt))+pval->offset); +} + +static void *HspVarInt64_Cnv( const void *buffer, int flag ) +{ + // リクエストされた型 -> 自分の型への変換を行なう + // (組み込み型にのみ対応でOK) + // (参照元のデータを破壊しないこと) + // + switch( flag ) { + case HSPVAR_FLAG_STR: + conv = (int64_t)atof( (char *)buffer ); + return &conv; + case HSPVAR_FLAG_INT: + conv = (int64_t)( *(int *)buffer ); + return &conv; + case HSPVAR_FLAG_DOUBLE: + conv = (int64_t)( *(double *)buffer ); + break; + case HSPVAR_FLAG_FLOAT: + conv = (int64_t)( *(float *)buffer ); + break; + case HSPVAR_FLAG_INT64: + break; + default: + throw HSPVAR_ERROR_TYPEMISS; + } + return (void *)buffer; +} + +/* +static void *HspVarInt64_CnvCustom( const void *buffer, int flag ) +{ + // (カスタムタイプのみ) + // 自分の型 -> リクエストされた型 への変換を行なう + // (組み込み型に対応させる) + // (参照元のデータを破壊しないこと) + // + return buffer; +} +*/ + +static int GetVarSize( PVal *pval ) +{ + // PVALポインタの変数が必要とするサイズを取得する + // (sizeフィールドに設定される) + // + return HspVarCoreCountElems(pval) * sizeof(int64_t); +} + + +static void HspVarInt64_Free( PVal *pval ) +{ + // PVALポインタの変数メモリを解放する + // + if ( pval->mode == HSPVAR_MODE_MALLOC ) { sbFree( pval->pt ); } + pval->pt = NULL; + pval->mode = HSPVAR_MODE_NONE; +} + + +static void HspVarInt64_Alloc( PVal *pval, const PVal *pval2 ) +{ + HspVarCoreAllocPODArray(pval, pval2, sizeof(int64_t)); +} + +/* +static void *HspVarInt64_ArrayObject( PVal *pval, int *mptype ) +{ + // 配列要素の指定 (文字列/連想配列用) + // + throw HSPERR_UNSUPPORTED_FUNCTION; + return NULL; +} +*/ + +// Size +static int HspVarInt64_GetSize( const PDAT *pval ) +{ + return sizeof(int64_t); +} + +// Set +static void HspVarInt64_Set( PVal *pval, PDAT *pdat, const void *in ) +{ + //*GetPtr(pdat) = *((int64_t *)(in)); + memcpy(pdat, in, sizeof(int64_t)); +} + +// Add +static void HspVarInt64_AddI( PDAT *pval, const void *val ) +{ + *GetPtr(pval) += *((int64_t *)(val)); + *aftertype = HSPVAR_FLAG_INT64; +} + +// Sub +static void HspVarInt64_SubI( PDAT *pval, const void *val ) +{ + *GetPtr(pval) -= *((int64_t *)(val)); + *aftertype = HSPVAR_FLAG_INT64; +} + +// Mul +static void HspVarInt64_MulI( PDAT *pval, const void *val ) +{ + *GetPtr(pval) *= *((int64_t *)(val)); + *aftertype = HSPVAR_FLAG_INT64; +} + +// Div +static void HspVarInt64_DivI( PDAT *pval, const void *val ) +{ + int64_t p = *((int64_t *)(val)); + if ( p == 0.0 ) throw( HSPVAR_ERROR_DIVZERO ); + *GetPtr(pval) /= p; + *aftertype = HSPVAR_FLAG_INT64; +} + +// Mod +static void HspVarInt64_ModI( PDAT *pval, const void *val ) +{ + int64_t p = *((int64_t *)(val)); + int64_t dval; + if ( p == 0.0 ) throw( HSPVAR_ERROR_DIVZERO ); + dval = *GetPtr(pval); + *GetPtr(pval) = fmod( dval, p ); + *aftertype = HSPVAR_FLAG_INT64; +} + + +// Eq +static void HspVarInt64_EqI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) == *((int64_t *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// Ne +static void HspVarInt64_NeI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) != *((int64_t *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// Gt +static void HspVarInt64_GtI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) > *((int64_t *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// Lt +static void HspVarInt64_LtI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) < *((int64_t *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// GtEq +static void HspVarInt64_GtEqI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) >= *((int64_t *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +// LtEq +static void HspVarInt64_LtEqI( PDAT *pval, const void *val ) +{ + *((int *)pval) = ( *GetPtr(pval) <= *((int64_t *)(val)) ); + *aftertype = HSPVAR_FLAG_INT; +} + +/* +// INVALID +static void HspVarInt64_Invalid( PDAT *pval, const void *val ) +{ + throw( HSPVAR_ERROR_INVALID ); +} +*/ + +static void *GetBlockSize( PVal *pval, PDAT *pdat, int *size ) +{ + *size = pval->size - ( ((char *)pdat) - pval->pt ); + return (pdat); +} + +static void AllocBlock( PVal *pval, PDAT *pdat, int size ) +{ +} + + +/*------------------------------------------------------------*/ + +void HspVarInt64_Init( HspVarProc *p ) +{ + aftertype = &p->aftertype; + + p->Set = HspVarInt64_Set; + p->Cnv = HspVarInt64_Cnv; + p->GetPtr = HspVarInt64_GetPtr; +// p->CnvCustom = HspVarInt64_CnvCustom; + p->GetSize = HspVarInt64_GetSize; + p->GetBlockSize = GetBlockSize; + p->AllocBlock = AllocBlock; + +// p->ArrayObject = HspVarInt64_ArrayObject; + p->Alloc = HspVarInt64_Alloc; + p->Free = HspVarInt64_Free; + + p->AddI = HspVarInt64_AddI; + p->SubI = HspVarInt64_SubI; + p->MulI = HspVarInt64_MulI; + p->DivI = HspVarInt64_DivI; + p->ModI = HspVarInt64_ModI; + +// p->AndI = HspVarInt64_Invalid; +// p->OrI = HspVarInt64_Invalid; +// p->XorI = HspVarInt64_Invalid; + + p->EqI = HspVarInt64_EqI; + p->NeI = HspVarInt64_NeI; + p->GtI = HspVarInt64_GtI; + p->LtI = HspVarInt64_LtI; + p->GtEqI = HspVarInt64_GtEqI; + p->LtEqI = HspVarInt64_LtEqI; + +// p->RrI = HspVarInt64_Invalid; +// p->LrI = HspVarInt64_Invalid; + + p->vartype_name = "int64"; // タイプ名 + p->version = 0x001; // 型タイプランタイムバージョン(0x100 = 1.0) + p->support = HSPVAR_SUPPORT_STORAGE|HSPVAR_SUPPORT_FLEXARRAY; + // サポート状況フラグ(HSPVAR_SUPPORT_*) + p->basesize = sizeof(int64_t); // 1つのデータが使用するサイズ(byte) / 可変長の時は-1 +} + +/*------------------------------------------------------------*/ + diff --git a/src/hsp3/hspvar_str.cpp b/src/hsp3/hspvar_str.cpp index ea18a151..5798322b 100644 --- a/src/hsp3/hspvar_str.cpp +++ b/src/hsp3/hspvar_str.cpp @@ -63,6 +63,16 @@ static void *HspVarStr_Cnv( const void *buffer, int flag ) //_gcvt( *(double *)buffer, 32, conv ); sprintf( conv,"%f", *(double *)buffer ); return conv; + case HSPVAR_FLAG_INT64: +#ifdef HSPWIN + _i64toa( *(int64_t *)buffer, conv, 10 ); +#else + sprintf( conv, "%ld", *(int64_t*)buffer); +#endif + return conv; + case HSPVAR_FLAG_FLOAT: + sprintf( conv,"%f", *(float *)buffer ); + return conv; default: throw HSPVAR_ERROR_TYPEMISS; } diff --git a/test/test_hspvars/Makefile b/test/test_hspvars/Makefile new file mode 100644 index 00000000..ca1ff717 --- /dev/null +++ b/test/test_hspvars/Makefile @@ -0,0 +1,3 @@ +TARGET := test_hspvars +PREFIX = ../ +include ../Makefile diff --git a/test/test_hspvars/test_hspvars.hsp b/test/test_hspvars/test_hspvars.hsp new file mode 100644 index 00000000..a02e1656 --- /dev/null +++ b/test/test_hspvars/test_hspvars.hsp @@ -0,0 +1,38 @@ +#include "hsp3cl.as" + + mes "int" + dimtype var_int32, vartype("int"), 1 + var_int32 += 2147483647 + mes var_int32 + repeat 10 + var_int32 *= 2 + mes str(cnt) + ":" + str(var_int32) + loop + + mes "int64" + dimtype var_int64, vartype("int64"), 1 + var_int64 += 2147483647 + mes var_int64 + repeat 10 + var_int64 *= 2 + mes str(cnt) + ":" + str(var_int64) + loop + + mes "double" + dimtype var_double, vartype("double"), 1 + var_double += 100000 + mes var_double + repeat 10 + var_double *= 10 + mes str(cnt) + ":" + str(var_double) + loop + + mes "float" + dimtype var_float, vartype("float"), 1 + mes var_float + var_float += 100000 + mes var_float + repeat 10 + var_float *= 10 + mes str(cnt) + ":" + str(var_float) + loop From 67f820a14470fc6cf2b024aa220bc00ff5f0d4a7 Mon Sep 17 00:00:00 2001 From: Kensuke Matsuzaki Date: Thu, 29 May 2025 23:48:13 +0900 Subject: [PATCH 2/5] =?UTF-8?q?64bit=E7=92=B0=E5=A2=83=E3=81=A7=E3=83=9D?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=BF=E3=82=92INT64=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- makefile | 2 +- src/hsp3/hsp3code.cpp | 45 +++++++++++++++++++++++++++++++++++++++ src/hsp3/hsp3code.h | 2 ++ src/hsp3/hsp3int.cpp | 13 +++++++++++ test/test_ptr/dupptr1.hsp | 8 +++++++ test/test_ptr/varptr1.hsp | 9 ++++++++ 6 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 test/test_ptr/dupptr1.hsp create mode 100644 test/test_ptr/varptr1.hsp diff --git a/makefile b/makefile index 0bc1daf8..c856ac10 100644 --- a/makefile +++ b/makefile @@ -3,7 +3,7 @@ CXX = g++ AR = ar # CFLAGS_ENV = # 32bit -CFLAGS_ENV = -DHSP64 # 64bit +CFLAGS_ENV = -DHSP64 -Werror=int-to-pointer-cast # 64bit CFLAGS_DISH = -Wno-write-strings --exec-charset=UTF-8 -DHSPDISH -DHSPLINUX -DHSPDEBUG -DUSE_OBAQ -DHSP_COM_UNSUPPORTED $(CFLAGS_ENV) CFLAGS_GP = -Wno-write-strings --exec-charset=UTF-8 -DHSPDISH -DHSPDISHGP -DHSPLINUX -DHSPDEBUG -DHSP_COM_UNSUPPORTED -DPNG_ARM_NEON_OPT=0 -I src/hsp3dish/extlib/src -I src/hsp3dish/extlib/src/glew -I src/hsp3dish/gameplay/src -std=c++11 $(CFLAGS_ENV) CFLAGS_CL = -Wno-write-strings -std=c++11 --exec-charset=UTF-8 -DHSPLINUX -DHSPDEBUG -DHSP_COM_UNSUPPORTED $(CFLAGS_ENV) diff --git a/src/hsp3/hsp3code.cpp b/src/hsp3/hsp3code.cpp index 6c475392..b5ec3349 100644 --- a/src/hsp3/hsp3code.cpp +++ b/src/hsp3/hsp3code.cpp @@ -983,6 +983,42 @@ int code_getdi( const int defval ) } +int64_t code_getl( void ) +{ + // 数値パラメーターを取得 + // + int chk; + chk = code_get(); + if ( chk<=PARAM_END ) { throw HSPERR_NO_DEFAULT; } + if ( mpval->flag != HSPVAR_FLAG_INT64 ) { + if ( mpval->flag == HSPVAR_FLAG_INT ) + return (int64_t)(*(int *)(mpval->pt)); + if ( mpval->flag == HSPVAR_FLAG_DOUBLE ) + return (int64_t)(*(double *)(mpval->pt)); + throw HSPERR_TYPE_MISMATCH; + } + return *(int64_t *)(mpval->pt); +} + + +int64_t code_getdl( const int64_t defval ) +{ + // 数値パラメーターを取得(デフォルト値あり) + // + int chk; + chk = code_get(); + if ( chk<=PARAM_END ) { return defval; } + if ( mpval->flag != HSPVAR_FLAG_INT64 ) { + if ( mpval->flag == HSPVAR_FLAG_INT ) + return (int64_t)(*(int *)(mpval->pt)); + if ( mpval->flag == HSPVAR_FLAG_DOUBLE ) + return (int64_t)(*(double *)(mpval->pt)); + throw HSPERR_TYPE_MISMATCH; + } + return *(int64_t *)(mpval->pt); +} + + double code_getd( void ) { // 数値(double)パラメーターを取得 @@ -2036,6 +2072,7 @@ static int cmdfunc_prog( int cmd ) // int p1,p2,p3,p4,p5; + int64_t lp1; code_next(); // 次のコードを取得(最初に必ず必要です) @@ -2237,13 +2274,21 @@ static int cmdfunc_prog( int cmd ) { PVal *pval_m; pval_m = code_getpval(); +#ifdef HSP64 + lp1 = code_getl(); +#else p1 = code_geti(); +#endif p2 = code_geti(); p3 = code_getdi( HSPVAR_FLAG_INT ); if ( p2<=0 ) throw HSPERR_ILLEGAL_FUNCTION; if ( HspVarCoreGetProc(p3)->flag == 0 ) throw HSPERR_ILLEGAL_FUNCTION; if (pval_m->support & HSPVAR_SUPPORT_FIXEDVALUE) throw HSPERR_FIXED_VARVALUE; +#ifdef HSP64 + HspVarCoreDupPtr( pval_m, p3, (void *)lp1, p2 ); +#else HspVarCoreDupPtr( pval_m, p3, (void *)p1, p2 ); +#endif break; } diff --git a/src/hsp3/hsp3code.h b/src/hsp3/hsp3code.h index e3b17430..31a773b8 100644 --- a/src/hsp3/hsp3code.h +++ b/src/hsp3/hsp3code.h @@ -41,6 +41,8 @@ char *code_getds( const char *defval ); char *code_getdsi( const char *defval ); int code_geti( void ); int code_getdi( const int defval ); +int64_t code_getl( void ); +int64_t code_getdl( const int64_t defval ); double code_getd( void ); double code_getdd( const double defval ); PVal *code_getpval( void ); diff --git a/src/hsp3/hsp3int.cpp b/src/hsp3/hsp3int.cpp index 66fc2e0d..19e1ed09 100644 --- a/src/hsp3/hsp3int.cpp +++ b/src/hsp3/hsp3int.cpp @@ -1366,6 +1366,7 @@ static int cmdfunc_intcmd( int cmd ) } static int reffunc_intfunc_ivalue; +static int64_t reffunc_intfunc_lvalue; static HSPREAL reffunc_intfunc_value; static void *reffunc_intfunc( int *type_res, int arg ) @@ -1513,13 +1514,25 @@ static void *reffunc_intfunc( int *type_res, int arg ) STRUCTDAT *st; if ( *type == TYPE_DLLFUNC ) { st = &(ctx->mem_finfo[ *val ]); +#ifdef HSP64 + reffunc_intfunc_lvalue = (int64_t)(st->proc); + *type_res = HSPVAR_FLAG_INT64; + ptr = &reffunc_intfunc_lvalue; +#else reffunc_intfunc_ivalue = (int)(size_t)(st->proc); +#endif code_next(); break; } aptr = code_getva( &pval ); pdat = HspVarCorePtrAPTR( pval, aptr ); +#ifdef HSP64 + reffunc_intfunc_lvalue = (int64_t)(pdat); + *type_res = HSPVAR_FLAG_INT64; + ptr = &reffunc_intfunc_lvalue; +#else reffunc_intfunc_ivalue = (int)(size_t)(pdat); +#endif HspVarCoreGetBlockSize(pval, pdat, &ctx->strsize); break; } diff --git a/test/test_ptr/dupptr1.hsp b/test/test_ptr/dupptr1.hsp new file mode 100644 index 00000000..09e10ff4 --- /dev/null +++ b/test/test_ptr/dupptr1.hsp @@ -0,0 +1,8 @@ +dim a +dupptr b , varptr(a) , 4 , 4 + +a=1 +mes b + +a=123 +mes b diff --git a/test/test_ptr/varptr1.hsp b/test/test_ptr/varptr1.hsp new file mode 100644 index 00000000..d0d2365b --- /dev/null +++ b/test/test_ptr/varptr1.hsp @@ -0,0 +1,9 @@ +a = "foo" +mes varptr(a) +p = varptr(a) +mes p + +b = 10 +mes varptr(b) +p = varptr(b) +mes p From 64a8868156acbb1bcbb9ef492ebf0443b804448f Mon Sep 17 00:00:00 2001 From: Kensuke Matsuzaki Date: Thu, 29 May 2025 22:35:01 +0900 Subject: [PATCH 3/5] =?UTF-8?q?Linux=E3=81=AETYPE=5FDLLCTRL=E5=AF=BE?= =?UTF-8?q?=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hsp3/linux/hsp3ext_linux.cpp | 128 ++++++++++++++++++++++++++++++ src/hsp3/linux/hsp3extlib_ffi.cpp | 53 ++++++++++++- src/hsp3/linux/hsp3extlib_ffi.h | 12 +-- 3 files changed, 180 insertions(+), 13 deletions(-) diff --git a/src/hsp3/linux/hsp3ext_linux.cpp b/src/hsp3/linux/hsp3ext_linux.cpp index 1f10f19f..f0cfb5df 100644 --- a/src/hsp3/linux/hsp3ext_linux.cpp +++ b/src/hsp3/linux/hsp3ext_linux.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "../hsp3config.h" #include "../hsp3code.h" @@ -25,8 +26,12 @@ static int *type; static int *val; static int *exflg; static int reffunc_intfunc_ivalue; +static int64_t reffunc_intfunc_lvalue; static int reset_flag = 0; +#define GetPRM(id) (&hspctx->mem_finfo[id]) +#define strp(dsptr) &hspctx->mem_mds[dsptr] + /*------------------------------------------------------------*/ /* System Information initialization @@ -78,6 +83,127 @@ static void InitSystemInformation(void) */ /*------------------------------------------------------------*/ +static int cmdfunc_ctrlcmd( int cmd ) +{ + // cmdfunc : TYPE_DLLCTRL + // (拡張DLLコントロールコマンド) + // + code_next(); // 次のコードを取得(最初に必ず必要です) + + switch( cmd ) { // サブコマンドごとの分岐 + default: + throw ( HSPERR_SYNTAX ); + } + return RUNMODE_RUN; +} + + +static void *reffunc_ctrlfunc( int *type_res, int arg ) +{ + // reffunc : TYPE_DLLCTRL + // (拡張DLLコントロール関数) + // + void *ptr; + int p1, p2; + int64_t lp1, lp2; + + // '('で始まるかを調べる + // + if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM ); + if ( *val != '(' ) throw ( HSPERR_INVALID_FUNCPARAM ); + code_next(); + + ptr = &reffunc_intfunc_ivalue; + *type_res = HSPVAR_FLAG_INT; + + switch( arg ) { // サブコマンドごとの分岐 + case 0x100: // callfunc + { + PVal *pval; + PDAT *p; + int fl; + char *sptr; + pval = code_getpval(); + p = HspVarCorePtrAPTR( pval, 0 ); + lp1 = code_getl(); + p2 = code_geti(); + fl = code_getdi(HSPVAR_FLAG_INT); + switch( fl ) { + case HSPVAR_FLAG_NONE: + case HSPVAR_FLAG_STR: + case HSPVAR_FLAG_DOUBLE: + case HSPVAR_FLAG_INT: + case HSPVAR_FLAG_INT64: + case HSPVAR_FLAG_FLOAT: + break; + case HSPVAR_FLAG_LABEL: + case HSPVAR_FLAG_STRUCT: + case HSPVAR_FLAG_COMSTRUCT: + case 7: // VARIANT + case HSPVAR_FLAG_USERDEF: + default: + throw ( HSPERR_TYPE_MISMATCH ); + } + reffunc_intfunc_lvalue = call_extfunc( (void *)lp1, (int**)p, p2, fl ); + switch( fl ) { + case HSPVAR_FLAG_STR: + ptr = sptr = code_stmp( strlen((char*)reffunc_intfunc_lvalue) + 1 ); + strcpy( sptr, (char*) reffunc_intfunc_lvalue ); + *type_res = HSPVAR_FLAG_STR; + break; + default: + *type_res = fl; + break; + } + break; + } + + case 0x103: // libptr + { + //LIBDAT *lib; + STRUCTDAT *st; + switch( *type ) { + case TYPE_DLLFUNC: + case TYPE_MODCMD: + p1 = *val; + break; + case TYPE_DLLCTRL: + p1 = *val; + if ( p1 >= TYPE_OFFSET_COMOBJ ) { + p1 -= TYPE_OFFSET_COMOBJ; + break; + } + default: + throw ( HSPERR_TYPE_MISMATCH ); + } + code_next(); + st = GetPRM( p1 ); + //lib = &hspctx->mem_linfo[ st->index ]; +#ifdef HSP64 + reffunc_intfunc_lvalue = (uint64_t)st; + ptr = &reffunc_intfunc_lvalue; + *type_res = HSPVAR_FLAG_INT64; +#else + reffunc_intfunc_ivalue = (int)st; + ptr = &reffunc_intfunc_ivalue; + *type_res = HSPVAR_FLAG_INT; +#endif + break; + } + + default: + throw ( HSPERR_SYNTAX ); + } + + // ')'で終わるかを調べる + // + if ( *type != TYPE_MARK ) throw ( HSPERR_INVALID_FUNCPARAM ); + if ( *val != ')' ) throw ( HSPERR_INVALID_FUNCPARAM ); + code_next(); + + return ptr; +} + static void *reffunc_dllcmd( int *type_res, int arg ) { @@ -129,6 +255,8 @@ void hsp3typeinit_dllcmd( HSP3TYPEINFO *info ) void hsp3typeinit_dllctrl( HSP3TYPEINFO *info ) { + info->cmdfunc = cmdfunc_ctrlcmd; + info->reffunc = reffunc_ctrlfunc; } diff --git a/src/hsp3/linux/hsp3extlib_ffi.cpp b/src/hsp3/linux/hsp3extlib_ffi.cpp index 758dbcf6..f257fd85 100644 --- a/src/hsp3/linux/hsp3extlib_ffi.cpp +++ b/src/hsp3/linux/hsp3extlib_ffi.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -424,10 +425,10 @@ int cnvwstr( void *out, char *in, int bufsize ) { // hspchar->unicode に変換 // -#ifndef HSPUTF8 +#ifndef HSPUTF8 return MultiByteToWideChar( CP_ACP, 0, in, -1, (LPWSTR)out, bufsize ); #else - return MultiByteToWideChar(CP_UTF8, 0, in, -1, (LPWSTR)out, bufsize); + return MultiByteToWideChar(CP_UTF8, 0, in, -1, (LPWSTR)out, bufsize); #endif } @@ -708,6 +709,54 @@ static int code_expand_next( ffi_type **prm_args, void **prm_values, const STRUC return result; } +int64_t call_extfunc( void *proc, int **prm, int prms, int rettype ) +{ + ffi_cif cif; + + std::vector args(prms); + std::vector values(prms); + + int64_t result = 0; + ffi_type *result_type; + + switch (rettype) { + case HSPVAR_FLAG_NONE: + result_type = &ffi_type_void; + break; + case HSPVAR_FLAG_STR: + result_type = &ffi_type_pointer; + break; + case HSPVAR_FLAG_DOUBLE: + result_type = &ffi_type_double; + break; + case HSPVAR_FLAG_INT: + result_type = &ffi_type_sint; + break; + case HSPVAR_FLAG_INT64: + result_type = &ffi_type_sint64; + break; + case HSPVAR_FLAG_FLOAT: + result_type = &ffi_type_float; + break; + case HSPVAR_FLAG_LABEL: + case HSPVAR_FLAG_STRUCT: + case HSPVAR_FLAG_COMSTRUCT: + case 7: // VARIANT + case HSPVAR_FLAG_USERDEF: + default: + throw ( HSPERR_TYPE_MISMATCH ); + } + + for (int i = 0; i < prms; i++) { + args[i] = &ffi_type_pointer; + values[i] = prm[i]; + } + ffi_prep_cif(&cif, FFI_DEFAULT_ABI, prms, result_type, args.data()); + ffi_call(&cif, FFI_FN(proc), &result, values.data()); + + return result; +} + int exec_dllcmd( int cmd, int mask ) { STRUCTDAT *st; diff --git a/src/hsp3/linux/hsp3extlib_ffi.h b/src/hsp3/linux/hsp3extlib_ffi.h index 4751899b..a23003c5 100644 --- a/src/hsp3/linux/hsp3extlib_ffi.h +++ b/src/hsp3/linux/hsp3extlib_ffi.h @@ -65,17 +65,7 @@ void Hsp3ExtLibTerm( void ); int cmdfunc_dllcmd( int cmd ); int exec_dllcmd( int cmd, int mask ); int code_expand_and_call( const STRUCTDAT *st ); - -/* -#if defined(HSP64) || defined(PTR64BIT) - -extern "C" int CallFunc64(int **, void*, int); -#define call_extfunc(externalFunction, arguments, numberOfArguments) CallFunc64((int**)(arguments), (void*)(externalFunction), numberOfArguments) - -#else -int call_extfunc( void *proc, int **prm, int prms ); -#endif -*/ +int64_t call_extfunc( void *proc, int **prm, int prms, int rettype ); int cnvwstr( void *out, char *in, int bufsize ); int cnvsjis( void *out, char *in, int bufsize ); From 33769ac9f38453f616375f230f87961a7f5878bb Mon Sep 17 00:00:00 2001 From: Kensuke Matsuzaki Date: Fri, 30 May 2025 21:49:05 +0900 Subject: [PATCH 4/5] =?UTF-8?q?wip=20=E5=A4=96=E9=83=A8=E3=81=AE=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=97=E3=81=AE=E5=9E=8B?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hsp3/hsp3.cpp | 5 +- src/hsp3/hsp3code.cpp | 6 +-- src/hsp3/hsp3struct.h | 24 +++++++-- src/hsp3/linux/hsp3ext_linux.cpp | 6 +-- src/hsp3/linux/hsp3extlib_ffi.cpp | 85 ++++++++++++++++++++++++------- src/hsp3/linux/hsp3extlib_ffi.h | 4 +- src/hspcmp/codegen.cpp | 6 ++- test/test_ptr/test.cpp | 47 +++++++++++++++++ test/test_ptr/test_dll1.hsp | 60 ++++++++++++++++++++++ 9 files changed, 209 insertions(+), 34 deletions(-) create mode 100644 test/test_ptr/test.cpp create mode 100644 test/test_ptr/test_dll1.hsp diff --git a/src/hsp3/hsp3.cpp b/src/hsp3/hsp3.cpp index 2a882e8a..64bf8a9e 100644 --- a/src/hsp3/hsp3.cpp +++ b/src/hsp3/hsp3.cpp @@ -404,7 +404,8 @@ STRUCTDAT *Hsp3::copy_STRUCTDAT(HSPHED *hsphed, char *ptr, size_t size) dst->index = org_dat.index; dst->subid = org_dat.subid; dst->prmindex = org_dat.prmindex; - dst->prmmax = org_dat.prmmax; + dst->prm.prmmax = org_dat.prm.prmmax; + dst->prm.rettype = org_dat.prm.rettype; dst->nameidx = org_dat.nameidx; dst->size = org_dat.size; dst->otindex = org_dat.otindex; @@ -420,7 +421,7 @@ STRUCTDAT *Hsp3::copy_STRUCTDAT(HSPHED *hsphed, char *ptr, size_t size) // STRUCTPRMのoffset,size値を調整する (各メンバのサイズを2倍にする) int j; dst->size *= 2; - for (j = 0; j < dst->prmmax; j++) { + for (j = 0; j < dst->prm.prmmax; j++) { STRUCTPRM *prm = &hspctx.mem_minfo[dst->prmindex + j]; if (prm->mptype == MPTYPE_STRUCTTAG) continue; //Alertf("INIT: type%d: subid:%d offset:%d", prm->mptype, prm->subid, prm->offset); diff --git a/src/hsp3/hsp3code.cpp b/src/hsp3/hsp3code.cpp index b5ec3349..1302765f 100644 --- a/src/hsp3/hsp3code.cpp +++ b/src/hsp3/hsp3code.cpp @@ -1315,7 +1315,7 @@ static void customstack_delete( STRUCTDAT *st, char *stackptr ) char *ss; STRUCTPRM *prm; prm = &hspctx->mem_minfo[ st->prmindex ]; - for(i=0;iprmmax;i++) { // パラメーターを取得 + for(i=0;iprm.prmmax;i++) { // パラメーターを取得 if ( prm->mptype == MPTYPE_LOCALSTRING ) { out = stackptr + prm->offset; ss = *(char **)out; @@ -1523,7 +1523,7 @@ void code_expandstruct( char *p, STRUCTDAT *st, int option ) STRUCTPRM *prm; prm = &hspctx->mem_minfo[ st->prmindex ]; - for(i=0;iprmmax;i++) { // パラメーターを取得 + for(i=0;iprm.prmmax;i++) { // パラメーターを取得 out = p + prm->offset; switch( prm->mptype ) { case MPTYPE_INUM: @@ -1641,7 +1641,7 @@ void code_delstruct( PVal *in_pval, APTR in_aptr ) code_callbackfunc( st->otindex ); } - for(i=0;iprmmax;i++) { // パラメーターを取得 + for(i=0;iprm.prmmax;i++) { // パラメーターを取得 out = p + prm->offset; switch( prm->mptype ) { case MPTYPE_LOCALVAR: diff --git a/src/hsp3/hsp3struct.h b/src/hsp3/hsp3struct.h index 8b194464..42312aef 100644 --- a/src/hsp3/hsp3struct.h +++ b/src/hsp3/hsp3struct.h @@ -279,7 +279,13 @@ typedef struct STRUCTDAT { short index; // base LIBDAT index short subid; // struct index int prmindex; // STRUCTPRM index(MINFO) - int prmmax; // number of STRUCTPRM + union { + int oldprmmax; // number of STRUCTPRM + struct { + short prmmax; // number of STRUCTPRM + short rettype; // return type + } prm; + }; int nameidx; // name index (DS) int size; // struct size (stack) int otindex; // OT index(Module) / cleanup flag(Dll) @@ -291,7 +297,13 @@ typedef struct HED_STRUCTDAT { short index; // base LIBDAT index short subid; // struct index int prmindex; // STRUCTPRM index(MINFO) - int prmmax; // number of STRUCTPRM + union { + int oldprmmax; // number of STRUCTPRM + struct { + short prmmax; // number of STRUCTPRM + short rettype; // return type + } prm; + }; int nameidx; // name index (DS) int size; // struct size (stack) int otindex; // OT index(Module) / cleanup flag(Dll) @@ -303,7 +315,13 @@ typedef struct STRUCTDAT { short index; // base LIBDAT index short subid; // struct index int prmindex; // STRUCTPRM index(MINFO) - int prmmax; // number of STRUCTPRM + union { + int prmmax; // number of STRUCTPRM + struct { + short prmmax; // number of STRUCTPRM + short rettype; // return type + } prm; + }; int nameidx; // name index (DS) int size; // struct size (stack) int otindex; // OT index(Module) / cleanup flag(Dll) diff --git a/src/hsp3/linux/hsp3ext_linux.cpp b/src/hsp3/linux/hsp3ext_linux.cpp index f0cfb5df..bfa2cff7 100644 --- a/src/hsp3/linux/hsp3ext_linux.cpp +++ b/src/hsp3/linux/hsp3ext_linux.cpp @@ -217,8 +217,8 @@ static void *reffunc_dllcmd( int *type_res, int arg ) if ( *val != '(' ) throw ( HSPERR_INVALID_FUNCPARAM ); *type_res = HSPVAR_FLAG_INT; - exec_dllcmd( arg, STRUCTDAT_OT_FUNCTION ); - reffunc_intfunc_ivalue = hspctx->stat; + void* retptr = nullptr; + exec_dllcmd( arg, STRUCTDAT_OT_FUNCTION, &retptr, type_res ); // ')'で終わるかを調べる // @@ -226,7 +226,7 @@ static void *reffunc_dllcmd( int *type_res, int arg ) if ( *val != ')' ) throw ( HSPERR_INVALID_FUNCPARAM ); code_next(); - return &reffunc_intfunc_ivalue; + return retptr; } diff --git a/src/hsp3/linux/hsp3extlib_ffi.cpp b/src/hsp3/linux/hsp3extlib_ffi.cpp index f257fd85..7955ebc1 100644 --- a/src/hsp3/linux/hsp3extlib_ffi.cpp +++ b/src/hsp3/linux/hsp3extlib_ffi.cpp @@ -40,6 +40,7 @@ static HSPCTX *hspctx; // Current Context static HSPEXINFO *exinfo; // Info for Plugins static PVal **pmpval; +static int64_t reffunc_intfunc_lvalue; static int libmax, prmmax, hpimax; static MEM_HPIDAT *hpidat; @@ -245,13 +246,13 @@ static void ExitFunc( STRUCTDAT *st ) ffi_type *args[16]; BindFUNC( st, NULL ); if ( st->proc == NULL ) return; - for (int i = 0; i < st->prmmax; i++) { + for (int i = 0; i < st->prm.prmmax; i++) { p[i] = &zero; args[i] = &ffi_type_sint; } ffi_cif cif; - ffi_prep_cif(&cif, FFI_DEFAULT_ABI, st->prmmax, &ffi_type_sint32, args); + ffi_prep_cif(&cif, FFI_DEFAULT_ABI, st->prm.prmmax, &ffi_type_sint32, args); int result = 0; ffi_call(&cif, FFI_FN(st->proc), &result, p); @@ -497,7 +498,7 @@ static char *prepare_localstr( char *src, int mode ) return dst; } -static int code_expand_next( ffi_type **prm_args, void **prm_values, const STRUCTDAT *, int ); +static int64_t code_expand_next( ffi_type **prm_args, void **prm_values, const STRUCTDAT *st, int index, int *type_res ); // libffi用引数をスタック上に保持する union FfiParam { @@ -507,7 +508,7 @@ union FfiParam { void *ptr; }; -int code_expand_and_call( const STRUCTDAT *st ) +int64_t code_expand_and_call( const STRUCTDAT *st, int *type_res ) { // パラメータの取得および関数呼び出し(再帰処理による) // @@ -517,13 +518,13 @@ int code_expand_and_call( const STRUCTDAT *st ) // DLL 関数呼び出し時は st->proc に関数アドレスをセットして // おかなければなりません( BindFUNC() により)。 // - int result; + int64_t result; - ffi_type **prm_args = (ffi_type **) sbAlloc(st->prmmax * sizeof(ffi_type *)); - void **prm_values = (void **) sbAlloc(st->prmmax * sizeof(void *)); + ffi_type **prm_args = (ffi_type **) sbAlloc(st->prm.prmmax * sizeof(ffi_type *)); + void **prm_values = (void **) sbAlloc(st->prm.prmmax * sizeof(void *)); try { - result = code_expand_next( prm_args, prm_values, st, 0 ); + result = code_expand_next( prm_args, prm_values, st, 0, type_res ); } catch (...) { sbFree( prm_args ); @@ -535,13 +536,13 @@ int code_expand_and_call( const STRUCTDAT *st ) return result; } -static int code_expand_next( ffi_type **prm_args, void **prm_values, const STRUCTDAT *st, int index ) +static int64_t code_expand_next( ffi_type **prm_args, void **prm_values, const STRUCTDAT *st, int index, int *type_res ) { // 次のパラメータを取得(および関数呼び出し)(再帰処理) // - int result; + int64_t result = 0; HSPAPICHAR *hactmp1 = 0; - if ( index == st->prmmax ) { + if ( index == st->prm.prmmax ) { // 関数(またはメソッド)の呼び出し //if ( !code_getexflg() ) throw HSPERR_TOO_MANY_PARAMETERS; switch ( st->subid ) { @@ -552,8 +553,52 @@ static int code_expand_next( ffi_type **prm_args, void **prm_values, const STRUC // 外部 DLL 関数の呼び出し //Alertf("%s:%d call_extfun(%p, *, %d)\n", __func__, __LINE__, st->proc, st->prmmax); ffi_cif cif; - // TODO intと互換性のない返り値の受け取り - ffi_prep_cif(&cif, FFI_DEFAULT_ABI, st->prmmax, &ffi_type_sint, prm_args); + ffi_type *result_type; + switch (st->prm.rettype) { + case MPTYPE_NONE: + case MPTYPE_INUM: + result_type = &ffi_type_sint; + if (type_res) + *type_res = HSPVAR_FLAG_INT; + break; + case MPTYPE_DNUM: + result_type = &ffi_type_double; + if (type_res) + *type_res = HSPVAR_FLAG_DOUBLE; + break; + case MPTYPE_FLOAT: + result_type = &ffi_type_float; + if (type_res) + *type_res = HSPVAR_FLAG_FLOAT; + break; + case MPTYPE_PVARPTR: + result_type = &ffi_type_pointer; + if (type_res) { +#ifdef HSP64 + *type_res = HSPVAR_FLAG_INT64; +#else + *type_res = HSPVAR_FLAG_INT; +#endif + } + break; + case MPTYPE_LOCALSTRING: + case MPTYPE_LOCALWSTR: + case MPTYPE_PPVAL: + case MPTYPE_PBMSCR: + case MPTYPE_FLEXSPTR: + case MPTYPE_FLEXWPTR: + case MPTYPE_PTR_REFSTR: + case MPTYPE_PTR_EXINFO: + case MPTYPE_PTR_DPMINFO: + case MPTYPE_NULLPTR: + #ifndef HSP_COM_UNSUPPORTED + case MPTYPE_IOBJECTVAR: + #endif + default: + Alertf("### Unsupported return type %s:%d %d\n", __func__, __LINE__, st->prm.rettype); + throw ( HSPERR_UNSUPPORTED_FUNCTION ); + } + ffi_prep_cif(&cif, FFI_DEFAULT_ABI, st->prm.prmmax, result_type, prm_args); ffi_call(&cif, FFI_FN(st->proc), &result, prm_values); break; #ifndef HSP_COM_UNSUPPORTED @@ -693,7 +738,7 @@ static int code_expand_next( ffi_type **prm_args, void **prm_values, const STRUC // 次のパラメータの取り出し(再帰的に処理) // (例外処理により動的確保したオブジェクトを確実に解放する) try { - result = code_expand_next( prm_args, prm_values, st, index + 1 ); + result = code_expand_next( prm_args, prm_values, st, index + 1, type_res ); } catch (...) { if ( localbuf ) sbFree( localbuf ); @@ -757,11 +802,10 @@ int64_t call_extfunc( void *proc, int **prm, int prms, int rettype ) return result; } -int exec_dllcmd( int cmd, int mask ) +int exec_dllcmd( int cmd, int mask, void** res, int *type_res ) { STRUCTDAT *st; void* pFn; - int result; code_next(); // 次のコードを取得(最初に必ず必要です) @@ -778,7 +822,7 @@ int exec_dllcmd( int cmd, int mask ) } if (( st->otindex & mask ) == 0 ) throw ( HSPERR_SYNTAX ); - result = code_expand_and_call( st ); + int64_t result = code_expand_and_call( st, type_res ); if ( st->subid == STRUCTPRM_SUBID_OLDDLLINIT ) { if ( result > 0 ) { @@ -796,9 +840,12 @@ int exec_dllcmd( int cmd, int mask ) } hspctx->stat = -result; } else { - hspctx->stat = result; + reffunc_intfunc_lvalue = result; } + if ( res != NULL ) { + *res = &reffunc_intfunc_lvalue; + } return RUNMODE_RUN; } @@ -807,6 +854,6 @@ int cmdfunc_dllcmd( int cmd ) // cmdfunc : TYPE_DLLCMD // (拡張DLLコマンド) // - return exec_dllcmd( cmd, STRUCTDAT_OT_STATEMENT ); + return exec_dllcmd( cmd, STRUCTDAT_OT_STATEMENT, nullptr, nullptr ); } diff --git a/src/hsp3/linux/hsp3extlib_ffi.h b/src/hsp3/linux/hsp3extlib_ffi.h index a23003c5..0771c887 100644 --- a/src/hsp3/linux/hsp3extlib_ffi.h +++ b/src/hsp3/linux/hsp3extlib_ffi.h @@ -63,8 +63,8 @@ int Hsp3ExtLibInit( HSP3TYPEINFO *info ); void Hsp3ExtLibTerm( void ); int cmdfunc_dllcmd( int cmd ); -int exec_dllcmd( int cmd, int mask ); -int code_expand_and_call( const STRUCTDAT *st ); +int exec_dllcmd( int cmd, int mask, void** res, int *type_res ); +// int code_expand_and_call( const STRUCTDAT *st ); int64_t call_extfunc( void *proc, int **prm, int prms, int rettype ); int cnvwstr( void *out, char *in, int bufsize ); diff --git a/src/hspcmp/codegen.cpp b/src/hspcmp/codegen.cpp index b30eabd2..022e1a2e 100644 --- a/src/hspcmp/codegen.cpp +++ b/src/hspcmp/codegen.cpp @@ -2990,7 +2990,8 @@ int CToken::PutStructEnd( int i, char *name, int libindex, int otindex, int func st.nameidx = PutDSBuf( name ); st.subid = i; st.prmindex = cg_stptr; - st.prmmax = cg_stnum; + st.prm.prmmax = cg_stnum; + st.prm.rettype = 0; st.funcflag = funcflag; st.size = cg_stsize; if ( otindex < 0 ) { @@ -3027,7 +3028,8 @@ int CToken::PutStructEndDll( char *name, int libindex, int subid, int otindex ) } st.subid = subid; st.prmindex = cg_stptr; - st.prmmax = cg_stnum; + st.prm.prmmax = cg_stnum; + st.prm.rettype = 0; //st.proc = NULL; st.funcflag = 0; st.size = cg_stsize; diff --git a/test/test_ptr/test.cpp b/test/test_ptr/test.cpp new file mode 100644 index 00000000..33edaa15 --- /dev/null +++ b/test/test_ptr/test.cpp @@ -0,0 +1,47 @@ +/* + * test code + * g++ -shared -fPIC -o test.so test.cpp -g -O2 + */ +#include +#include +#include + +extern "C" { + +uint64_t count = 0; + +int func0() { + //printf("called func0() %d\n", count); + return count++; +} + +int64_t func0_64() { + //printf("called func0() %d\n", count); + return count++; +} + +int func1(char *p0, int p1, int p2, int p3) { + //printf("called func1(%p, %d, %d, %d)\n", (void*)p0, p1, p2, p3); + for (int i = 0; i < 10; i++) { + if (p0 && p0[i]) { + printf(" %d: %c\n", i, p0[i]); + } else { + break; + } + } + return p1 + p2 + p3 + 12340000; +} + +float floatMulAdd(float p0, double p1, int64_t p2) { + float r = p0 * p1 + p2; + printf(" called floatMulAdd(%f, %f, %ld) = %f\n", p0, p1, p2, r); + return r; +} + +double doubleMulAdd(float p0, int p1, double p2) { + double r = p0 * p1 + p2; + printf(" called doubleMulAdd(%f, %d, %f) = %f\n", p0, p1, p2, r); + return r; +} + +} diff --git a/test/test_ptr/test_dll1.hsp b/test/test_ptr/test_dll1.hsp new file mode 100644 index 00000000..df3cbedb --- /dev/null +++ b/test/test_ptr/test_dll1.hsp @@ -0,0 +1,60 @@ +#uselib "test.so" + +#cfunc test0 "func0" +#cfunc test0_64 "func0_64" +#cfunc test1 "func1" var,int,int,int + +//float floatMulAdd(float p0, double p1, int p2); +#cfunc floatMulAdd "floatMulAdd" float, double, sptr + +//double doubleMulAdd(float p0, int p1, double p2); +#cfunc doubleMulAdd "doubleMulAdd" float, int, double + + +repeat 2 + mes "call test0" + res=test0() + mes "return " + res + a = "abc" + + mes "call test1" + res=test1(a,1,2,3) + mes "return " + res +loop + +mes "call floatMulAdd" +longval = 100 +res = floatMulAdd(0.1, 2.0, longval) +mes res + +ladr=libptr( floatMulAdd ) +dupptr lptr,ladr,28 ; STRUCTDAT構造体を取得 +lib_id=wpeek(lptr,0) +prm_max=wpeek(lptr,8) +prm_type=wpeek(lptr,10) +mes "LIB#"+lib_id + " prm:" + prm_max + " ret:" + prm_type +wpoke lptr, 10, -4 // MPTYPE_FLOAT -4 +prm_type=wpeek(lptr,10) +mes "LIB#"+lib_id + " prm:" + prm_max + " ret:" + prm_type + +res = floatMulAdd(0.1, 2.0, longval) +mes res + + +mes "call doubleMulAdd" +res = doubleMulAdd(0.1, 2.0, 100) +mes res + +ladr=libptr( doubleMulAdd ) +dupptr lptr,ladr,28 ; STRUCTDAT構造体を取得 +lib_id=wpeek(lptr,0) +prm_max=wpeek(lptr,8) +prm_type=wpeek(lptr,10) +mes "LIB#"+lib_id + " prm:" + prm_max + " ret:" + prm_type +wpoke lptr, 10, 3 // MPTYPE_DNUM 3 +prm_type=wpeek(lptr,10) +mes "LIB#"+lib_id + " prm:" + prm_max + " ret:" + prm_type + +mes "call doubleMulAdd" +res = doubleMulAdd(0.1, 2.0, 100) +mes res From 58e7c15d4b5d6c7b57cd77b8895a09ed93f219c1 Mon Sep 17 00:00:00 2001 From: Kensuke Matsuzaki Date: Fri, 20 Jun 2025 20:31:38 +0900 Subject: [PATCH 5/5] Refine CalcValue arithmetic widening --- src/hspcmp/token.cpp | 136 ++++++++++++++++----------------- src/hspcmp/token.h | 174 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 241 insertions(+), 69 deletions(-) diff --git a/src/hspcmp/token.cpp b/src/hspcmp/token.cpp index eb670919..846d9f01 100644 --- a/src/hspcmp/token.cpp +++ b/src/hspcmp/token.cpp @@ -940,30 +940,30 @@ void CToken::Calc_token( void ) void CToken::Calc_factor( CALCVAR &v ) { - CALCVAR v1; - int id,type; - char *ptr_dval; - if ( ttype==TK_NUM ) { - v=(CALCVAR)val; - Calc_token(); - return; - } - if ( ttype==TK_DNUM ) { - v=(CALCVAR)val_d; - Calc_token(); - return; + CALCVAR v1; + int id,type; + char *ptr_dval; + if ( ttype==TK_NUM ) { + v = CALCVAR(val); + Calc_token(); + return; + } + if ( ttype==TK_DNUM ) { + v = CALCVAR(val_d); + Calc_token(); + return; } if ( ttype==TK_OBJ ) { id = lb->Search( (char *)s3 ); if ( id == -1 ) { ttype=TK_CALCERROR; return; } type = lb->GetType( id ); - if ( type != LAB_TYPE_PPVAL ) { ttype=TK_CALCERROR; return; } - ptr_dval = lb->GetData2( id ); - if ( ptr_dval == NULL ) { - v = (CALCVAR)lb->GetOpt( id ); - } else { - v = *(CALCVAR *)ptr_dval; - } + if ( type != LAB_TYPE_PPVAL ) { ttype=TK_CALCERROR; return; } + ptr_dval = lb->GetData2( id ); + if ( ptr_dval == NULL ) { + v = CALCVAR( lb->GetOpt( id ) ); + } else { + v = *(CALCVAR *)ptr_dval; + } Calc_token(); return; } @@ -997,13 +997,13 @@ void CToken::Calc_muldiv( CALCVAR &v ) while( (ttype=='*')||(ttype=='/')||(ttype==0x5c)) { op=ttype; Calc_token(); Calc_unary(v2); - if (op=='*') v1*=v2; - else if (op=='/') { - if ( v2==0.0 ) { ttype=TK_CALCERROR; return; } - v1/=v2; - } else if (op==0x5c) { - if ( (int)v2==0 ) { ttype=TK_CALCERROR; return; } - v1 = fmod( v1, v2 ); + if (op=='*') v1 = v1 * v2; + else if (op=='/') { + if ( v2.toDouble()==0.0 ) { ttype=TK_CALCERROR; return; } + v1 = v1 / v2; + } else if (op==0x5c) { + if ( v2.toInt()==0 ) { ttype=TK_CALCERROR; return; } + v1 = v1.mod( v2 ); } } v=v1; @@ -1017,8 +1017,8 @@ void CToken::Calc_addsub( CALCVAR &v ) while( (ttype=='+')||(ttype=='-')) { op=ttype; Calc_token(); Calc_muldiv(v2); - if (op=='+') v1+=v2; - else if (op=='-') v1-=v2; + if (op=='+') v1 = v1 + v2; + else if (op=='-') v1 = v1 - v2; } v=v1; } @@ -1034,49 +1034,49 @@ void CToken::Calc_compare( CALCVAR &v ) if (op=='=') { Calc_token(); Calc_addsub(v2); - v1i = v1==v2; - v1=(CALCVAR)v1i; continue; + v1i = (v1 == v2); + v1 = CALCVAR(v1i); continue; } if (op=='<') { if ( *wp=='=' ) { wp++; Calc_token();Calc_addsub(v2); - v1i=(v1<=v2); v1=(CALCVAR)v1i; continue; + v1i=(v1<=v2); v1 = CALCVAR(v1i); continue; } if ( *wp=='<' ) { wp++; Calc_token();Calc_addsub(v2); - v1i = (int)v1; - v2i = (int)v2; + v1i = (int)v1.toInt(); + v2i = (int)v2.toInt(); v1i<<=v2i; - v1=(CALCVAR)v1i; continue; + v1 = CALCVAR(v1i); continue; } Calc_token(); Calc_addsub(v2); v1i=(v1') { if ( *wp=='=' ) { wp++; Calc_token();Calc_addsub(v2); v1i=(v1>=v2); - v1=(CALCVAR)v1i; continue; + v1 = CALCVAR(v1i); continue; } if ( *wp=='>' ) { wp++; Calc_token();Calc_addsub(v2); - v1i = (int)v1; - v2i = (int)v2; + v1i = (int)v1.toInt(); + v2i = (int)v2.toInt(); v1i>>=v2i; - v1=(CALCVAR)v1i; continue; + v1 = CALCVAR(v1i); continue; } Calc_token(); Calc_addsub(v2); - v1i=(v1>v2); - v1=(CALCVAR)v1i; continue; + v1i=(v1>v2); + v1 = CALCVAR(v1i); continue; } - v1=(CALCVAR)v1i; + v1 = CALCVAR(v1i); } v=v1; } @@ -1090,10 +1090,10 @@ void CToken::Calc_bool2( CALCVAR &v ) while( ttype=='!') { Calc_token(); Calc_compare(v2); - v1i = (int)v1; - v2i = (int)v2; + v1i = (int)v1.toInt(); + v2i = (int)v2.toInt(); v1i = v1i != v2i; - v1=(CALCVAR)v1i; + v1 = CALCVAR(v1i); } v=v1; } @@ -1107,12 +1107,12 @@ void CToken::Calc_bool( CALCVAR &v ) while( (ttype=='&')||(ttype=='|')||(ttype=='^')) { op=ttype; Calc_token(); Calc_bool2(v2); - v1i = (int)v1; - v2i = (int)v2; + v1i = (int)v1.toInt(); + v2i = (int)v2.toInt(); if (op=='&') v1i&=v2i; else if (op=='|') v1i|=v2i; else if (op=='^') v1i^=v2i; - v1=(CALCVAR)v1i; + v1 = CALCVAR(v1i); } v=v1; } @@ -1614,13 +1614,13 @@ char *CToken::ExpandToken( char *str, int *type, int ppmode ) { // constマクロ展開 GenerateLabelListAndTagRefPP(fixname, LABBUF_FLAG_MACRO); - char *ptr_dval; - ptr_dval = lb->GetData2( id ); - if ( ptr_dval == NULL ) { - sprintf(cnvstr, "%d", lb->GetOpt(id)); - } else { - sprintf(cnvstr, "%.16f", *(CALCVAR*)ptr_dval); - } + char *ptr_dval; + ptr_dval = lb->GetData2( id ); + if ( ptr_dval == NULL ) { + sprintf(cnvstr, "%d", lb->GetOpt(id)); + } else { + sprintf(cnvstr, "%.16f", ((CALCVAR*)ptr_dval)->toDouble()); + } chk = ReplaceLineBuf( str, (char *)vs, cnvstr, 0, NULL ); break; } @@ -2322,23 +2322,23 @@ ppresult_t CToken::PP_Const( void ) if ( ahtkeyword != NULL ) { if ( ahtbuf != NULL ) { // AHT出力時 - AHTPROP *prop; - CALCVAR dbval; + AHTPROP *prop; + CALCVAR dbval; prop = ahtmodel->GetProperty( keyword ); if ( prop != NULL ) { id = lb->Regist( keyword, LAB_TYPE_PPVAL, prop->GetValueInt() ); - if ( cres != floor( cres ) ) { - dbval = prop->GetValueDouble(); - lb->SetData2( id, (char *)(&dbval), sizeof(CALCVAR) ); - } + if ( cres != floor( cres.toDouble() ) ) { + dbval = CALCVAR( prop->GetValueDouble() ); + lb->SetData2( id, (char *)(&dbval), sizeof(CALCVAR) ); + } if ( glmode ) lb->SetEternal( id ); return PPRESULT_SUCCESS; } } else { // AHT読み出し時 - if ( cres != floor( cres ) ) { - ahtmodel->SetPropertyDefaultDouble( keyword, (double)cres ); + if ( cres != floor( cres.toDouble() ) ) { + ahtmodel->SetPropertyDefaultDouble( keyword, cres.toDouble() ); } else { - ahtmodel->SetPropertyDefaultInt( keyword, (int)cres ); + ahtmodel->SetPropertyDefaultInt( keyword, cres.toInt() ); } if ( ahtmodel->SetAHTPropertyString( keyword, ahtkeyword ) ) { SetError( "AHT parameter syntax error" ); return PPRESULT_ERROR; @@ -2347,9 +2347,9 @@ ppresult_t CToken::PP_Const( void ) } - id = lb->Regist( keyword, LAB_TYPE_PPVAL, (int)cres ); + id = lb->Regist( keyword, LAB_TYPE_PPVAL, cres.toInt() ); if ( valuetype == ConstType::Double - || (valuetype == ConstType::Indeterminate && cres != floor(cres)) ) { + || (valuetype == ConstType::Indeterminate && cres != floor(cres.toDouble())) ) { lb->SetData2( id, (char *)(&cres), sizeof(CALCVAR) ); } if ( glmode ) lb->SetEternal( id ); @@ -2393,7 +2393,7 @@ ppresult_t CToken::PP_Enum( void ) if ( GetToken() == '=' ) { if ( Calc( cres ) ) return PPRESULT_ERROR; - enumgc = (int)cres; + enumgc = cres.toInt(); } res = enumgc++; id = lb->Regist( keyword, LAB_TYPE_PPVAL, res ); @@ -3580,7 +3580,7 @@ ppresult_t CToken::Preprocess( char *str ) else { res = PPRESULT_SUCCESS; if (Calc(cres) == 0) { - a = (int)cres; + a = cres.toInt(); res = PP_SwitchStart(a); } else res = PPRESULT_ERROR; diff --git a/src/hspcmp/token.h b/src/hspcmp/token.h index 738926c2..66369305 100644 --- a/src/hspcmp/token.h +++ b/src/hspcmp/token.h @@ -71,8 +71,180 @@ #define CG_LIBMODE_COM 2 #define CG_LIBMODE_COMNEW 3 -#define CALCVAR double +#include +#include + +// value type used for compile time calculations +class CalcValue { +public: + enum class Type { Int, Int64, Float, Double }; + + CalcValue() : type(Type::Int) { val.i = 0; } + CalcValue(int v) : type(Type::Int) { val.i = v; } + CalcValue(long long v) : type(Type::Int64) { val.i64 = v; } + CalcValue(float v) : type(Type::Float) { val.f = v; } + CalcValue(double v) : type(Type::Double) { val.d = v; } + + bool isInt() const { return type == Type::Int; } + bool isInt64() const { return type == Type::Int64; } + bool isFloat() const { return type == Type::Float; } + bool isDouble() const { return type == Type::Double; } + bool isFloating() const { return type == Type::Float || type == Type::Double; } + Type getType() const { return type; } + + static Type widen(Type a, Type b) { + if (a == Type::Double || b == Type::Double) return Type::Double; + if (a == Type::Float || b == Type::Float) return Type::Float; + if (a == Type::Int64 || b == Type::Int64) return Type::Int64; + return Type::Int; + } + + long long toInt() const { + switch(type) { + case Type::Int: return val.i; + case Type::Int64: return val.i64; + case Type::Float: return static_cast(val.f); + case Type::Double: default: return static_cast(val.d); + } + } + long long toInt64() const { + return toInt(); + } + float toFloat() const { + switch(type) { + case Type::Int: return static_cast(val.i); + case Type::Int64: return static_cast(val.i64); + case Type::Float: return val.f; + case Type::Double: default: return static_cast(val.d); + } + } + double toDouble() const { + switch(type) { + case Type::Int: return static_cast(val.i); + case Type::Int64: return static_cast(val.i64); + case Type::Float: return val.f; + case Type::Double: default: return val.d; + } + } + + CalcValue operator-() const { + switch(type) { + case Type::Double: return CalcValue(-val.d); + case Type::Float: return CalcValue(-val.f); + case Type::Int64: return CalcValue(-val.i64); + case Type::Int: default: return CalcValue(-val.i); + } + } + + CalcValue operator+(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: return CalcValue(toDouble() + r.toDouble()); + case Type::Float: return CalcValue(toFloat() + r.toFloat()); + case Type::Int64: return CalcValue(toInt64() + r.toInt64()); + case Type::Int: default: return CalcValue(toInt() + r.toInt()); + } + } + CalcValue operator-(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: return CalcValue(toDouble() - r.toDouble()); + case Type::Float: return CalcValue(toFloat() - r.toFloat()); + case Type::Int64: return CalcValue(toInt64() - r.toInt64()); + case Type::Int: default: return CalcValue(toInt() - r.toInt()); + } + } + CalcValue operator*(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: return CalcValue(toDouble() * r.toDouble()); + case Type::Float: return CalcValue(toFloat() * r.toFloat()); + case Type::Int64: return CalcValue(toInt64() * r.toInt64()); + case Type::Int: default: return CalcValue(toInt() * r.toInt()); + } + } + CalcValue operator/(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: return CalcValue(toDouble() / r.toDouble()); + case Type::Float: return CalcValue(toFloat() / r.toFloat()); + case Type::Int64: return CalcValue(toInt64() / r.toInt64()); + case Type::Int: default: return CalcValue(toInt() / r.toInt()); + } + } + CalcValue mod(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: + return CalcValue(fmod(toDouble(), r.toDouble())); + case Type::Float: + return CalcValue(static_cast(fmod(toFloat(), r.toFloat()))); + case Type::Int64: + return CalcValue(toInt64() % r.toInt64()); + case Type::Int: default: + return CalcValue(toInt() % r.toInt()); + } + } + + bool operator==(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: return toDouble() == r.toDouble(); + case Type::Float: return toFloat() == r.toFloat(); + default: return toInt64() == r.toInt64(); + } + } + bool operator!=(const CalcValue& r) const { return !(*this == r); } + bool operator<(const CalcValue& r) const { + Type rt = widen(type, r.type); + switch(rt) { + case Type::Double: return toDouble() < r.toDouble(); + case Type::Float: return toFloat() < r.toFloat(); + default: return toInt64() < r.toInt64(); + } + } + bool operator>(const CalcValue& r) const { return r < *this; } + bool operator<=(const CalcValue& r) const { return !(*this > r); } + bool operator>=(const CalcValue& r) const { return !(*this < r); } + + CalcValue operator&(const CalcValue& r) const { + Type rt = widen(type, r.type); + if (rt == Type::Int64) return CalcValue(toInt64() & r.toInt64()); + return CalcValue(static_cast(toInt()) & static_cast(r.toInt())); + } + CalcValue operator|(const CalcValue& r) const { + Type rt = widen(type, r.type); + if (rt == Type::Int64) return CalcValue(toInt64() | r.toInt64()); + return CalcValue(static_cast(toInt()) | static_cast(r.toInt())); + } + CalcValue operator^(const CalcValue& r) const { + Type rt = widen(type, r.type); + if (rt == Type::Int64) return CalcValue(toInt64() ^ r.toInt64()); + return CalcValue(static_cast(toInt()) ^ static_cast(r.toInt())); + } + CalcValue operator<<(const CalcValue& r) const { + Type rt = widen(type, r.type); + if (rt == Type::Int64) return CalcValue(toInt64() << r.toInt64()); + return CalcValue(static_cast(toInt()) << static_cast(r.toInt())); + } + CalcValue operator>>(const CalcValue& r) const { + Type rt = widen(type, r.type); + if (rt == Type::Int64) return CalcValue(toInt64() >> r.toInt64()); + return CalcValue(static_cast(toInt()) >> static_cast(r.toInt())); + } + +private: + Type type; + union { + int i; + long long i64; + float f; + double d; + } val; +}; + +using CALCVAR = CalcValue; #define LINEBUF_MAX 0x10000 // line mode type