NO.1001:mdl_wr_logモジュール(マクロ?)

mdl_wr_logモジュール(マクロ?)

TACKはスクリプトを書くとき、不安があります
例えば代入した時に、きちんと代入されているか?
綴りは間違っていないか?
代入された値は何か?
短いスクリプトなら、代入式の近くに代入される値があるからいいんだけど
代入と代入する値が遠い時、不安になります
もしくは
代入と代入する値を書いた日が一緒の日ならいいんだけど
代入する値を書いて、後日その値を代入したりする時も不安になります
そう思うのは決まって、ゲームを作っている時です(たいしたの作ったことないけどw)
(ゲームのスクリプトは一日でガーッと作れないし、スクリプト自体長いし...)

今作っているしょぼいゲームに、シナリオをログ出力する処理を書いたんですが
案外、短いスクリプトでその処理を書けたので
代入の変数と値もログ出力してみようと思い立ち
ログ出力モジュール(マクロ?)を書いてみました
ついでに命令呼び出しもログ出力しようということで、その処理も追加しました

例えばスキルレベルによって、消費スキルポイントが違う時
さらにはダンジョンのレベルでも消費スキルポイントが違う時
全組み合わせをデバッグするのは無理なので
引数で渡す変数の名前と値がログ出力して
例えばスキルレベルを1、2、3のどれか
ダンジョンレベルを1、2、3のどれかとすると
デバッグするには9通り必要なのですが
スキルレベルを1、2、3の3通り渡されたことを確認して
ダンジョンレベルも1、2、3通り渡されたことを確認すると
6通りのデバッグで済みます(ログ出力するのできちんと渡したか確認できます)
3通りだとメリットも少ないですが
レベルがそれぞれ1から9だと81通りになります
渡す値それぞれ1から9と1から9を確認するのは18通りです
複合的なデバッグは自作の命令を機械的にデバッグする予定です

というわけでこのモジュールは
渡す変数と値
もしくは代入する変数と値をログ出力させて確認するのに作成しました

注:このスクリプトを実行する時の注意点
mdl_wr_log.hspの中でテキストファイル(この場合txt_from_log.txt)を
読み込んでいるので、あらかじめテキストファイルを用意しておいて下さい

ファイル名:mdl_wr_log.hsp
#include "multi_str_array.hsp"

#module wr_save_log
#define MY_DBG
//    このマクロが有効だとデバッグ情報出力
//    無効にしたい場合はコメントアウトして下さい
#define WR_LOG
//    このマクロが有効だとデバッグ情報をログに出力
//    無効にしたい場合はコメントアウトして下さい
#define WR_FILE
//    このマクロが有効だとデバッグ情報をファイルに出力
//    無効にしたい場合はコメントアウトして下さい
#define SAVE_CNT 10    //    ノートパッドにこの数だけ書き込んだらファイルに保存

//    初期化処理 配列/変数の確保 と ログをインスタンスi_ms_arに読み込む
#deffunc note_read_log_init
#ifdef MY_DBG
log_no=0    //    logに出力されるナンバーの初期値
#ifdef WR_FILE
log_cnt=0
sdim log_str,256000    //    ノートパッド命令用の文字列変数
sdim set_txt,2048    //    ノートパッドに一行書き込む際に用いる文字列変数
newmod i_ms_ar,multi_str_array,1024
#define READ_FILE "txt_from_log.txt"    //    noteload,notesave命令で読み書きするファイル名
arrayload_at_multi_str_array i_ms_ar,READ_FILE
r=""
get_youso_at_multi_str_array i_ms_ar,r
if r==""{set_youso_at_multi_str_array i_ms_ar,"0",0}
log_no=int(r)
#endif
#endif
return

//    ログをファイルに書き出す処理
//    log_cntを+1してSAVE_CNTに達したら書き出す
#deffunc count_log
#ifdef MY_DBG
#ifdef WR_FILE
log_cnt++
if log_cnt==SAVE_CNT{
arraysave_at_multi_str_array i_ms_ar,READ_FILE
log_cnt=0
}
#endif
#endif
return

