STRUCTDAT, STRUCTPRM あたりを調べた
HSP on JS でそろそろユーザ定義命令・関数を実装するかーと思ったんで、理解が浅い STRUCTDAT, STRUCTPRM あたりを調べることにした。結構複雑。
STRUCTDAT
ユーザー定義命令・関数や DLL の関数、モジュール変数定義の情報。 ax の FINFO にこれの配列が格納されている。
// DLL function flags #define STRUCTDAT_OT_NONE 0 #define STRUCTDAT_OT_CLEANUP 1 #define STRUCTDAT_OT_STATEMENT 2 #define STRUCTDAT_OT_FUNCTION 4 // Module function flags #define STRUCTDAT_INDEX_FUNC -1 #define STRUCTDAT_INDEX_CFUNC -2 #define STRUCTDAT_INDEX_STRUCT -3 #define STRUCTDAT_FUNCFLAG_CLEANUP 0x10000 // function,module specific data typedef struct STRUCTDAT { short index; // base LIBDAT index short subid; // struct index int prmindex; // STRUCTPRM index(MINFO) int prmmax; // number of STRUCTPRM int nameidx; // name index (DS) int size; // struct size (stack) int otindex; // OT index(Module) / cleanup flag(Dll) union { void *proc; // proc address int funcflag; // function flags(Module) }; } STRUCTDAT;
- index
- LINFO のインデックス。LINFO は LIBDAT の配列で、 LIBDAT は #uselib で定義した DLL 一つにつき一つ用意されている。ユーザ定義命令・関数の場合はこれが負数になり、 STRUCTDAT_INDEX_*** で定義された値になる。 STRUCTDAT_INDEX_FUNC はユーザ定義命令、STRUCTDAT_INDEX_CFUNCはユーザ定義関数、 STRUCTDAT_INDEX_STRUCT はモジュール変数の定義。
- subid
- FINFO のインデックス。または STRUCTPRM_SUBID_*** のいずれかの値。
- prmindex
- MINFO のインデックス。 MINFO は STRUCTPRM の配列で、パラメータの情報が格納されている。
- prmmax
- パラメータの数。 MINFO には prmindex から prmmax 個連続して STRUCTPRM が格納されている。
- nameidx
- 関数名の DS オフセット。
- size
- すべてのパラメータの値を格納するのに必要なサイズ。たとえば、 #deffunc foo int a, double b, var c だったら sizeof(int) + sizeof(double) + sizeof(MPVarData) で 20 になる。
- otindex
- ラベルID (OT のインデックス)。 OT はラベルID の順に CS の位置が格納されている。ここから関数のコード位置を取得できる。DLL関数の場合、otindexには STRUCTDAT_OT_*** のフラグが格納されている。モジュール変数定義の場合、デストラクタの FINFO インデックスが格納されているようだ。
- proc, funcflag
- 実行時に DLL 関数の関数ポインタを格納する場所である。 DLL 関数でなければ、 STRUCTDAT_FUNCFLAG_*** のフラグが格納されている。
STRUCTPRM
DLL 命令・関数やユーザ定義命令・関数のパラメータに関する情報。 ax の MINFO にこれの配列が格納されている。
typedef struct STRUCTPRM { short mptype; // Parameter type short subid; // struct index int offset; // offset from top } STRUCTPRM;
- mptype
- パラメータのタイプ。MPTYPE_*** のいずれかの値。
- subid
- FINFO のインデックス。または STRUCTPRM_SUBID_*** のいずれかの値。
- offset
- 同じ関数の先頭パラメータからのオフセット。たとえば、 #deffunc foo int a, double b, var c だったら int a は 0, double b は sizeof(int) で 4, var c は sizeof(int) + sizeof(double) で 12。
MPTYPE 一覧
名前 | 値 | 説明 | |
---|---|---|---|
MPTYPE_NONE | 0 | ||
MPTYPE_VAR | 1 | ||
MPTYPE_STRING | 2 | ||
MPTYPE_DNUM | 3 | double | |
MPTYPE_INUM | 4 | int | |
MPTYPE_STRUCT | 5 | ||
MPTYPE_LABEL | 7 | label | |
MPTYPE_LOCALVAR | -1 | ユーザ定義関数の local | |
MPTYPE_ARRAYVAR | -2 | ユーザ定義関数の array | |
MPTYPE_SINGLEVAR | -3 | ユーザ定義関数の var | |
MPTYPE_FLOAT | -4 | DLL 関数の float | |
MPTYPE_STRUCTTAG | -5 | モジュール変数定義の最初につけられるパラメータ。*1 | |
MPTYPE_LOCALSTRING | -6 | str | |
MPTYPE_MODULEVAR | -7 | #modfunc の最初につけられるパラメータ | |
MPTYPE_PPVAL | -8 | DLL 関数の pval | |
MPTYPE_PBMSCR | -9 | DLL 関数の bmscr | |
MPTYPE_PVARPTR | -10 | DLL 関数の var | |
MPTYPE_IMODULEVAR | -11 | #modinit の最初につけられるパラメータ | |
MPTYPE_IOBJECTVAR | -12 | DLL 関数の comobj *2 | |
MPTYPE_LOCALWSTR | -13 | DLL 関数の wstr | |
MPTYPE_FLEXSPTR | -14 | DLL 関数の sptr | |
MPTYPE_FLEXWPTR | -15 | DLL 関数の wptr | |
MPTYPE_PTR_REFSTR | -16 | DLL 関数の prefstr | |
MPTYPE_PTR_EXINFO | -17 | DLL 関数の pexinfo | |
MPTYPE_PTR_DPMINFO | -18 | #func に数値を指定したとき 0x20 を立てると第四引数がこれになる | |
MPTYPE_NULLPTR | -19 | DLL 関数の nullptr | |
MPTYPE_TMODULEVAR | -20 | #modterm の最初につけられるパラメータ |
MPTYPE_STRING や MPTYPE_STRUCT は ax には現れることはないが、実行時に内部で使っているようだ。
MPTYPE_STRING, MPTYPE_DNUM, MPTYPE_INUM, MPTYPE_STRUCT は HSPVAR_FLAG_STR, HSPVAR_FLAG_DOUBLE, HSPVAR_FLAG_INT, HSPVAR_FLAG_STRUCT と同じ値である。 MPTYPE_LABEL と HSPVAR_FLAG_LABEL は違う値。
STRUCTPRM_SUBID_***
STRUCTDAT や STRUCTPRM の subid メンバに格納されることがある値。
STRUCTPRM_SUBID_STACK は TYPE_STRUCT でモジュール変数のメンバか、関数のパラメータかを識別するためにあるようだ。ユーザ定義命令・関数の STRUCTDAT::subid やそのパラメータの STRUCTPRM::subid はすべて STRUCTPRM_SUBID_STACK になっていた。ユーザ定義命令・関数のSTRUCTDAT::subidは STRUCTPRM_SUBID_STACK ではなく、 FINFO ID でした。勘違いしてました。ただし、mptype が MPTYPE_MODULEVAR, MPTYPE_IMODULEVAR, MPTYPE_TMODULEVAR のいずれかである STRUCTPRM では subid にモジュール変数定義の FINFO インデックスが格納されていた。
STRUCTPRM_SUBID_STID はコンパイル中に内部で使用するためのものらしい。ひとまず STRUCTPRM_SUBID_STID を格納しておいて、後からそれを FINFO インデックスに置き換えるようだ。
#define STRUCTPRM_SUBID_STACK -1 #define STRUCTPRM_SUBID_STID -2 #define STRUCTPRM_SUBID_DLL -3 #define STRUCTPRM_SUBID_DLLINIT -4 #define STRUCTPRM_SUBID_OLDDLL -5 #define STRUCTPRM_SUBID_OLDDLLINIT -6 #define STRUCTPRM_SUBID_COMOBJ -7