Fortran internal write suddenly an error according to Intel compiler - io

A Fortran code I am working on has several lines similar to
WRITE(filename, '(A16,"_",I4,".dat")') filename, indx
This code has been successfully compiled and run literally hundreds of times, on many different platforms and pretty much all major compilers. But suddenly the newest (or, new, anyway) Intel compiler doesn't like it. It gives a warning message "forrtl: .... Internal file write-to-self; undefined results". After this line executes, "filename", which was a reasonable character array, becomes blank.
I suppose the problem is that filename is both an input into the write and the destination of the internal write. The fix is easy enough. It works to replace filename as the destination with something like filename_tmp. But as I have said, this has never been necessary until now.
So I am wondering, does filename as both an input and destination violate the Fortran standard, but all these compilers have been turning a blind eye to it for all these years, and now Intel is getting strict? Or is Intel being "snobbish"? Or outright buggy?

Execution1 of the write statement of the question has always been explicitly prohibited.
We currently see (F2018 12.6.4.5.1 p7):
During the execution of an output statement that specifies an internal file, no part of that internal file shall be referenced, defined, or become undefined as the result of evaluating any output list item.
filename is an internal file, and the evaluation of the output list item filename is a reference to that internal file.
This is not a programming violation that the compiler is required to detect, so you can view this as a case of improved diagnostic capability/pickiness of the compiler as you desire. No Fortran program is harmed by the change in this behaviour of the compiler.
Fortran 66 didn't have internal files (or character types), of course, and Fortrans 77, 90 and 95 used different words for the same effect (see for example, F90 9.4.4):
If an internal file has been specified, an input/output list item must not be in the file or associated with the file.
In case it looks like this is more restrictive, from Fortran 2003 the restrictions for input and output statements are stated separately (only output was quoted above, p8 for input).
1 Note the use of execution: there's nothing wrong with the statement itself as a statement. It is allowed to exist in source code that isn't reached. Checking this statement when compiling is not a simple matter.

Related

Variable length strings in fortran