//    ログをインスタンスi_ms_arにpush
#deffunc addlog str to_file_str
#ifdef MY_DBG
#ifdef WR_FILE
push_youso_at_multi_str_array i_ms_ar,to_file_str
#endif
#endif
return
//    ログを強制的にファイルに書き出す処理
//    log_cntがSAVE_CNTに達してなくても書き出す
#deffunc addlog_rest
#ifdef MY_DBG
#ifdef WR_FILE
arraysave_at_multi_str_array i_ms_ar,READ_FILE
log_cnt=0
#endif
#endif
return
//    ログ出力
#deffunc output str p_str
#ifdef MY_DBG
#ifdef WR_LOG
logmes p_str
#endif
#ifdef WR_FILE
addlog p_str
#endif
#endif
return
//    ログは一行目に書き出したログの数を記入しているのですが
//    その書き出したログの数をファイルの一行目に書き出す処理
#deffunc set_log_no
#ifdef WR_FILE
set_youso_at_multi_str_array i_ms_ar,str(log_no),0
#endif
return
#ifdef MY_DBG

//    ログに行とファイル名を書き出すマクロ
#define wr_file_and_line:\
set_txt = "file:"+__file__:output set_txt:\
set_txt = "line:"+__line__:output set_txt:output ""
//    ログに代入文を出力するマクロ
#define ctype wr_one_line(%1)set_txt = "%1 = "+%1:output set_txt

//    ログに一行出力するマクロ
#define ctype wr_one_mes(%1):\
set_txt = %1:output set_txt

//    一件のログの終わりを出力
#define sep_end output "sep_end":output "":count_log

//    一行のログを出力
#define ctype wr_log_one_mes(%1):\
set_txt = "sep one mes":output set_txt:\
set_txt = "log count = "+log_no@wr_save_log:output set_txt:\
set_txt = %1:output set_txt:log_no@wr_save_log++:sep_end@wr_save_log

//    複数行のログの出力の最初の出力
//    ログは、wr_mesマクロで出力して
//    最後に、wr_end_mesマクロでログ出力を終了します
#define wr_begin_mes:\
set_txt = "sep begin of mes":output set_txt:set_log_no:\
set_txt = "log count = "+log_no@wr_save_log:output set_txt:\
log_no@wr_save_log++:wr_file_and_line@wr_save_log

//    複数行ログ出力の中身
#define ctype wr_mes(%1) output %1

//    複数行ログ出力の終了処理
#define wr_end_mes sep_end@wr_save_log

//    代入処理のログ出力の先頭処理
#define ctype sep_begin_of_set(%1):\
set_txt = "sep begin of set : %1":output set_txt:set_log_no:\
set_txt = "log count = "+log_no@wr_save_log:output set_txt:log_no@wr_save_log++

//    命令呼び出しのログ出力の先頭処理
#define ctype sep_begin_of_func(%1):\
set_txt = "sep begin of func : %1":output set_txt:set_log_no:\
set_txt = "log count = "+log_no@wr_save_log:output set_txt:log_no@wr_save_log++
#else

//    モジュールを使用しない時の処理
#define wr_file_and_line /**/
#define ctype wr_one_mes(%1)/**/
#define ctype wr_log_one_mes(%1)/**/
#define wr_begin_mes /**/
#define ctype wr_mes(%1)/**/
#define wr_end_mes /**/
#define ctype sep_begin_of_set(%1)/**/
#define ctype sep_begin_of_func(%1)/**/
#define sep_end /**/
#define ctype wr_one_line(%1)/**/

#endif

#ifdef MY_DBG

//    代入処理のログ出力
#define ctype wr_set(%1,%2)%1=%2:\
sep_begin_of_set@wr_save_log(%1):wr_file_and_line@wr_save_log:\
set_txt = "%1 <- %2("+%2+")":output set_txt:sep_end@wr_save_log

//    引数が無しの命令呼び出しのログ出力
#define ctype wr_func_p_is_0(%1)%1:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1":\
sep_end@wr_save_log

//    引数が一つの命令呼び出しのログ出力
#define ctype wr_func_p_is_1(%1,%2)%1 %2:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2)":\
wr_one_line@wr_save_log(%2):\
sep_end@wr_save_log

//    引数が二つの命令呼び出しのログ出力
#define ctype wr_func_p_is_2(%1,%2,%3)%1 %2,%3:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):\
sep_end@wr_save_log

//    引数が三つの命令呼び出しのログ出力
#define ctype wr_func_p_is_3(%1,%2,%3,%4) %1 %2,%3,%4:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
sep_end@wr_save_log

