Changing stdout in gfortran - fortran

By setting export GFORTRAN_STDOUT_UNIT=777 I want to change my stdout in gfortran. If I run the program
program main
implicit none
write (*,*) "*"
write (6,*) "6"
write (777,*) "777"
end program main
it will output
> $ ./a.out
777
and create a file:
> $ cat fort.6
*
6
Why isn't * forwarded to the stdout (now 777) anymore? Is this a gfortran bug or intended behaviour?

I believe the behaviour is as expected. The following paragraphs are of interest here:
GFORTRAN_STDOUT_UNIT: Unit number for standard output
This environment variable can be used to select the unit number preconnected to standard output. This must be a positive integer. The default value is 6.
source: GCC Gfortran Documentation
So this just states that /dev/stdout will be connected to the unit number GFORTRAN_STDOUT_UNIT.
The Fortran Standard makes the following statements:
9.5 File connection
9.5.1 Referring to a file
4 In a WRITE statement, an io-unit that is an asterisk identifies an external unit that is preconnected for sequential formatted output. This unit is also
identified by the value of the named constant OUTPUT_UNIT of the intrinsic module ISO_FORTRAN_ENV.
Note 9.15: Even though OUTPUT_UNIT is connected to a separate file on each image, it is expected that the processor could merge the sequences of records from these files into a single sequence of records that is sent to the
physical device associated with this unit, such as the user’s terminal.
source: Fortran 2008 Standard
All we know is that <asterisk> (ergo OUTPUT_UNIT) are preconnected to a unit for sequential formatted output. The standard makes no statement what this external unit is. It makes no reference to /dev/stdout. The standard actually explicitly mentions in a note that the user's terminal is a possible pre-connected unit, it could as well have been your printer.
So in the end, by setting GFORTRAN_STDOUT_UNIT=777, you just preconnect unit 777 to /dev/stdout and <asterisk> will be preconnected to an external unit for sequential output (i.e. in this case fort.6)

Related

How did the fortran standard of unit numbers came to be?

In fortran stderr is unit 0. Stdin is unit 5 and stdout is unit 6. This appears to be a cray decision as far as Google seems to indicate, but it is not clear why they chose so. Why not 1 and 2? What was the use of 1-4 on old fortran compilers that shifted stdin and out to 5 and 6?
According to this page (the "Professional Programmer's Guide to Fortran77" by Clive G. Page), units 5 and 6 are assigned to stdin and stdout, respectively, for backwards compatibility and that card-readers were typically connected to "unit 5" and line printers to "unit 6", quote:
In order to retain compatibility with Fortran66, many systems provide other pre-connected files. It used to be customary to have unit 5 connected to the card-reader, and unit 6 to the line printer. Other units were usually connected to disc files with appropriate names: thus unit 39 might be connected to a file called FTN039.DAT or even TAPE39.
Not that this gives any logic to why numbers 5 and 6 were chosen, but only some historical context. Still leaves open what was connected to unit numbers 1-4 on historic machines. The following old books/handbooks might shed some light:
According to D.D. Fisher et al. An Introduction to Fortran Programming, page 90, not all FORTRAN compilers used units 5 and 6 for card-reader input and line printer output:
Waterloo FORTRAN IV and IBM System/360 FORTRAN IV did use units 5 and 6 for that purpose, on the IBM 1130, however, units 2 and 1 were used for card-reader input and line printer output.
And finally according to the FORTRAN-10/20 and VAX FORTRAN Compatibility Manual, page 3-6, in case of FORTRAN-10/20 "unit 1 is disk, unit 2 is the card reader, unit 3 is line printer, unit 5 is the terminal". With VAX FORTRAN, unit 5 is good for both I and O with the terminal.
Maybe this final part indicates that because some machines started to have terminals for I/O in addition to card-reader input and line printer output, and the preferred/default devices might have become terminals for both input and output, that the higher terminal-related units have become I/O defaults.

Fortran: pipe to program

