! ! go print : tools for standard output ! ! Example: ! ! ! messages printed by root only: ! call GO_Print_Init( status, apply=myid==root, & ! prompt_pe=npes>1, pe=myid, & ! trace=.false. ) ! if (status/=0) stop ! ! ! set routine label: ! call goLabel( 'mymod/myroutine' ) ! ! ! write single message (including processor prompt?) : ! ! [00] This is number 3 ! write (gol,'("This is number ",i2)') 3; call goPr ! ! ! write error message and traceback using the ! ! previous defined routine label: ! ! [00] ERROR - Something wrong. ! ! [00] ERROR in mymod/myroutine ! write (gol,'("Something wrong.")'); call goErr ! call goErr ! ! ! close label ! call goLabel() ! ! ! done ! call GO_Print_Done( status ) ! if (status/=0) stop ! ! Nedit macro's: ! ! o change error traceback: ! write (*,'("ERROR in ",a)') rname ! call goErr ! ! o change error traceback: ! write (*,'("ERROR in ",a)') rname ! write (gol,'("in ",a)') rname; call goErr ! ! o change error message: ! write \(\*,'\("ERROR - (.*$) ! write (gol,'("\1; call goErr ! ! o change other message: ! write \(\*,(.*$) ! write (gol,\1; call goPr ! ! o change error time messages: ! (goprdt.*ERROR.*$) ! \1; call goErr ! ! o change time messages: ! printdate2 ! wrtgol ! call printdate2\( 'ERROR - (.*$) ! call wrtgol( '\1; call goErr ! printdate ! wrtgol ! call printdate\( 'ERROR - (.*$) ! call wrtgol( '\1; call goErr ! ! ! ! o change error messages: ! (ERROR.*; call )goPr ! \1goErr ! ! o change time messages: ! (call goprdt.*$) ! \1; call goPr ! module GO_Print implicit none ! --- in/out --------------------------------- private public :: gol public :: GO_Print_Init, GO_Print_Done public :: goPr, goErr, goBug public :: goLabel ! --- const --------------------------------- character(len=*), parameter :: mname = 'GO_Print' ! --- var ------------------------------------ ! buffer for standard output character(len=1024) :: gol ! stack with labels: integer, parameter :: mstack = 400 character(len=64) :: labels(0:mstack) integer :: istack = 0 ! initialized ? ! some errors might be printed before initialization ... logical :: pr_initialized = .false. ! destination file unit: integer :: pr_fu ! flags etc logical :: pr_apply logical :: pr_trace ! processor prompt logical :: pr_prompt_pe integer :: pr_pe ! white space for indents: integer, parameter :: dindent = 2 integer :: indent = 0 ! writ to file ? logical :: pr_file character(len=256) :: pr_file_name contains ! *************************************************************************** ! *** ! *** module init/done ! *** ! *************************************************************************** subroutine GO_Print_Init( status, apply, prompt_pe, pe, trace, file, file_name ) use go_fu, only : goStdOut ! --- in/out ---------------------------- integer, intent(out) :: status logical, intent(in), optional :: apply logical, intent(in), optional :: prompt_pe integer, intent(in), optional :: pe logical, intent(in), optional :: trace logical, intent(in), optional :: file character(len=*), intent(in), optional :: file_name ! --- const ---------------------------- character(len=*), parameter :: rname = mname//'/GO_Print_Init' ! --- local ----------------------------- logical :: opened ! --- begin ----------------------------- ! print or not ? pr_apply = .true. if ( present(apply) ) pr_apply = apply ! processor number pr_pe = 0 if ( present(pe) ) pr_pe = pe ! prompt processor number ? pr_prompt_pe = .false. if ( present(prompt_pe) ) pr_prompt_pe = prompt_pe ! trace labels ? pr_trace = .false. if ( present(trace) ) pr_trace = trace ! write to file ? pr_file = .false. if ( present(file) ) pr_file = file pr_file_name = 'go.out' if ( present(file_name) ) pr_file_name = file_name ! init label stack: labels(0) = '' istack = 0 ! no indent yet indent = 0 if ( .not. pr_trace ) indent = -2 ! write messages to file ? if ( pr_file ) then ! select free file unit: pr_fu = 10 do inquire( pr_fu, opened=opened ) if ( .not. opened ) exit pr_fu = pr_fu + 1 end do ! open requested output file: open( unit=pr_fu, file=pr_file_name, status='replace', iostat=status ) if ( status/=0 ) then write (*,'("ERROR - opening file for output:")') write (*,'("ERROR - unit : ",i6)') pr_fu write (*,'("ERROR - file : ",a)') trim(pr_file_name) write (*,'("ERROR in ",a)') rname; status=1; return end if else ! write to standard output: pr_fu = goStdOut end if ! now the module is initialized ... pr_initialized = .true. ! ok status = 0 end subroutine GO_Print_Init ! *** subroutine GO_Print_Done( status ) ! --- in/out ---------------------------- integer, intent(out) :: status ! --- const ---------------------------- character(len=*), parameter :: rname = mname//'/GO_Print_Done' ! --- begin ----------------------------- ! output to file ? if ( pr_file ) then ! close file: close( pr_fu, iostat=status ) if ( status/=0 ) then write (*,'("ERROR - closing output file:")') write (*,'("ERROR - unit : ",i6)') pr_fu write (*,'("ERROR - file : ",a)') trim(pr_file_name) write (*,'("ERROR in ",a)') rname; status=1; return end if end if ! ok status = 0 end subroutine GO_Print_Done ! *************************************************************************** ! *** ! *** printing ! *** ! *************************************************************************** subroutine goPr ! --- local -------------------------------- character(len=16) :: prompt, s integer :: nind ! --- const ---------------------------- character(len=*), parameter :: rname = mname//'/goPr' ! --- begin -------------------------------- ! not initialized yet ? then print to standard output: if ( .not. pr_initialized ) then write (*,'(a)') trim(gol) gol = '' return end if ! print go line ? if ( pr_apply ) then ! number of spaces to indent: nind = max( 0, indent ) ! processor prompt ? if ( pr_prompt_pe ) then write (prompt,'("[",i2.2,"]")') pr_pe nind = nind + 1 else prompt = '' end if ! write prompt, indention, go line: if ( nind > 0 ) then write (pr_fu,'(a,a,a)') trim(prompt), repeat(' ',nind), trim(gol) else write (pr_fu,'(a,a)') trim(prompt), trim(gol) end if end if ! clear output line: gol = '' end subroutine goPr ! *** ! Print error message. ! Now printed to standard output, in future to standard error ? ! Make gol empty before leaving. ! If still empty in next call, this is a trace back ! (print error label, one label back) subroutine goErr ! --- local ------------------------------- integer :: ilab ! --- const ---------------------------- character(len=*), parameter :: rname = mname//'/goErr' ! --- local ---------------------------- logical :: save_pr_apply character(len=len(gol)) :: gol2 ! --- begin -------------------------------- ! store original apply flag: save_pr_apply = pr_apply ! always print error messages: pr_apply = .true. ! message in buffer ? if ( len_trim(gol) > 0 ) then ! error message; ! make a copy of the message to avoid problems with ! re-writing a character string that occures on some machines: gol2 = trim(gol) write (gol,'("ERROR - ",a)') trim(gol2); call goPr else ! label index: ilab = min( istack, mstack ) ! write error message: write (gol,'("ERROR in ",a)') trim(labels(ilab)); call goPr ! one level back: call goLabel() end if ! restore apply flag: pr_apply = save_pr_apply end subroutine goErr ! *** subroutine goBug ! --- local ---------------------------- logical :: save_pr_apply ! --- begin -------------------------------- ! store original apply flag: save_pr_apply = pr_apply ! always print bug messages: pr_apply = .true. ! write message write (gol,'("BUG - ",a)') trim(gol); call goPr ! restore apply flag: pr_apply = save_pr_apply end subroutine goBug ! *************************************************************************** ! *** ! *** routine labels ! *** ! *************************************************************************** subroutine goLabel( label ) ! --- in/out ------------------------------- character(len=*), intent(in), optional :: label ! --- const ---------------------------- character(len=*), parameter :: rname = mname//'/goLabel' ! --- begin -------------------------------- ! add new label to stack ? if ( present(label) ) then istack = istack + 1 if ( istack > mstack ) then write (gol,'("BUG - stack too small; please increase mstack in go_print")'); call goPr else labels(istack) = label end if if (pr_trace) then write (gol,'("<",a,">")') trim(labels(istack)); call goPr end if indent = indent + dindent else indent = indent - dindent if (pr_trace) then write (gol,'("(",a,")")') trim(labels(istack)); call goPr end if istack = max( 0, istack - 1 ) end if end subroutine goLabel end module go_print ! ############################################################################# ! ### ! ### test program ! ### ! ############################################################################# ! ! !module testmod ! ! implicit none ! ! public ! !contains ! ! subroutine subr( i, status ) ! ! use go_print, only : goLabel, gol, goPr, goErr ! ! ! --- in/out ---------------------------------------- ! ! integer, intent(in) :: i ! integer, intent(out) :: status ! ! ! --- begin ----------------------------------------- ! ! call goLabel( 'subr' ) ! ! write (gol,'("welcome to subr !")'); call goPr ! ! select case ( i ) ! ! case ( 0 ) ! write (gol,'("testing i : ",i2)') i; call goPr ! ! case ( 1 ) ! call subr2( 0, status ) ! if (status/=0) then; call goErr; status=1; return; end if ! ! case ( 2 ) ! call subr2( 1, status ) ! if (status/=0) then; call goErr; status=1; return; end if ! ! case default ! write (gol,'("unsupported i : ",i2)') i; call goErr ! call goErr; status=1; return ! ! end select ! ! call goLabel(); status=0 ! ! end subroutine subr ! ! ! ! *** ! ! ! subroutine subr2( i, status ) ! ! use go_print, only : goLabel, gol, goPr, goErr ! ! ! --- in/out ---------------------------------------- ! ! integer, intent(in) :: i ! integer, intent(out) :: status ! ! ! --- begin ----------------------------------------- ! ! call goLabel('subr2') ! ! write (gol,'("testing subr2")'); call goPr ! ! select case ( i ) ! case ( 0 ) ! case default ! write (gol,'("wrong i : ",i2)') i; call goErr ! call goErr; status=1; return ! end select ! ! call goLabel; status=0 ! ! end subroutine subr2 ! ! ! !end module testmod ! ! ! ################################################################ ! ! !program test ! ! use go_print ! use testmod ! ! ! --- local ----------------------------------------- ! ! integer :: status ! ! ! --- begin ------------------------------------------ ! ! call GO_Print_Init( status, trace=.false. ) ! call goLabel('test prog') ! ! write (gol,'("begin of program")'); call goPr ! ! call Subr( 2, status ) ! if (status/=0) then; call goErr; call exit(1); end if ! ! write (gol,'("end of program")'); call goPr ! ! call goLabel() ! call GO_Print_Done( status ) ! !end program test !