This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]