So I'm just getting started learning Fortran because apparently it's still used for a lot of scientific computing. One of the things that I already hate about it is that compared to C++, strings are a nightmare. At the moment, I'm just trying to find a simple way to read in a string provided by the user and then spit it back out without all the trailing whitespace.
Here's the code I have right now, which according to what I've read should work under later Fortran standards, i.e. 2003/2008 (though I could easily have made errors of which I'm unaware). I'm trying to compile it on the MinGW version of gfortran that came with Code::Blocks 13.12.
program tstring
implicit none
character(100) io_name
character(len=:), allocatable :: final_name
print *, "What is your name, O master?"
read *, io_name
final_name = trim(io_name)
print *, "Excellent, master ", final_name, "!"
end program
It compiles just fine, but still has a massive amount of whitespace between final_name and the "!". The whitespace is somewhat dependent on the number of characters I give to io_name, but not in a particularly logical manner (15 characters gives more whitespace than 30, for example). Particularly bewildering to me is that if I give certain numbers of characters to io_name (between about 17 and 22) then instead of printing out the name, the program runs into a segfault.
Perhaps the most difficult part of this for me is that good Fortran documentation is very hard to find, especially for the 2003 and later standards. So if anybody could point me to some good documentation, I'd really appreciate it!
Get a more recent compiler. Gfortran 4.8 (AFAIK the oldest supported version) should work just fine with your code.
Strings are not really any nightmare, just stop thinking in C++ and trying to translate that in Fortran. It is quite possible to write tokenizers, parsers and DSL interpreters in Fortran.
Regarding the resources, it is off-topic here and there are numerous books and tutorials out there. Search for Fortran Resources at http://fortranwiki.org/fortran/show/HomePage

How to retrieve the type of architecture (linux versus Windows) within my fortran code

How can I retrieve the type of architecture (linux versus Windows) in my fortran code? Is there some sort of intrinsic function or subroutine that gives this information? Then I would like to use a switch like this every time I have a system call:
if (trim(adjustl(Arch))=='Linux') then
resul = system('ls > output.txt')
elseif (trim(adjustl(Arch))=='Windows')
resul = system('dir > output.txt')
else
write(*,*) 'architecture not supported'
stop
endif
thanks
A.
The Fortran 2003 standard introduced the GET_ENVIRONMENT_VARIABLE intrinsic subroutine. A simple form of call would be
call GET_ENVIRONMENT_VARIABLE (NAME, VALUE)
which will return the value of the variable called NAME in VALUE. The routine has other optional arguments, your favourite reference documentation will explain all. This rather assumes that you can find an environment variable to tell you what the executing platform is.
If your compiler doesn't yet implement this standard approach it is extremely likely to have a non-standard approach; a routine called getenv used to be available on more than one of the Fortran compilers I've used in the recent past.
The 2008 standard introduced a standard function COMPILER_OPTIONS which will return a string containing the compilation options used for the program, if, that is, the compiler supports this sort of thing. This seems to be less widely implemented yet than GET_ENVIRONMENT_VARIABLE, as ever consult your compiler documentation set for details and availability. If it is available it may also be useful to you.
You may also be interested in the 2008-introduced subroutine EXECUTE_COMMAND_LINE which is the standard replacement for the widely-implemented but non-standard system routine that you use in your snippet. This is already available in a number of current Fortran compilers.
There is no intrinsic function in Fortran for this. A common workaround is to use conditional compilation (through makefile or compiler supported macros) such as here. If you really insist on this kind of solution, you might consider making an external function, e.g., in C. However, since your code is built for a fixed platform (Windows/Linux, not both), the first solution is preferable.

Fortran `write (*, '(3G24.16)')` error

I have a Fortran file that must write these complicated numbers, basically I can't change these numbers:
File name: complicatedNumbers.f
implicit none
write (*,'(3G24.16)') 0.4940656458412465-323, 8.651144521298990, 495.6336980600139
end
It's then run with gfortran -o outa complicatedNumbers.f on my Ubuntu, but this error comes up:
Error: Expected expression in WRITE statement at (1)
I'm sure it has something to do with the complicated numbers because there are no errors if I change the three complicated numbers into simple numbers such as 11.11, 22.2, 33.3.
This is actually a stripped-down version of a complex Fortran file that contains many variables and links to other files. So ideally, the 3G24.16 should not be changed.
What does the 3G24.16 mean?
How can I fix it so that I can ultimately print out these numbers with ./outa?
There is nothing syntactically wrong in the snippet you've shown us. However, your use of a file name with the suffix .f makes me think that the compiler is assuming that your code is written in fixed form. That is the usual default behaviour of gfortran. If that is the case it probably truncates that line at about the last , which means that the compiler sees
write (*,'(3G24.16)') 0.4940656458412465-323, 8.651144521298990,
and raises the complaint you have shared with us. Either join us in the 21st Century and switch to free form source files, change .f to .f90 and see what fun ensues, or continue the line correctly with some character in column 6 of the next line.
As to what 3G24.16 means, refer to your favourite Fortran reference material under the heading of data edit descriptors, in particular the g data edit descriptor.
Oh, and if my bandying about of the terms fixed form source and free form source bamboozles you, read about them in your favourite Fortran reference material too.
Three errors in your program :
as you clearly use the Fortran fixed format, instructions are limited to 72 characters (132 in free format)
the number 0.4940656458412465-323 is probably not correctly written. The exponent character is missing. Try 0.4940656458412465D-323 instead. Here Fortran computes the substraction => 0.4940656458412465-323 is replaced by -322.505934354159. Notice that I propose the exponent D (double precision). Writing 0.4940656458412465E-323 is inaccurate because, for a single precision number, the minimum value for the exponent is -127.
other numbers should have an exponent D0 too because, in single precision, the number of significant digits do not exceed 6.
Possible correction, always in fixed format :
implicit none
write (*,'(3G24.16)') 0.4940656458412465D-323,
& 8.651144521298990d0,
& 495.6336980600139d0
end

Avoid newline in list-directed output with Intel Fortran compiler

I have noticed the results of list-directed output write(*,*) in Fortran is compiler dependent.
Indeed, with the code:
program one
real(8), dimension(5):: r1
do i=1,5
r1(i)=sqrt(i*10.0)
end do
write(*,*) (r1(i), i =1,5)
end program one
intel compiler ifort gives standard output broken by a newline:
3.16227769851685 4.47213602066040 5.47722530364990
6.32455539703369 7.07106781005859
while gfortran gives the equivalent one line result:
3.1622776601683795 4.4721359549995796 5.4772255750516612 6.3245553203367590 7.0710678118654755
I think that ifort is writing maximum 3 items per line (when floating real numbers).
Is there any way to make the ifort output be like gfrotran, i.e. avoid the newline?
Ideally, I would like to keep list-directed output (*,*) instructions, so I am looking for something like a compiler option or so, if any.
Since verson 14, intel fortran compiler has the wrap-margin function. By default, the record is wrapped after 80 characters. For disabling this restriction, you should specify:
on Linux: -no-wrap-margin
on WIndows: /wrap-margin-
See more on Intel Fortran's reference guide
No. List-directed (free-format) output provides convenience, but you give up control. Various aspects of the output are unspecified and allowed to be chosen to the compiler. If you want full control, you have to use formatted output.
Look into edit descriptors in your favorite Fortran book or online documentation. You can use fmt specifier in the write statement to specify edit descriptors. For example:
write(*,fmt='(5(F6.4,3X))') (r1(i), i =1,5)
should output something similar to:
3.1623 4.4721 5.4772 6.3246 7.0711
See https://software.intel.com/en-us/forums/topic/401555
Specify FORT_FMT_RECL or use
write (,"(G0,1X))"

for a function in binary without source code, is there any way to get the number of parameters

I don't have the source code but have the binary. With command "nm binary_name" I could know the functions inside the binary.
Can I know how many parameters a function has? Under solaris, is there anyway to do that?
e.g, if the function is: func1(a int,b int,c int), then there are 3 parameters.
Thanks
Daniel
No. Neil Butterworth's suggestion to examine the function signature is a good one for C++ (since the parameters are often encoded into the function so the linker can tell the difference between "int x(int)" and "int x(float)" for example) but, for C, you're going to have to get your hands dirty and disassemble the function, taking particular note of how the stack frames are built and used in your environment.
Keep in mind that SPARC has a rotating window stack rather than regular grow-down stack. You're really going to delve deep into the way the CPU works. If you're talking Solaris for Intel, the rotating stack is not there, of course.
Assuming this is C code, then no there is not - the
compiler/linker elides that information. If it is C++ code, it is just possible that the mangled name of the function is retained and includes the parameters in encoded form.
At the lowest level, if you emulate the function running on the machine, then it will read some information either from registers or the stack which it has not written. If you compare these reads to the ABI of the platform ( You don't say whether it's Sparc Solaris or Intel Solaris ) then some of them should correspond to the registers/stack locations of the parameters of the function. Of course, there's no guarantee that a function will read all its parameters.
For Solaris, elfdump might give more information than nm ( a quick google for elfdump signature indicates support was requested and added, but you'd need to check what version you've got )
IDA Pro (http://www.hex-rays.com/idapro/) is a disassembler which is pretty clever at infering parameters of a function from object code;
maybe there is also symbolic information you can use; eg. on Win32 the symbol _function#8 reveals that 8 bytes (2 parameters) are passed
one can also demangle C++ names to get the parameters and types

Resources