@@ -6,17 +6,16 @@ module fpm_filesystem
6
6
OS_UNKNOWN, OS_LINUX, OS_MACOS, OS_WINDOWS, &
7
7
OS_CYGWIN, OS_SOLARIS, OS_FREEBSD, OS_OPENBSD
8
8
use fpm_environment, only: separator, get_env, os_is_unix
9
- use fpm_strings, only: f_string, replace, string_t, split, notabs , str_begins_with_str
9
+ use fpm_strings, only: f_string, replace, string_t, split, dilate , str_begins_with_str
10
10
use iso_c_binding, only: c_char, c_ptr, c_int, c_null_char, c_associated, c_f_pointer
11
11
use fpm_error, only : fpm_stop, error_t, fatal_error
12
12
implicit none
13
13
private
14
14
public :: basename, canon_path, dirname, is_dir, join_path, number_of_rows, list_files, get_local_prefix, &
15
15
mkdir, exists, get_temp_filename, windows_path, unix_path, getline, delete_file, fileopen, fileclose, &
16
16
filewrite, warnwrite, parent_dir, is_hidden_file, read_lines, read_lines_expanded, which, run, &
17
- LINE_BUFFER_LEN, os_delete_dir, is_absolute_path, env_variable, get_home, execute_and_read_output, &
17
+ os_delete_dir, is_absolute_path, env_variable, get_home, execute_and_read_output, &
18
18
get_dos_path
19
- integer , parameter :: LINE_BUFFER_LEN = 32768
20
19
21
20
#ifndef FPM_BOOTSTRAP
22
21
interface
@@ -332,14 +331,13 @@ function read_lines_expanded(fh) result(lines)
332
331
type (string_t), allocatable :: lines(:)
333
332
334
333
integer :: i
335
- integer :: ilen
336
- character (LINE_BUFFER_LEN) :: line_buffer_read, line_buffer_expanded
334
+ integer :: iostat
335
+ character (len = :), allocatable :: line_buffer_read
337
336
338
337
allocate (lines(number_of_rows(fh)))
339
338
do i = 1 , size (lines)
340
- read (fh, ' (A)' ) line_buffer_read
341
- call notabs(line_buffer_read, line_buffer_expanded, ilen)
342
- lines(i)% s = trim (line_buffer_expanded)
339
+ call getline(fh, line_buffer_read, iostat)
340
+ lines(i)% s = dilate(line_buffer_read)
343
341
end do
344
342
345
343
end function read_lines_expanded
@@ -350,12 +348,11 @@ function read_lines(fh) result(lines)
350
348
type (string_t), allocatable :: lines(:)
351
349
352
350
integer :: i
353
- character (LINE_BUFFER_LEN) :: line_buffer
351
+ integer :: iostat
354
352
355
353
allocate (lines(number_of_rows(fh)))
356
354
do i = 1 , size (lines)
357
- read (fh, ' (A)' ) line_buffer
358
- lines(i)% s = trim (line_buffer)
355
+ call getline(fh, lines(i)% s, iostat)
359
356
end do
360
357
361
358
end function read_lines
@@ -560,6 +557,7 @@ logical function exists(filename) result(r)
560
557
function get_temp_filename () result(tempfile)
561
558
!
562
559
use iso_c_binding, only: c_ptr, C_NULL_PTR, c_f_pointer
560
+ integer , parameter :: MAX_FILENAME_LENGTH = 32768
563
561
character (:), allocatable :: tempfile
564
562
565
563
type (c_ptr) :: c_tempfile_ptr
@@ -582,7 +580,7 @@ end subroutine c_free
582
580
end interface
583
581
584
582
c_tempfile_ptr = c_tempnam(C_NULL_PTR, C_NULL_PTR)
585
- call c_f_pointer(c_tempfile_ptr,c_tempfile,[LINE_BUFFER_LEN ])
583
+ call c_f_pointer(c_tempfile_ptr,c_tempfile,[MAX_FILENAME_LENGTH ])
586
584
587
585
tempfile = f_string(c_tempfile)
588
586
@@ -628,8 +626,68 @@ function unix_path(path) result(nixpath)
628
626
629
627
end function unix_path
630
628
631
-
632
- ! > read a line of arbitrary length into a CHARACTER variable from the specified LUN
629
+ ! >AUTHOR: fpm(1) contributors
630
+ ! !LICENSE: MIT
631
+ ! >
632
+ ! !##NAME
633
+ ! ! getline(3f) - [M_io:READ] read a line of arbintrary length from specified
634
+ ! ! LUN into allocatable string (up to system line length limit)
635
+ ! ! (LICENSE:PD)
636
+ ! !
637
+ ! !##SYNTAX
638
+ ! ! subroutine getline(unit,line,iostat,iomsg)
639
+ ! !
640
+ ! ! integer,intent(in) :: unit
641
+ ! ! character(len=:),allocatable,intent(out) :: line
642
+ ! ! integer,intent(out) :: iostat
643
+ ! ! character(len=:), allocatable, optional :: iomsg
644
+ ! !
645
+ ! !##DESCRIPTION
646
+ ! ! Read a line of any length up to programming environment maximum
647
+ ! ! line length. Requires Fortran 2003+.
648
+ ! !
649
+ ! ! It is primarily expected to be used when reading input which will
650
+ ! ! then be parsed or echoed.
651
+ ! !
652
+ ! ! The input file must have a PAD attribute of YES for the function
653
+ ! ! to work properly, which is typically true.
654
+ ! !
655
+ ! ! The simple use of a loop that repeatedly re-allocates a character
656
+ ! ! variable in addition to reading the input file one buffer at a
657
+ ! ! time could (depending on the programming environment used) be
658
+ ! ! inefficient, as it could reallocate and allocate memory used for
659
+ ! ! the output string with each buffer read.
660
+ ! !
661
+ ! !##OPTIONS
662
+ ! ! LINE The line read when IOSTAT returns as zero.
663
+ ! ! LUN LUN (Fortran logical I/O unit) number of file open and ready
664
+ ! ! to read.
665
+ ! ! IOSTAT status returned by READ(IOSTAT=IOS). If not zero, an error
666
+ ! ! occurred or an end-of-file or end-of-record was encountered.
667
+ ! ! IOMSG error message returned by system when IOSTAT is not zero.
668
+ ! !
669
+ ! !##EXAMPLE
670
+ ! !
671
+ ! ! Sample program:
672
+ ! !
673
+ ! ! program demo_getline
674
+ ! ! use,intrinsic :: iso_fortran_env, only : stdin=>input_unit
675
+ ! ! use,intrinsic :: iso_fortran_env, only : iostat_end
676
+ ! ! use FPM_filesystem, only : getline
677
+ ! ! implicit none
678
+ ! ! integer :: iostat
679
+ ! ! character(len=:),allocatable :: line, iomsg
680
+ ! ! open(unit=stdin,pad='yes')
681
+ ! ! INFINITE: do
682
+ ! ! call getline(stdin,line,iostat,iomsg)
683
+ ! ! if(iostat /= 0) exit INFINITE
684
+ ! ! write(*,'(a)')'['//line//']'
685
+ ! ! enddo INFINITE
686
+ ! ! if(iostat /= iostat_end)then
687
+ ! ! write(*,*)'error reading input:',iomsg
688
+ ! ! endif
689
+ ! ! end program demo_getline
690
+ ! !
633
691
subroutine getline (unit , line , iostat , iomsg )
634
692
635
693
! > Formatted IO unit
@@ -644,11 +702,13 @@ subroutine getline(unit, line, iostat, iomsg)
644
702
! > Error message
645
703
character (len= :), allocatable , optional :: iomsg
646
704
647
- character (len= LINE_BUFFER_LEN) :: buffer
648
- character (len= LINE_BUFFER_LEN) :: msg
705
+ integer , parameter :: BUFFER_SIZE = 32768
706
+ character (len= BUFFER_SIZE) :: buffer
707
+ character (len= 256 ) :: msg
649
708
integer :: size
650
709
integer :: stat
651
710
711
+
652
712
allocate (character (len= 0 ) :: line)
653
713
do
654
714
read (unit, ' (a)' , advance= ' no' , iostat= stat, iomsg= msg, size= size) &
@@ -1095,7 +1155,7 @@ subroutine execute_and_read_output(cmd, output, error, exitstat)
1095
1155
1096
1156
integer :: cmdstat, unit, stat = 0
1097
1157
character (len= :), allocatable :: cmdmsg, tmp_file
1098
- character (len= 1000 ) :: output_line
1158
+ character (len= :), allocatable :: output_line
1099
1159
1100
1160
tmp_file = get_temp_filename()
1101
1161
@@ -1105,12 +1165,12 @@ subroutine execute_and_read_output(cmd, output, error, exitstat)
1105
1165
open (newunit= unit, file= tmp_file, action= ' read' , status= ' old' )
1106
1166
output = ' '
1107
1167
do
1108
- read (unit, * , iostat = stat) output_line
1109
- if (stat /= 0 ) exit
1110
- output = output// trim ( output_line) // ' '
1168
+ call getline (unit, output_line, stat)
1169
+ if (stat /= 0 ) exit
1170
+ output = output// output_line// ' '
1111
1171
end do
1112
- close (unit, status= ' delete' )
1113
- end
1172
+ close (unit, status= ' delete' ,iostat = stat )
1173
+ end subroutine execute_and_read_output
1114
1174
1115
1175
! > Ensure a windows path is converted to an 8.3 DOS path if it contains spaces
1116
1176
function get_dos_path (path ,error )
0 commit comments