//    引数が四つの命令呼び出しのログ出力
#define ctype wr_func_p_is_4(%1,%2,%3,%4,%5) %1 %2,%3,%4,%5:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4,%5)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
wr_one_line@wr_save_log(%5):\
sep_end@wr_save_log

//    引数が五つの命令呼び出しのログ出力
#define ctype wr_func_p_is_5(%1,%2,%3,%4,%5,%6)    %1 %2,%3,%4,%5,%6:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4,%5,%6)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
wr_one_line@wr_save_log(%5):wr_one_line@wr_save_log(%6):\
sep_end@wr_save_log

//    引数が六つの命令呼び出しのログ出力
#define ctype wr_func_p_is_6(%1,%2,%3,%4,%5,%6,%7):\
%1 %2,%3,%4,%5,%6,%7:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4,%5,%6,%7)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
wr_one_line@wr_save_log(%5):wr_one_line@wr_save_log(%6):wr_one_line@wr_save_log(%7):\
sep_end@wr_save_log

//    引数が七つの命令呼び出しのログ出力
#define ctype wr_func_p_is_7(%1,%2,%3,%4,%5,%6,%7,%8):\
%1 %2,%3,%4,%5,%6,%7,%8:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4,%5,%6,%7,%8)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
wr_one_line@wr_save_log(%5):wr_one_line@wr_save_log(%6):wr_one_line@wr_save_log(%7):\
wr_one_line@wr_save_log(%8):\
sep_end@wr_save_log

//    引数が八つの命令呼び出しのログ出力
#define ctype wr_func_p_is_8(%1,%2,%3,%4,%5,%6,%7,%8,%9):\
%1 %2,%3,%4,%5,%6,%7,%8,%9:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4,%5,%6,%7,%8,%9)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
wr_one_line@wr_save_log(%5):wr_one_line@wr_save_log(%6):wr_one_line@wr_save_log(%7):\
wr_one_line@wr_save_log(%8):wr_one_line@wr_save_log(%9):\
sep_end@wr_save_log

//    引数が九つの命令呼び出しのログ出力
#define ctype wr_func_p_is_9(%1,%2,%3,%4,%5,%6,%7,%8,%9,%10):\
%1 %2,%3,%4,%5,%6,%7,%8,%9,%10:\
sep_begin_of_func@wr_save_log(%1):wr_file_and_line@wr_save_log:\
output "func %1(%2,%3,%4,%5,%6,%7,%8,%9,%10)":\
wr_one_line@wr_save_log(%2):wr_one_line@wr_save_log(%3):wr_one_line@wr_save_log(%4):\
wr_one_line@wr_save_log(%5):wr_one_line@wr_save_log(%6):wr_one_line@wr_save_log(%7):\
wr_one_line@wr_save_log(%8):wr_one_line@wr_save_log(%9):wr_one_line@wr_save_log(%10):\
sep_end@wr_save_log

#else

//    モジュールを使用しない時の処理
#define ctype wr_set(%1,%2)%1=%2
#define ctype wr_func_p_is_0(%1)%1
#define ctype wr_func_p_is_1(%1,%2)%1 %2
#define ctype wr_func_p_is_2(%1,%2,%3)%1 %2,%3
#define ctype wr_func_p_is_3(%1,%2,%3,%4) %1 %2,%3,%4
#define ctype wr_func_p_is_4(%1,%2,%3,%4,%5) %1 %2,%3,%4,%5
#define ctype wr_func_p_is_5(%1,%2,%3,%4,%5,%6)    %1 %2,%3,%4,%5,%6
#define ctype wr_func_p_is_6(%1,%2,%3,%4,%5,%6,%7):\
%1 %2,%3,%4,%5,%6,%7
#define ctype wr_func_p_is_7(%1,%2,%3,%4,%5,%6,%7,%8):\
%1 %2,%3,%4,%5,%6,%7,%8
#define ctype wr_func_p_is_8(%1,%2,%3,%4,%5,%6,%7,%8,%9):\
%1 %2,%3,%4,%5,%6,%7,%8,%9
#define ctype wr_func_p_is_9(%1,%2,%3,%4,%5,%6,%7,%8,%9,%10):\
%1 %2,%3,%4,%5,%6,%7,%8,%9,%10

#endif
#global

