PROGRAM JUNK
EXTERNAL FOO
CHARACTER*8 FOO
CHARACTER*8 STMTFA,STMTFB
INTEGER A
STMTFA(A) = FOO('A',A)
STMTFB(A) = FOO('B',A)
CALL BAR(STMTFA(1),STMTFB(2))
STOP
END
CHARACTER*(*) FUNCTION FOO(A,B)
CHARACTER*(*) A
INTEGER B
CHARACTER*4 C
WRITE(C,'(I4)') B
FOO = A // C
RETURN
END
SUBROUTINE BAR(A,B)
CHARACTER*(*) A,B
WRITE(*,*) A,' ',B
RETURN
END
The important part of all this, from my point of view, is that we have
multiple occurrences of the same external function appearing as actual
arguments to a subroutine via different statement functions.$$
--
INET: Mark-...@UAI.COM NIC: ML255 ICBM: USA; Lower Left Coast
"Anything worth doing in Japan is worth doing in a crowd." -- T. R. Reid
Mark> I would like some opinions about whether the following program
Mark> conforms to ANSI X3.9-1978:
[sample omitted]
Yes, it conforms (unless I missed something, but it looks ok).
Mark> The important part of all this, from my point of view, is that we have
Mark> multiple occurrences of the same external function appearing as actual
Mark> arguments to a subroutine via different statement functions.
No you don't. The external function does not appear as an actual
argument. The value of the external function is evaluated and
used in computing the expressions in the actual arguments. Only
the resulting expression value is passed as an argument. It is
completely irrelevant that the evaluation of the expression happens
to involve external functions.
It is possible to pass external functions as arguments, but that
is a very different thing from passing an expression that involves
a function evaluation. When you pass such an expression, the
function is evaluated only once, for the specific values given
in the expression. When you pass an external function itself,
it is not evaluated at all during the call; just the address of
the function is passed.
--
--
Richard Maine
ma...@altair.dfrf.nasa.gov
Well, I think you missed something:
CHARACTER*(*) FUNCTION FOO(A,B)
CHARACTER*(*) A
* ^^^^
INTEGER B
CHARACTER*4 C
WRITE(C,'(I4)') B
FOO = A // C
* ^^^^
RETURN
END
Isn't the underlined in violation of the standard? You can't append to
a string with length * if I remember some postings here correctly.
Michael
--
Michael Lemke
Astronomy, UT Austin, Texas
(mic...@io.as.utexas.edu or UTSPAN::UTADNX::IO::MICHAEL [SPAN])
>Yes, it conforms (unless I missed something, but it looks ok).
Well, I think you missed something:
CHARACTER*(*) FUNCTION FOO(A,B)
CHARACTER*(*) A
* ^^^^
INTEGER B
CHARACTER*4 C
WRITE(C,'(I4)') B
FOO = A // C
* ^^^^
RETURN
END
Isn't the underlined in violation of the standard? You can't append to
a string with length * if I remember some postings here correctly.
No, it looks fine to me. You can have a *-length subexpression in
an expression involving concatenation (//) in an assignment statement --
but not as an actual argument. Reason being that FOO = A // C does not
require run-time heap allocation because it never needs more
space than is already allocated for the return value of FOO (by the
caller, typically); but CALL X(A//C) would require run-time allocation of
memory since the maximum length of the argument could not be calculated until
run time and no space would already be set aside to hold it.
--
James Craig Burley, Software Craftsperson bur...@gnu.ai.mit.edu
Member of the League for Programming Freedom (LPF) l...@uunet.uu.net
On Tue, 24 Aug 1993 21:53:46 GMT, m...@uai.com (Mark R. Ludwig) said:
Mark> I would like some opinions about whether the following program
Mark> conforms to ANSI X3.9-1978:
[sample omitted]
Yes, it conforms (unless I missed something, but it looks ok).
Mark> The important part of all this, from my point of view, is that we have
Mark> multiple occurrences of the same external function appearing as actual
Mark> arguments to a subroutine via different statement functions.
No you don't. The external function does not appear as an actual
argument. The value of the external function is evaluated and
used in computing the expressions in the actual arguments. Only
the resulting expression value is passed as an argument. It is
completely irrelevant that the evaluation of the expression happens
to involve external functions.
Well, not _completely_ irrelevant...here's the sample program again:
PROGRAM JUNK
EXTERNAL FOO
CHARACTER*8 FOO
CHARACTER*8 STMTFA,STMTFB
INTEGER A
STMTFA(A) = FOO('A',A)
STMTFB(A) = FOO('B',A)
CALL BAR(STMTFA(1),STMTFB(2))
STOP
END
CHARACTER*(*) FUNCTION FOO(A,B)
CHARACTER*(*) A
INTEGER B
CHARACTER*4 C
WRITE(C,'(I4)') B
FOO = A // C
RETURN
END
SUBROUTINE BAR(A,B)
CHARACTER*(*) A,B
WRITE(*,*) A,' ',B
RETURN
END
Now, delete subroutine BAR and replace CALL BAR(STMTFA(1),STMTFB(2)) with:
WRITE(*,*) STMTFA(1),STMTFB(2)
With these changes, the program is not standard-conforming, because during
execution of the new WRITE statement, FOO is invoked, which in turn
attempts to do I/O of some kind, and FORTRAN 77 does not allow nested I/O.
But I can't see anything wrong with the program as written. Maybe if the
poster actually spelled out what was apparently going wrong?
Craig> But I can't see anything wrong with the program as written. Maybe if the
Craig> poster actually spelled out what was apparently going wrong?
As it turns out, the problem had nothing to do with what I thought it
did. The problem was with some hairy call chains involving more than
20 arguments, nested 3 or 4 deep, some of which are these statement
function evaluations. I made the mistake of trying to read the
standard regarding these things, and misinterpreted the part about not
being able to pass the statement function _itself_ as meaning one
could not pass an expression involving a statement function reference.
Then I started thinking about how the compiler allocates memory for
the return values from all the function calls in the actual argument
list, and confused myself even further.
The actual problem turned out to be a mismatch in some _other_ calls
earlier in the program. Too few arguments were being passed. The
manifestation was truly festive, because it somehow clobbered the
length descriptors for the other character arguments, so when they
were used later, their lengths were gigantic.
Maybe I have a candidate for that hairiest bug trawler after all....$$
Thanks, this makes much more sense now. So the code is just fine.
Sorry for my faulty posting.
I would say that the last three statements are all invalid, as STMTFA
and STMTFB have not been defined as arrays.
There must be something that I'm overlooking here, because I'm sure
that somebody as sharp as Craig would have caught this...
--
#include <Standard_Disclaimer.h>
Michael F. Stemper
Power Systems Consultant
mste...@empros.com
In article <MRL.93Au...@hp.uai.com>, m...@uai.com (Mark R. Ludwig) writes:
>I would like some opinions about whether the following program
>conforms to ANSI X3.9-1978:
>
> PROGRAM JUNK
> EXTERNAL FOO
> CHARACTER*8 FOO
> CHARACTER*8 STMTFA,STMTFB
> INTEGER A
> STMTFA(A) = FOO('A',A)
> STMTFB(A) = FOO('B',A)
> CALL BAR(STMTFA(1),STMTFB(2))
I would say that the last three statements are all invalid, as STMTFA
and STMTFB have not been defined as arrays.
Indeed, which means that the first two of those three statements are
(interpreted by the compiler as) statement function definitions.
There must be something that I'm overlooking here, because I'm sure
that somebody as sharp as Craig would have caught this...
Well, comments in the code would certainly help. It's annoying for a
language definition to provide identical syntax for two kinds of
statements that have such widely different meaning. But such
annoyances weren't well-understood, apparently, when this aspect of
Fortran was designed. So comments like "DEFINE TWO STATEMENT FUNCTIONS",
even though typically overly verbose in more modern languages
(as in the C case of "i += 1; /* Add 1 to i. */"), can, when
thoughtfully used, help the human reader of Fortran code skim
stuff, and when abused, completely mislead any but the most cynical
and experienced Fortran hacker. :-)
Neat thing, though. As part of thinking about this post, I typed in
a sample program to GNU Fortran (my local in-development copy, as
yet unreleased), and it crashed! So, even though you might have missed
the statement-function angle, your post did trigger the discovery
of a g77 bug. (Gee, I hope it'll be easy to find and fix....)