Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Internal file question

1 view
Skip to first unread message

Paul van Delst

unread,
Dec 10, 2007, 11:10:48 AM12/10/07
to
Hello,

A colleague received some code from a third party and asked me if the following usage of
internal files is standard:

PROGRAM t
character(len=16) :: strtofind !String one is looking for
strtofind = "1 "
print *, "|", strtofind , "|"
write(strtofind,'(A1,A,A1)') ',',trim(adjustl(strtofind)),','
print *, "|", strtofind , "|"
END PROGRAM t


Results from a slew of compilers:

lnx:f90_Test/Feature_Test_Programs : lf95 test_internalfile.f90
Encountered 0 errors, 0 warnings in file test_internalfile.f90.
lnx:f90_Test/Feature_Test_Programs : a.out
|1 |
|,1, |
lnx:f90_Test/Feature_Test_Programs : g95 test_internalfile.f90
lnx:f90_Test/Feature_Test_Programs : a.out
|1 |
|,,, |
lnx:f90_Test/Feature_Test_Programs : gfortran test_internalfile.f90
lnx:f90_Test/Feature_Test_Programs : a.out
|1 |
|,,, |
lnx:f90_Test/Feature_Test_Programs : pgf95 test_internalfile.f90
lnx:f90_Test/Feature_Test_Programs : a.out
|1 |
|,1, |

(xlf95 compiler also outputs "|,,, |" after the write.

After reading the standard, I *think* (but not sure) the code itself is legal, but the
standard does say the following about internal file properties (sec 9.2.2.1. I think these
are the only relevant bits):

(4) A record of the internal file becomes defined by writing the record.
If the number of characters written in a record is less than the length
of the record, the remaining portion of the record is filled with blanks.
The number of characters to be written shall not exceed the length of the
record.

(6) A record of an internal file may become defined (or undefined) by means
other than an output statement. For example, the character variable may become
defined by a character assignment statement.

(7) An internal file is always positioned at the beginning of the first record prior
to data transfer. This record becomes the current record.


It seems to me that the test result of ",,," is the "correct" one since #4 states:
- An internal file is always positioned at the beginning of the first record prior
to data transfer
Thus, even though the string in question was defined via an assignment statement
beforehand, because the internal I/O positions the file at the beginning of the first
record the existing data in the file is overwritten. Couple that with #7
- A record of the internal file becomes defined by writing the record.

That, to me, means that it doesn't matter what was in the character variable prior to the
write statement because the internal file unit record is always "re"defined for each write
statement.

So, any opinions? Which is the "correct" output:
,1,
or
,,,

??


cheers,

paulv

Dick Hendrickson

unread,
Dec 10, 2007, 12:12:08 PM12/10/07
to
Paul van Delst wrote:
> Hello,
>
> A colleague received some code from a third party and asked me if the
> following usage of internal files is standard:
>
> PROGRAM t
> character(len=16) :: strtofind !String one is looking for
> strtofind = "1 "
> print *, "|", strtofind , "|"
> write(strtofind,'(A1,A,A1)') ',',trim(adjustl(strtofind)),','

I think it's ",1," for the correct output.
Try replacing the internal write with a print. The write into
strtofind is sort of a red herring.
My reasoning is
1) the value of adjustl(strtofind) is "1 "
since strtofind is already left adjusted and adjustl is
length preserving
2) the value if trim("1 ") is "1"
3) so, the output list eventually looks like ',', "1", ','
4) printing this with (A1,A,A1) should give ",1,"
5) The internal write should stuff that value into strtofind and,
by your (4) below, it then gets blank filled.

At least that's how it looks to me. It's a bugger to read I/O
lists that have quoted commas in them, that's why I spaced it out
in 3).

If I had to guess, I'd guess that some compilers recognize adjustl
and trim as essentially trivial functions and do leads from strtofind
at the same time as they are doing internal writes into it. They
need to make a temporary copy of strtofind to use during the
on-the-fly evaluation of trim(adjustl(strfunction)). It's not
much different from
call sub(x, (x), x+x-x, 1*x, x+0)
the compiler needs to make lots of copies of x.

