This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: ASM allowed in Fortran? and OpenDir?
Hi Chris,
Christopher D. Rickett wrote:
> also, the parameter to opendir is not null terminated!
I think one should check for this in gfortran: If a procedure is BIND(C)
and an one passes an non-'\0'-terminated string to an assumed size
character array, there should be printed a warning. (There are some -
extremely few - cases where one does not want to have '\0' terminated
strings; thus a warning which is on by default is should be useful.) I'm
thinking of the simple us such as 'call proc("string")' where one
forgets the C_NULL_CHAR the easiest (as with normal Fortran routines and
also in C itself one does not need it). - It is too easy to forget this
and the implications are quite big.
Thanks for reminding to use VALUE; using VALUE with a pointer sounds a
bit strange - even though it makes sense ("&pointer" vs. "pointer").
> the following code should fix the bugs i found:
Thanks. I planned to look at it this evening - I run out of time this
morning.
Remarks:
- With -m64 on x86-64 I get an illegal instruction in glibc's printf, in
-m32 it works. I don't understand where the illegal instruction comes from.
- One can create easily a C function which implements the needed bits
for the output; instead of size(d%d_name) one could also write a
c_strlen() in Fortran.
Tobias
program test
use iso_c_binding
implicit none
type, bind(C) :: dirent
integer(c_long) :: d_ino
integer(c_long) :: d_off
integer(c_short) :: d_reclen
! Check your system whether d_type exists or not
integer(c_signed_char) :: d_type
character(len=1,kind=c_char) :: d_name(256)
end type
interface
function opendir(a) bind(C,name='opendir')
import
type(c_ptr) :: opendir
character(len=1,kind=c_char), intent(in) :: a(*)
end function opendir
function readdir(dir) bind(C,name='readdir')
import
type(c_ptr), value :: dir
type(c_ptr) :: readdir
end function readdir
end interface
type(c_ptr) :: dir, dc
type(dirent), pointer :: d
character(kind=c_char,len=20), target :: format_string
format_string = 'Result: %s\n' // C_NULL_CHAR
dir = opendir("."//C_NULL_CHAR)
if(.not.c_associated(dir)) then
print *, 'Error opening "."'
else
do
dc = readdir (dir)
if(.not. c_associated(dc)) exit
call c_f_pointer(dc,d)
write(*,*) 'Result: ', trim(c_f_string(d%d_name, size(d%d_name,1)))
end do
end if
contains
! Using allocatable string lengths of Fortran 2003,
! one could get rid of the argument "n"
function c_f_string(string,n)
character(kind=c_char),intent(in) :: string(*)
character(kind=c_char,len=n) :: c_f_string
integer, intent(in) :: n
integer :: i
c_f_string = ' '
do i = 1, n
if(string(i) == C_NULL_CHAR) exit
c_f_string(i:i) = string(i)
end do
end function c_f_string
end program