このモジュールを使用する時は、以下のテストコードを参考にして下さい
#include "mdl_wr_log.hsp"
//    テストコード用命令定義
goto *@f
#deffunc Hello
mes "Hello"
return
#deffunc say str p1
mes "say "+p1
return
#deffunc add_1 var to_ret,int to_add_1
to_ret=to_add_1+1
return
#deffunc add var to_ret,int to_add1,int to_add2
to_ret=to_add1+to_add2
return
#deffunc sum_3  var to_ret,int p1,int p2,int p3
to_ret=p1+p2+p3
return
#deffunc sum_4  var to_ret,int p1,int p2,int p3,int p4
to_ret=p1+p2+p3+p4
return
#deffunc sum_5  var to_ret,int p1,int p2,int p3,int p4,int p5
to_ret=p1+p2+p3+p4+p5
return
#deffunc sum_6  var to_ret,int p1,int p2,int p3,int p4,int p5,int p6
to_ret=p1+p2+p3+p4+p5+p6
return
#deffunc sum_7  var to_ret,int p1,int p2,int p3,int p4,int p5,int p6,int p7
to_ret=p1+p2+p3+p4+p5+p6+p7
return
#deffunc sum_8  var to_ret,int p1,int p2,int p3,int p4,int p5,int p6,int p7,int p8
to_ret=p1+p2+p3+p4+p5+p6+p7+p8
return
*@

//    ログ出力モジュールのテストコード
note_read_log_init

wr_one_mes@wr_save_log("abc")

wr_log_one_mes@wr_save_log("12345")

wr_begin_mes@wr_save_log
wr_mes@wr_save_log("あいうえお")
wr_mes@wr_save_log("かきくけこ")
wr_mes@wr_save_log("さしすせそ")
wr_end_mes@wr_save_log

a=0
b=10
wr_set@wr_save_log(a,b)

wr_func_p_is_0@wr_save_log(Hello)

s="hoo!"
wr_func_p_is_1@wr_save_log(say,s)

n=20
r=0
wr_func_p_is_2@wr_save_log(add_1,r,n)
mes r

n=3
m=6
r=0
wr_func_p_is_3@wr_save_log(add,r,m,n)
mes r

a=8
b=70
c=600
d=5000
e=40000
f=300000
g=2000000
h=10000000

r=0
wr_func_p_is_4@wr_save_log(sum_3,r,a,b,c)
mes r

r=0
wr_func_p_is_5@wr_save_log(sum_4,r,a,b,c,d)
mes r

r=0
wr_func_p_is_6@wr_save_log(sum_5,r,a,b,c,d,e)
mes r

r=0
wr_func_p_is_7@wr_save_log(sum_6,r,a,b,c,d,e,f)
mes r

r=0
wr_func_p_is_8@wr_save_log(sum_7,r,a,b,c,d,e,f,g)
mes r

r=0
wr_func_p_is_9@wr_save_log(sum_8,r,a,b,c,d,e,f,g,h)
mes r

addlog_rest
stop

なお、このモジュールはHSP開発wikiに投稿したmulti_str_arrayモジュールを使用しています
一応掲載しますが、問題があればゲストブックにでも報告して下さい


ファイル名:multi_str_array.hsp
#module multi_str_array str_array,count,index
#modinit int size
// インスタンス作成。文字列配列str_arrayを、大きさsizeの一次元配列で確保
sdim str_array,128,size
count = 0:index = 0
return
#modfunc secure_at_multi_str_array int size
//    文字列配列str_arrayを確保しなおす
sdim str_array,128,size
count = 0:index = 0
return

//    getterとsetter
#modfunc get_count_at_multi_str_array var to_ret
//    モジュール変数countの値をto_retに代入して取得
to_ret = count
return
#modfunc set_youso_at_multi_str_array str to_set,int _index
//    文字列配列str_arrayの_indexの要素へto_setを代入
//    要素がcountより大きい場合、代入は行わず、statに-1を代入
if _index > count{return -1}
str_array._index = to_set
return 1
#modfunc get_youso_at_multi_str_array var to_ret,int _index
//    文字列配列str_arrayの_indexの要素をto_getに代入して取得
//    要素がcountより大きい場合、to_retに空文字列を代入して、statに-1を代入
if _index > count{to_ret="":return -1}
to_ret = str_array._index
return 1