Dick Hendrickson

Dick Hendrickson

Michael Metcalf

unread,
Dec 10, 2007, 12:16:02 PM12/10/07
to

"Paul van Delst" <Paul.v...@noaa.gov> wrote in message
news:475D650...@noaa.gov...

>
> So, any opinions? Which is the "correct" output:

On p. 188 of "Fortran 95/2003 Explained" it says "... no item in a the
input/output list may be in the file or associated with the file.". Thus, I
think your code is not legal.

Regards,

Mike Metcalf


Richard Maine

unread,
Dec 10, 2007, 12:26:15 PM12/10/07
to
Paul van Delst <Paul.v...@noaa.gov> wrote:

> A colleague received some code from a third party and asked me if the
> following usage of internal files is standard:
>
> PROGRAM t
> character(len=16) :: strtofind !String one is looking for
> strtofind = "1 "
> print *, "|", strtofind , "|"
> write(strtofind,'(A1,A,A1)') ',',trim(adjustl(strtofind)),','
> print *, "|", strtofind , "|"
> END PROGRAM t

I don't think so, though I'm having trouble finding exactly the right
citation in the standard to cover it. I can find some simillar
restrictions, but not quite that exact one.

> After reading the standard, I *think* (but not sure) the code itself is
> legal, but the standard does say the following about internal file
> properties (sec 9.2.2.1. I think these are the only relevant bits):

[elided]

Nah. I'd say you are focusing on the wrong part of the question. Yes,
you have those parts right. I can't imagine any disagreement of subtance
with your conclusion:

> t doesn't matter what was in the character
> variable prior to the write statement because the internal file unit
> record is always "re"defined for each write statement.

But that's not the "interesting" part of this sample. The tricky bit is
that strtofind appears in two places in the write statement. One of
those places (as the internal unit) causes it to become defined. The
other place (in the I/O list) references it. Thus, there are questions
about the order in which things happen in the write statement.

The standard has a whole bunch of restrictions against things that might
cause ambiguities like that in I/O statements. For the most part, those
restrictions allow the processor to do things in pretty much any
"reasonable" order, disallowing the cases where the processor's choice
of order might matter. Unfortunately, in my view, those restrictions are
alll phrased in very specific terms, making it awfully easy for cases to
"slip by". I suppose that specificity might be because there are a few
cases where the standard intentionally does allow interactions; writing
the description in more general terms would probably hit those cases
also.

For example, you can do

read (....) n,(x(i),i=1,n)

even though n is defined by one of its appearances and referenced in
another.

Anyway, even though I can't quite find an exactly matching restriction
(the internal file is part of a "specifier"; the I/O list is not), I'm
quite certain that is your problem area. One could perhaps argue whether
the compilers or the code are in error, but I bet that is the area of
the error.

Note that assignment statements make it quite explicit that the
right-hand-side is evaluated first, before assigning the value to the
left-hand-side. Implementations sometimes have to make use of temporary
storage in order to make this work out right. (This is as of f90; f77
was different on that and disallowed the problem cases.)

> So, any opinions? Which is the "correct" output:

None, because I think the code is invalid.

To fix it, make the temporary variable yourself, as in

PROGRAM t
character(len=16) :: strtofind, temp


strtofind = "1 "
print *, "|", strtofind , "|"

temp = strtofind
write(strtofind,'(A1,A,A1)') ',',trim(adjustl(temp)),','


print *, "|", strtofind , "|"
END PROGRAM t

That makes the ordering of things explicit. The string that is used in
the I/O list is one that is defined prior to the IO statement and does
not change during the I/O statement.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain

Richard Maine

unread,
Dec 10, 2007, 12:35:02 PM12/10/07
to
Michael Metcalf <michael...@compuserve.com> wrote:

