From: glen herrmannsfeldt on
James Van Buskirk <not_valid(a)comcast.net> wrote:
(snip)

> I had this problem with recursive I/O when I wrote a code generator
> and posted it to the web so people could test it. It seemed
> illogical to me that f90 allowed the programmer to write recursive
> code but that f95 permitted compilers to implement I/O, even
> internal I/O, via fixed data structures that made all I/O operations
> non-reentrant.

It seems that way, but it really shouldn't be so much of a problem
in most cases. I was thinking that the problem goes back to Fortran II,
but even in Fortran 66 you can't have function calls in I/O statements.
Probably the most common extension to Fortran 66 allows expressions
in subscripts, instead of the restricted subscripts allowed by the
standard. In that case, you could have function calls in subscripts,
but not as I/O list elements.

I believe, at least at the time, my favorite addition in Fortran 77
was allowing expressions in the I/O list of WRITE statements. So many
temporary variables used to be needed.

So, why didn't they fix this with Fortran 90? I would guess that
there were already so many other things being added that it was
decided that this wasn't really needed.

> But if my code was going to be generally usable I had to modify my
> code. What I did was to create functions that could compose strings
> from numbers using specification functions to determine their LENs.
> Then I could compose a line of output via concatenation of several
> such strings (function results) and invoke a subroutine to print
> out a line of output. Worked really well except that some f95
> compilers had problems with the specification functions or in
> general with complicated specification expressions. Here is an
> example adapted to your program:

(snip)

I would have thought it easier to remove function calls from I/O
lists, and use temporary variables to store the value. Though
complicated by not knowing the length in advance, and no
non-advancing I/O.

-- glen
From: Den7 on
On Dec 21, 1:32 pm, "James Van Buskirk" <not_va...(a)comcast.net> wrote:
> "Den7" <rrr7...(a)gmail.com> wrote in message
>
> news:7af7ef60-ae7a-4287-95fc-9e19c71ef671(a)a39g2000pre.googlegroups.com...
>
> > So because I have to ask exactly what i need, the program-maximum is
> > (can i mask more?)
> >          integer foo
> >          external foo
> >          open(11,file='11.out')
> >          open(11,file='12.out')
> >          write(11,*) foo(12)
> >          end
> >          integer function foo(i)
> >          character*9 char_I
> >          write(char_i,'(i9)') i
> >          write(12,*,err=1000) char_i
> > 1000      foo=i
> >          end
>
> I had this problem with recursive I/O when I wrote a code generator
> and posted it to the web so people could test it.  It seemed
> illogical to me that f90 allowed the programmer to write recursive
> code but that f95 permitted compilers to implement I/O, even
> internal I/O, via fixed data structures that made all I/O operations
> non-reentrant.
>
> But if my code was going to be generally usable I had to modify my
> code.  What I did was to create functions that could compose strings
> from numbers using specification functions to determine their LENs.
> Then I could compose a line of output via concatenation of several
> such strings (function results) and invoke a subroutine to print
> out a line of output.  Worked really well except that some f95
> compilers had problems with the specification functions or in
> general with complicated specification expressions.  Here is an
> example adapted to your program:
>
> C:\gfortran\clf\recursive_io>type recursive_io.f90
> module stuff
>    implicit none
>    contains
>       subroutine write_unit(iunit,x)
>          integer, intent(in) :: iunit
>          character(*), intent(in) :: x
>
>          write(iunit,'(a)') x
>       end subroutine write_unit
>       function compose_i4(x)
>          integer, intent(in) :: x
>          character(compose_i4_len(x)) compose_i4
>
>          write(compose_i4,*) x
>       end function compose_i4
>       pure function compose_i4_len(x)
>          integer compose_i4_len
>          integer, intent(in) :: x
>          character(range(x)+3) temp
>
>          write(temp,*) x
>          compose_i4_len = len_trim(temp)
>       end function compose_i4_len
> end module stuff
>
> program test
>    use stuff
>    implicit none
>           integer foo
>           external foo
>
>           open(11,file='11.out')
> !          open(11,file='12.out') ! BUG!
>           open(12,file='12.out')
> !          write(11,*) foo(12)
>           call write_unit(11,compose_i4(foo(12)))
> end program test
>
> integer function foo(i)
>    implicit none
>    integer i
>           character*9 char_I
>           write(char_i,'(i9)') i
>           write(12,*,err=1000) char_i
> 1000      foo=i
> end function foo
>
> C:\gfortran\clf\recursive_io>gfortran -Wall recursive_io.f90 -orecursive_io
>
> C:\gfortran\clf\recursive_io>recursive_io
>
> C:\gfortran\clf\recursive_io>type 11.out
>           12
>
> C:\gfortran\clf\recursive_io>type 12.out
>         12
>
> For a more complex example, consider the usage of subroutine WX
> inhttp://home.comcast.net/~kmbtib/conv2c.f90.
>
> --
> write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
> 6.0134700243160014d-154/),(/'x'/)); end