Is there any possibility to launch an external program from Fortran and write something to this programs standard input?
I know e.g. of gfortran's SYSTEM but there is no such option.
As you have noticed, GFortran does not have anything like the pipe()/fork()/exec() functions builtin.
If you're on Linux or some other Unix-like system you could do something like
execute_command_line("mkfifo /path/to/fifo")
The mkfifo command creates a named pipe, that is, a pipe that also has a name in the filesystem.
open(newunit=plot_unit, file="/path/to/fifo", access="stream", format="formatted")
execute_command_line("gnuplot < /path/to/fifo")
So the idea is that you can then open the FIFO like a normal external unit in GFortran, then execute gnuplot with standard input connected to the FIFO.
You might need to exchange the order of #2 and #3 in case this deadlocks. But some minor variation of the above should work (I've used it to connect to one Fortran program from another).
Firstly, if you're using a relatively recent compiler you should be able to use execute_command_line (part of the f2008 spec) instead of system (compiler extension). This launches a command using the C library's system call which uses the sh shell on nix and cmd.exe on Windows (see here). As such you can use standard input redirection type approaches to connect to stdin of the launched program, but it may not be suitable for more complicated use.
The following example shows a simple example
program stdIn
implicit none
character(len=20) :: cmd, args
character(len=50) :: fullcmd
cmd = "bc"
args = "1+2"
fullcmd = cmd//" <<< "//args
print*,"Running ",fullcmd
call execute_command_line(fullcmd)
end program stdIn
Which should output
Running bc <<< 1+2
3

How to get CMocka report in JUnit format?

I am able to use cmocka and getting default results on the screen. I want to get the results for the unit test in JUnit format.
CMocka supports JUnit format by using the env variable CMOCKA_MESSAGE_OUTPUT or using API cmocka_set_message_output(CM_OUTPUT_XML);
But still no xml file gets generated. Can anyone help out in obtaining results in JUnit format?
The most credible source is actually the cmocka.c source file that contains entire implementation of the framework. This file is not too large, so I will cite something from the source file version 1.0.1.
There are two conditions to generate XML output by cmocka and the third condition is needed to store output in file.
1. XML output can be generated only if tests are called by cmocka_run_group_tests()
The customizable output format can be obtained only from the test runner cmocka_run_group_tests() or from its full variation cmocka_run_group_tests_name().
There is no other route that can lead to XML output. If a singe test is started by run_test() the output cannot be XML.
The summary format
[ PASSED ] 0 test(s).
[ FAILED ] 1 test(s), listed below:
can be generated in one of the following possible cases:
the test is started by one of the deprecated test runners: run_tests(), _run_tests() or run_group_tests(), _run_group_tests(); in that case it is even possible to see compilation warning about usage of a deprecated function;
the test is started by cmocka_run_group_tests() and the output format is CM_OUTPUT_STDOUT.
2. cmocka message output should be set to CM_OUTPUT_XML
The default output format can be set by calling cmocka_set_message_output(CM_OUTPUT_XML) before running tests. However, even if such default is set in the test source it can be overwritten by the environment variable CMOCKA_MESSAGE_OUTPUT. That variable has higher priority than the default set by cmocka_set_message_output().
The value of CMOCKA_MESSAGE_OUTPUT is case insensitive. The variable is taken into account if it is equal to one of the following values: stdout, subunit, tab or xml.
So, if the environment variable has value stdout the function mocka_set_message_output() has no effect.
That variable can be used to force different output formats of already compiled binary:
CMOCKA_MESSAGE_OUTPUT=stdout ./nulltest
CMOCKA_MESSAGE_OUTPUT=subunit ./nulltest
CMOCKA_MESSAGE_OUTPUT=tap ./nulltest
CMOCKA_MESSAGE_OUTPUT=xml ./nulltest
Thus, if the test is started by cmocka_run_group_tests() but the output is not affected by mocka_set_message_output() it means that there is set variable CMOCKA_MESSAGE_OUTPUT=stdout in the shell.
3. It should be possible to create a new file by cmocka to write its XML output directly to that file
If both previous conditions are satisfied, it is possible to ask cmocka to write its XML output directly to a file. If the environment variable CMOCKA_XML_FILE is set, then cmocka will try to write XML to file with name of that variable value.
Usage example:
CMOCKA_XML_FILE='./out.xml' CMOCKA_MESSAGE_OUTPUT=xml ./nulltest
The file is written if:
file with such name does not exist;
such file can be created.
Thus if there are more than one test runners in one compiled binary test application, only the first runner can write its output to that file.
The output is written to the shell even if CMOCKA_XML_FILE is set, but the file already exists or it cannot be created.
Of course, it is possible just to redirect shell output to a file overwriting existent file or appending to existent file if such file exists.
The example bellow can be used to check different options for output. It can be built by the command
gcc -g nulltest.c -o nulltest -Ipath_to_cmocka_headers -Lpath_to_cmocka_library_binary -lcmocka
nulltest.c
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
/* A test case that fails. */
static void null_test_failed(void **state) {
(void) state; /* unused */
assert_int_equal(0, 1);
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(null_test_failed),
};
const struct UnitTest tests_deprecated[] = {
unit_test(null_test_failed),
};
cmocka_set_message_output(CM_OUTPUT_XML);
/* group test functions that use customizable output format */
cmocka_run_group_tests(tests, NULL, NULL);
cmocka_run_group_tests_name("custom group name", tests, NULL, NULL);
/* run single test with standard output */
run_test(null_test_failed);
/* DEPRECATED TEST RUNNER functions that can give only standard output */
run_tests(tests_deprecated);
_run_tests(tests_deprecated, 1);
run_group_tests(tests_deprecated);
_run_group_tests(tests_deprecated, 1);
return 0;
}
The XML is printed to stdout, you need to redirect it to a file ...