That would be the restriction I was looking for (mentioned in my
long-winded reply that I typed before seeing this one). I still don't
see that in the standard (f2003 is the only one I looked in) , but my
skim was pretty quick, so I might have missed it (or... I suppose there
might have been some rewording between f95 and f2003 that confused
this.)

Paul van Delst

unread,
Dec 10, 2007, 12:55:35 PM12/10/07
to
Richard Maine wrote:
> Michael Metcalf <michael...@compuserve.com> wrote:
>
>> "Paul van Delst" <Paul.v...@noaa.gov> wrote in message
>> news:475D650...@noaa.gov...
>>> So, any opinions? Which is the "correct" output:
>> On p. 188 of "Fortran 95/2003 Explained" it says "... no item in a the
>> input/output list may be in the file or associated with the file.". Thus, I
>> think your code is not legal.
>
> That would be the restriction I was looking for (mentioned in my
> long-winded reply that I typed before seeing this one). I still don't
> see that in the standard (f2003 is the only one I looked in) , but my
> skim was pretty quick, so I might have missed it (or... I suppose there
> might have been some rewording between f95 and f2003 that confused
> this.)

Hello again,

I found it. In section "9.4.4.4 Data Transfer" the f95 standard states (nearly the same as
MRC):

"If an internal file has been specified, an input/output list item shall not be in the

file or associated with the file."

So, you and Mike were correct. The code is illegal.

Thanks very much.

cheers,

paulv

Richard Maine

unread,
Dec 10, 2007, 1:18:31 PM12/10/07
to
Paul van Delst <Paul.v...@noaa.gov> wrote:

>
> I found it. In section "9.4.4.4 Data Transfer" the f95 standard states
> (nearly the same as MRC):
>
> "If an internal file has been specified, an input/output list item shall
> not be in the file or associated with the file."

Ah, yes. It is also in the corresponding place in f2003, so I'm glad it
hasn't gotten accidentally reworded to fail to cover that. Darned
strange place for it, though.

glen herrmannsfeldt

unread,
Dec 10, 2007, 3:05:40 PM12/10/07
to
Richard Maine wrote:
> Paul van Delst <Paul.v...@noaa.gov> wrote:

(snip)


>>PROGRAM t
>> character(len=16) :: strtofind !String one is looking for
>> strtofind = "1 "
>> print *, "|", strtofind , "|"
>> write(strtofind,'(A1,A,A1)') ',',trim(adjustl(strtofind)),','
>> print *, "|", strtofind , "|"
>>END PROGRAM t

(snip)

> But that's not the "interesting" part of this sample. The tricky bit is
> that strtofind appears in two places in the write statement. One of
> those places (as the internal unit) causes it to become defined. The
> other place (in the I/O list) references it. Thus, there are questions
> about the order in which things happen in the write statement.

I have seen this done in C with sprintf, where the output string is
the first item written to append to a string. It is just as illegal
in C, but if it is the first item it is likely to work.

In your case, it is likely to copy the ',' first overwriting the
first character of strtofind. It then likely copies strtofind one
character at a time, filling the string with ','.
(snip)

> For example, you can do

> read (....) n,(x(i),i=1,n)

> even though n is defined by one of its appearances and referenced in
> another.

I sometimes do this with unformatted files. It is a little
dangerous in that you can't check that n is within the array
bounds, but otherwise it works well.

-- glen

Michael Metcalf

unread,
Dec 10, 2007, 3:09:41 PM12/10/07
to

"glen herrmannsfeldt" <g...@ugcs.caltech.edu> wrote in message
news:sI-dnZ6NGslqB8Da...@comcast.com...

>
>> For example, you can do
>
>> read (....) n,(x(i),i=1,n)
>
>> even though n is defined by one of its appearances and referenced in
>> another.
>
> I sometimes do this with unformatted files. It is a little
> dangerous in that you can't check that n is within the array
> bounds, but otherwise it works well.
>
Right, but what OP was trying to do was the equivalent of