Thanks for the example. Just report immediate error without looking
inside to fix that : "attempt to write past end of internal file"
From: Den7 on
On Dec 21, 1:32 pm, "James Van Buskirk" <not_va...(a)comcast.net> wrote:
> "Den7" <rrr7...(a)gmail.com> wrote in message
>
> news:7af7ef60-ae7a-4287-95fc-9e19c71ef671(a)a39g2000pre.googlegroups.com...
>
> > So because I have to ask exactly what i need, the program-maximum is
> > (can i mask more?)
> >          integer foo
> >          external foo
> >          open(11,file='11.out')
> >          open(11,file='12.out')
> >          write(11,*) foo(12)
> >          end
> >          integer function foo(i)
> >          character*9 char_I
> >          write(char_i,'(i9)') i
> >          write(12,*,err=1000) char_i
> > 1000      foo=i
> >          end
>
> I had this problem with recursive I/O when I wrote a code generator
> and posted it to the web so people could test it.  It seemed
> illogical to me that f90 allowed the programmer to write recursive
> code but that f95 permitted compilers to implement I/O, even
> internal I/O, via fixed data structures that made all I/O operations
> non-reentrant.
>
> But if my code was going to be generally usable I had to modify my
> code.  What I did was to create functions that could compose strings
> from numbers using specification functions to determine their LENs.
> Then I could compose a line of output via concatenation of several
> such strings (function results) and invoke a subroutine to print
> out a line of output.  Worked really well except that some f95
> compilers had problems with the specification functions or in
> general with complicated specification expressions.  Here is an
> example adapted to your program:
>
> C:\gfortran\clf\recursive_io>type recursive_io.f90
> module stuff
>    implicit none
>    contains
>       subroutine write_unit(iunit,x)
>          integer, intent(in) :: iunit
>          character(*), intent(in) :: x
>
>          write(iunit,'(a)') x
>       end subroutine write_unit
>       function compose_i4(x)
>          integer, intent(in) :: x
>          character(compose_i4_len(x)) compose_i4
>
>          write(compose_i4,*) x
>       end function compose_i4
>       pure function compose_i4_len(x)
>          integer compose_i4_len
>          integer, intent(in) :: x
>          character(range(x)+3) temp
>
>          write(temp,*) x
>          compose_i4_len = len_trim(temp)
>       end function compose_i4_len
> end module stuff
>
> program test
>    use stuff
>    implicit none
>           integer foo
>           external foo
>
>           open(11,file='11.out')
> !          open(11,file='12.out') ! BUG!
>           open(12,file='12.out')
> !          write(11,*) foo(12)
>           call write_unit(11,compose_i4(foo(12)))
> end program test
>
> integer function foo(i)
>    implicit none
>    integer i
>           character*9 char_I
>           write(char_i,'(i9)') i
>           write(12,*,err=1000) char_i
> 1000      foo=i
> end function foo
>
> C:\gfortran\clf\recursive_io>gfortran -Wall recursive_io.f90 -orecursive_io
>
> C:\gfortran\clf\recursive_io>recursive_io
>
> C:\gfortran\clf\recursive_io>type 11.out
>           12
>
> C:\gfortran\clf\recursive_io>type 12.out
>         12
>
> For a more complex example, consider the usage of subroutine WX
> inhttp://home.comcast.net/~kmbtib/conv2c.f90.
>
> --
> write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
> 6.0134700243160014d-154/),(/'x'/)); end

Thanks for the example. Just report immediate error without looking
inside to fix that : "attempt to write past end of internal file"

I did not get though your idea as soon as i see killing it
write(iunit,'(a)') x

This compiler does not allow recursive I/O was it real I/O or internal
file I/O
From: robin on
Den7 wrote in message ...
>Please look at this code, why this code is forbidden (in my compiler
>at least) ?

And what compiler is that? F77?

>
> integer foo
> external foo
>
> open(11,file='11.out')
> open(12,file='12.out')
> write(11,*) foo(12)
> end
>
> integer function foo(i)
> write(12,*) i
>1000 foo=i
> end function foo
>
>Even if i write into character variable (so called internal write or
>something like that) i have the same problem.
>Even more, if i make
>
> write(12,*,err=1000) i
>
>i still have the crash. How about your compiler?
>
>The error is "The function called from within an I/O statement has
>itself performed an I/O".

That's because it is recursive I/O.

>It sounds to me as silly as this: "The function called from within
>multiplication has itself performed a multiplication", but there could
>be nasty reasons for forbidding this kind of I/Os requiring
>multithreading or so.

It requires recursion, not multithreading.

Why not change FOO to a subroutine?
Then you don't have that problem.


From: Den7 on
On Dec 21, 3:46 pm, "robin" <robi...(a)bigpond.com> wrote:
> Den7 wrote in message ...
> >Please look at this code, why this code is forbidden (in my compiler
> >at least) ?
>
> And what compiler is that?  F77?
>
>
>
>
>
>
>
> >          integer foo
> >          external foo
>
> >          open(11,file='11.out')
> >          open(12,file='12.out')
> >          write(11,*) foo(12)
> >          end
>
> >          integer function foo(i)
> >          write(12,*) i
> >1000      foo=i
> >          end function foo
>
> >Even if i write into character variable (so called internal write or
> >something like that) i have the same problem.
> >Even more, if i make
>
> >          write(12,*,err=1000) i
>
> >i still have the crash. How about your compiler?
>
> >The error is "The function called from within an I/O statement has
> >itself performed an I/O".
>
> That's because it is recursive I/O.
>
> >It sounds to me as silly as this: "The function called from within
> >multiplication has itself performed a multiplication", but there could
> >be nasty reasons for forbidding this kind of I/Os requiring
> >multithreading or so.
>
> It requires recursion, not multithreading.
>
> Why not change FOO to a subroutine?
> Then you don't have that problem.

in mulththreading we have special lock mechanism which
allows I/O even on the same unit, if you lock
it until it finishes its work, then unlock. Another
I/O will then safely come so two overlapping in time
I/Os will not conflict. That is one more option i
reluctantly pursue now...