//    文字列のpushとpop
#modfunc push_youso_at_multi_str_array str to_push
//    文字列配列str_arrayに引数として受け取ったto_pushの値を追加
str_array.count = to_push
count++
return
#modfunc pop_youso_at_multi_str_array var to_pop
//    文字列配列str_arrayの最後の要素を変数to_popに代入して取得
//    文字列配列str_arrayの最後の要素は空文字列になる(削除のつもり)
count--
to_pop = str_array.count
str_array.count = ""
return

//    ノートパッド関連命令を改造した命令
#modfunc array2note_at_multi_str_array var note_str
//    文字列配列str_arrayを配列じゃない文字列変数note_strに展開
note_str = ""
if count >= 1{note_str+=str_array.0}
repeat (count-1),1
note_str+="\n"+str_array.cnt
loop
return
#modfunc note2array_at_multi_str_array var note_str
//    文字列変数note_strをノートパッド命令の対象にして
//    文字列配列str_arrayにコピー。配列の大きさをcountに確保
notesel note_str
count = notemax
if notemax > length(str_array){sdim str_array,128,notemax}
repeat notemax
noteget str_array.cnt, cnt
loop
noteunsel
return
#modfunc arraysave_at_multi_str_array str p_file_name,local p_str_tmp
//    モジュール変数(配列)を連結してファイルに保存します
//    複数行文字列に変換して保存します
array2note_at_multi_str_array thismod,p_str_tmp
notesel p_str_tmp
notesave p_file_name
noteunsel
return
#modfunc arrayload_at_multi_str_array str p_file_name,local p_str_tmp
//    テキストファイルをモジュール変数(配列)に読み込みます
//    読み込んだ複数行文字列の各行を配列要素に変換します
notesel p_str_tmp
noteload p_file_name
noteunsel
note2array_at_multi_str_array thismod,p_str_tmp
return

//    ノートパッド命令を使用した、要素の追加、削除、及び
//    命令の初期処理と終了処理

//    begin_add_or_del_at_multi_str_array命令を呼び出して
//    その中で、noteselを使っていて
//    finish_add_or_del_at_multi_str_array命令の中で
//    noteunselを使用しているので
//    begin_add_or_del_at_multi_str_array命令を呼び出してから
//    finish_add_or_del_at_multi_str_array命令のを呼び出すまで
//    notesel命令でノートパッド命令の対象を変更しないで下さい
//    notesel命令でノートパッド命令の対象を変更したい時は
//    一度、finish_add_or_del_at_multi_str_array命令を使用して、追加、削除を終了して
//    また、追加、削除したい時に、begin_add_or_del_at_multi_str_array命令を呼び出して下さい

#modfunc begin_add_or_del_at_multi_str_array
//    ノートパッドにモジュール変数(配列)を出力して
//    それに、要素の追加用にノートパッド命令の対象にする
//    noteadd_at_multi_str_array命令、及び
//    notedel_at_multi_str_array命令を呼び出す前に使用する
sdim var_of_inner2note,4096
array2note_at_multi_str_array thismod,var_of_inner2note
notesel var_of_inner2note
return
#modfunc noteadd_at_multi_str_array str to_add,int index_to_add,int mode_to_add
//    ノートパッドに要素を追加する
noteadd to_add,index_to_add,mode_to_add
return
#modfunc notedel_at_multi_str_array int index_to_del
//    ノートパッドから要素を削除する
notedel index_to_del
return
#modfunc finish_add_or_del_at_multi_str_array
//    ノートパッドの対象を配列に展開する
//    noteadd_at_multi_str_array命令、及び
//    notedel_at_multi_str_array命令で、要素の追加、削除
//    を行った後に呼び出す
count = notemax
if notemax > length(str_array){sdim str_array,128,notemax}
repeat notemax
noteget str_array.cnt, cnt
loop
sdim var_of_inner2note,1
noteunsel
return
//    文字列連続出力用の命令
#modfunc output_begin_at_multi_str_array
//    文字列連続出力の準備
index = 0
if count <= 0 { return -1 }
return 1
#modfunc output_at_multi_str_array var to_ret
//    文字列連続出力命令
if index >= count { return -1 }
to_ret = str_array.index
index++
return 1

//    デバッグ用命令
#modfunc logmes_at_multi_str_array
//    文字列配列str_arrayの値をログ出力(デバッグ用)
logmes "count = "+count
repeat count
logmes str_array.cnt
loop
return
#modfunc print_at_multi_str_array
//    文字列配列str_arrayの値を出力(デバッグ用)
repeat count
mes str_array.cnt
loop
return
#global