dc_trace.f90
Go to the documentation of this file.
1 != デバッグ時の追跡用モジュール
2 !
3 ! Authors:: Yasuhiro MORIKAWA, Eizi TOYODA
4 ! Version:: $Id: dc_trace.F90,v 1.3 2010-04-11 14:13:51 morikawa Exp $
5 ! Tag Name:: $Name: $
6 ! Copyright:: Copyright (C) GFD Dennou Club, 2000-2005. All rights reserved.
7 ! License:: See COPYRIGHT[link:../../COPYRIGHT]
8 !
9 ! This file provides dc_trace
10 !
11 module dc_trace
12  !
13  != デバッグ時の追跡用モジュール
14  !
15  ! dc_trace はデバッグ時の原因の追跡を補助するためのサブルーチン群
16  ! を持つモジュールです。 このモジュールを利用する事で、
17  ! 以下のようにサブルーチンの階層構造がそのまま分かるような
18  ! デバッグメッセージを出力する事が可能です。
19  !
20  ! :
21  ! #call HistoryPut0
22  ! #| call HistoryPutEx : time
23  ! #| | call TimeGoAhead : varname=time head=1.
24  ! #| | | call lookup_dimension
25  ! #| | | | call gtvarinquire : var.mapid=1
26  ! #| | | | | call gdncvarinqurie : var.id=1
27  ! #| | | | | end gdncvarinqurie : ok
28  ! #| | | | |-name=time
29  ! #| | | | end gtvarinquire
30  ! #| | | end lookup_dimension : ord=1
31  ! #| | | call gtvarslice : var%mapid=1 dimord=1
32  ! #| | | |-[gt_variable 1: ndims=1, map.size=1]
33  ! #| | | |-[dim1 dimno=1 ofs=0 step=1 all=0 start=1 count=0 stride=1 url=]
34  ! #| | | |-[vartable 1: class=netcdf cid=1 ref=1]
35  ! #| | | |-[GD_NC_VARIABLE(file=3, var=1, dim=1)]
36  ! #| | | |-map(dimord): originally start=1 count=0 stride=1
37  ! #| | | |-start=1 (1 specified)
38  ! #| | | |-count=1 (1 specified)
39  ! #| | | end gtvarslice
40  ! #| | end TimeGoAhead
41  ! #| |-gdncfiledefinemode
42  ! #| end HistoryPutEx
43  ! #end HistoryPut0
44  ! :
45  !
46  !== Tutorial
47  !
48  ! * gtool5 オフィシャルチュートリアル:
49  ! {デバッグ補助}[link:../tutorial/dc_trace.htm]
50  !
51  !== Procedures list
52  !
53  ! SetDebug :: デバッグモードをオンオフ
54  ! BeginSub :: 副プログラム開始のメッセージ出力
55  ! EndSub :: 副プログラム終了のメッセージ出力
56  ! DbgMessage :: デバッグ用メッセージ出力
57  !
58  !== Usage
59  !
60  ! dc_trace モジュールを利用するための一連の流れを解説します。
61  ! 詳しくは各手続きの詳細を参照してください。
62  !
63  ! まず、以下の例のように副プログラムの実行文の先頭と最後で
64  ! BeginSub と EndSub を使用します。
65  !
66  ! subroutine TestRoutine(file, var, times, db, url)
67  ! use dc_types, only: STRING, DP
68  ! use dc_trace, only: BeginSub, EndSub
69  ! character(len = *), intent(in) :: file, var
70  ! integer , intent(in) :: times
71  ! real(DP) , intent(in) :: db(5)
72  ! character(len = *), intent(out):: url
73  ! character(len = STRING), parameter:: subname = "TestRoutine"
74  ! continue
75  ! call BeginSub(subname, 'file=%c, var=%c, times=%d', &
76  ! & c1=trim(file), c2=trim(var), i=(/times/) )
77  !
78  ! url = trim(file) // trim(var) // ' ' // ','
79  ! url = repeat(trim(url), times)
80  !
81  ! call EndSub(subname, 'url=%c', c1=trim(url) )
82  ! end subroutine TestRoutine
83  !
84  ! そして、主プログラムの実行文の先頭で SetDebug を使用します。
85  ! 引数は必須ではありませんが、その場合デバッグメッセージは
86  ! 標準エラー出力に表示されます。もしも標準出力などその他へ
87  ! 出力したい場合は出力したい装置番号を引数として与えてください。
88  !
89  ! program main
90  ! use dc_types, only: STRING, DP
91  ! use dc_trace, only: SetDebug
92  ! character(len = STRING), parameter:: file = 'test.nc'
93  ! character(len = STRING), parameter:: var = 'div'
94  ! integer , parameter:: times = 2
95  ! character(len = STRING) :: url
96  ! real(DP) :: db(5) = (/1.1, 2.2, 3.3, 4.4, 5.5/)
97  ! character(len = STRING), parameter:: subname = "TestProgram"
98  !
99  ! continue
100  !
101  ! call SetDebug
102  !
103  ! call TestRoutine(file, var, times, db, url)
104  !
105  ! stop
106  ! end program main
107  !
108  ! 上記のプログラムからは以下のようなデバッグメッセージが
109  ! 標準エラー出力に出力されます。
110  !
111  ! #SetDebug: dbg = 0
112  ! #call TestRoutine : file=test.nc, var=div, times=2
113  ! #end TestRoutine : url=test.ncdiv ,test.ncdiv ,
114  !
115  ! 以下に注意および補足を記します。
116  !
117  ! * 上記のように BeginSub よりも前に SetDebug が呼ばれている必要があります。
118  ! * BeginSub と同じ回数だけ EndSub が呼ばれていなければなりません。
119  ! * 副プログラムの最初と最後以外でデバッグメッセージ
120  ! を出力したい場合には DbgMessage を用いて下さい。
121  ! * デバッグメッセージとして多次元データを出力したい場合は
122  ! DataDump がを用いてください。
123  ! * 現在のデバッグモードの状態 (デバッグモードか否か、
124  ! 副プログラムの深度、出力装置番号) を調べたい場合は、
125  ! それぞれ Debug, SubLevel, dbg を利用してください。
126  !
127  !== Example
128  !
129  ! program main
130  ! use dc_types, only: STRING, DP
131  ! use dc_trace, only: SetDebug
132  ! character(len = STRING), parameter:: file = 'test.nc'
133  ! character(len = STRING), parameter:: var = 'div'
134  ! integer , parameter:: times = 2
135  ! character(len = STRING) :: url
136  ! real(DP) :: db(5) = (/1.1, 2.2, 3.3, 4.4, 5.5/)
137  ! character(len = STRING), parameter:: subname = "TestProgram"
138  !
139  ! continue
140  !
141  ! call SetDebug
142  !
143  ! call TestRoutine(file, var, times, db, url)
144  !
145  ! stop
146  ! end program main
147  !
148  ! subroutine TestRoutine(file, var, times, db, url)
149  ! use dc_types, only: STRING, DP
150  ! use dc_trace, only: BeginSub, EndSub
151  ! character(len = *), intent(in) :: file, var
152  ! integer , intent(in) :: times
153  ! real(DP) , intent(in) :: db(5)
154  ! character(len = *), intent(out):: url
155  ! character(len = STRING), parameter:: subname = "TestRoutine"
156  ! continue
157  ! call BeginSub(subname, 'file=%c, var=%c, times=%d', &
158  ! & c1=trim(file), c2=trim(var), i=(/times/) )
159  !
160  ! url = trim(file) // trim(var) // ' ' // ','
161  ! call DbgMessage('url=%c', c1=trim(url))
162  ! url = repeat(trim(url), times)
163  ! call DataDump('db', db, strlen=60)
164  !
165  ! call EndSub(subname, 'url=%c', c1=trim(url) )
166  ! end subroutine TestRoutine
167  !
168  ! 上記のプログラムからは以下のようなデバッグメッセージが
169  ! 標準エラー出力に出力されます。
170  !
171  ! #SetDebug: dbg = 0
172  ! #call TestRoutine : file=test.nc, var=div, times=2
173  ! #|-url=test.ncdiv ,
174  ! #|-db(1-3)=1.1000000238418580000, 2.2000000476837160000, 3.2999999523162840000
175  ! #|-db(4-5)=4.4000000953674320000, 5.5000000000000000000
176  ! #end TestRoutine : url=test.ncdiv ,test.ncdiv ,
177  !
178  !
179  use dc_types, only: token, string
180  implicit none
181  private
182  logical, save :: lfirst = .true.
183  ! 初回フラグ
184  integer, save, public :: dbg = -1 ! SetDebug で設定された
185  ! デバッグメッセージの
186  ! 出力される装置番号です。
187  integer, save :: level = 0 ! サブルーチンレベル
188  integer, parameter :: trace_stack_size = 128
189  ! 最大階層数
190  character(TOKEN), save:: table(trace_stack_size)
191  ! 階層⇔プログラム名
192  character(STRING), save, allocatable:: called_subname(:), &
193  & called_subname_tmp(:)
194  ! 既に一度呼ばれており,
195  ! *version* 引数を指定している
196  ! 副プログラム名を格納する配列
197  character(1), parameter:: head = '#' ! 行頭文字
198  character(2), parameter :: indent = '| ' ! 字下げ文字
199  character(2), parameter :: meshead = '|-' ! DbgMessage 用行頭文字
201  public:: sublevel, datadump
202  interface debug
203  module procedure dctracedebug
204  end interface
205  interface datadump
206  module procedure datad1dump, datad2dump, datad3dump
207  end interface
208 contains
209  integer function sublevel() result(result)
210  !
211  !== 副プログラムの階層レベルを返す
212  !
213  ! 副プログラムの階層レベルを返します。 レベルのデフォルトは 0 で、
214  ! BeginSub によりレベルは 1 増え、 EndSub によりレベルは 1 減ります。
215  !
216  result = level
217  end function sublevel
218  subroutine dbg_scratch(on)
219  !
220  !== デバッグメッセージの抹消
221  !
222  ! <b>動作未確認ですので利用の際にはご注意下さい。</b>
223  !
224  ! 論理型変数 on に .true. を与える事で、
225  ! 以降の デバッグメッセージを抹消する事が出来ます。
226  !
227  ! なお、論理型変数 on に <tt>.false.</tt> を 与える事で、
228  ! 直前に呼んだ Dbg_Scratch 以降のメッセージを
229  ! デバッグメッセージとして再び出力し、
230  ! 以降のデバッグメッセージも 出力されるようにします。
231  !
232  logical, intent(in):: on
233  integer, save:: saved_dbg = -1
234  logical:: x, p
235  character(80):: line
236  integer:: ios
237  continue
238  if (on) then
239  if (dbg < 0) return
240  saved_dbg = dbg
241  ! 有効な 1 〜 99 の装置番号の内の大きめの値を設定 (?)
242  dbg = 98
243  do
244  inquire(unit=dbg, exist=x, opened=p)
245  ! 装置番号 dbg が接続可能で、かつ未接続の場合
246  if (x .and. .not. p) then
247  ! 装置番号 deg をスクラッチファイルとして開く。
248  ! ※ スクラッチファイルとは、特殊な外部ファイルである。
249  ! これは名前なしの一時ファイルであり、開いている
250  ! 間だけ存在する。つまり、プログラムが終了すると
251  ! 存在しなくなる。
252  open(unit=dbg, status='SCRATCH')
253  ! 開く事が出来ればそれで終了。
254  return
255  endif
256  ! 装置番号 dbg が利用不可、または利用済の場合は 0 以下に
257  ! なるまで dbg - 1 して繰り返す。
258  dbg = dbg - 1
259  if (dbg < 0) exit
260  enddo
261  ! 装置番号 dbg が開けない場合、dbg と saved_dbg を初期化
262  dbg = saved_dbg
263  saved_dbg = -1
264  else
265  ! 以前に装置番号 dbg = 98〜0 でスクラッチファイルを開けてい
266  ! なければそれで終了
267  if (saved_dbg < 0) return
268  ! 装置番号 dbg に接続されたスクラッチファイルをその開始位置
269  ! に位置付ける。エラーが生じたら「100 continue」へ
270  rewind(dbg, err=100)
271  do
272  ! 装置番号 dbg に接続されたスクラッチファイルの一行を
273  ! line へ
274  read(dbg, '(A)', iostat=ios) line
275  if (ios /= 0) exit
276  ! line を装置番号 saved_dbg へ書き出す。
277  write(saved_dbg, '(A)', iostat=ios) trim(line)
278  if (ios /= 0) exit
279  enddo
280  100 continue
281  close(dbg, iostat=ios)
282  ! 最後に dbg と saved_dbg を初期化
283  dbg = saved_dbg
284  saved_dbg = -1
285  endif
286  end subroutine dbg_scratch
287  subroutine setdebug(debug)
288  use dc_types, only: stdout, stderr
289  implicit none
290  !
291  !== デバッグモードをオンオフ
292  !
293  ! デバッグメッセージを出力したい時にこのサブルーチンを呼びます。
294  !
295  ! 整数型変数 debug が与えられる場合は、その装置番号 debug に、
296  ! 以降のサブルーチンによるデバッグメッセージを出力するようにします。
297  ! debug が与えられない場合、装置番号 0 (標準エラー出力)
298  ! にデバッグメッセージが出力されるようになります。
299  ! 装置番号 0 への出力が成功しない場合は代わりに
300  ! 装置番号 6 (標準出力) にデバッグメッセージが出力されるようになります。
301  !
302  ! debug に負の整数を与える場合、デバッグモードが解除され、
303  ! 以降デバッグメッセージは出力されません。
304  !
305  ! なお、この SetDebug を呼んだ際にも、装置番号 debug
306  ! に以下のメッセージ が表示されます。
307  !
308  ! #SetDebug: dbg = debug
309  !
310  integer, intent(in), optional:: debug
311  integer:: ios
312  continue
313  if (present(debug)) then
314  ! debug が与えられる時は装置番号として deg を用いる。
315  dbg = debug
316  write(dbg, "(A, 'SetDebug: dbg =', i4)", iostat=ios) &
317  & trim(head), dbg
318  if (ios == 0) return
319  else
320  ! debug が与えられ無い時は装置番号 0 (標準エラー出力)
321  dbg = stderr
322  write(dbg, "(A, 'SetDebug: dbg = ', I0)", iostat=ios) trim(head), dbg
323  if (ios == 0) return
324  ! 装置番号 0 への出力が失敗したら装置番号 6 (標準出力)
325  dbg = stdout
326  write(dbg, "(A, 'SetDebug: dbg = ', I0)", iostat=ios) trim(head), dbg
327  if (ios == 0) return
328  endif
329  ! 例外処理として dbg の初期化
330  dbg = -1
331  end subroutine setdebug
332  subroutine dctracedebug(dbg_mode)
333  !
334  !== デバックモードかどうかの診断
335  !
336  ! SetDebugでデバッグモードになっている場合には .true. が、
337  ! デバッグモードでない場合には .false. が返ります。
338  !
339  logical, intent(out):: dbg_mode
340  dbg_mode = dbg >= 0
341  end subroutine dctracedebug
342  subroutine initialize
343  !
344  ! 初期化
345  !
346  table(:) = ' '
347  lfirst = .false.
348  end subroutine initialize
349  subroutine beginsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca, &
350  & version)
351  !
352  !== 副プログラム開始のメッセージ出力
353  !
354  ! 文字型変数 *name* に与えた副プログラム名を以下のように出力します.
355  !
356  ! # call name
357  !
358  ! 複数回呼ぶ事で上記 (dc_trace の Overview 参照)
359  ! のようにメッセージが出力されます.
360  ! 必ず BeginSub と同様な数だけ EndSub を呼ぶようにしてください.
361  !
362  ! また, 文字型変数 *fmt* およびそれ以降の引数を与える事で,
363  ! 以下のように付加メッセージも出力可能です. *fmt*
364  ! とそれ以降の引数に関する書式は dc_string#CPrintf
365  ! の説明を参照して下さい.
366  !
367  ! # call name : fmt
368  !
369  ! 利用例に関しては dc_trace の Usage および Example を参照してください.
370  !
371  ! *version* には, 副プログラムのバージョンナンバーを与えます.
372  ! *version* に与えられた文字列は, ある副プログラム
373  ! が複数回呼び出されたうち, 初回に呼び出された時のみ表示されます.
374  !
375  !--
376  !== 開発者向け解説
377  !
378  ! このサブルーチンにより, このモジュール内で内部的に保持される
379  ! 整数型変数 level の値が 1 増えます。
380  !
381  !++
382  use dc_types, only: string, dp
383  use dc_string, only: cprintf, strinclude
384  character(*), intent(in) :: name
385  character(*), intent(in), optional:: fmt
386  integer, intent(in), optional:: i(:), n(:)
387  real, intent(in), optional:: r(:)
388  real(DP), intent(in), optional:: d(:)
389  logical, intent(in), optional:: L(:)
390  character(*), intent(in), optional:: c1, c2, c3
391  character(*), intent(in), optional:: ca(:)
392  character(*), intent(in), optional:: version
393  character(STRING) :: cbuf
394  character(STRING) :: name_ver
395  logical :: dbg_mode, print_version
396  integer :: alloc_size
397  continue
398  if ( dbg < 0 ) return
399  if (lfirst) call initialize
400  call debug( dbg_mode )
401  if ( dbg_mode ) then
402  name_ver = name
403  print_version = .false.
404  !---------------------------------
405  ! Print Version check
406  if (present(version)) then
407  if (.not. allocated(called_subname)) then
408  allocate(called_subname(1))
409  called_subname(1) = name
410  print_version = .true.
411  else
412  if (.not. strinclude(called_subname, trim(name))) then
413  alloc_size = size(called_subname)
414  allocate(called_subname_tmp(alloc_size))
416  deallocate(called_subname)
417  allocate(called_subname(alloc_size + 1))
418  called_subname(1:alloc_size) = called_subname_tmp
419  deallocate(called_subname_tmp)
420  called_subname(alloc_size + 1) = name
421  print_version = .true.
422  end if
423  end if
424  if (print_version) then
425  name_ver = cprintf('%c version=<%c>', &
426  & c1=trim(name), c2=trim(version))
427  end if
428  end if
429  !---------------------------------
430  ! Print Debug message
431  if (present(fmt)) then
432  cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
433  write(dbg, "(A, A, 'call ', A, ' : ', A)") trim(head), &
434  & repeat(indent, level), trim(name_ver), trim(cbuf)
435  else
436  write(dbg, "(A, A, 'call ',A)") trim(head), &
437  & repeat(indent, level), trim(name_ver)
438  endif
439  endif
440  ! call errtra ! --- for Fujitsu debug
441  if (level > size(table)) return
442  level = level + 1
443  table(level) = name
444  end subroutine beginsub
445  subroutine endsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca)
446  !
447  !== 副プログラム終了のメッセージ出力
448  !
449  ! 文字型変数 name に与えた副プログラム名を以下のように出力します。
450  !
451  ! # end name
452  !
453  ! BeginSub に対して一対一対応していますので、name には対応する
454  ! BeginSub の引数 name と同じものを与えて下さい。
455  !
456  ! また、文字型変数 fmt およびそれ以降の引数を与える事で、
457  ! 以下のように付加メッセージも出力可能です。 fmt
458  ! とそれ以降の引数に関する書式は dc_string#CPrintf
459  ! の説明を参照して下さい。
460  !
461  ! # end name fmt
462  !
463  ! 利用例に関しては dc_trace の Usage および Exampleを参照してください。
464  !--
465  !== 開発者向け解説
466  !
467  ! このサブルーチンにより, このモジュール内で内部的に保持される
468  ! 整数型変数 level の値が 1 減ります。
469  !
470  !++
471  use dc_types, only: string, dp
472  use dc_string, only: cprintf
473  character(*), intent(in) :: name
474  character(*), intent(in), optional:: fmt
475  integer, intent(in), optional:: i(:), n(:)
476  real, intent(in), optional:: r(:)
477  real(DP), intent(in), optional:: d(:)
478  logical, intent(in), optional:: L(:)
479  character(*), intent(in), optional:: c1, c2, c3
480  character(*), intent(in), optional:: ca(:)
481  character(STRING):: cbuf
482  logical:: debug_mode
483  continue
484  if ( dbg < 0 ) return
485  if (lfirst) call initialize
486  ! call errtra ! --- for Fujitsu debug
487  if (level <= 0) then
488  write(*, "(A, 'Warning EndSub[',A,'] without BeginSub')") &
489  & trim(head), trim(name)
490  else if (name /= table(level)) then
491  write(*, "(A, 'Warning EndSub[',A,'] but tos[',A,']')") &
492  & trim(head), trim(name), trim(table(level))
493  else
494  level = level - 1
495  endif
496  call debug( debug_mode )
497  if ( debug_mode ) then
498  if (present(fmt)) then
499  cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
500  write(dbg, "(A, A, 'end ', A, ' : ', A)") trim(head), &
501  & repeat(indent, level), trim(name), trim(cbuf)
502  else
503  write(dbg, "(A, A, 'end ', A)") trim(head), &
504  & repeat(indent, level), trim(name)
505  endif
506  endif
507  end subroutine endsub
508  subroutine dbgmessage(fmt, i, r, d, L, n, c1, c2, c3, ca)
509  !
510  !== デバッグ用メッセージ出力
511  !
512  ! フォーマット文字列 fmt に従ってデバッグメッセージを出力します。
513  ! fmt とそれ以降の引数に関する書式は dc_string#CPrintf
514  ! の説明を参照して下さい。
515  !
516  ! 利用例に関しては dc_trace の Example を参照して下さい。
517  !
518  !--
519  !== 開発者向け解説
520  !
521  ! このサブルーチンを用いても、このモジュール内で内部的に保持される
522  ! 整数型変数 level の値は変化しません。
523  !
524  !++
525  use dc_types, only: string, dp
526  use dc_string, only: cprintf, tochar
527  character(*), intent(in) :: fmt
528  integer, intent(in), optional:: i(:), n(:)
529  real, intent(in), optional:: r(:)
530  real(DP), intent(in), optional:: d(:)
531  logical, intent(in), optional:: L(:)
532  character(*), intent(in), optional:: c1, c2, c3
533  character(*), intent(in), optional:: ca(:)
534  character(STRING):: cbuf
535  character(STRING):: meshead_tmp
536  integer :: meshead_len
537  continue
538  if ( dbg < 0 ) return
539  cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
540  if (level < 1) then
541  meshead_tmp = ''
542  meshead_len = 0
543  else
544  meshead_tmp = meshead
545  meshead_len = len(meshead)
546  endif
547  write(dbg, "(A, A, A, A)") &
548  & trim(head), repeat( indent, max(level-1, 0) ), &
549  & meshead_tmp(1:meshead_len), trim(cbuf)
550  end subroutine dbgmessage
551  subroutine datad1dump(header, d, strlen, multi)
552  !
553  !== 1 次元データ出力
554  !
555  ! デバッグメッセージとして、多次元データ d (倍精度実数型)
556  ! を出力します。 文字型変数 header は出力時の頭文字として利用されます。
557  ! 整数型配列 strlen を与える事で、一行の文字数を指定できます
558  ! (デフォルトの文字数は dc_types#STRING で指定されています)。
559  ! 整数型配列 multi(:) を与えることで、
560  ! header の後ろに次元添字をつける事が可能です。
561  !
562  ! 利用例に関しては dc_trace の Example を参照して下さい。
563  !
564  !--
565  !== 開発者向け解説
566  !
567  ! このサブルーチンを用いても、このモジュール内で内部的に保持される
568  ! 整数型変数 level の値は変化しません。
569  !
570  !++
571  use dc_types, only: string, dp
572  use dc_string, only: tochar
573  character(*), intent(in) :: header ! データの名称
574  real(DP), intent(in) :: d(:) ! 倍精度実数1次元データ
575  integer, intent(in), optional:: strlen ! 一行の文字数
576  integer, intent(in), optional:: multi(:)! 上位の次元添字
577  integer :: i, j
578  character(STRING):: unit ! データ文字列
579  character(STRING):: unitbuf ! データ文字列バッファ
580  integer :: ucur ! unit に書かれた文字数
581  character(STRING):: cbuf ! read/write 文のバッファ
582  integer :: stat ! ステータス
583  logical :: first ! 1つ目のデータかどうか
584  integer :: begini ! 1つ目のデータの添字
585  integer :: endi ! 最後のデータの添字
586  character(STRING):: cmulti ! 次元添字用文字列
587  character(STRING):: cout ! 出力する文字列
588  character(STRING):: meshead_tmp
589  integer :: meshead_len
590  continue
591  if ( dbg < 0 ) return
592  ! 初期化
593  unit = ''
594  unitbuf = ''
595  ucur = 0
596  stat = 0
597  first = .true.
598  cmulti = ''
599  ! デバッグメッセージヘッダの作成。
600  if (level < 1) then
601  meshead_tmp = ''
602  meshead_len = 0
603  else
604  meshead_tmp = meshead
605  meshead_len = len(meshead)
606  endif
607  ! 次元添字用文字列を作成
608  if (present(multi)) then
609  do j = 1, size(multi)
610  cmulti = trim(cmulti) // ', ' // trim( tochar( multi(j) ) )
611  enddo
612  endif
613  i = 1
614  dim_1_loop : do
615  if (first) begini = i
616  endi = i
617  write(cbuf, "(g40.20)") d(i)
618  if (.not. first) cbuf = ', ' // adjustl(cbuf)
619  unitbuf = unit
620  call append(unit, ucur, trim(adjustl(cbuf)), stat, strlen)
621  if ( stat /= 0 .or. i == size( d(:) ) ) then
622  ! 一回目は、文字数オーバーでもそのまま出力。
623  if (first) then
624  cout = header // '(' &
625  & // trim(tochar(begini)) &
626  & // trim(cmulti) &
627  & // ')=' // trim(unit)
628  ! 二回目以降は、オーバーしたものは次回へ
629  elseif (stat /= 0 .and. begini == endi-1) then
630  cout = header // '(' &
631  & // trim(tochar(begini)) &
632  & // trim(cmulti) &
633  & // ')='// trim(unitbuf)
634  ! 1つ巻戻す
635  i = i - 1
636  elseif (stat /= 0 .and. begini /= endi-1) then
637  cout = header // '(' &
638  & // trim(tochar(begini)) // '-' &
639  & // trim(tochar(endi-1)) &
640  & // trim(cmulti) &
641  & // ')=' // trim(unitbuf)
642  ! 1つ巻戻す
643  i = i - 1
644  ! i が size(d) まで到達した場合もそのまま出力。
645  elseif ( i == size( d(:) ) ) then
646  cout = header // '(' &
647  & // trim(tochar(begini)) // '-' &
648  & // trim(tochar(endi)) &
649  & // trim(cmulti) &
650  & // ')='// trim(unit)
651  endif
652  write(dbg, "(A, A, A, A)") &
653  & trim(head), repeat( indent, max(level-1, 0) ), &
654  & meshead_tmp(1:meshead_len), trim(cout)
655  ! unit, unitbuf をクリア
656  unit = ''
657  unitbuf = ''
658  ucur = 0
659  first = .true.
660  else
661  first = .false.
662  endif
663  if (i == size( d(:) ) ) exit dim_1_loop
664  i = i + 1
665  enddo dim_1_loop
666  end subroutine datad1dump
667  subroutine datad2dump(header, d, strlen, multi)
668  !
669  !== 2 次元データ出力
670  !
671  ! 詳しくは DataDump または DataD1Dump を参照ください。
672  !
673  use dc_types, only: string, dp
674  character(*), intent(in) :: header ! データの名称
675  real(DP), intent(in) :: d(:,:) ! 倍精度実数2次元データ
676  integer, intent(in), optional:: strlen ! 一行の文字数
677  integer, intent(in), optional:: multi(:)! 上位の次元添字
678  integer, allocatable :: total(:)
679  integer :: j
680  continue
681  if ( dbg < 0 ) return
682  if (present(multi)) then
683  allocate( total(size(multi)+1) )
684  total(2:size(multi)+1) = multi(:)
685  else
686  allocate( total(1) )
687  endif
688  do j = 1, size( d(:,:), 2 )
689  total(1) = j
690  call datadump(header, d(:,j), strlen=strlen, multi=total(:))
691  enddo
692  deallocate( total )
693  end subroutine datad2dump
694  subroutine datad3dump(header, d, strlen, multi)
695  !
696  !== 3 次元データ出力
697  !
698  ! 詳しくは DataDump または DataD1Dump を参照ください。
699  !
700  use dc_types, only: string, dp
701  character(*), intent(in) :: header ! データの名称
702  real(DP), intent(in) :: d(:,:,:)! 倍精度実数3次元データ
703  integer, intent(in), optional:: strlen ! 一行の文字数
704  integer, intent(in), optional:: multi(:)! 上位の次元添字
705  integer, allocatable :: total(:)
706  integer :: k
707  continue
708  if ( dbg < 0 ) return
709  if (present(multi)) then
710  allocate( total(size(multi)+1) )
711  total(2:size(multi)+1) = multi(:)
712  else
713  allocate( total(1) )
714  endif
715  do k = 1, size( d(:,:,:), 3 )
716  total(1) = k
717  call datadump(header, d(:,:,k), strlen=strlen, multi=total(:))
718  enddo
719  deallocate( total )
720  end subroutine datad3dump
721  subroutine append(unit, ucur, val, stat, strlen)
722  !
723  ! DataD1Dump の内部関数。
724  ! unit に val を付加。その際、unit がその最大文字列長を越えた場合
725  ! には stat = 2 を返す。
726  !
727  character(*), intent(inout):: unit ! 最終的に返される文字列
728  integer, intent(inout):: ucur ! unit の文字数
729  character(*), intent(in) :: val ! unit に付加される文字列
730  integer, intent(out) :: stat ! ステータス
731  integer, intent(in), &
732  & optional :: strlen ! 文字数の手動指定
733  integer :: wrsz ! val の文字列
734  continue
735  ! unit の最大長を越えた場合には stat = 2 を返す。
736  if (present(strlen)) then
737  if (ucur >= strlen) then
738  stat = 2
739  return
740  endif
741  else
742  if (ucur >= len(unit)) then
743  stat = 2
744  return
745  endif
746  endif
747  ! 正常時の処理。
748  ! unit の長さを越えた場合も考慮して unit に val を付加する。
749  wrsz = min(len(val), len(unit) - ucur)
750  unit(1+ucur: wrsz+ucur) = val(1: wrsz)
751  ucur = ucur + wrsz
752  stat = 0
753  if (wrsz < len(val)) stat = 1
754  end subroutine append
755 end module dc_trace
subroutine, public dbg_scratch(on)
Definition: dc_trace.f90:219
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
Definition: dc_types.f90:109
logical, save lfirst
Definition: dc_trace.f90:182
subroutine, public setdebug(debug)
Definition: dc_trace.f90:288
character(2), parameter meshead
Definition: dc_trace.f90:199
integer, save, public dbg
Definition: dc_trace.f90:184
subroutine datad3dump(header, d, strlen, multi)
Definition: dc_trace.f90:695
character(string), dimension(:), allocatable, save called_subname_tmp
Definition: dc_trace.f90:192
subroutine initialize
Definition: dc_trace.f90:343
integer, parameter trace_stack_size
Definition: dc_trace.f90:188
character(token), dimension(trace_stack_size), save table
Definition: dc_trace.f90:190
integer function, public sublevel()
Definition: dc_trace.f90:210
subroutine datad2dump(header, d, strlen, multi)
Definition: dc_trace.f90:668
integer, parameter, public stderr
標準エラー出力の装置番号
Definition: dc_types.f90:103
integer, parameter, public dp
倍精度実数型変数
Definition: dc_types.f90:83
character(1), parameter head
Definition: dc_trace.f90:197
subroutine, public dbgmessage(fmt, i, r, d, L, n, c1, c2, c3, ca)
Definition: dc_trace.f90:509
subroutine dctracedebug(dbg_mode)
Definition: dc_trace.f90:333
subroutine, public beginsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca, version)
Definition: dc_trace.f90:351
character(string), dimension(:), allocatable, save called_subname
Definition: dc_trace.f90:192
integer, parameter, public stdout
標準出力の装置番号
Definition: dc_types.f90:98
文字型変数の操作.
Definition: dc_string.f90:24
種別型パラメタを提供します。
Definition: dc_types.f90:49
subroutine datad1dump(header, d, strlen, multi)
Definition: dc_trace.f90:552
integer, save level
Definition: dc_trace.f90:187
character(2), parameter indent
Definition: dc_trace.f90:198
subroutine append(unit, ucur, val, stat, strlen)
Definition: dc_trace.f90:722
subroutine, public endsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca)
Definition: dc_trace.f90:446
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition: dc_types.f90:118