How to know that we reached EOF in Fortran 77? - io

So let's assume that I have the following subroutine:
subroutine foo(a_date)
character*10 dummy, a_date
open(unit=1,file='ifile.txt',status='old')
read(1, 100) dummy
100 format(A10)
a_date = dummy
return
end
which only reads a line from the file. But I want to read all the lines recursively. So when I call the subroutine recursively in my main procedure, I get an error after reaching EOF. So is there a way to prevent it so that the program knows when I reach EOF?
Basically, I want to be able to know when I reach EOF.

Here are two methods. I refuse to teach the obsolete Fortran 77 which shouldn't have been used or taught in 25 years+, but the first method should work in any version of Fortran from 77 onwards
Method 1:
ijb#ianbushdesktop ~/stackoverflow $ cat data.dat
1
2
3
ijb#ianbushdesktop ~/stackoverflow $ cat end.f90
Program eof
Implicit None
Integer :: data
Open( 10, file = 'data.dat' )
Do
Read( 10, *, End = 1 ) data
Write( *, * ) data
End Do
1 Write( *, * ) 'Hit EOF'
End Program eof
ijb#ianbushdesktop ~/stackoverflow $ gfortran -std=f2003 -Wall -Wextra -O -fcheck=all end.f90
ijb#ianbushdesktop ~/stackoverflow $ ./a.out
1
2
3
Hit EOF
Method 2:
This needs F2003, but that's what you should be using these days
ijb#ianbushdesktop ~/stackoverflow $ cat data.dat
1
2
3
ijb#ianbushdesktop ~/stackoverflow $ cat end2.f90
Program eof
Use, intrinsic :: iso_fortran_env, Only : iostat_end
Implicit None
Integer :: data, error
Open( 10, file = 'data.dat' )
Do
Read( 10, *, iostat = error ) data
Select Case( error )
Case( 0 )
Write( *, * ) data
Case( iostat_end )
Exit
Case Default
Write( *, * ) 'Error in reading file'
Stop
End Select
End Do
Write( *, * ) 'Hit EOF'
End Program eof
ijb#ianbushdesktop ~/stackoverflow $ gfortran -std=f2003 -Wall -Wextra -O -fcheck=all end2.f90
ijb#ianbushdesktop ~/stackoverflow $ ./a.out
1
2
3
Hit EOF

In Fortran 77 you use the END=label specifier, it instructs the program to go the given label when the end of file condition is triggered. Basically it works like a GO TO statement triggered by the READ statement.
In Fortran 90 and later you can also use the IOSTAT=integer_var specifier. If an error condition happened, integer_var will be positive, if an end-of-record (EOR) or end-of-file (EOF) condition happened, the value will be negative.
In Fortran 2003, one can find out the actual values for the EOR and EOF conditions in named constant as shown in the answer by Ian Bush.

Related

How to print something to the right-most of the console in Linux shell script

Say I want to search for "ERROR" within a bunch of log files.
I want to print one line for every file that contains "ERROR".
In each line, I want to print the log file path on the left-most edge while the number of "ERROR" on the right-most edge.
I tried using:
printf "%-50s %d" $filePath $errorNumber
...but it's not perfect, since the black console can vary greatly, and the file path sometimes can be quite long.
Just for the pleasure of the eyes, but I am simply incapable of doing so.
Can anyone help me to solve this problem?
Using bash and printf:
printf "%-$(( COLUMNS - ${#errorNumber} ))s%s" \
"$filePath" "$errorNumber"
How it works:
$COLUMNS is the shell's terminal width.
printf does left alignment by putting a - after the %. So printf "%-25s%s\n" foo bar prints "foo", then 22 spaces, then "bar".
bash uses the # as a parameter length variable prefix, so if x=foo, then ${#x} is 3.
Fancy version, suppose the two variables are longer than will fit in one column; if so print them on as many lines as are needed:
printf "%-$(( COLUMNS * ( 1 + ( ${#filePath} + ${#errorNumber} ) / COLUMNS ) \
- ${#errorNumber} ))s%s" "$filePath" "$errorNumber"
Generalized to a function. Syntax is printfLR foo bar, or printfLR < file:
printfLR() { if [ "$1" ] ; then echo "$#" ; else cat ; fi |
while read l r ; do
printf "%-$(( ( 1 + ( ${#l} + ${#r} ) / COLUMNS ) \
* COLUMNS - ${#r} ))s%s" "$l" "$r"
done ; }
Test with:
# command line args
printfLR foo bar
# stdin
fortune | tr -s ' \t' '\n\n' | paste - - | printfLR

