FV3 Bundle
Message_Handler.f90
Go to the documentation of this file.
1 ! Module to define simple error/exit codes
2 ! and output messages.
3 !
5 
6  ! Module use statements
7  USE file_utility, ONLY: get_lun
8 
9  ! Disable all implicit typing
10  IMPLICIT NONE
11 
12  ! Visibilities
13  PRIVATE
14  ! Module parameters
15  PUBLIC :: success
16  PUBLIC :: information
17  PUBLIC :: warning
18  PUBLIC :: failure
19  PUBLIC :: undefined
20  ! Module procedures
21  PUBLIC :: program_message
22  PUBLIC :: display_message
23  PUBLIC :: open_message_log
24 
25  ! Integer values that define the error or exit state.
26  ! Note: These values are totally arbitrary.
27  INTEGER, PARAMETER :: success = 0
28  INTEGER, PARAMETER :: information = 1
29  INTEGER, PARAMETER :: warning = 2
30  INTEGER, PARAMETER :: failure = 3
31  INTEGER, PARAMETER :: undefined = 4
32 
33  ! Character descriptors of the error states
34  INTEGER, PARAMETER :: max_n_states = 4
35  CHARACTER(*), PARAMETER, DIMENSION( 0:MAX_N_STATES ) :: &
36  state_descriptor = (/ 'SUCCESS ', &
37  'INFORMATION', &
38  'WARNING ', &
39  'FAILURE ', &
40  'UNDEFINED ' /)
41 
42 
43 CONTAINS
44 
45 
46  ! Subroutine to output a program header consisting of
47  ! the program name, description, and its revision
48  !
49  SUBROUTINE program_message( Name, Description, Revision )
50  ! Arguments
51  CHARACTER(*), INTENT(IN) :: name
52  CHARACTER(*), INTENT(IN) :: description
53  CHARACTER(*), INTENT(IN) :: revision
54  ! Local parameters
55  CHARACTER(*), PARAMETER :: program_header = &
56  '**********************************************************'
57  CHARACTER(*), PARAMETER :: space = ' '
58  ! Local variables
59  INTEGER :: pn_pos
60  CHARACTER(80) :: pn_fmt
61  INTEGER :: phlen
62  INTEGER :: dlen
63  INTEGER :: i, i1, i2
64 
65  ! Determine the format for outputing the name
66  pn_pos = ( len(program_header) / 2 ) - ( len_trim(adjustl(name)) / 2 )
67  pn_pos = max( pn_pos, 0 ) + 5
68  WRITE( pn_fmt, '( "( ",i2,"x, a, / )" )' ) pn_pos
69 
70  ! Write the program header and program name
71  WRITE(*,'(/5x, a )' ) program_header
72  WRITE(*,fmt=trim(pn_fmt)) trim(adjustl(name))
73 
74  ! Write the program description splitting lines at spaces
75  phlen = len(program_header)-1
76  dlen = len_trim(description)
77  i1=1
78  i2=phlen
79 
80  DO
81  IF ( dlen > phlen ) THEN
82  IF ( description(i2:i2) /= space .AND. i2 /= dlen) THEN
83  ! Search for a space character
84  i = index( description(i1:i2), space, back=.true. )
85  IF ( i > 0 ) THEN
86  ! Found one. Update end-of-line
87  i2 = i1 + i - 1
88  ELSE
89  ! No space. Output rest of description
90  i2 = dlen
91  END IF
92  END IF
93  ELSE
94  i2 = dlen
95  END IF
96  WRITE(*,'(6x, a )' ) description(i1:i2)
97  i1 = i2+1
98  i2 = min(i1+phlen-1,dlen)
99  IF ( i1 > dlen ) EXIT
100  END DO
101 
102  ! Write the program revision and end header
103  WRITE(*,'(/6x, a )' ) trim(revision)
104  WRITE(*,'(5x, a, / )' ) program_header
105 
106  END SUBROUTINE program_message
107 
108 
109  ! Subroutine to display messages.
110  !
111  ! This routine calls itself if the optional argument Message_Log
112  ! is passed and an error occurs opening the output log file.
113  !
114  RECURSIVE SUBROUTINE display_message(Routine_Name, &
115  Message, &
116  Error_State, &
117  Message_Log )
118  ! Arguments
119  CHARACTER(*), INTENT(IN) :: routine_name
120  CHARACTER(*), INTENT(IN) :: message
121  INTEGER, INTENT(IN) :: error_state
122  CHARACTER(*), INTENT(IN), OPTIONAL :: message_log
123  ! Local parameters
124  CHARACTER(*), PARAMETER :: this_routine_name = 'Display_Message'
125  CHARACTER(*), PARAMETER :: fmt_string = '( 1x, a, "(", a, ") : ", a )'
126  ! Local variables
127  INTEGER :: error_state_to_use
128  LOGICAL :: log_to_stdout
129  INTEGER :: file_id
130  INTEGER :: error_status
131 
132  ! Check the input error state
133  error_state_to_use = error_state
134  IF ( error_state < 0 .OR. error_state > max_n_states ) THEN
135  error_state_to_use = undefined
136  END IF
137 
138  ! Set the message log. Default is output to stdout
139  log_to_stdout = .true.
140  IF ( PRESENT( message_log ) ) THEN
141  log_to_stdout = .false.
142  error_status = open_message_log( trim( message_log ), file_id )
143  IF ( error_status /= 0 ) THEN
144  CALL display_message( this_routine_name, &
145  'Error opening message log file', &
146  failure )
147  log_to_stdout = .true.
148  END IF
149  END IF
150 
151  ! Output the message
152  IF ( log_to_stdout ) THEN
153  WRITE( *, fmt = fmt_string ) &
154  trim( routine_name ), &
155  trim( state_descriptor( error_state_to_use ) ), &
156  trim( message )
157  ELSE
158  WRITE( file_id, fmt = fmt_string ) &
159  trim( routine_name ), &
160  trim( state_descriptor( error_state_to_use ) ), &
161  trim( message )
162  CLOSE( file_id )
163  END IF
164 
165  END SUBROUTINE display_message
166 
167 
168  ! Function to open the message log file.
169  !
170  ! SIDE EFFECTS:
171  ! The file is opened for SEQUENTIAL, FORMATTED access with
172  ! UNKNOWN status, position of APPEND, and action of READWRITE.
173  !
174  ! Hopefully all of these options will not cause an existing file
175  ! to be inadvertantly overwritten.
176  !
177  FUNCTION open_message_log(Message_Log, File_ID) RESULT(Error_Status)
178  ! Arguments
179  CHARACTER(*), INTENT(IN) :: message_log
180  INTEGER, INTENT(OUT) :: file_id
181  ! Function result
182  INTEGER :: error_status
183  ! Local variables
184  INTEGER :: lun
185  INTEGER :: io_status
186 
187  ! Set successful return status
188  error_status = success
189 
190  ! Get a file unit number
191  lun = get_lun()
192  IF ( lun < 0 ) THEN
193  error_status = failure
194  RETURN
195  END IF
196 
197  ! Open the file
198  OPEN( lun, file = trim( message_log ), &
199  access = 'SEQUENTIAL', &
200  form = 'FORMATTED', &
201  status = 'UNKNOWN', &
202  position = 'APPEND', &
203  action = 'READWRITE', &
204  iostat = io_status )
205  IF ( io_status /= 0 ) THEN
206  error_status = failure
207  RETURN
208  END IF
209 
210  ! Return the file ID
211  file_id = lun
212 
213  END FUNCTION open_message_log
214 
215 END MODULE message_handler
integer, parameter, public failure
integer function, public open_message_log(Message_Log, File_ID)
integer, parameter, public warning
integer, parameter max_n_states
integer function, public get_lun()
subroutine, public program_message(Name, Description, Revision)
integer, parameter, public undefined
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
#define max(a, b)
Definition: mosaic_util.h:33
character(*), dimension(0:max_n_states), parameter state_descriptor
#define min(a, b)
Definition: mosaic_util.h:32
integer, parameter, public success
integer, parameter, public information