n = 99
read (n) n,(x(i),i=1,n)

Regards,

Mike Metcalf


Paul van Delst

unread,
Dec 10, 2007, 3:51:28 PM12/10/07
to

Hello,

But that *is* allowed, right? The restriction is on internal, not external, files. In
fact, there is a descriptive note with the equivalent of your example:


NOTE 9.32
In the example,
READ (N) N, X (N)
the old value of N identifies the unit, but the new value of N is the subscript of X.


It's a few (short) paragraphs later that the restriction on internal files is mentioned.

cheers,

paulv

Michael Metcalf

unread,
Dec 10, 2007, 4:30:45 PM12/10/07
to

"Paul van Delst" <Paul.v...@noaa.gov> wrote in message
news:fjk8sh$k96$1...@news.nems.noaa.gov...

>
> But that *is* allowed, right? The restriction is on internal, not
> external, files. In fact, there is a descriptive note with the equivalent
> of your example:
>
>
> NOTE 9.32
> In the example,
> READ (N) N, X (N)
> the old value of N identifies the unit, but the new value of N is the
> subscript of X.
>
Right, I'd overlooked that, probably because of being in a state of denial
that it's even allowed.

Regards,

Mike Metcalf


Dick Hendrickson

unread,
Dec 10, 2007, 4:39:24 PM12/10/07
to
Richard Maine wrote:
> Paul van Delst <Paul.v...@noaa.gov> wrote:
>
>> I found it. In section "9.4.4.4 Data Transfer" the f95 standard states
>> (nearly the same as MRC):
>>
>> "If an internal file has been specified, an input/output list item shall
>> not be in the file or associated with the file."
>
> Ah, yes. It is also in the corresponding place in f2003, so I'm glad it
> hasn't gotten accidentally reworded to fail to cover that. Darned
> strange place for it, though.
>
I think you're wrong. The input/output list item in question is
"trim(adjustl(strtofind))". That's an expr and I'd be willing to say
that it's not in strtofind any more than COS(X(3)) is in an array
called X. It's also not associated with the file. In F2003 association
is defined as name, pointer, storage, or inheritance and the expr
isn't any of those. We don't say that SQRT(z) is associated with z.

We almost for sure don't want to allow in in an output list, but I
don't think the words in the standard say that.

Dick Hendrickson

Richard Maine

unread,
Dec 10, 2007, 5:00:49 PM12/10/07
to
Michael Metcalf <michael...@compuserve.com> wrote:

It isn't allowed. But that restriction is in a different place (a much
more sensible one). I sure wish those restrictions were either collected
together or at least organized better. There have been attempts, but
they obviously are half-measures... or less. As mentioned before, I also
wish they could be stated more generally; the way they are done now is
subject to so many niggling oversights.

For that one see 9.11 in f2003 (The section titled "Restrictions on
input/output statements", which was at least an attempt to collect these
things). Sixth para

"The value of a specifier in an input/output statement shall not
depend on any input-item..."

But this is specific to input items. The original case was output. And
as Dick noted, the darned phrasing might indeed have a hole in that
strtosearch wasn't exactly an output item.

Paul van Delst

unread,
Dec 10, 2007, 5:08:41 PM12/10/07
to

Hmm.... good point.

How does one resolve these sorts of ambiguities wrt the standard?

cheers,

paulv

Paul van Delst

unread,
Dec 10, 2007, 5:12:51 PM12/10/07
to
Richard Maine wrote:
> Michael Metcalf <michael...@compuserve.com> wrote:
>
>> "Paul van Delst" <Paul.v...@noaa.gov> wrote in message
>> news:fjk8sh$k96$1...@news.nems.noaa.gov...
>>> But that *is* allowed, right? The restriction is on internal, not
>>> external, files. In fact, there is a descriptive note with the equivalent
>>> of your example:
>>>
>>>
>>> NOTE 9.32
>>> In the example,
>>> READ (N) N, X (N)
>>> the old value of N identifies the unit, but the new value of N is the
>>> subscript of X.
>>>
>> Right, I'd overlooked that, probably because of being in a state of denial
>> that it's even allowed.
>
> It isn't allowed. But that restriction is in a different place (a much
> more sensible one).