Differences when writing to / reading from the console between gfortran- and g77-compiled code

This one's going to take a bit of explaining. Please bear with me.
What I Have
I have in my possession some Fortran source code and some binaries that have been compiled from that code. I did not do the compilation, but there is a build script that suggests G77 was used to do it.
As well as the Fortran stuff, there is also some Java code that provides users with a GUI "wrapper" around the binaries. It passes information between itself and the binaries via their input/output/error pipes. The Java code is very messy, and this way of doing things adds a lot of boilerplate and redundancy, but it does the job and I know it works.
What I Need
Unfortunately, I'd like to make some changes:
I want to create a new Python wrapper for the binaries (or, more precisely, extend an existing Python program to become the new wrapper).
I want to be able to compile the Fortran code as part of this existing program's build process. I would like to use gfortran for this, since MinGW is used elsewhere in the build and so it will be readily available.
The Problem
When I compile the Fortran code myself using gfortran, I cannot get the resulting binaries to "talk" to either the current Java wrapper or my new Python wrapper.
Here are the various ways of printing to the console that I have tried in the Fortran code:
subroutine printA(message)
write(6,*) message
end
subroutine printB(message)
write(*,*) message
end
subroutine printC(message)
use iso_fortran_env
write(output_unit,*) message
end
There are also read commands as well, but the code doesn't even get a change to execute that part so I'm not worrying about it yet.
Extra Info
I have to call gfortran with the -ffixed-line-length-132 flag so that the code compiles, but apart from that I don't use anything else. I have tried using the -ff2c flag in the vague hope that it will make a difference. It doesn't.
This stackoverflow post is informative, but doesn't offer me anything that works.
The relavant manual page suggests that printA should work just fine.
I'm working on Windows, but will need this to be multi-platform.
Juse in case you're intested, the Java code uses Runtime.getRuntime().exec("prog.exe") to call the binaries and then the various "stream" methods of the resulting Process object to communicate with them. The Python code uses equivalents of this provided by the Popen object of the subprocess module.
I should also say that I am aware there are alternatives. Rewriting the code in Python (or something else like C++), or making amendments so that is it can be called via F2Py have been ruled out as options. Using g77 is also a no-go; we have enough dependencies as it is. I'd like to be able to write to / read from the console properly with gfortran, or know that it's just not possible.
Hard to say without seeing more details from your Fortran and Python codes. The following pair of code works for me (at least under Linux):
Fortran program repeating its input line by line prefixed with line number:
program test_communication
use iso_fortran_env, stdout => output_unit, stdin => input_unit
implicit none
character(100) :: buffer
integer :: ii
ii = 1
do while (.true.)
read(stdin, *) buffer
write(stdout, "(I0,A,A)") ii, "|", trim(buffer)
flush(stdout)
ii = ii + 1
end do
end program test_communication
Python program invoking the Fortran binary. You can feed it with arbitrary strings from the console.
import subprocess as sub
print "Starting child"
proc = sub.Popen("./a.out", stdin=sub.PIPE, stdout=sub.PIPE)
while True:
send = raw_input("Enter a string: ")
if not send:
print "Exiting loop"
break
proc.stdin.write(send)
proc.stdin.write("\n")
proc.stdin.flush()
print "Sent:", send
recv = proc.stdout.readline()
print "Received:", recv.rstrip()
print "Killing child"
proc.kill()