How to pipe multiple inputs into a python script via the shell?

I'm looking to input a few strings into a python script so I can do test on my computer not http://www.ideone.com. But the ways I'm doing it all combine the strings instead of making them into lines or separate lines.
My code for python is 0001.py
testCases = int(input())
Counter = 0
while Counter < testCases:
Line = str(input())
countTwo = 1
for i in range(int(len(Line)/2)):
if countTwo % 2 == 0:
print(Line[i], end='')
countTwo += 1
print('\n', end='')
Counter += 1
I'm trying to do something like echo '5' 'hello' 'hello' 'hello' 'hello' | python3 001.py
Try
echo -e "line1\nline2\nline3"
This works because programs take input line by line. This echo statement separates the inputs over lines so it functions like you want.
Editing now that you've provided your OS.
For Linux, this works (credit to #pteronewone who also answered):
$ echo -e "5\nhello\nhello\nhello\nhello\nhello" | python3 001.py
e
e
e
e
e
For Windows (leaving here for future reference), this is ugly and inefficient but works (Windows 7 cmd.exe shell):
C:\> (echo 5 & echo hello & echo hello & echo hello & echo hello & echo hello) | 001.py
e
e
e
e
e
(Not sure exactly what you're trying to accomplish, but that's what your script outputs.)
A few other suggestions:
Wrap the input() in a try/except. In your example you only included four "hello" but told it to expect five, so it tries to read a fifth input which results in an exception.
try:
Line = str(input())
except:
break
Use the integer division operator // so you don't need to cast from float back to int in your range().
for i in range(len(Line) // 2):

where is the text printed by C printf

I happened encounter a trouble with calling C printf function from SBCL via cffi. The problem is when I call printf function, I can't find the output text, just the return value of printf function show on the REPL. But when I quit SBCL, the output text appears on the terminal magically.
$ sbcl
* (ql:quickload :cffi)
* (cffi:foreign-funcall "printf" :string "hello" :int)
;;=> 5
* (quit)
hello$
The last line, "hello$" means when quit from SBCL, the text "hello" appears on terminal and followed with the shell prompt "$". So where does printf print the text "hello" to?
I tried `finish-output', `force-output' on *standard-output* but that does not work.
The problem is that C's stdio library has its own buffering that has nothing to do with Lisp's. Flushing the output requires you to have a pointer to C's FILE *stdout variable. You can get this pointer like this:
(cffi:defcvar ("stdout" stdout) :pointer)
Then, after using printf:
(cffi:foreign-funcall "fflush" :pointer stdout :int)
Write in flush.c:
#include <stdio.h>
void flush() {
fflush(stdout);
}
Then:
gcc -fpic -shared flush.c -o flush.so
Then in SLIME:
(cffi:load-foreign-library "./flush.so")
(cffi:foreign-funcall "puts" :string "Hello World" :int)
(cffi:foreign-funcall "flush")
But only print in *inferior-lisp*, even with (with-output-to-string (*standard-output*...)

how to define script interpreter with shebang

It is clear that one can use the
#!/usr/bin/perl
shebang notation in the very first line of a script to define the interpreter. However, this presupposes an interpreter that ignores hashmark-starting lines as comments. How can one use an interpreter that does not have this feature?
With a wrapper that removes the first line and calls the real interpreter with the remainder of the file. It could look like this:
#!/bin/sh
# set your "real" interpreter here, or use cat for debugging
REALINTERP="cat"
tail -n +2 $1 | $REALINTERP
Other than that: In some cases ignoring the error message about that first line could be an option.
Last resort: code support for the comment char of your interpreter into the kernel.
I think the first line is interpreted by the operating system.
The interpreter will be started and the name of the script is handed down to the script as its first parameter.
The following script 'first.myint' calls the interpreter 'myinterpreter' which is the executable from the C program below.
#!/usr/local/bin/myinterpreter
% 1 #########
2 xxxxxxxxxxx
333
444
% the last comment
The sketch of the personal interpreter:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 256 /* input buffer size */
int
main ( int argc, char *argv[] )
{
char comment_leader = '%'; /* define the coment leader */
char *line = NULL;
size_t len = 0;
ssize_t read;
// char buffer[BUFFERSIZE];
// argv[0] : the name of this executable
// argv[1] : the name the script calling this executable via shebang
FILE *input; /* input-file pointer */
char *input_file_name = argv[1]; /* the script name */
input = fopen( input_file_name, "r" );
if ( input == NULL ) {
fprintf ( stderr, "couldn't open file '%s'; %s\n",
input_file_name, strerror(errno) );
exit (EXIT_FAILURE);
}
while ((read = getline(&line, &len, input)) != -1) {
if ( line[0] != comment_leader ) {
printf( "%s", line ); /* print line as a test */
}
else {
printf ( "Skipped a comment!\n" );
}
}
free(line);
if( fclose(input) == EOF ) { /* close input file */
fprintf ( stderr, "couldn't close file '%s'; %s\n",
input_file_name, strerror(errno) );
exit (EXIT_FAILURE);
}
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
Now call the script (made executable before) and see the output:
...~> ./first.myint
#!/usr/local/bin/myinterpreter
Skipped a comment!
2 xxxxxxxxxxx
333
444
Skipped a comment!
I made it work. I especially thank holgero for his tail opion trick
tail -n +2 $1 | $REALINTERP
That, and finding this answer on Stack overflow made it possible:
How to compile a linux shell script to be a standalone executable *binary* (i.e. not just e.g. chmod 755)?
"The solution that fully meets my needs would be SHC - a free tool"
SHC is a shell to C translator, see here:
http://www.datsi.fi.upm.es/~frosal/
So I wrote polyscript.sh:
$ cat polyscript.sh
#!/bin/bash
tail -n +2 $1 | poly
I compiled this with shc and in turn with gcc:
$ shc-3.8.9/shc -f polyscript.sh
$ gcc -Wall polyscript.sh.x.c -o polyscript
Now, I was able to create a first script written in ML:
$ cat smlscript
#!/home/gergoe/projects/shebang/polyscript $0
print "Hello World!"
and, I was able to run it:
$ chmod u+x smlscript
$ ./smlscript
Poly/ML 5.4.1 Release
> > # Hello World!val it = (): unit
Poly does not have an option to suppress compiler output, but that's not an issue here. It might be interesting to write polyscript directly in C as fgm suggested, but probably that wouldn't make it faster.
So, this is how simple it is. I welcome any comments.

How to pass "*" in command line arguments.?

see i have below code
#include<stdio.h>
int main ( int argc, char *argv[] )
{
int i=0;
for(i=1;i<argc-1;i++)
printf(" %s \n",argv[i]);
return 0;
}
compiles and run as follows
gcc test.c
./a.out 1 * 2
and now its o/p is scarred..!
o/p is :
1
a.out
Desktop
Documents
Downloads
ipmsg.log
linux-fusion-3.2.6
Music
Pictures
Public
Templates
test.c
Use single quotes around the asterisk:
./a.out 1 '*' 2
This should prevent your shell from interpreting it as a special character.
You could invoke your test using
./a.out 1 \* 2
if you want to pass * as an argument. You can also use single quotes '*' (as suggested by Esa) or double quotes "*".
Note also that your loop currently ignores the last argument. Use i<argc as your exit condition if this isn't deliberate.

Resources