Wha..? Isn't that slightly misleading? The descriptive note strongly implies that the
source is legal since there is no statement close by that I could find stating otherwise.

> I sure wish those restrictions were either collected
> together or at least organized better. There have been attempts, but
> they obviously are half-measures... or less. As mentioned before, I also
> wish they could be stated more generally; the way they are done now is
> subject to so many niggling oversights.

I think establishing a convention for labelling or tagging them would be a good start.
E.g. I can search a section of the document for "constraint" when I want to know what they
are for a particular topic.

>
> For that one see 9.11 in f2003 (The section titled "Restrictions on
> input/output statements", which was at least an attempt to collect these
> things). Sixth para
>
> "The value of a specifier in an input/output statement shall not
> depend on any input-item..."
>
> But this is specific to input items. The original case was output. And
> as Dick noted, the darned phrasing might indeed have a hole in that
> strtosearch wasn't exactly an output item.

Yep. It's sort of turned into a bit of mess in my mind.

cheers,

paulv

Dan Nagle

unread,
Dec 10, 2007, 5:20:36 PM12/10/07
to
Hello,

Paul van Delst wrote:

> How does one resolve these sorts of ambiguities wrt the standard?

One ventures down a dark and foreboding path
called "Interpretation Request", and in several years, perhaps,
if others agree one has spotted something really in need of repair,
a Corrigendum will be published with one's question suitably enshrined.

The first step is to obtain a consensus that some really is wrong
with the standard. If so, it's all downhill from there. ;-)

--

Dan Nagle
Purple Sage Computing Solutions, Inc.

Dick Hendrickson

unread,
Dec 10, 2007, 5:34:34 PM12/10/07
to

Actually, there is an interpretation request in to J3 saying that the
restriction is too strong. It's paper 266 from the London meeting.
The example in note 9.32 used to be specifically allowed in
normative text in F90 and the interp proposes reallowing it. The
reasoning being that formally allowed code shouldn't be made
non-standard without explicit intent. It turns out that there are
a number of things in the I/O control list whose usage was
suddenly restricted by the new F2003 sentence. The intep passed the
preliminary meeting vote, but then failed in the subsequent written
vote because of the need to consider the other control list items.
At least, that's my recollection about the interp status.

Dick Hendrickson

PS: I'm shocked that Richard didn't know this ;). The issue came
up at an author's meeting for a book he's co-writing.

Richard Maine

unread,
Dec 10, 2007, 5:35:52 PM12/10/07
to
Paul van Delst <Paul.v...@noaa.gov> wrote:

> Richard Maine wrote:
> > Michael Metcalf <michael...@compuserve.com> wrote:
> >
> >> "Paul van Delst" <Paul.v...@noaa.gov> wrote in message
> >> news:fjk8sh$k96$1...@news.nems.noaa.gov...

> >>> NOTE 9.32


> >>> In the example,
> >>> READ (N) N, X (N)
> >>> the old value of N identifies the unit, but the new value of N is the
> >>> subscript of X.
> >>>
> >> Right, I'd overlooked that, probably because of being in a state of denial
> >> that it's even allowed.
> >
> > It isn't allowed. But that restriction is in a different place (a much
> > more sensible one).
>
> Wha..? Isn't that slightly misleading? The descriptive note strongly
> implies that the source is legal since there is no statement close by that
> I could find stating otherwise.

Oh. I overlooked the fact that you were quoting a note from the
standard. I just jumped right into looking at the code and then went to
the restriction I figured would apply. Yukk. Well, at least for f2003,
the restriction that I mentioned is in normative text. (I haven't gone
looking in f95). Normative text trumps notes. They aren't supposed to
conflict, but if they do, the normative text wins. At least that's the
rule. When such conflicts are found, that is generally grounds for an
interp to fix it anyway.

