概要
このシリーズはHSPの.ax
ファイルの作成をするhspcmpを読んでいくものです。
間違いに気づいた方や、加筆すべきポイントを見つけた人はコメントで指摘してください。
今回はhspcmp(exe版)の最新のコードを読む 2-1 ~membuf.cpp/.h編~の続きになります。
あとここに掲載されたコードは
Hot Soup Processor (HSP) / OpenHSP Copyright (c) 1997-2020, onion software/onitama in collaboration with Sencha, Yume-Yume Yuuka, Y-JINN, chobin, Usuaji, Kenji Yuukoku, puma, tom, sakura, fujidig, zakki, naznyark, Lonely Wolf, Shark++, HyperPageProject, Chokuto, S.Programs, Yuki, K-K, USK, NGND001, yoshis, naka, JET, eller, arue, mjhd_otsuka, tds12 All rights reserved.
から一部改変したものです。
必要に応じて元のコードからインデントを調整したり、空行を省いています。
あと、これは2023/06/23時点のコードになります。
以前別名義で投稿していたものをほぼそのまま再投稿したものです。
またこれらのコードはOpenHSP 3.6のコードに基づいているため、3.6正式版や最新(3.7β)のものと異なる可能性があることに注意してください。
membuf.cpp(membuf.h)
hspcmp.exe内で文字列を扱うためのバッファとして使われています。
また、使い方には大きく分けて以下の3つがあります。
- プリプロセスするファイルの格納
- プリプロセスとコンパイル時のメッセージの格納
- 生成する
.ax
ファイルの格納
今回はこの3つの使い方のうち、主に最後の一つに関係するメソッドを紹介します。
CMemBufクラス
これがmembuf.cpp/hの本体です。
フィールド(一部)
- int idxflag
-
idxbuf
がInitIndexBufメソッドでメモリを確保されているかどうか。確保されていたら1
、確保されていなければ0
が代入されます。
-
- int *idxbuf
- 配列的に使われています。
- int idxmax
-
idxbuf
が何Byte分確保されているか。
-
- int curidx
-
idxbuf
の最終インデックス番号。いまどれだけidxbuf
が使われているのかをも示します。
-
AddIndexBufferメソッド
2種類のコンストラクタがありますが、idxbuf
を256Byteか指定バイト分で初期化するように引数を取っているだけで、初期化の処理はInitIndexBufメソッドに丸投げしています。
引数(一つ目の方)
なし(void)
コードを見てみる(一つ目の方)
void CMemBuf::AddIndexBuffer( void )
{
InitIndexBuf( 256 );
}
idxbuf
を256Byteで初期化することになります。
引数(二つ目の方)
コードを見てみる
void CMemBuf::AddIndexBuffer( int sz )
{
InitIndexBuf( sz );
}
idxbuf
をsz
Byteで初期化することになります。
InitIndexBufメソッド
引数
- int sz
-
idxbuf
を何byte分確保するか。
-
コードを見てみる
void CMemBuf::InitIndexBuf( int sz )
{
// Indexバッファ初期化
idxflag = 1;
idxmax = sz;
curidx = 0;
idxbuf = (int *)malloc( sizeof(int)*sz );
}
ここでフィールドを初期化しています。それぞれがどの値に初期化されるかはコードを見てください。
デストラクタ
mem_buf
とidxbuf
とをfree
を使って解放しています。
(前回のやつで一部紹介しています。)
コードを見てみる
CMemBuf::~CMemBuf( void )
{
if ( mem_buf != NULL ) {
free( mem_buf );
mem_buf = NULL;
}
if ( idxbuf != NULL ) {
free( idxbuf );
idxbuf = NULL;
}
}
membuf
はInitMemBufメソッドで、idxbuf
はInitIndexBufメソッドでmalloc
を用いてメモリを確保しておりfree
でメモリを解放する必要があるので、ここでそれをやっていますね。
GetSizeメソッド
cur
の値を返します。
GetBufferメソッド
mem_buf
の値を返します。
GetBufferSizeメソッド
size
の値を返します。
GetIndexBufferメソッド
idxbuf
の値を返します。
GetFileNameメソッド
name
の値を返します。
GetIndexメソッド
指定したインデックスの値を返します。指定したインデックスがなければ0が返されます。
引数
- int idx
- 指定するインデックス番号
コードを見てみる
int CMemBuf::GetIndex( int idx )
{
if ( idxflag==0 ) return 0;
if ((idx < 0) || ( idx>=curidx)) return 0;
return idxbuf[idx];
}
ここでは、idxbuf
が初期化されているかどうかを判断して指定するインデックスが本当に存在するのかを調べて、なければ0
が返され、あればそのインデックスの値(idxbuf[idx]
)が返されます。
GetIndexBufferSizeメソッド
今idxbuf
が何Byte使われているかを示します。そもそもidxbuf
がメモリ確保されていなければ-1
が返されます。
引数
なし(void)
コードを見てみる
int CMemBuf::GetIndexBufferSize( void )
{
if ( idxflag==0 ) return -1;
return curidx;
}
idxflag
が0
かどうかでidxbuf
が確保されているかを判断して、確保されていればcuridx
の値を返します。
なぜここで返す値がcuridx
でよいのかというと、curidx
はidxflag
のポインタの代わりのようなものであり、その値を調べることで現在idxflag
が何Byte使われているのかがわかるからです。
SearchIndexValueメソッド
指定した値が登録されているかどうかを調べ、登録されていればidxbuf
の何番目に登録されているかが、そうでなければ-1
が返されます。
引数
- int val
- 調べる値
使われている変数
- int i
-
for
の添字。この値が返されます。
-
コードを見てみる
int CMemBuf::SearchIndexValue( int val )
{
int i;
if ( idxflag==0 ) return -1;
for(i=0;i< curidx;i++) {
if ( idxbuf[i] == val ) return i;
}
return -1;
}
初めにそもそもidxbuf
が初期化(メモリの確保)がされているかを確認し、確保されていなければ-1
が返されます。
次にfor
で全探索して値がヒットすればその時のi
の値が、ヒットしなければ-1
が返されます。
SearchIndexedDataメソッド
mem_buf
の末尾とidexbuf
の一つを合わせたものと指定した文字が指定したByte分が一致するかどうかを調べます。
一致しなければ-1
が、一致すればその時合わせたidexbuf
の値が返されます。
引数
- char* data
- 調べる文字列
- int size
- 指定するByte数
使われている変数
- int i
-
for
で使う添字
-
- int j
- この値が返される。
- int sz
-
size
か、data
の文字数(ヌル文字含む)
-
コードを見てみる
int CMemBuf::SearchIndexedData(char* data, int size)
{
int i; int j;
int sz = size;
if (idxflag == 0) return -1;
if (sz < 0) sz = (int)strlen(data)+1;
if (sz == 0) return -1;
ここまでで、idxbuf
の初期化(メモリの確保)がされているかを確認して、変数の定義やsz
の設定をしています。
j = -1;
for (i = 0; i < curidx; i++) {
char* p = mem_buf + idxbuf[i];
if (memcmp( p, data, sz )==0) j = idxbuf[i];
}
return j;
}
ここでmem_buf
のポインタとidexbuf[i]
とを合わせたものとdata
が、初めからsz
Byte分一致するかどうかを調べます。
一致すればidexbuf[i]
を、一致しなければ-1
を返します。
SetIndexメソッド
指定したインデックスに指定した値を代入します。
idxbuf
の最後に登録したいときは、RegistIndexメソッドを使います。
引数
- int idx
- 値を登録したい
idxbuf
の番号。
- 値を登録したい
- int val
- 登録したい値。
コードを見てみる
void CMemBuf::SetIndex( int idx, int val )
{
if ( idxflag==0 ) return;
idxbuf[idx] = val;
}
初めにそもそもidxbuf
が初期化(メモリの確保)がされているかを確認して値(val
)をidxbuf[idx]
に登録しています。
RegistIndexメソッド
引数で指定した値をidxbuf
の末尾に追加します。
引数
- int val
-
idxbuf
に追加する値。
-
使われている変数
- int *p
- これを操作して値を代入する。
コードを見てみる
void CMemBuf::RegistIndex( int val )
{
int *p;
if ( idxflag==0 ) return;
idxbuf[ curidx++ ]= val;
if ( curidx >= idxmax ) {
idxmax+=256;
p = (int *)malloc( sizeof(int)*idxmax );
memcpy( p, idxbuf, sizeof(int)*curidx );
free( idxbuf );
idxbuf = p;
}
}
初めにそもそもidxbuf
が初期化(メモリの確保)がされているかを確認して値(val
)をidxbuf[curidx++]
に登録しています。
そのあと、次に書き込むときにcuridx
がidxbuf
のメモリ確保分を超えてしまうかどうかチェックして、超えていたら256Byte追加でidxbuf
を確保します。
Indexメソッド
引数がcur
のRegistIndexメソッドを呼び出します。
つまり、cur
の値を追加します。
IndexExclusiveメソッド
現在のcur
の値が登録されているかどうかを確認して、登録されていなければその値をidxbuf
の末尾に追加します。
引数
なし(void)
コードを見てみる
void CMemBuf::IndexExclusive(void)
{
if (SearchIndexValue(cur) < 0) {
RegistIndex(cur);
}
}
SearchIndexValueメソッドでcur
の値が登録されているかどうかを確認して、登録されていなければその値をRegistIndexメソッドで登録してます。
ReduceSizeメソッド
新しいcur
の値を指定します。
引数
- int new_cur
- 新しい
cur
の値
- 新しい
コードを見てみる
void CMemBuf::ReduceSize( int new_cur )
{
assert( new_cur >= 0 && new_cur <= cur );
cur = new_cur;
}
単にcur
にnew_cur
を代入するだけです。
PutStrDQメソッド
ダブルクオート内のデータをmem_buf
に書き込みます。
執筆時点ではこのメソッドはhspcmp.exe内で使用されていません。
引数
- char *data
-
mem_buf
に書き込むダブルクオート内の文字列。
-
SaveFileメソッド
mem_buf
の内容を指定したファイルに書き出します。
書き出しに成功すればファイルサイズが、失敗すれば-1
が返されます。
引数
- char *fname
- セーブするときのファイル名
使われている変数
- FILE *fp
- ファイルを操作するときに必要な奴。(C#でいうところの
Stream
に近い)
- ファイルを操作するときに必要な奴。(C#でいうところの
- int flen
- 書き込んだファイルのファイルサイズ。
コードを見てみる
int CMemBuf::SaveFile( char *fname )
{
FILE *fp;
int flen;
fp=fopen(fname,"wb");
if (fp==NULL) return -1;
ここまででファイルを開いてfp
を設定しています。
もしファイルが見つからなかったときは-1
を返すようになっています。
flen = fwrite( mem_buf, 1, cur, fp );
fclose(fp);
strcpy( name,fname );
return flen;
}
ここでファイルfp
にmem_buf
を書き込んで、ファイル操作を終了しています。
そのあとname
にfname
をコピーして書き込んだファイルの(実質的に)ファイルサイズを返しています。
次は
次回は、tagstack.cpp/.hを解説します。
hspcmp(exe版)のコードを読む 3 ~tagstack.cpp/.h編~