Prev: Caveat: Can One Dim Local Arrays Using Argument List Integers ??
Next: Spam removal - volunteer?
From: Den7 on 20 Dec 2009 23:56 Please look at this code, why this code is forbidden (in my compiler at least) ? 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". 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. How old VAX ENCODE is implemented in your compiler? Is it done via internal write or by some proprietary other non-I/O way? In other words, can you check if this code below is also crashing, and if it does, is it crashing on ENCODE line statement or on the next lines with WRITE statement? Or may be your compiler allows all these writes and you do not experience a problem at all despite the standard may forbid that? (Please also check syntax of this snippet, i can not run it, my compiler does not support these long forbidden ENCODE/DECODE extensions) open(11,file='11.out') open(12,file='12.out') write(11,*) foo(1) end integer function foo(i) character*9 CHAR_I ENCODE (9,1,CHAR_I) i 1 format (i9) write(12,*) char_i write(12,*) i foo=i end TIA !
From: glen herrmannsfeldt on 21 Dec 2009 00:20 Den7 <rrr7rrr(a)gmail.com> wrote: > Please look at this code, why this code is forbidden (in my compiler > at least) ? > 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 usual implementation has a subroutine call to start, specifying the unit, format, and other options, then one call per element in the I/O list, and finally one to finish the I/O operation. If you do I/O in a function then things get mixed up. This restriction came when machines had much smaller main memory than they do today. For the internal I/O case, I believe the restriction was removed in Fortran 2003. > The error is "The function called from within an I/O statement has > itself performed an I/O". Yes, see above. > 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 happens even without multithreading. Systems can, for example, reuse buffers. You can see, though, that I/O to the same unit could still be a problem. As to multiplication, you can't call a function in the middle of a multiply operation. There are restictions on changing variables used in the same expression, though. Consider: integer foo i=3 j=i*foo(i) print *,i,j end integer function foo(k) foo=k k=k+1 return end > How old VAX ENCODE is implemented in your compiler? Is it done via > internal write or by some proprietary other non-I/O way? In other > words, can you check if this code below is also crashing, and if it > does, is it crashing on ENCODE line statement or on the next lines > with WRITE statement? Or may be your compiler allows all these writes > and you do not experience a problem at all despite the standard may > forbid that? (Please also check syntax of this snippet, i can not run > it, my compiler does not support these long forbidden ENCODE/DECODE > extensions) ENCODE/DECODE were in DEC Fortran 66 compilers. Internal I/O wasn't added to Fortran until Fortran 77. Presumably slowly removed as internal I/O became more popular. -- glen
From: Richard Maine on 21 Dec 2009 00:35 Den7 <rrr7rrr(a)gmail.com> wrote: > Please look at this code, why this code is forbidden .... > The error is "The function called from within an I/O statement has > itself performed an I/O". > It sounds to me as silly as this:... Well, the simple answer is that it is forbidden because the standard says so. Guessing based on what "sounds silly" doesn't tend to be very reliable, at least until one becomes quite an expert; even then one's guesses sometimes come out wrong. (Trust me on that part. :-)) If you want a slightly deeper "why", this one isn't actually particularly difficult. This kind of thing is called recursive I/O. There have been compiler implementations where the I/O routines were not reentrant in the ways required to make this work. Note that the Fortran standard is about what you can count on working in *ALL* implementations. The fact that it might work with some compiler implementations isn't good enough. Also note that the restriction in question originated several decades ago. There existed major compiler implementations of the time where reentrancy was a major pain. Even if one might argue (as people have) that such compilers could have been done otherwise, that wasn't the question at hand. Arguing about what should have been different in the past tends to be pointless (unless one first spends a lot of time in understanding the context of the era). Current compiler technology is a different matter. As of f2003, this code is standard. Odds are reasonably good that many recent f90/f95 compilers allow it, as did some f77 ones. But you can't count on it until f2003. It is the kind of thing that I would suggest not counting on unless it is specifically documented as being supported, insomuch as bugs relating to reentrancy can easily hide in simple testing, only to surface later in more complicated situations. Some cases of recursive I/O also have other complications. That's particularly so of cases where the recursive I/O is to the same file. But that's not a problem when the I/O in the function is to an internal file. > How old VAX ENCODE is implemented in your compiler? Is it done via > internal write or by some proprietary other non-I/O way? That question doesn't really make much sense. Encode is a bit of language syntax, as is internal I/O. You don't implement one piece of language syntax via another (well, not normally; when you do, that's generally called a preprocessor). And encode preceded internal write, so it scarely would have been implemented that way. I'm not going to bother to try to check the sample encode snippet. I don't recall whether encode is supported at all on the compilers I have handy, and even if it was, such a test would show nothing useful. Of course,the standard "forbids" it, as encode has always been nonstandard. I don't need to run compilers test sto tell that; reading the standard tells me much better. That doesn't mean it might or might not work in any particular compiler. And it working with one compiler would tell nothing about whether it would work with another. Nor would it tell anything about recursive internal I/O. Anyway... Prior to f2003, I recommend one of two solutions for recursive I/O. 1. Make it non-recursive by invoking the function in a separate statement before the I/O and storing the result in a variable. In some cases, one might as well then also make it a subroutine. or 2. Avoid I/O in the function, even internal I/O. One can sometimes do the equivalent functionality (such as converting between integer/character) by writing it out in detail. Yes, that can be awkward. That's why internal I/O came about to take advantage of the compiler runtimes already having implemented that for you. That's also why f2003 allows recursive internal I/O - because it is often convenient. But I've done the "longhand" version in simple cases where it only adds a few lines. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: Richard Maine on 21 Dec 2009 00:40 glen herrmannsfeldt <gah(a)ugcs.caltech.edu> wrote: > As to multiplication, you can't call a function in the middle of > a multiply operation. Well, yes you can if the multiply operation is implemented via a defined operation (which you can't do for the cases where the standard defines an intrinsic multiply.) If you happen to do a defined operation for multiply, you will run into the same kinds of limitations. In particular, your multiply routine may not recursively invoke itself (unless it is explicitly declared to be recursive). This is indeed something that could relistically come up if one was doing defined operations. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
From: Tim Prince on 21 Dec 2009 00:42
Den7 wrote: ........ Fortran 2003 permits recursive I/O in a limited set of circumstances, specifically excluding operating on multiple external units, as you suggest you would like to do. F2003 does support use of internal file I/O in a recursive situation, such as might have been done with VAX ENCODE over 30 years ago. Under standards before f2003, there was no requirement to support recursive I/O, and there are several compilers still existent which don't go beyond f95 I/O. |