> > "The value of a specifier in an input/output statement shall not
> > depend on any input-item..."

N is an input-item and the value of the unit specifier depends (rather
strongly :-)) on N.

The answer to your other question about how one resolves such
ambiguities (or conflicts) in the standard is that that's what the
interpretation process is for. But that is a long and laborious process.
It can take multiple years to get through the whole thing. You do *NOT*
want to be waiting on that process. It is good to get things fixed in
the standard, but not something you want to have a project that is
waiting on.

In the original case here, the "obvious" thing to do is fix the code
regardless instead of waiting a few years for an interp of the standard
to say whether or not it is conforming, and maybe a few more years for
vendors to implement the fix.

Richard Maine

unread,
Dec 10, 2007, 5:40:08 PM12/10/07
to
Dick Hendrickson <dick.hen...@att.net> wrote:

> PS: I'm shocked that Richard didn't know this ;). The issue came
> up at an author's meeting for a book he's co-writing.

Yes, but I'm almost as old/senile as the other authors. :-( And that
area of the I/O stuff is a mess that my mind easily slides over. Or
maybe its just that I fall asleep. Glad I didn't have to write that
chapter. It went to someone smarter than me. :-)

glen herrmannsfeldt

unread,
Dec 10, 2007, 6:00:58 PM12/10/07
to
Dick Hendrickson wrote:

(previous snip regarding:


write(strtofind,'(A1,A,A1)') ',',trim(adjustl(strtofind)),','

)

> Richard Maine wrote:
>> Paul van Delst <Paul.v...@noaa.gov> wrote:
>>> I found it. In section "9.4.4.4 Data Transfer" the f95 standard states
>>> (nearly the same as MRC):

>>> "If an internal file has been specified, an input/output list item shall
>>> not be in the file or associated with the file."

>> Ah, yes. It is also in the corresponding place in f2003, so I'm glad it
>> hasn't gotten accidentally reworded to fail to cover that. Darned
>> strange place for it, though.

> I think you're wrong. The input/output list item in question is
> "trim(adjustl(strtofind))". That's an expr and I'd be willing to say
> that it's not in strtofind any more than COS(X(3)) is in an array
> called X. It's also not associated with the file. In F2003 association
> is defined as name, pointer, storage, or inheritance and the expr
> isn't any of those. We don't say that SQRT(z) is associated with z.

It isn't quite the same. X(3) fits in a register or small amount
of memory. Also, there isn't a direct connection between the bits
in X(3) and COS(X(3)). With the adjustl() it isn't so obvious, but
for trim() addressing the same memory with a new length seems
fairly easy. Since some compilers did, in fact, generate ',,,'
for strtofind it seems that at least some do use the same bits.

> We almost for sure don't want to allow in in an output list, but I
> don't think the words in the standard say that.

So, how about

write(STR,'(F10.5)') COS(DFLOAT(ICHAR(STR(3:3))))

I would be pretty surprised if it didn't work, but I don't believe
that the standard tries to make the distinction between what could
possibly be affected by the change and what couldn't.

-- glen

Dick Hendrickson

unread,
Dec 14, 2007, 12:31:19 PM12/14/07
to

I just sent the question to J3 as either an add-on to an existing
similar interpretation request or as a new one. As Dan said, it
takes a while ;(. It's always hard to predict the future, but I'd
guess the answer will be "That's illegal." That sure looks like
the intent of the quoted text above.

Dick Hendrickson
>
> cheers,
>
> paulv

Paul van Delst

unread,
Dec 17, 2007, 7:47:12 AM12/17/07
to

Wow. Thanks. Given the other answers I got to my resolution question, I adopted the lazy
cynic approach and wasn't going to bother any further. I really appreciate you taking the
effort. Since you've got the proverbial moving, if you need any additional voices, let me
know.

cheers,

paulv

0 new messages