38 use,
intrinsic :: iso_fortran_env, only : stdout => output_unit, &
59 integer,
private :: indent_ = 0
60 integer,
private :: section_id_ = 0
61 integer,
private :: tab_size_ = 1
63 integer,
private :: unit_ = stdout
65 character(len=LOG_SIZE),
private :: section_header =
""
68 character(len=50),
private,
dimension(:),
allocatable :: deprecated_list
87 procedure,
private, pass(this) :: print_section_header => &
102 class(
log_t),
intent(inout) :: this
103 character(len=*),
intent(in),
optional :: env_prefix
104 character(len=255) :: log_level
105 character(len=255) :: log_tab_size
106 character(len=255) :: log_file
107 character(len=32) :: prefix
108 integer :: envvar_len
110 if (
present(env_prefix))
then
119 call get_environment_variable(trim(prefix) //
"_LOG_TAB_SIZE", &
120 log_tab_size, envvar_len)
121 if (envvar_len .gt. 0)
then
122 read(log_tab_size(1:envvar_len), *) this%tab_size_
127 call get_environment_variable(trim(prefix) //
"_LOG_LEVEL", &
128 log_level, envvar_len)
129 if (envvar_len .gt. 0)
then
130 read(log_level(1:envvar_len), *) this%level_
135 call get_environment_variable(trim(prefix) //
"_LOG_FILE", &
136 log_file, envvar_len)
137 if (envvar_len .gt. 0)
then
138 open(newunit = this%unit_,
file = trim(log_file), status =
'replace', &
148 class(
log_t),
intent(inout) :: this
154 if (this%section_id_ .ne. 0)
then
158 if (
allocated(this%deprecated_list))
then
161 do i = 1,
size(this%deprecated_list)
164 call this%end_section()
167 if (this%unit_ .ne. stdout)
then
177 if (
allocated(this%deprecated_list))
then
178 deallocate(this%deprecated_list)
187 class(
log_t),
intent(in) :: this
200 class(
log_t),
intent(in) :: this
209 class(
log_t),
intent(inout) :: this
212 this%section_id_ = this%section_id_ + 1
213 this%indent_ = this%indent_ + this%tab_size_
220 class(
log_t),
intent(inout) :: this
223 if (this%section_id_ .eq. 0)
then
226 this%section_id_ = this%section_id_ - 1
227 this%indent_ = this%indent_ - this%tab_size_
230 this%section_header =
""
236 class(
log_t),
intent(in) :: this
239 write(this%unit_,
'(A)', advance =
'no') repeat(
' ', this%indent_)
246 class(
log_t),
intent(in) :: this
247 integer,
optional :: lvl
251 if (
present(lvl))
then
257 if (lvl_ .gt. this%level_)
then
262 write(this%unit_,
'(A)')
''
269 class(
log_t),
intent(inout) :: this
270 character(len=*),
intent(in) :: msg
271 integer,
optional :: lvl
274 if (
present(lvl))
then
280 if (lvl_ .gt. this%level_)
then
284 if (len_trim(this%section_header) .gt. 0)
then
285 call this%print_section_header(lvl)
290 write(this%unit_,
'(A)') trim(msg)
297 class(
log_t),
intent(in) :: this
298 character(len=*),
intent(in) :: version
299 character(len=*),
intent(in) :: build_info
302 write(this%unit_,
'(A)')
''
303 write(this%unit_,
'(1X,A)')
' _ __ ____ __ __ ____ '
304 write(this%unit_,
'(1X,A)')
' / |/ / / __/ / //_/ / __ \ '
305 write(this%unit_,
'(1X,A)')
' / / / _/ / ,< / /_/ / '
306 write(this%unit_,
'(1X,A)')
'/_/|_/ /___/ /_/|_| \____/ '
307 write(this%unit_,
'(A)')
''
308 write(this%unit_,
'(1X,A,A,A)')
'(version: ', trim(version),
')'
309 write(this%unit_,
'(1X,A)') trim(build_info)
310 write(this%unit_,
'(A)')
''
318 class(
log_t),
intent(in) :: this
319 character(len=*),
intent(in) :: msg
331 class(
log_t),
intent(in) :: this
332 character(len=*),
intent(in) :: msg
336 write(this%unit_,
'(A,A,A)')
'*** WARNING: ', trim(msg),
' ***'
347 class(
log_t),
intent(inout) :: this
348 character(len=*),
intent(in) :: feature
349 character(len=*),
intent(in) :: removal_version
350 character(len=*),
intent(in),
optional :: extra_info
351 character(len=50),
dimension(:),
allocatable :: tmp_list
352 character(len=255) :: deprecation_error
353 character(len=LOG_SIZE) :: msg
362 if (.not.
allocated(this%deprecated_list))
then
363 allocate(
character(len=50) :: this%deprecated_list(1))
364 this%deprecated_list = trim(feature)
366 do i = 1,
size(this%deprecated_list)
367 if (trim(this%deprecated_list(i)) .eq. trim(feature))
return
371 call move_alloc(this%deprecated_list, tmp_list)
372 allocate(
character(len=50)::this%deprecated_list(size(tmp_list)+1))
373 this%deprecated_list(1:
size(tmp_list)) = tmp_list
374 this%deprecated_list(
size(tmp_list) + 1) = trim(feature)
379 write(msg,
'(A,A)')
'*** DEPRECATION: ', trim(feature)
381 write(msg,
'(A,A,A)')
'The feature "', trim(feature),
'" is deprecated.'
383 write(msg,
'(A,A,A)')
'It will be removed in version ', &
384 trim(removal_version),
'.'
387 if (
present(extra_info))
then
393 deprecation_error =
""
394 call get_environment_variable(
"NEKO_DEPRECATION_ERROR", &
397 if (trim(deprecation_error) .eq.
"1")
then
398 call neko_error(
'Deprecated feature "' // trim(feature) // &
399 '" is scheduled for removal in version: ' // &
400 trim(removal_version) //
' (current version: ' // &
403 call neko_warning(
'Deprecated feature "' // trim(feature) // &
404 '" is scheduled for removal in version: ' // &
405 trim(removal_version) //
' (current version: ' // &
414 class(
log_t),
intent(inout) :: this
415 character(len=*),
intent(in) :: msg
416 integer,
optional :: lvl
420 if (len_trim(this%section_header) .gt. 0)
then
421 call this%print_section_header(lvl)
427 pre = (30 - len_trim(msg)) / 2
428 pos = 30 - (len_trim(msg) + pre)
430 if (pre .lt. 0 .or. pos .lt. 0)
then
433 write(this%section_header,
'(A,A,A)') &
437 write(this%section_header,
'(A,A,A)') &
438 repeat(
'-', pre), trim(msg), repeat(
'-', pos)
446 class(
log_t),
intent(inout) :: this
447 integer,
optional :: lvl
450 if (
present(lvl))
then
456 if (lvl_ .gt. this%level_)
then
461 call this%newline(lvl)
463 write(this%unit_,
'(A)') trim(this%section_header)
464 this%section_header =
""
471 class(
log_t),
intent(inout) :: this
472 character(len=*),
intent(in),
optional :: msg
473 integer,
optional :: lvl
475 if (
present(msg))
then
476 call this%message(msg, lvl)
490 use,
intrinsic :: iso_c_binding
491 character(kind=c_char),
dimension(*),
intent(in) :: c_msg
492 character(len=LOG_SIZE) :: msg
498 if (c_msg(len+1) .eq. c_null_char)
exit
500 msg(len:len) = c_msg(len)
503 call neko_log%message(trim(msg(1:len)))
511 use,
intrinsic :: iso_c_binding
512 character(kind=c_char),
dimension(*),
intent(in) :: c_msg
513 character(len=LOG_SIZE) :: msg
519 if (c_msg(len+1) .eq. c_null_char)
exit
521 msg(len:len) = c_msg(len)
526 write(stderr,
'(A,A,A)')
'*** ERROR: ', trim(msg(1:len)),
' ***'
535 use,
intrinsic :: iso_c_binding
536 character(kind=c_char),
dimension(*),
intent(in) :: c_msg
537 character(len=LOG_SIZE) :: msg
543 if (c_msg(len+1) .eq. c_null_char)
exit
545 msg(len:len) = c_msg(len)
550 '*** WARNING: ', trim(msg(1:len)),
' ***'
559 use,
intrinsic :: iso_c_binding
560 character(kind=c_char),
dimension(*),
intent(in) :: c_msg
561 character(len=LOG_SIZE) :: msg
567 if (c_msg(len+1) .eq. c_null_char)
exit
569 msg(len:len) = c_msg(len)
572 call neko_log%section(trim(msg(1:len)))
590 character(len=*),
intent(in) :: version_removal
591 character(len=50) :: current_str, removal_str
592 integer :: current_number(3), removal_number(3)
593 integer :: i, current_size, removal_size
594 integer :: iostat_current, iostat_removal
595 logical :: versions_are_valid, is_newer_than_removal
598 removal_str = trim(version_removal)
601 do i = 1, len_trim(current_str)
602 if (current_str(i:i) .eq.
'.')
then
603 current_str(i:i) =
' '
604 current_size = current_size + 1
609 do i = 1, len_trim(removal_str)
610 if (removal_str(i:i) .eq.
'.')
then
611 removal_str(i:i) =
' '
612 removal_size = removal_size + 1
616 read(current_str, *, iostat = iostat_current) &
617 current_number(1:current_size)
618 read(removal_str, *, iostat = iostat_removal) &
619 removal_number(1:removal_size)
620 versions_are_valid = (iostat_current .eq. 0 .and. iostat_removal .eq. 0)
622 if (.not. versions_are_valid)
then
623 call neko_error(
'Invalid version string in deprecation check: ' // &
625 'removal_version=' // trim(version_removal))
629 do i = 1, current_size
630 if (current_number(i) .gt. removal_number(i))
then
633 else if (current_number(i) .lt. removal_number(i))
then
integer, public pe_rank
MPI rank.
Module for file I/O operations.
subroutine log_end_section_c()
End a log section (from C)
subroutine log_end(this)
Decrease indention level.
subroutine log_print_section_header(this, lvl)
Print a section header.
pure integer function log_level(this)
Return the log level. Messages with a level above it are not written.
subroutine log_deprecated(this, feature, removal_version, extra_info)
Write a deprecation warning to a log.
subroutine log_header(this, version, build_info)
Write the Neko header to a log.
integer, parameter, public neko_log_deprecation
Deprecation.
integer, parameter, public neko_log_verbose
Verbose.
subroutine log_message(this, msg, lvl)
Write a message to a log.
integer, parameter, public neko_log_quiet
Always.
subroutine log_begin(this)
Increase indention level.
subroutine log_message_c(c_msg)
Write a message to a log (from C)
subroutine log_end_section(this, msg, lvl)
End a log section.
subroutine log_warning(this, msg)
Write a warning message to a log.
subroutine log_init(this, env_prefix)
Initialize a log.
subroutine log_error_c(c_msg)
Write an error message to a log (from C)
subroutine log_indent(this)
Indent a log.
subroutine log_flush(this)
Flush the log stream, ensuring buffered output leaves the process.
subroutine log_warning_c(c_msg)
Write a warning message to a log (from C)
subroutine log_newline(this, lvl)
Write a new line to a log.
logical function is_deprecated(version_removal)
Compare version strings.
integer, parameter, public sec_head_size
Length of the section header.
subroutine log_section_c(c_msg)
Begin a new log section (from C)
integer, parameter, public neko_log_debug
Debug.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
integer, parameter, public neko_log_info
Default.
subroutine log_free(this)
Free a log.
subroutine log_section(this, msg, lvl)
Begin a new log section.
subroutine log_error(this, msg)
Write an error message to a log.
character(len=10), parameter neko_version
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.