develooper Front page | perl.perl5.porters | Postings from August 2008

Re: How to tell whether readline got an error or EOF

Thread Previous | Thread Next
Tom Christiansen
August 2, 2008 10:06
Re: How to tell whether readline got an error or EOF
Message ID:
> OK, I see that I managed to thoroughly confuse myself and what I posted is not
> particularly coherent or correct :-(.

I would still like to ask the same questions though:

>> % echo x | perl -e 'getc; print $!; print 0; open FH, "nonexistent"; getc; print
>> $!; print 0; getc; print $!'
>> 0No such file or directory0Bad file descriptor

>> The first two getc calls succeed because echo prints two characters (x and
>> newline), but the second of them, even though it succeeded, leaves $! with the
>> leftover error code from the open() call earlier.  The third getc sets $! to
>> 'Bad file descriptor'.  Is that the magic code for end of file?

It is now and has always been valid to inspect errno only after a syscall
should fail; no syscall clears errno on success.

You may, however, clear it yourself prior to the syscall.

But really, you have to read the fgetc man page, where you learn:

     If successful, these routines return the next requested object from the
     stream.  If the stream is at end-of-file or a read error occurs, the rou-
     tines return EOF.  The routines feof(3) and ferror(3) must be used to
     distinguish between end-of-file and error.  If an error occurs, the glob-
     al variable errno is set to indicate the error.  The end-of-file condi-
     tion is remembered, even on a terminal, and all subsequent attempts to
     read will return EOF until the condition is cleared with clearerr(3).

     ferror(3), fopen(3), fread(3), putc(3), ungetc(3)

     The fgetc(), getc(), and getchar() functions conform to ANSI X3.159-1989
     (``ANSI C'').

     Since EOF is a valid integer value, feof(3) and ferror(3) must be used to
     check for failure after calling getw().  The size and byte order of an
     int varies from one machine to another, and getw() is not recommended for
     portable applications.

Then undre IO::Handle, you learn:

           Returns a true value if the given handle has experienced any
           errors since it was opened or since the last call to "clearerr",
           or if the handle is invalid. It only returns false for a valid
           handle with no outstanding errors.

           Clear the given handle's error indicator. Returns -1 if the
           handle is invalid, 0 otherwise.

Clearly you must 

    (1) clear errno before the getc / readline 
and (2) use IO::Handle and inspect STDIN->error() to determine 
        whether your undef means eof or error, and only if it does
	say there's an error might errno be of any use to you.

Something like this should work better than what you're doing:

    use IO::Handle;
    $! = 0;
    unless (defined($ch = getc(STDIN))) {
	print "STDIN has ", STDIN->error() 
				?  "had an error: $!\n";
				:  "hit EOF\n";


Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About