[prev in list] [next in list] [prev in thread] [next in thread]
List: gcc
Subject: Re: getline() doesn't seem to work?
From: Per Bothner <bothner () cygnus ! com>
Date: 1998-01-31 3:39:59
[Download RAW message or body]
> > I don't know if this is a bug in getline, or just a bug in my
> > understanding of getline. When I have the following program just
> > reading from my terminal, I have to hit control-D twice before the
> > loop exits. It appears that the first time I hit control-D, getline
> How is this patch?
> Fri Jan 30 07:47:57 1998 H.J. Lu (hjl@gnu.org)
> * isgetline.cc (istream::getline, istream::get): Call
> * isgetline.cc (istream::getline, istream::get): Call
> streambuf::in_avail () to check EOF when _IO_getline ()
> returns 0.
This is wrong. istream::getline should not call streambuf::in_avail.
istream::getline should just be a more convienient and efficient
interface than you could write yourself as a loop using sgetc/sbumpc.
It should not require the more magic streambuf::in_avail.
Furthermore, this solution is not consistent. fgets and gets do not
check for availability. Instead they check if fp->_IO_file_flags
has _IO_ERR_SEEN set. istream::getline should work similarly,
except use _IO_EOF_SEEN.
I thought about changing the interface of _IO_getline so it returns
-1 on EOF. (The return type should then be changed from _IO_size_t
to _IO_ssize_t.) That would make it easy to test if EOF was seen.
However, that would not solve the problem of a partial line line
followed by EOF (and no delimiter). The code would still try to read
the delimiter - even after EOF is seen. While this is presumably
harmless except on terminals, and a terminal would not return
a partial line followed by EOF - still, we should avoid reading an
extra character after EOF has been seen. So I propose something like
the following. (Note I have not looked at istream::get.)
Fri Jan 30 19:36:24 1998 Per Bothner <bothner@cygnus.com>
* isgetline.c (istream::getline): Don't try to sbumpc
if _IO_getline returned 0 chars, and we have seen EOF.
Index: isgetline.cc
===================================================================
RCS file: /cvs/cvsfiles/devo/libio/isgetline.cc,v
retrieving revision 1.7
diff -u -r1.7 isgetline.cc
--- isgetline.cc 1995/11/06 23:06:45 1.7
+++ isgetline.cc 1998/01/31 03:34:08
@@ -34,22 +34,25 @@
set(ios::failbit);
return *this;
}
- int ch;
+ int ch = EOF;
if (ipfx1())
{
streambuf *sb = rdbuf();
_gcount = _IO_getline(sb, buf, len - 1, delim, -1);
- ch = sb->sbumpc();
- if (ch == EOF)
- set (_gcount == 0 ? (ios::failbit|ios::eofbit) : ios::eofbit);
- else if (ch != (unsigned char) delim)
+ if (_gcount == 0 && (sb->_IO_file_flags & _IO_EOF_SEEN))
+ set (ios::eofbit);
+ else
{
- set(ios::failbit);
- sb->sungetc(); // Leave delimiter unread.
+ ch = sb->sbumpc();
+ if (ch == EOF)
+ set (ios::failbit|ios::eofbit);
+ else if (ch != (unsigned char) delim)
+ {
+ set(ios::failbit);
+ sb->sungetc(); // Leave delimiter unread.
+ }
}
}
- else
- ch = EOF;
buf[_gcount] = '\0';
if (ch == (unsigned char)delim)
_gcount++; // The delimiter is counted in the gcount().
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic