gt4f90ioリファレンスマニュアル - 手続名のリスト

デバッグ時の追跡 (dc_trace モジュール)

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.) 以降のメッセージを デバッグメッセージとして再び出力し、以降のデバッグメッセージも 出力されるようにします。