| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | unit |
Formatted IO unit |
||
| character(len=:), | intent(out), | allocatable | :: | line |
Line to read |
|
| integer, | intent(out) | :: | iostat |
Status of operation |
||
| character(len=:), | intent(out), | optional, | allocatable | :: | iomsg |
Error message |
subroutine getline(unit, line, iostat, iomsg) !> Formatted IO unit integer, intent(in) :: unit !> Line to read character(len=:), allocatable, intent(out) :: line !> Status of operation integer, intent(out) :: iostat !> Error message character(len=:), allocatable, intent(out), optional :: iomsg integer, parameter :: bufsize = 512 character(len=bufsize) :: buffer character(len=bufsize) :: msg integer :: size integer :: stat do ! Passing iomsg to every read statement is costly, only do so on request if (present(iomsg)) then read(unit, "(a)", advance="no", iostat=stat, iomsg=msg, size=size) & & buffer else read(unit, "(a)", advance="no", iostat=stat, size=size) buffer end if if (stat > 0) exit ! Most lines fit into the buffer and need a single allocation if (allocated(line)) then line = line // buffer(:size) else line = buffer(:size) end if if (stat < 0) then if (is_iostat_eor(stat)) then stat = 0 end if exit end if end do if (.not.allocated(line)) allocate(character(len=0) :: line) if (stat /= 0) then if (present(iomsg)) iomsg = trim(msg) end if iostat = stat end subroutine getline