[comp.sys.mips] Fortran compiler bug?

lilian@mips.COM (Lilian Leung) (05/26/90)

In article <149@snll-arpagw.UUCP>, dandy@snll-arpagw.UUCP (David Dandy) writes:
> I ported a public domain Fortran code to my DECstation 3100, and received
> an f77 compiler error associated with a WRITE statement.  Eliminating all but
> the essential code, the offending subroutine looks like
> 
>       SUBROUTINE SKTEST ( LOUT, LINE, ILEN )
>       IMPLICIT DOUBLE PRECISION ( A-H, O-Z ), INTEGER ( I-N )
>       CHARACTER LINE*(*)
>       WRITE (LOUT, '(A)')
>      1    'Error in SKSNUM...'//LINE(:ILEN)//' not found...'
>       RETURN
>       END
...
> 
> Whether or not this is a bug with the MIPS 2.1 compiler, I have to admit
> that I don't know what the WRITE statement is supposed to be doing (even
> afters reading Wagener's explanation).  Does anyone know a work-around to
> this problem?  I need to get this working before MIPS releases their next
> compiler version.  Is this a bug, or is it not "standard F77"?  Please
> respond by e-mail if you know of a fix or a work-around.  It's frustrating
> to RTFM and still not be sure what's going on.


The above is a documented restriction on MIPS and ANSI FORTRAN.  
In Mips's Part II: FORTRAN Language Reference manaul, page 3-8, 
it states that "Except in a character assignment statement, 
concatenation of an operand with an asterisk(*) as its length specification 
is not allowed unless the operand is the symbolic name of a constant."
In ASNI X3.9-1978 FORTRAN, page 6-8, it says the same thing.

We will input this as a request for enhancement to our FORTRAN compiler.  

Meanwhile, the workaround is to assign  LINE(:ILEN) to a local character
variable with constant length specified and use that variable in your
write statement, like this:

        SUBROUTINE SKTEST ( LOUT, LINE, ILEN )
        IMPLICIT DOUBLE PRECISION ( A-H, O-Z ), INTEGER ( I-N )
        CHARACTER LINE*(*)
	CHARACTER*100 TEMP
	TEMP = LINE
        WRITE (LOUT, '(A)')
       1    'Error in SKSNUM...'//TEMP(:ILEN)//' not found...'
        RETURN
        END

-- 
UUCP:	{ames,decwrl,prls,pyramid}!mips!lilian	(or lilian@mips.com)
DDD:	408-991-7848 Lilian Leung		(or 408-720-1700, Ext. 848)
USPS:	MIPS Computer Systems, 930 Arques, Sunnyvale, CA 94086-3650

sjc@key.COM (Steve Correll) (05/28/90)

In article <149@snll-arpagw.UUCP>, dandy@snll-arpagw.UUCP (David Dandy) writes:
> 
>       SUBROUTINE SKTEST ( LOUT, LINE, ILEN )
>       IMPLICIT DOUBLE PRECISION ( A-H, O-Z ), INTEGER ( I-N )
>       CHARACTER LINE*(*)
>       WRITE (LOUT, '(A)')
>      1    'Error in SKSNUM...'//LINE(:ILEN)//' not found...'
>       RETURN
>       END
> 
> produces the following from the compiler:
>   Error on line 4 of sktest.f: impossible element in concatenation.
> 
> I'm confused because
>   1.  "Fortran 77: Principles of Programming" by J. L. Wagener (pp. 323-
>       325) discusses this as a valid Fortran77 statement.
>   2.  This code compiles without error using VAX/VMS F77 compilers, 
>       UNICOS CFT77 compilers, and Sun release 4.0 f77 compilers.
>       (And probably others--these are the only three I tried.)
> 
> Whether or not this is a bug with the MIPS 2.1 compiler, I have to admit
> that I don't know what the WRITE statement is supposed to be doing (even
> afters reading Wagener's explanation).  Does anyone know a work-around...

The program is telling the compiler to print 'Error in SKSNUM...', followed by
the first ILEN characters of the string variable named "LINE", followed by
' not found...'. I believe the program is illegal because section 6.2.2 on page
6-8 of the ANSI X3.9-1978 "Fortran 77" standard says:

  Except in a character assignment statement (10.4), a character expression
  must not involve concatenation of an operand whose length specification is
  an asterisk in parentheses (8.4.2) unless the operand is the symbolic name
  of a constant.

For good measure, section 15.5.3 on page 15-9 says:

  A character dummy argument whose length specification is an asterisk in
  parentheses must not appear as an operand for concatenation, except in a
  character assignment statement (10.4).

This funny restriction is meant to relieve the compiler of the burden of
allocating temporary storage dynamically (it needs a temporary place to copy
the concatenated strings into, and 'ILEN' is not known at compilation time).

Wagener might claim the use of the substring "(:ILEN)" makes his code legal,
but I don't buy that, since "line", "line(:)", and "line(:len(line))" are
supposed to be identical, and clearly those substrings don't make the
 compiler's task any different.

Anyway, all is not lost. Try the following workaround, which is perfectly
legal Fortran 77:

	write(lout, '(3a)') 'Error in SKSNUM', line(:ilen),
       1    'not found...'

If you really must concatenate the strings, you can do it legally by creating
your own temporary, though you must anticipate the maximum length you will ever
need:

	subroutine sktest(lout, line, ilen)
        character*(*) line, head, tail
        integer tmpsiz
        parameter (head='Error in SKSNUM...',tail=' not found...')
        parameter (tmpsiz=256)
        character temp*(tmpsiz)
        temp = head // line(:ilen) // tail
        write(lout, '(a)') temp(1:len(head)+ilen+len(tail))
        end
-- 
...{sun,pyramid}!pacbell!key!sjc 				Steve Correll