gtool5 Fortran 90/95 ライブラリ 1.0.0-rc5
English
Loading...
Searching...
No Matches
dc_trace.f90
Go to the documentation of this file.
1! -*- mode: f90; coding: utf-8 -*-
2!-----------------------------------------------------------------------
3! Copyright (c) 2000-2026 Gtool Development Group. All rights reserved.
4!-----------------------------------------------------------------------
151 use dc_types, only: token, string
152 implicit none
153 private
154 logical, save :: lfirst = .true.
155 ! 初回フラグ
156 integer, save, public :: dbg = -1 ! SetDebug で設定された
157 ! デバッグメッセージの
158 ! 出力される装置番号です。
159 integer, save :: level = 0 ! サブルーチンレベル
160 integer, parameter :: trace_stack_size = 128
161 ! 最大階層数
162 character(TOKEN), save:: table(trace_stack_size)
163 ! 階層⇔プログラム名
164 character(STRING), save, allocatable:: called_subname(:), &
165 & called_subname_tmp(:)
166 ! 既に一度呼ばれており,
167 ! *version* 引数を指定している
168 ! 副プログラム名を格納する配列
169 character(1), parameter:: head = '#' ! 行頭文字
170 character(2), parameter :: indent = '| ' ! 字下げ文字
171 character(2), parameter :: meshead = '|-' ! DbgMessage 用行頭文字
173 public:: sublevel, datadump
174 interface debug
175 module procedure dctracedebug
176 end interface
177 interface datadump
178 module procedure datad1dump, datad2dump, datad3dump
179 end interface
180contains
198 integer function sublevel() result(result)
199 result = level
200 end function sublevel
233 subroutine dbg_scratch(on)
234 logical, intent(in):: on
235 integer, save:: saved_dbg = -1
236 logical:: x, p
237 character(80):: line
238 integer:: ios
239 continue
240 if (on) then
241 if (dbg < 0) return
242 saved_dbg = dbg
243 ! 有効な 1 〜 99 の装置番号の内の大きめの値を設定 (?)
244 dbg = 98
245 do
246 inquire(unit=dbg, exist=x, opened=p)
247 ! 装置番号 dbg が接続可能で、かつ未接続の場合
248 if (x .and. .not. p) then
249 ! 装置番号 deg をスクラッチファイルとして開く。
250 ! ※ スクラッチファイルとは、特殊な外部ファイルである。
251 ! これは名前なしの一時ファイルであり、開いている
252 ! 間だけ存在する。つまり、プログラムが終了すると
253 ! 存在しなくなる。
254 open(unit=dbg, status='SCRATCH')
255 ! 開く事が出来ればそれで終了。
256 return
257 endif
258 ! 装置番号 dbg が利用不可、または利用済の場合は 0 以下に
259 ! なるまで dbg - 1 して繰り返す。
260 dbg = dbg - 1
261 if (dbg < 0) exit
262 enddo
263 ! 装置番号 dbg が開けない場合、dbg と saved_dbg を初期化
264 dbg = saved_dbg
265 saved_dbg = -1
266 else
267 ! 以前に装置番号 dbg = 98〜0 でスクラッチファイルを開けてい
268 ! なければそれで終了
269 if (saved_dbg < 0) return
270 ! 装置番号 dbg に接続されたスクラッチファイルをその開始位置
271 ! に位置付ける。エラーが生じたら「100 continue」へ
272 rewind(dbg, err=100)
273 do
274 ! 装置番号 dbg に接続されたスクラッチファイルの一行を
275 ! line へ
276 read(dbg, '(A)', iostat=ios) line
277 if (ios /= 0) exit
278 ! line を装置番号 saved_dbg へ書き出す。
279 write(saved_dbg, '(A)', iostat=ios) trim(line)
280 if (ios /= 0) exit
281 enddo
282 100 continue
283 close(dbg, iostat=ios)
284 ! 最後に dbg と saved_dbg を初期化
285 dbg = saved_dbg
286 saved_dbg = -1
287 endif
288 end subroutine dbg_scratch
335 subroutine setdebug(debug)
336 use dc_types, only: stdout, stderr
337 implicit none
338 integer, intent(in), optional:: debug
339 integer:: ios
340 continue
341 if (present(debug)) then
342 ! debug が与えられる時は装置番号として deg を用いる。
343 dbg = debug
344 write(dbg, "(A, 'SetDebug: dbg =', i4)", iostat=ios) &
345 & trim(head), dbg
346 if (ios == 0) return
347 else
348 ! debug が与えられ無い時は装置番号 0 (標準エラー出力)
349 dbg = stderr
350 write(dbg, "(A, 'SetDebug: dbg = ', I0)", iostat=ios) trim(head), dbg
351 if (ios == 0) return
352 ! 装置番号 0 への出力が失敗したら装置番号 6 (標準出力)
353 dbg = stdout
354 write(dbg, "(A, 'SetDebug: dbg = ', I0)", iostat=ios) trim(head), dbg
355 if (ios == 0) return
356 endif
357 ! 例外処理として dbg の初期化
358 dbg = -1
359 end subroutine setdebug
377 subroutine dctracedebug(dbg_mode)
378 logical, intent(out):: dbg_mode
379 dbg_mode = dbg >= 0
380 end subroutine dctracedebug
382 subroutine initialize
383 table(:) = ' '
384 lfirst = .false.
385 end subroutine initialize
455 subroutine beginsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca, &
456 & version)
457 use dc_types, only: string, dp
458 use dc_string, only: cprintf, strinclude
459 character(*), intent(in) :: name
460 character(*), intent(in), optional:: fmt
461 integer, intent(in), optional:: i(:), n(:)
462 real, intent(in), optional:: r(:)
463 real(dp), intent(in), optional:: d(:)
464 logical, intent(in), optional:: l(:)
465 character(*), intent(in), optional:: c1, c2, c3
466 character(*), intent(in), optional:: ca(:)
467 character(*), intent(in), optional:: version
468 character(STRING) :: cbuf
469 character(STRING) :: name_ver
470 logical :: dbg_mode, print_version
471 integer :: alloc_size
472 continue
473 if ( dbg < 0 ) return
474 if (lfirst) call initialize
475 call debug( dbg_mode )
476 if ( dbg_mode ) then
477 name_ver = name
478 print_version = .false.
479 !---------------------------------
480 ! Print Version check
481 if (present(version)) then
482 if (.not. allocated(called_subname)) then
483 allocate(called_subname(1))
484 called_subname(1) = name
485 print_version = .true.
486 else
487 if (.not. strinclude(called_subname, trim(name))) then
488 alloc_size = size(called_subname)
489 allocate(called_subname_tmp(alloc_size))
490 called_subname_tmp = called_subname
491 deallocate(called_subname)
492 allocate(called_subname(alloc_size + 1))
493 called_subname(1:alloc_size) = called_subname_tmp
494 deallocate(called_subname_tmp)
495 called_subname(alloc_size + 1) = name
496 print_version = .true.
497 end if
498 end if
499 if (print_version) then
500 name_ver = cprintf('%c version=<%c>', &
501 & c1=trim(name), c2=trim(version))
502 end if
503 end if
504 !---------------------------------
505 ! Print Debug message
506 if (present(fmt)) then
507 cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
508 write(dbg, "(A, A, 'call ', A, ' : ', A)") trim(head), &
509 & repeat(indent, level), trim(name_ver), trim(cbuf)
510 else
511 write(dbg, "(A, A, 'call ',A)") trim(head), &
512 & repeat(indent, level), trim(name_ver)
513 endif
514 endif
515 ! call errtra ! --- for Fujitsu debug
516 if (level > size(table)) return
517 level = level + 1
518 table(level) = name
519 end subroutine beginsub
579 subroutine endsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca)
580 use dc_types, only: dp
581 use dc_string, only: cprintf
582 character(*), intent(in) :: name
583 character(*), intent(in), optional:: fmt
584 integer, intent(in), optional:: i(:), n(:)
585 real, intent(in), optional:: r(:)
586 real(dp), intent(in), optional:: d(:)
587 logical, intent(in), optional:: l(:)
588 character(*), intent(in), optional:: c1, c2, c3
589 character(*), intent(in), optional:: ca(:)
590 character(STRING):: cbuf
591 logical:: debug_mode
592 continue
593 if ( dbg < 0 ) return
594 if (lfirst) call initialize
595 ! call errtra ! --- for Fujitsu debug
596 if (level <= 0) then
597 write(*, "(A, 'Warning EndSub[',A,'] without BeginSub')") &
598 & trim(head), trim(name)
599 else if (name /= table(level)) then
600 write(*, "(A, 'Warning EndSub[',A,'] but tos[',A,']')") &
601 & trim(head), trim(name), trim(table(level))
602 else
603 level = level - 1
604 endif
605 call debug( debug_mode )
606 if ( debug_mode ) then
607 if (present(fmt)) then
608 cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
609 write(dbg, "(A, A, 'end ', A, ' : ', A)") trim(head), &
610 & repeat(indent, level), trim(name), trim(cbuf)
611 else
612 write(dbg, "(A, A, 'end ', A)") trim(head), &
613 & repeat(indent, level), trim(name)
614 endif
615 endif
616 end subroutine endsub
660 subroutine dbgmessage(fmt, i, r, d, L, n, c1, c2, c3, ca)
661 use dc_types, only: string, dp
662 use dc_string, only: cprintf, tochar
663 character(*), intent(in) :: fmt
664 integer, intent(in), optional:: i(:), n(:)
665 real, intent(in), optional:: r(:)
666 real(dp), intent(in), optional:: d(:)
667 logical, intent(in), optional:: l(:)
668 character(*), intent(in), optional:: c1, c2, c3
669 character(*), intent(in), optional:: ca(:)
670 character(STRING):: cbuf
671 character(STRING):: meshead_tmp
672 integer :: meshead_len
673 continue
674 if ( dbg < 0 ) return
675 cbuf = cprintf(fmt, i, r, d, l, n, c1, c2, c3, ca)
676 if (level < 1) then
677 meshead_tmp = ''
678 meshead_len = 0
679 else
680 meshead_tmp = meshead
681 meshead_len = len(meshead)
682 endif
683 write(dbg, "(A, A, A, A)") &
684 & trim(head), repeat( indent, max(level-1, 0) ), &
685 & meshead_tmp(1:meshead_len), trim(cbuf)
686 end subroutine dbgmessage
724 subroutine datad1dump(header, d, strlen, multi)
725 use dc_types, only: string, dp
726 use dc_string, only: tochar
727 character(*), intent(in) :: header
728 real(DP), intent(in) :: d(:)
729 integer, intent(in), optional:: strlen
730 integer, intent(in), optional:: multi(:)
731 integer :: i, j
732 character(STRING):: unit ! データ文字列
733 character(STRING):: unitbuf ! データ文字列バッファ
734 integer :: ucur ! unit に書かれた文字数
735 character(STRING):: cbuf ! read/write 文のバッファ
736 integer :: stat ! ステータス
737 logical :: first ! 1つ目のデータかどうか
738 integer :: begini ! 1つ目のデータの添字
739 integer :: endi ! 最後のデータの添字
740 character(STRING):: cmulti ! 次元添字用文字列
741 character(STRING):: cout ! 出力する文字列
742 character(STRING):: meshead_tmp
743 integer :: meshead_len
744 continue
745 if ( dbg < 0 ) return
746 ! 初期化
747 unit = ''
748 unitbuf = ''
749 ucur = 0
750 stat = 0
751 first = .true.
752 cmulti = ''
753 ! デバッグメッセージヘッダの作成。
754 if (level < 1) then
755 meshead_tmp = ''
756 meshead_len = 0
757 else
758 meshead_tmp = meshead
759 meshead_len = len(meshead)
760 endif
761 ! 次元添字用文字列を作成
762 if (present(multi)) then
763 do j = 1, size(multi)
764 cmulti = trim(cmulti) // ', ' // trim( tochar( multi(j) ) )
765 enddo
766 endif
767 i = 1
768 dim_1_loop : do
769 if (first) begini = i
770 endi = i
771 write(cbuf, "(g40.20)") d(i)
772 if (.not. first) cbuf = ', ' // adjustl(cbuf(1:254))
773 unitbuf = unit
774 call append(unit, ucur, trim(adjustl(cbuf)), stat, strlen)
775 if ( stat /= 0 .or. i == size( d(:) ) ) then
776 ! 一回目は、文字数オーバーでもそのまま出力。
777 if (first) then
778 cout = header // '(' &
779 & // trim(tochar(begini)) &
780 & // trim(cmulti) &
781 & // ')=' // trim(unit)
782 ! 二回目以降は、オーバーしたものは次回へ
783 elseif (stat /= 0 .and. begini == endi-1) then
784 cout = header // '(' &
785 & // trim(tochar(begini)) &
786 & // trim(cmulti) &
787 & // ')='// trim(unitbuf)
788 ! 1つ巻戻す
789 i = i - 1
790 elseif (stat /= 0 .and. begini /= endi-1) then
791 cout = header // '(' &
792 & // trim(tochar(begini)) // '-' &
793 & // trim(tochar(endi-1)) &
794 & // trim(cmulti) &
795 & // ')=' // trim(unitbuf)
796 ! 1つ巻戻す
797 i = i - 1
798 ! i が size(d) まで到達した場合もそのまま出力。
799 elseif ( i == size( d(:) ) ) then
800 cout = header // '(' &
801 & // trim(tochar(begini)) // '-' &
802 & // trim(tochar(endi)) &
803 & // trim(cmulti) &
804 & // ')='// trim(unit)
805 endif
806 write(dbg, "(A, A, A, A)") &
807 & trim(head), repeat( indent, max(level-1, 0) ), &
808 & meshead_tmp(1:meshead_len), trim(cout)
809 ! unit, unitbuf をクリア
810 unit = ''
811 unitbuf = ''
812 ucur = 0
813 first = .true.
814 else
815 first = .false.
816 endif
817 if (i == size( d(:) ) ) exit dim_1_loop
818 i = i + 1
819 enddo dim_1_loop
820 end subroutine datad1dump
842 subroutine datad2dump(header, d, strlen, multi)
843 use dc_types, only: dp
844 character(*), intent(in) :: header
845 real(DP), intent(in) :: d(:,:)
846 integer, intent(in), optional:: strlen
847 integer, intent(in), optional:: multi(:)
848 integer, allocatable :: total(:)
849 integer :: j
850 continue
851 if ( dbg < 0 ) return
852 if (present(multi)) then
853 allocate( total(size(multi)+1) )
854 total(2:size(multi)+1) = multi(:)
855 else
856 allocate( total(1) )
857 endif
858 do j = 1, size( d(:,:), 2 )
859 total(1) = j
860 call datadump(header, d(:,j), strlen=strlen, multi=total(:))
861 enddo
862 deallocate( total )
863 end subroutine datad2dump
885 subroutine datad3dump(header, d, strlen, multi)
886 use dc_types, only: dp
887 character(*), intent(in) :: header
888 real(DP), intent(in) :: d(:,:,:)
889 integer, intent(in), optional:: strlen
890 integer, intent(in), optional:: multi(:)
891 integer, allocatable :: total(:)
892 integer :: k
893 continue
894 if ( dbg < 0 ) return
895 if (present(multi)) then
896 allocate( total(size(multi)+1) )
897 total(2:size(multi)+1) = multi(:)
898 else
899 allocate( total(1) )
900 endif
901 do k = 1, size( d(:,:,:), 3 )
902 total(1) = k
903 call datadump(header, d(:,:,k), strlen=strlen, multi=total(:))
904 enddo
905 deallocate( total )
906 end subroutine datad3dump
932 subroutine append(unit, ucur, val, stat, strlen)
933 character(*), intent(inout):: unit
934 integer, intent(inout):: ucur
935 character(*), intent(in) :: val
936 integer, intent(out) :: stat
937 integer, intent(in), &
938 & optional :: strlen
939 integer :: wrsz ! val の文字列
940 continue
941 ! unit の最大長を越えた場合には stat = 2 を返す。
942 if (present(strlen)) then
943 if (ucur >= strlen) then
944 stat = 2
945 return
946 endif
947 else
948 if (ucur >= len(unit)) then
949 stat = 2
950 return
951 endif
952 endif
953 ! 正常時の処理。
954 ! unit の長さを越えた場合も考慮して unit に val を付加する。
955 wrsz = min(len(val), len(unit) - ucur)
956 unit(1+ucur: wrsz+ucur) = val(1: wrsz)
957 ucur = ucur + wrsz
958 stat = 0
959 if (wrsz < len(val)) stat = 1
960 end subroutine append
962end module dc_trace
subroutine append(unitx, ucur, val, stat)
文字型変数の操作
Definition dc_string.f90:83
デバッグ時の追跡用モジュール
Definition dc_trace.f90:150
integer function, public sublevel()
Definition dc_trace.f90:199
subroutine, public setdebug(debug)
Definition dc_trace.f90:336
subroutine, public dbgmessage(fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:661
subroutine, public beginsub(name, fmt, i, r, d, l, n, c1, c2, c3, ca, version)
Definition dc_trace.f90:457
subroutine, public dbg_scratch(on)
Definition dc_trace.f90:234
integer, save, public dbg
Definition dc_trace.f90:156
subroutine, public endsub(name, fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:580
種別型パラメタを提供します。
Definition dc_types.f90:55
integer, parameter, public stdout
標準出力の装置番号
Definition dc_types.f90:117
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
Definition dc_types.f90:128
integer, parameter, public dp
倍精度実数型変数
Definition dc_types.f90:92
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition dc_types.f90:137
integer, parameter, public stderr
標準エラー出力の装置番号
Definition dc_types.f90:122