!> Implementation of basic error handling. module fpm_error use,intrinsic :: iso_fortran_env, only : stdin=>input_unit, stdout=>output_unit, stderr=>error_unit use fpm_strings, only : is_fortran_name, to_fortran_name implicit none private public :: error_t public :: fatal_error, syntax_error, file_not_found_error public :: file_parse_error public :: bad_name_error public :: fpm_stop !> Data type defining an error type :: error_t !> Error message character(len=:), allocatable :: message end type error_t contains !> Generic fatal runtime error subroutine fatal_error(error, message) !> Instance of the error data type(error_t), allocatable, intent(out) :: error !> Error message character(len=*), intent(in) :: message allocate(error) error%message = message end subroutine fatal_error subroutine syntax_error(error, message) !> Instance of the error data type(error_t), allocatable, intent(out) :: error !> Error message character(len=*), intent(in) :: message allocate(error) error%message = message end subroutine syntax_error function bad_name_error(error, label,name) !> Instance of the error data type(error_t), allocatable, intent(out) :: error !> Error message label to add to message character(len=*), intent(in) :: label !> name value to check character(len=*), intent(in) :: name logical :: bad_name_error if(.not.is_fortran_name(to_fortran_name(name)))then bad_name_error=.true. allocate(error) error%message = 'manifest file syntax error: '//label//' name must be composed only of & &alphanumerics, "-" and "_" and start with a letter ::'//name else bad_name_error=.false. endif end function bad_name_error !> Error created when a file is missing or not found subroutine file_not_found_error(error, file_name) !> Instance of the error data type(error_t), allocatable, intent(out) :: error !> Name of the missing file character(len=*), intent(in) :: file_name allocate(error) error%message = "'"//file_name//"' could not be found, check if the file exists" end subroutine file_not_found_error !> Error created when file parsing fails subroutine file_parse_error(error, file_name, message, line_num, & line_string, line_col) !> Instance of the error data type(error_t), allocatable, intent(out) :: error !> Name of file character(len=*), intent(in) :: file_name !> Parse error message character(len=*), intent(in) :: message !> Line number of parse error integer, intent(in), optional :: line_num !> Line context string character(len=*), intent(in), optional :: line_string !> Line context column integer, intent(in), optional :: line_col character(50) :: temp_string allocate(error) error%message = 'Parse error: '//message//new_line('a') error%message = error%message//file_name if (present(line_num)) then write(temp_string,'(I0)') line_num error%message = error%message//':'//trim(temp_string) end if if (present(line_col)) then if (line_col > 0) then write(temp_string,'(I0)') line_col error%message = error%message//':'//trim(temp_string) end if end if if (present(line_string)) then error%message = error%message//new_line('a') error%message = error%message//' | '//line_string if (present(line_col)) then if (line_col > 0) then error%message = error%message//new_line('a') error%message = error%message//' | '//repeat(' ',line_col-1)//'^' end if end if end if end subroutine file_parse_error subroutine fpm_stop(value,message) ! TODO: if verbose mode, call ERROR STOP instead of STOP ! TODO: if M_escape is used, add color ! to work with older compilers might need a case statement for values !> value to use on STOP integer, intent(in) :: value !> Error message character(len=*), intent(in) :: message integer :: iostat if(message/='')then flush(unit=stderr,iostat=iostat) flush(unit=stdout,iostat=iostat) if(value>0)then write(stderr,'("<ERROR> ",a)')trim(message) else write(stderr,'("<INFO> ",a)')trim(message) endif flush(unit=stderr,iostat=iostat) endif stop value end subroutine fpm_stop end module fpm_error