2004/12/26 森川靖大
dc_trace はデバッグ時の原因の追跡を補助するためのサブルーチン群を持つモジュールです。 このモジュールを利用する事で、以下のようにサブルーチンの階層構造がそのまま 分かるようなデバッグメッセージを出力する事が可能です。
: #call HistoryPut0 #| call HistoryPutEx : time #| | call TimeGoAhead : varname=time head=1. #| | | call lookup_dimension #| | | | call gtvarinquire : var.mapid=1 #| | | | | call anvarinqurie : var.id=1 #| | | | | end anvarinqurie : ok #| | | | |-name=time #| | | | end gtvarinquire #| | | end lookup_dimension : ord=1 #| | | call gtvarslice : var%mapid=1 dimord=1 #| | | |-[gt_variable 1: ndims=1, map.size=1] #| | | |-[dim1 dimno=1 ofs=0 step=1 all=0 start=1 count=0 stride=1 url=] #| | | |-[vartable 1: class=netcdf cid=1 ref=1] #| | | |-[AN_VARIABLE(file=3, var=1, dim=1)] #| | | |-map(dimord): originally start=1 count=0 stride=1 #| | | |-start=1 (1 specified) #| | | |-count=1 (1 specified) #| | | end gtvarslice #| | end TimeGoAhead #| |-anfiledefinemode #| end HistoryPutEx #end HistoryPut0 :
subroutine SetDebug(debug) integer, intent(in), optional:: debug end subroutine
デバッグメッセージを出力したい時にこのサブルーチンを呼びます。
整数型変数 debug が与えられる場合は、その装置番号 debug に、 以降のサブルーチンによるデバッグメッセージを出力するようにします。 debug が与えられない場合、装置番号 0 (標準エラー出力) にデバッグメッセージが出力されるようになります。装置番号 0 への出力が成功しない場合は代わりに装置番号 6 (標準出力) にデバッグメッセージが出力されるようになります。
debug に負の整数を与える場合、デバッグモードが解除され、 以降デバッグメッセージは出力されません。
なお、この SetDebug を呼んだ際にも、装置番号 debug に以下のメッセージ が表示されます。
#SetDebug: dbg = debug
subroutine BeginSub(name, fmt, i, r, d, L, s, n, c1, c2, c3) character(*), intent(in) :: name character(*), intent(in), optional:: fmt integer, intent(in), optional:: i(:), n(:) real, intent(in), optional:: r(:) real(8), intent(in), optional:: d(:) logical, intent(in), optional:: L(:) type(vstring),intent(in), optional:: s(:) character(*), intent(in), optional:: c1, c2, c3 end subroutine
文字型変数 name に与えた副プログラム名を以下のように出力します。
# call name
複数回呼ぶ事で上記のようにメッセージが 出力されます。
また、文字型変数 fmt およびそれ以降の引数を与える事で、 以下のように付加メッセージも出力可能です。 fmt とそれ以降の引数に関する書式は dc_string モジュールの CPrintf の説明を参照して下さい。
# call name : fmt
以下に利用例を示します。 BeginSub よりも前に SetDebug が呼ばれている必要があります。 また、BeginSub と同じ回数だけ EndSub が呼ばれていなければなりません。 なお、サブルーチン中でデバッグメッセージを出力したい場合には DbgMessage を用いて下さい。 デバッグメッセージとして多次元データを出力したい場合は DataDump が便利です。
program main use gt4f90io use dc_types, only: string use dc_trace, only: SetDebug character(len = string), parameter:: file = 'test.nc' character(len = string), parameter:: var = 'div' integer , parameter:: times = 2 character(len = string) :: url real(8) :: db(5) = (/1.1, 2.2, 3.3, 4.4, 5.5/) character(len = string), parameter:: subname = "TestProgram" continue call SetDebug call TestRoutine(file, var, times, db, url) stop end program main !===== Subroutines ========================================= subroutine TestRoutine(file, var, times, db, url) use dc_types, only: STRING use dc_trace, only: BeginSub, EndSub, DbgMessage, DataDump character(len = *), intent(in) :: file character(len = *), intent(in) :: var integer , intent(in) :: times real(8) , intent(in) :: db(5) character(len = *), intent(out):: url character(len = string), parameter:: subname = "TestRoutine" continue call BeginSub(subname, 'file=%c, var=%c, times=%d', & & c1=trim(file), c2=trim(var), i=(/times/) ) url = trim(file) // trim(var) // ' ' // ',' call DbgMessage('url=%c', c1=trim(url)) url = repeat(trim(url), times) call DataDump('db', db, strlen=60) call EndSub(subname, 'url=%c', c1=trim(url) ) end subroutine TestRoutine
この結果は、標準エラー出力または装置番号 debug に以下のように表示されるでしょう。
#SetDebug: dbg = 0 #call TestRoutine : file=test.nc, var=div, times=2 #|-url=test.ncdiv , #|-db(1-3)=1.1000000238418580000, 2.2000000476837160000, 3.2999999523162840000 #|-db(4-5)=4.4000000953674320000, 5.5000000000000000000 #end TestRoutine : url=test.ncdiv ,test.ncdiv ,
subroutine EndSub(name, fmt, i, r, d, L, s, n, c1, c2, c3) character(*), intent(in) :: name character(*), intent(in), optional:: fmt integer, intent(in), optional:: i(:), n(:) real, intent(in), optional:: r(:) real(8), intent(in), optional:: d(:) logical, intent(in), optional:: L(:) type(vstring),intent(in), optional:: s(:) character(*), intent(in), optional:: c1, c2, c3 end subroutine
文字型変数 name に与えた副プログラム名を以下のように出力します。
# end name
BeginSub に対して一対一対応していますので、 name には対応する BeginSub の引数 name と同じものを与えて下さい。
また、文字型変数 fmt およびそれ以降の引数を与える事で、 以下のように付加メッセージも出力可能です。 fmt とそれ以降の引数に関する書式は dc_string モジュールの CPrintf の説明を参照して下さい。
# end name fmt
利用例に関しては BeginSub を参照して下さい。
subroutine DbgMessage(fmt, i, r, d, L, s, n, c1, c2, c3) character(*), intent(in) :: fmt integer, intent(in), optional:: i(:), n(:) real, intent(in), optional:: r(:) real(8), intent(in), optional:: d(:) logical, intent(in), optional:: L(:) type(vstring),intent(in), optional:: s(:) character(*), intent(in), optional:: c1, c2, c3 end subroutine
フォーマット文字列 fmt に従ってデバッグメッセージを出力します。 fmt とそれ以降の引数に関する書式は dc_string モジュールの CPrintf の説明を参照して下さい。
DbgMessage の結果は以下の太字の部分のように出力されます。
: #| | call TimeGoAhead : varname=time head=1. #| | | call gtvarslice : var%mapid=1 dimord=1 #| | | |-[gt_variable 1: ndims=1, map.size=1] #| | | |-[dim1 dimno=1 ofs=0 step=1 all=0 start=1 count=0 stride=1 url=] #| | | | | call anvarinqurie : var.id=1 #| | | | | end anvarinqurie : ok #| | | |-count=1 (1 specified) #| | | end gtvarslice #| | end TimeGoAhead :
利用例に関しては BeginSub を参照して下さい。
subroutine DataDump(header, d, strlen, multi) character(*), intent(in) :: header ! データの名称 real(8), intent(in) :: d(:) ! 倍精度実数1次元データ integer, intent(in), optional:: strlen ! 文字長制限 integer, intent(in), optional:: multi(:)! 上位の次元添字 end subroutine subroutine DataDump(header, d, strlen, multi) character(*), intent(in) :: header ! データの名称 real(8), intent(in) :: d(:,:) ! 倍精度実数2次元データ integer, intent(in), optional:: strlen ! 文字長制限 integer, intent(in), optional:: multi(:)! 上位の次元添字 end subroutine subroutine DataDump(header, d, strlen, multi) character(*), intent(in) :: header ! データの名称 real(8), intent(in) :: d(:,:,:)! 倍精度実数3次元データ integer, intent(in), optional:: strlen ! 一行の文字数 integer, intent(in), optional:: multi(:)! 上位の次元添字 end subroutine
デバッグメッセージとして、多次元データ d (倍精度実数型) を出力します。 文字型変数 header は出力時の頭文字として利用されます。 整数型配列 strlen を与える事で、一行の文字数を指定できます (デフォルトは 500 文字です)。 整数型配列 multi(:) を与えることで、 header の後ろに次元添字をつける事が可能です。
DataDump の結果は以下の太字の部分のように出力されます。
: #| | call TimeGoAhead : varname=time head=1. #| | | call gtvarslice : var%mapid=1 dimord=1 #| | ||-var(1-2)=1.1000000238418580000, 2.2000000476837160000 #| | ||-var(4-5)=3.2999999523162840000, 4.4000000953674320000 #| | ||-var(5)=5.5000000000000000000 #| | | | | call anvarinqurie : var.id=1 #| | | | | end anvarinqurie : ok #| | | |-count=1 (1 specified) #| | | end gtvarslice #| | end TimeGoAhead :
利用例に関しては BeginSub を参照して下さい。
logical function Debug() result(result) end function
SetDebugでデバッグモードになっている場合には
.true.
が、デバッグモードでない場合には .false.
が返ります。
integer function SubLevel() result(result) end function
副プログラムの階層レベルを返します。 レベルのデフォルトは 0 で、 BeginSub によりレベルは 1 増え、 EndSub によりレベルは 1 減ります。
subroutine Dbg_Scratch(on) logical, intent(in):: on end subroutine
論理型変数 on に .true.
を与える事で、以降の
デバッグメッセージを抹消する事が出来ます。
なお、論理型変数 on に .false.
を
与える事で、直前に呼んだ Dbg_Scratch(.true.) 以降のメッセージを
デバッグメッセージとして再び出力し、以降のデバッグメッセージも
出力されるようにします。