Open
Show file tree
Hide file tree
Changes from all commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Failed to load files.
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,38 @@ and monitoring of system commands or applications directly from Fortran.

[TOC]

## `fs_error` - A derived type for concise error handling

### Status

Experimental

### Description

The derived type contains a `code`, an integer and a fixed-length string containg a user friendly message.
The code is usually the one returned by C functions like `GetLastError` (Windows API) or global variables like `errno` (Unix platforms)
It is default initialized to `0` and it remains so if no errors occured.
In case the error is not because of any C functions, It is always set to `-1` (For distinguishability)

### Type-bound Procedures

The following convenience type-bound procedures are provided:
- `print()` returns a formatted allocatable character string containing the code and the message;
- `ok()` returns a `logical` flag that is `.true.` in case of no errors (`code == 0`);
- `error()` returns a `logical` flag that is `.true.` in case of an error (`code /= 0`).
- `handle([err])` assigns `err` to the calling variable or stops the program by calling `error stop`

### Overloaded Operators

operators `==`, `/=` are provided for comparing `type(fs_error)` variables and `integer` codes.

### Example

```
fortran
{!example/system/example_fs_error.f90!}
```

## `run` - Execute an external process synchronously

### Status
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,3 +11,4 @@ ADD_EXAMPLE(process_5)
ADD_EXAMPLE(process_6)
ADD_EXAMPLE(process_7)
ADD_EXAMPLE(sleep)
ADD_EXAMPLE(fs_error)
Original file line numberDiff line numberDiff line change
Expand Up@@ -198,6 +198,45 @@ module stdlib_system

end type process_type

! For Fileystem related error handling
type, public :: fs_error
! the status code returned by C-functions or
! global variables like `errno` etc whenever called
! When no C interface is involved but there is an error it is set to -1
integer :: code = 0

! A user friendly message about the error
character(len=128) :: message = repeat(' ', 128)

contains
! resets the error state
procedure :: destroy => fs_error_destroy

! returns the formatted error message
procedure :: print => fs_error_message

!> properties
procedure :: ok => fs_error_is_ok
procedure :: error => fs_error_is_error

!> Handle optional error message
procedure :: handle => fs_error_handling

end type fs_error

interface operator(==)
module procedure code_eq_err
module procedure err_eq_code
end interface operator(==)

interface operator(/=)
module procedure code_neq_err
module procedure err_neq_code
end interface operator(/=)

public :: operator(==)
public :: operator(/=)

interface runasync
!! version: experimental
!!
Expand DownExpand Up@@ -770,4 +809,77 @@ subroutine delete_file(path, err)
end if
end subroutine delete_file

elemental subroutine fs_error_destroy(this)
class(fs_error), intent(inout) :: this

this%code = 0
this%message = repeat(' ', len(this%message))
end subroutine fs_error_destroy

pure function fs_error_message(this) result(msg)
class(fs_error), intent(in) :: this
character(len=:), allocatable :: msg
character(len=7) :: tmp ! should be more than enough

if (this%code == 0) then
msg = 'No Error!'
else
write(tmp, '(i0)') this%code
msg = 'Filesystem Error, code '//trim(tmp)//': '// trim(this%message)
end if
end function fs_error_message

elemental function fs_error_is_ok(this) result(is_ok)
class(fs_error), intent(in) :: this
logical :: is_ok
is_ok = this%code == 0
end function fs_error_is_ok

elemental function fs_error_is_error(this) result(is_err)
class(fs_error), intent(in) :: this
logical :: is_err
is_err = this%code /= 0
end function fs_error_is_error

pure subroutine fs_error_handling(err,err_out)
class(fs_error), intent(in) :: err
class(fs_error), optional, intent(inout) :: err_out

character(len=:),allocatable :: err_msg

if (present(err_out)) then
! copy err into err_out
err_out%code = err%code
err_out%message = err%message
else if (err%error()) then
! stop the program
err_msg = err%print()
error stop err_msg
end if
end subroutine fs_error_handling

pure logical function code_eq_err(code, err)
integer, intent(in) :: code
type(fs_error), intent(in) :: err
code_eq_err = code == err%code
end function code_eq_err

pure logical function err_eq_code(err, code)
integer, intent(in):: code
type(fs_error), intent(in) :: err
err_eq_code = code == err%code
end function err_eq_code

pure logical function code_neq_err(code, err)
integer, intent(in) :: code
type(fs_error), intent(in) :: err
code_neq_err = code /= err%code
end function code_neq_err

pure logical function err_neq_code(err, code)
integer, intent(in) :: code
type(fs_error), intent(in) :: err
err_neq_code = code /= err%code
end function err_neq_code

end module stdlib_system
Loading