 |
The Question is:
I have routines code written in C and FORTRAN that use printf() and PRINT
statements to issue messages to the user. I need to redirect these to a file.
At program startup I introduced the statement:
stdout = freopen("msgfile.dat", "w", stdout);
This worked fine for the C-language routines, but the FORTRAN PRINT statements
continued to send data to the user's terminal.
As a second attempt to solve the problem, I got rid of the freopen statement,
and issued a DCL statement before the run command, as follows:
$ define/user SYS$OUTPUT msgfile.dat
$ run app.exe
This caused all the subsequent printf() statements to send their data to
msgfile.dat;1, and all FORTRAN PRINT statements sent data to a different file,
msgfile.dat;2.
What's going on?
The abstracted source code for the first attempted solution follows:
File 1 [print.c]:
#include <stdio.h>
void printfor();
void printc();
main()
{
FILE *fp=NULL;
stdout = freopen("msgfile.dat", "w", stdout);
if (stdout == NULL)
{
printf("cannot reopen stdout\n");
exit();
}
printc();
printfor();
}
FILE 2 [printc.c]:
#include <stdio.h>
void printc(void)
{
printf(" hello from c function\n");
}
FILE 3 [printfor.for]:
C PRINTFOR.FOR
SUBROUTINE PRINTFOR()
print 25
25 format(' hello from FORTRAN subroutine')
RETURN
END
I am using DEC C V6.0-001 and Digital Fortran 90 V7.1-330.
Many thanks
The Answer is :
I/O is performed via independent language-specific RTLs -- one for
FORTRAN, one for C. In this case, each RTL is opening its own channel
and is unaware of the other, and this results in two files.
Redirecting the output from a FORTRAN PRINT command can be done by
defining the logical name FOR$PRINT. For example:
$ DEFINE/USER FOR$PRINT PRINT_OUTPUT.TXT
$ RUN program
This clearly does not address the issue of "merging" the output from both
C and FORTRAN. To do this, you should remove the "freopen" call from your
code. This will cause C to send printf output to SYS$OUTPUT.
The next step is to make sure that SYS$OUTPUT is a process permanent file
(PPF). The effect is to capture both channels from the RTLs and merge them
together. There are a number of ways to do this. One is with a command
procedure. For example, create a command procedure called "PROG.COM"
containing the line:
$ RUN program
Now the command:
$ @PROG/OUTPUT=MSGFILE.DAT
MSGFILE.DAT will contain the output from both FORTRAN and C. If there is
any interactive input to the program, change the procedure to:
$ DEFINE/USER SYS$INPUT SYS$COMMAND
$ RUN program
This connects the input stream to the terminal (SYS$COMMAND), rather than
the command procedure itself.
Alternatively, you could use RTL calls such as lib$put_output or a common
set of application-specific I/O routines, which can (will) merge all of
the I/O together as desired.
If you don't want to create a command procedure, you can redirect the
output of any command, or sequence of commands typed at the terminal with:
$ @TT/OUTPUT=file
or
$ @SYS$COMMAND/OUTPUT=file
The prompt will change, adding "_" at the beginning. Type your commands and
finish with ^Z or EXIT. All output will be sent to the file. For example:
$ @TT/OUTPUT=MSGFILE.DAT
_$ RUN PRINTF
_$ EXIT
$
Another possibility, for OpenVMS V7.1 and later systems is the DCL PIPE
command. Simply pipe the output of your program into a command or program
that creates a file -- for example, COPY or CREATE.
$ PIPE RUN program | CREATE MSGFILE.DAT
$ PIPE RUN program | COPY SYS$PIPE MSGFILE.DAT
Note that ALL the above assume that you have not used freopen on stdout.
 |
|
|
 |
|