f77 -c -o alqueva.o alqueva.f
alqueva.f: In program `ssssss':
alqueva.f:402:
DO WHILE (.NOT. EOF(12))
1 2
.NOT. operator at (1) must operate on subexpression of logical type, but the subexpression at (2) is not of logical type
alqueva.f:415:
DO WHILE (.NOT. EOF(iread))
1 2
.NOT. operator at (1) must operate on subexpression of logical type, but the subexpression at (2) is not of logical type
make: *** [alqueva.o] Error 1
It's been a while since I did much fortran, but I don't believe that the EOF function is part of the standard for fortran 77, and I always used the end=label idiom
10 read (blah,end=20)
process stuff
goto 10
20 close (blah)
(but possibly using do instead of goto...)
Here is page which discusses several options including the above and one based on iostat
Related
I have to deal with an old piece of software written in Fortran (mainly written in the 70's and badly maintained up to 3 years ago).
I am trying to get it compiled with VS2017 and the Intel oneAPI compiler (Fortran Compiler Classic 2021.3.0) for 64-bits architectures.
In the process of updating one of its modules, I convinced myself that the compiler does not support what I have learned to be called "host association" between subroutines (via CONTAINS statement). None of the symbols defined in a containing subroutine seems to be visible in the contained subroutine (if I use IMPLICIT NONE in the contained subroutine the compiler tells me that I need to declare all of them while if I don't, the compilers gets the declarations very wrong and not matching with the declarations in the containing subroutine. Lots of misleading error messages are printed).
Can somebody of you confirm that this is the case or provide the compiler options to enable this feature that clearly was allowed in the past by some compilers? If needed I will post the source code (I am not posting it immediately because I think this could be a very naive question for a Fortran expert, I am instead a total novice).
Sincerely,
HERE I COMPLEMENT THE ORIGINAL POST AS REQUESTED IN THE COMMENTS
Original code:
Subroutine LoadUserLibs(TypesInDeck,*)
... OMITTED COMMENTS ...
! This routine is only used in the multi-DLL configuration (otherwise empty routine)
!dec$ if defined (TRNSYS_MULTI_DLL)
Use DFWIN
Use DFLIB
!Use KERNEL32
Use TrnsysConstants
Use TrnsysFunctions
Use TrnsysData, Only: steamMethod,isNISTSteamFound
! Force explicit variable declaration
Implicit None
! Local variable declarations
Type(T_WIN32_FIND_DATA):: WFD
Character (len=maxPathLength) UserDir,FoundListStr,SearchListStr
Character (len=maxMessageLength) msgString
Integer :: libFile, j, k
Logical :: bSt
Character (len=12) jStr,TypeNum,numDLLsStr
Character (len=20) routineName
Integer luw !listing file logical unit number
Integer (kind=8) ExistTest !declares an integer to temporarily contain a pointer
Integer i !not used but must be delcared as part of a POINTER declaration.
Integer (kind=8) LibHandles(100) !declares an array where handles to loaded libraries are stored.
Integer LibCount !a counter variable used to keep track of how many dlls have been loaded
Integer TypeCount !a counter variable used to count how many Types were found in a given dll.
Integer TypesInDeck(nMaxUnits) !an array containing a list of Types that are in the deck being run.
Integer TotalTypes/0/ !the total number of Types in the deck being run (no duplicates)
Integer TypesListed/0/ !a variable used to count how many of the Types that were found, have been listed so far.
Integer, Allocatable :: SearchList(:,:) !an array of Type numbers to look for in dlls.
Integer, Allocatable :: FoundList(:)
Logical :: isType155InDeck = .false., isType155DllFound = .false.
! Common black definitions
Integer(INT_PTR_KIND()) paa(nMaxTypes) !declares an integer array that will contain pointer addresses to the Types
Integer(INT_PTR_KIND()) saa !declares an integer that will contain a pointer address of the NIST steam routines.
Common /USRDLLS/ paa,saa
! Pointer definitions
Pointer (p,i)
... OMITTED CODE ...
!dec$ else
! Single-DLL configuration: empty routine
!dec$ endif
Return
Contains
Subroutine LoadTypesFromDll()
... OMITTED CODE ...
End Subroutine LoadTypesFromDll
End Subroutine LoadUserLibs
Errors I received compiling the original code:
Severity Code Description Project File Line Suppression State
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 276
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 284
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 303
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 309
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 314
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 315
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 317
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. [CFILENAME] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 302
Error error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. [CFILENAME] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 308
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 276
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 284
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 284
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 303
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 309
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 314
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 315
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 315
Error error #6362: The data types of the argument(s) are invalid. [TRIM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 317
Error error #6410: This name has not been declared as an array or a function. [FOUNDLIST] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 291
Error error #6410: This name has not been declared as an array or a function. [LIBHANDLES] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 268
Error error #6423: This name has already been used as an external function name. [PAA] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 289
Error error #6423: This name has already been used as an external function name. [SEARCHLIST] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 292
Error error #6460: This is not a component name that is defined in the encompassing structure. [CFILENAME] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 283
Error error #6514: Substring or array slice notation requires CHARACTER type or array. [CFILENAME] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 302
Error error #6514: Substring or array slice notation requires CHARACTER type or array. [CFILENAME] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 308
Error error #6514: Substring or array slice notation requires CHARACTER type or array. [FOUNDLIST] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 321
Error error #6514: Substring or array slice notation requires CHARACTER type or array. [TYPENUM] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 284
Error error #6515: This function, which is specified as the left side of an assignment statement, is invalid. [PAA] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 289
Error error #6515: This function, which is specified as the left side of an assignment statement, is invalid. [SEARCHLIST] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 292
Error error #6535: This variable or component must be of a derived or structure type. [WFD] C:\Development\trndll-vs2017-ifc\TRNDLL\SourceCode\Kernel\Userlib.f90 283
Internal procedures (following a CONTAINS) can see all entities declared in the "host scope" (before the CONTAINS), and can see other internal procedures, but cannot see entities declared within other internal procedures. Host association goes up the tree only. For example:
subroutine outer
integer :: X
...
contains
subroutine innerA
real :: A
end subroutine innerA
subroutine innerB
real :: B
end subroutine innerB
end subroutine outer
Subroutine outer can see explicit interfaces for innerA and innerB. innerA and innerB can see explicit interfaces for each other and variable X, but innerA cannot see innerB's variable B and innerB cannot see innerA's variable A.
I am skeptical that the behavior you describe was supported by other compilers. Given that you say it was written in the 70s, it could not have used modules, which started with Fortran 90. My guess is that your "updating one of the modules" introduced errors.
For the benefit of who will ever setup a VS2017 + oneAPI project to build the TRNSYS kernel, I post here the solution of the problem, which was not related to Fortran language incompatibilities between different versions. Instead, it was due to an undefined macro (TRNSYS_MULTI_DLL) and a sloppy usage of that macro in the above code.
As you can see from the comments in the source code above, the intention of the author was to provide an empty function when that macro is not defined. However, as the included function is placed after the end of the conditional compilation macro !dec$ endif, this results in the included function to exist even if the including function is empty. Therefore the compiler complains about symbols which really do not exist any more.
Better would be, in my opinion, to move the contained function within the conditional compilation macro, like below.
Subroutine LoadUserLibs(TypesInDeck,*)
... OMITTED COMMENTS ...
!dec$ if defined (TRNSYS_MULTI_DLL)
! This routine is only used in the multi-DLL configuration (otherwise empty routine)
... OMITTED CODE ...
Return
Contains
Subroutine LoadTypesFromDll()
... OMITTED CODE ...
Return
End Subroutine LoadTypesFromDll
!dec$ else
! Single-DLL configuration: empty routine
Return
!dec$ endif
End Subroutine LoadUserLibs
Here is the source (lets call it test4.F):
do 10 i=1
write(*,*) i
10 continue
end
With gfortran:
$gfortran test4.F
$./a.out
-259911288
with ifort:
$ifort test4.F
$./a.out
0
I know the syntax is incorrect. So both should throw compile-time errors.
Your test program is indeed not valid Fortran, but there isn't a syntax problem.
When the file has a .F suffix both gfortran and ifort assume that the program uses fixed form source. In fixed form source, blanks in statements aren't significant (outside character contexts). Your program is equivalent to:
do10i=1
write(*,*) i
10 continue
end
With comments:
do10i=1 ! Set the real variable do10i to value 1
write(*,*) i ! Write the undefined integer variable i
10 continue ! Do nothing
end ! End execution
Because of implicit typing you have a defaul real variable do10i and so there isn't a syntax error for a do control, and there isn't a do control that sets i to 1.
Instead your program is invalid because you are referencing the value of i although it hasn't first been defined (because it isn't a loop variable). But this isn't an error the compiler has to complain about at compile time (or even run time). A compiler is allowed to print any value it likes. gfortran chose one, ifort another.
Liberal use of implicit none and avoiding fixed-form source are good ways to avoid many programming errors. In this case, use of an end do instead of continue would also alert the compiler to the fact that you intended there to be some looping.
Which version of gfortran are you using? With gfortran-6, the following
PROGRAM MAIN
USE ISO_FORTRAN_ENV, ONLY:
1 COMPILER_VERSION,
2 COMPILER_OPTIONS
C EXPLICIT TYPING ONLY
IMPLICIT NONE
C VARIABLE DECLARATIONS
INTEGER I
DO 10 I = 1
WRITE (*,*) I
10 CONTINUE
PRINT '(/4A/)',
1 'THIS FILE WAS COMPILED USING ', COMPILER_VERSION(),
2 ' USING THE OPTIONS ', COMPILER_OPTIONS()
END PROGRAM MAIN
indeed throws the error
main.F:13:13:
DO 10 I = 1
1
Error: Symbol ‘do10i’ at (1) has no IMPLICIT type
I suspect that test4.F does not include the implicit none statement. Consequently, DO 10 I = 1 is interpreted as an implicitly defined real variable DO10I = 1. Here is a sample of a fixed form statement showing what are now (post Fortran 90) considered significant blanks followed by an equivalent statement without the blanks
DO I=1 , M AX ITER S
DO I = 1 , MAXITERS
Upshot, always use explicit variable declarations in all your programs. Better yet, only write Fortran in free source form main.f90. Free source form is more compatible with modern interactive input devices than fixed form. The maximum line length is 132 characters, compared to the older limit of 72 characters. This reduces the possibility of text exceeding the limit, which could lead the compiler to misinterpret names. Here's the same code in free source form
program main
use ISO_Fortran_env, only: &
stdout => OUTPUT_UNIT, &
compiler_version, &
compiler_options
! Explicit typing only
implicit none
! Variable declarations
integer :: i
do i = 1, 3
write (stdout, *) i
end do
print '(/4a/)', &
' This file was compiled using ', compiler_version(), &
' using the options ', compiler_options()
end program main
and
gfortran-6 -std=f2008ts -o main.exe main.f90
./main.exe
yields
1
2
3
This file was compiled using GCC version 6.1.1 20160802 using the options -mtune=generic -march=x86-64 -std=f2008ts
I have some legacy Fortran code which I was asked to analyze and translate to a modern language. I don't know which compiler was used in the past to compile the code, so for now, I'm trying to compile it with gfortran. The code contains a statement like this was causes gfortran to complain:
program test
implicit none
integer*4 :: var
var=.true.
if(var) then
write(*,*) "Hi"
endif
end program test
Compiling this with gfortran gives the following error:
test.f:6:9:
if(var) then
1
Error: IF clause at (1) requires a scalar LOGICAL expression
(In addition, it gives a warning about the conversion done in var=.true.).
I'm not sure which which compiler the code was compiled, but apparently the code should compile as it is. Is there a way to tell gfortran to accept this conversion?
According to the docs, no implicit conversion is done within if-statements though: https://gcc.gnu.org/onlinedocs/gfortran/Implicitly-convert-LOGICAL-and-INTEGER-values.html
This is not possible in GFortran. The manual states:
However, there is no implicit conversion of INTEGER values in
if-statements, nor of LOGICAL or INTEGER values in I/O operations.
You are only able to perform implicit conversions in assignments like your
integer :: var
var = .true.
but even there you must be very careful. It is not standard conforming and the value var will differ between compilers. Intel used to use -1 (all bits set to 1), unless -standard-semantics was chosen, for .true., but gfortran uses +1 as in the C language. New versions of Intel Fortran changes the default. The other direction is even trickier, there might be values which are neither .true. nor .false..
I have checked all the formats of the implicit type declaration but have not been able to find out the error in the following line . I have been running the code using f77 to compile this.
implicit real*4 (a-h,o-z)
while running the program it gives the following error for the above statement.
implicit real*4 (a-h,o-z)
1
Error: Unexpected character in variable list at (1)
A few basic rules if you are using F77 or earlier versions.
Put the implicit line first
Columns 1-5 are for labels
Column 6 is for continuation
Start the code in column 7
The code should not go past column 72. Some compilers have an option to extend the line length to 80 or 120 or 132 (widths of line printers when F77 first came out)
If you wish to use free format, use one of the later versions of fortran
I use the Intel Visual Fortran. The problem I'm dealing with has many PARAMETERS and I want to avoid repetitious declaration and initiation of them at the beginning of each routine.
Is there any way for initialization these PARAMETERS using MODULES?
Of course the answer is YES, but some of intrinsic function are not accepted in the initiation statement. Here is a simple sample code,
MODULE mod
IMPLICIT NONE
REAL, PARAMETER :: x = SQRT ( 4 )
END MODULE
PROGRAM prog
USE mod
IMPLICIT NONE
PRINT *, x
END PROGRAM
Once compiled, the compiler shows me this error :
Error #6362: The data types of the argument(s) are invalid.
[SQRT] Source1.f90
Albeit using ABS ( ) is not followed by this error, but SIN ( ) does.
The problem is that the sqrt (and sin) intrinsic requires a floating point argument. There just happens to be both floating point and integer implementations of abs.
Replace 4 with 4. and it should work.