How to pass parameters from input file to fortran 77 mpirun during run time?

I am an MPI and Fortran 77 noob. I have a fortran 77 code FKRPRO.f which I wanted to parallelize using OpenMPI. The code requires a lot of parameters which are fed into it during run time from a separate file. Compilation and running is something like this
gfortran -o FKRPRO FKRPRO.f
./FKRPRO < Modelfile.txt
the equivalent lines in the code (not my code) are
PARAMETER(LIN=5)
INTEGER ERROR
LOGICAL PRNTA
PRNTA=.FALSE.
READ(LIN,'(L3)') PRNTA
READ(LIN,21) M1,M2
21 FORMAT(11I5)
and so on. Can someone please explain to me what READ(LIN,'(L3)') PRNTA means. The input in the input file Modelfile.txt is something like this
.F.
0 64
and so on..
I put the necessary MPI statements in the code.
INCLUDE 'MPIF.H'
...
CALL MPI_INIT(ERROR)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD,NPROCS,ERROR)
CALL MPI_COMM_RANK(MPI_COMM_WORLD,PRANK,ERROR)
...
CALL MPI_TYPE_FREE(NEWMATRIX,ERROR)
CALL MPI_FINALIZE(ERROR)
All processes are not being able to read the input file. I have compiled and run the code like this
mpif77 -o bc3 FKRPROG5.f
mpirun -np 4 bc3 < Modelfile.txt
This is not working. I get the following errors. Only the first process or rank 0 can read the file.
At line 50 of file FKRPROG5.f (unit = 5, file = 'stdin')
Fortran runtime error: End of file
At line 50 of file FKRPROG5.f (unit = 5, file = 'stdin')
Fortran runtime error: End of file
At line 50 of file FKRPROG5.f (unit = 5, file = 'stdin')
Fortran runtime error: End of file
mpirun has exited due to process rank 3 with PID 866 on
node Avinash-rMBP.local exiting improperly. There are two reasons this could occur:
1. this process did not call "init" before exiting, but others in
the job did. This can cause a job to hang indefinitely while it waits
for all processes to call "init". By rule, if one process calls "init",
then ALL processes must call "init" prior to termination.
2. this process called "init", but exited without calling "finalize".
By rule, all processes that call "init" MUST call "finalize" prior to
exiting or it will be considered an "abnormal termination"
This may have caused other processes in the application to be
terminated by signals sent by mpirun (as reported here).
50th line is READ(LIN,'(L3)') PRNTA.Someone kindly point out where I am going wrong :(
So, how can I make all processes read from this input file < Modelfile.txt ?? Thanks.
The statement
READ(LIN,'(L3)') PRNTA
causes the program to read, from the unit attached to the channel with id LIN, a 3-character sequence which represents a logical value and assigns the value read to the variable PRNTA. From the fragments you've shown us the program will read .F. and set PRNTA to .false..
LIN is set to the constant value 5, which usually means stdin. This use of 5 to denote stdin is not a de jure standard, it is more of a de facto standard.
The straightforward way to read a parameter file into an MPI program is to ensure that only one process reads the file and then sends out the values to the other processes which need them.
You seem to have written a program in which all processes try to read the same input file but, at run-time, the redirection you've used to pass Modelfile.txt is only working for one process (presumably the process with rank 0). The other processes are not getting an input file at all and are complaining, then bringing the program crashing down. The error message you show is typical of a Fortran program which doesn't find an input file at all when it tries to read.
Far better to write code along the lines:
call mpi_init ...
...
if (myrank==0) then
open(...) inputfile
read(...) parameters
close(...)
end if
...
call mpi_bcast(parameters from 0 to all)
...
In general, don't expect the run-time environment for MPI processes to be identical copies of the run-time environment for a sequential program. I think that you are seeing evidence that your run-time directs the input only to the first process created when your program runs. Since mpirun is not standardised (though mpiexec is) I don't think you can rely on this run-time behaviour being the same for all MPI implementations. For portability and compatibility you're better off handling I/O explicitly within your program than using o/s features such as redirection.
You could, rather than have process 0 read the parameters and distribute them to other processes, write your code such that each process reads the same file. If you do write your code this way take care to ensure that the processes aren't fighting over access to the I/O channels; having multiple processes trying to (nearly-)simultaneously read across a single input channel is a sure way to slow things down.