変数を新しく定義(使用)すると、定義したサイズ分のスペースをメモリに確保します。
この変数内には保存するデータが格納されますが、HSPとしてはこのデータはもちろん、
データの型やサイズ、実際に確保したメモリのアドレス情報等も保存する必要があるのです。
型やサイズ等の付加情報は、PVALと呼ばれる構造体(変数1つに付き1つの構造体)に保存されます。
typedef struct PVal
{
// Memory Data structure (2.5 compatible)
short flag; // type of val
short mode; // mode (0=normal/1=clone/2=alloced)
int len[5]; // length of array 4byte align (dim)
int size; // size of Val
char *pt; // ptr to array
// Memory Data structure (3.0 compatible)
void *master; // Master pointer for data
short autoresize; // Auto Array Expand Flag
short arraycnt; // Array Set Count
int offset; // Array Data Offset
int arraymul; // Array Multiple Value
}
上記は、HSP3のSDK(hspvar_core.h)に記載されたものです。
前半の32バイトはHSP2.5と互換性のあるもの、
後半の16バイトはHSP3からの、文字列型変数の可変化に伴い追加されたものです。
PVAL構造体は、HSP2だとmref命令を利用することで、変数情報を取得することが出来ますが、
HSP3以降はmref命令で直接の取得できなくなったようです。
取り出しは、まずmref命令でHSPCTX構造体のアドレスを取得します。
SDK(hsp3struct.h)によると、HSPCTX構造体は下記のようになっているようです。
typedef struct HSPCTX
{
HSPHED *hsphed;
unsigned short *mcs;
unsigned short *mem_mcs;
char *mem_mds;
unsigned char *mem_di;
int *mem_ot;
IRQDAT *mem_irq;
int irqmax;
int iparam;
int wparam;
int lparam;
PVal *mem_var; // ★PVal構造体のポインタ★
int *actscr;
int *nptype;
int *npval;
int *strsize;
char *refstr;
void *(*HspFunc_prm_getv)( void );
int (*HspFunc_prm_geti)( void );
int (*HspFunc_prm_getdi)( const int defval );
char *(*HspFunc_prm_gets)( void );
char *(*HspFunc_prm_getds)( const char *defstr );
int (*HspFunc_val_realloc)( PVal *pv, int size, int mode );
int (*HspFunc_fread)( char *fname, void *readmem, int rlen, int seekofs );
int (*HspFunc_fsize)( char *fname );
void *(*HspFunc_getbmscr)( int wid );
int (*HspFunc_getobj)( int wid, int id, void *inf );
int (*HspFunc_setobj)( int wid, int id, const void *inf );
int *npexflg;
HSPCTX *hspctx;
int (*HspFunc_addobj)( int wid );
void (*HspFunc_puterror)( HSPERROR error );
HspVarProc *(*HspFunc_getproc)( int type );
HspVarProc *(*HspFunc_seekproc)( const char *name );
void (*HspFunc_prm_next)( void );
int (*HspFunc_prm_get)( void );
double (*HspFunc_prm_getd)( void );
double (*HspFunc_prm_getdd)( double defval );
unsigned short *(*HspFunc_prm_getlb)( void );
PVal *(*HspFunc_prm_getpval)( void );
APTR (*HspFunc_prm_getva)( PVal **pval );
void (*HspFunc_prm_setva)( PVal *pval, APTR aptr, int type, const void *ptr );
char *(*HspFunc_malloc)( int size );
void (*HspFunc_free)( void *ptr );
char *(*HspFunc_expand)( char *ptr, int size );
IRQDAT *(*HspFunc_addirq)( void );
int (*HspFunc_hspevent)( int event, int prm1, int prm2, void *prm3 );
void (*HspFunc_registvar)( int flag, HSPVAR_COREFUNC func );
void (*HspFunc_setpc)( const unsigned short *pc );
void (*HspFunc_call)( const unsigned short *pc );
void (*HspFunc_mref)( PVal *pval, int prm );
void (*HspFunc_dim)( PVal *pval, int flag, int len0, int len1, int len2, int len3, int len4 );
void (*HspFunc_redim)( PVal *pval, int lenid, int len );
void (*HspFunc_array)( PVal *pval, int offset );
}
11番(44バイト)目にあるPVALというのが、PVAL構造体のあるアドレスを指しているので、
dupptr命令に、この11番目のポインタを用いて、
PVAL構造体のサイズ48バイト分のクローンを作成すれば、取り出し完了です。
下記のサンプルは、PVAL構造体にアクセスするまでのもので、
アクセス後のサンプルについてはコチラを参照してみてください。
尚、HSP2は、既に書いたようにmref命令から取得するものですので、
ユーザ定義#deffunc命令で呼び出される(モジュールにする)ことを前提にしています。
まぁ、HSP3は、ローカルと同空間での使用が出来ますが、
HSP2と同じく、汎用性を考えるとモジュールによる別空間にすべきでしょう。
モジュールにする場合、引数変数のPVALを使うものと思いますが、
HSPCTX構造体の828バイト(連続したInt型配列の207番)目に引数1つ目のポインタです。
引数1つ目が対象変数以外のデータで、引数2つ目以降に入っている場合は、
1つ目の型サイズ分後に位置に2つ目が、さらに2つ目の型サイズ分後に位置に3つ目が入るようです。
型サイズは、引数がintの場合、4バイト分のデータがそのまま入っています。
strの場合も4バイト(一時格納用のポインタが入るため)が、doubleの場合、データ分の8バイト。
varやarrayの場合も8バイト(先頭ポインタ+配列ポインタが入るため)です。
対象引数の位置がわかったら、そのアドレスをdupptr命令に指定して、48バイト分取り出せばOKです。
実際の取り出しについてはHSP3サンプルをご覧ください。
|