GNU bug report logs -
#12216
peek-char incorrectly *CONSUMES* eof
Previous Next
Reported by: dwheeler <at> dwheeler.com
Date: Fri, 17 Aug 2012 02:03:01 UTC
Severity: normal
Done: Mark H Weaver <mhw <at> netris.org>
Bug is archived. No further changes may be made.
Full log
Message #66 received at 12216 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
The prerequisite patches are now in stable-2.0. Here's an updated patch
that applies against current stable-2.0. Otherwise it has not changed.
Mark
[0001-Peeks-do-not-consume-EOFs.patch (text/x-diff, inline)]
From 7d9ebc691519af7236e1fec8dfefd5fc8784f875 Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw <at> netris.org>
Date: Sun, 31 Mar 2013 19:06:51 -0400
Subject: [PATCH] Peeks do not consume EOFs.
Fixes <http://bugs.gnu.org/12216>.
* libguile/ports-internal.h (struct scm_port_internal): Add
'pending_eof' flag.
* libguile/inline.h (scm_peek_byte_or_eof): Set 'pending_eof' flag
before returning EOF.
* libguile/ports.c (scm_i_set_pending_eof): New function.
(scm_i_clear_pending_eof): New static function.
(scm_new_port_table_entry): Initialize 'pending_eof'.
(scm_fill_input): Check for 'pending_eof'.
(scm_end_input, scm_unget_byte, scm_seek): Clear 'pending_eof'.
(scm_peek_char): Set 'pending_eof' flag before returning EOF.
* libguile/ports.h (scm_i_set_pending_eof): Add prototype.
---
libguile/inline.h | 5 ++++-
libguile/ports-internal.h | 1 +
libguile/ports.c | 32 ++++++++++++++++++++++++++++++--
libguile/ports.h | 1 +
4 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/libguile/inline.h b/libguile/inline.h
index 88ba7f7..fffe101 100644
--- a/libguile/inline.h
+++ b/libguile/inline.h
@@ -134,7 +134,10 @@ scm_peek_byte_or_eof (SCM port)
if (pt->read_pos >= pt->read_end)
{
if (SCM_UNLIKELY (scm_fill_input (port) == EOF))
- return EOF;
+ {
+ scm_i_set_pending_eof (port);
+ return EOF;
+ }
}
c = *pt->read_pos;
diff --git a/libguile/ports-internal.h b/libguile/ports-internal.h
index 73a788f..333d4fb 100644
--- a/libguile/ports-internal.h
+++ b/libguile/ports-internal.h
@@ -48,6 +48,7 @@ struct scm_port_internal
{
scm_t_port_encoding_mode encoding_mode;
scm_t_iconv_descriptors *iconv_descriptors;
+ int pending_eof;
SCM alist;
};
diff --git a/libguile/ports.c b/libguile/ports.c
index becdbed..65e2e6f 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -241,6 +241,18 @@ scm_set_port_input_waiting (scm_t_bits tc, int (*input_waiting) (SCM))
scm_ptobs[SCM_TC2PTOBNUM (tc)].input_waiting = input_waiting;
}
+void
+scm_i_set_pending_eof (SCM port)
+{
+ SCM_PORT_GET_INTERNAL (port)->pending_eof = 1;
+}
+
+static void
+scm_i_clear_pending_eof (SCM port)
+{
+ SCM_PORT_GET_INTERNAL (port)->pending_eof = 0;
+}
+
SCM
scm_i_port_alist (SCM port)
{
@@ -645,6 +657,7 @@ scm_new_port_table_entry (scm_t_bits tag)
entry->input_cd = pti; /* XXX pointer to the internal port structure */
entry->output_cd = NULL; /* XXX unused */
+ pti->pending_eof = 0;
pti->alist = SCM_EOL;
SCM_SET_CELL_TYPE (z, tag);
@@ -1423,9 +1436,16 @@ int
scm_fill_input (SCM port)
{
scm_t_port *pt = SCM_PTAB_ENTRY (port);
+ scm_t_port_internal *pti = SCM_PORT_GET_INTERNAL (port);
assert (pt->read_pos == pt->read_end);
+ if (pti->pending_eof)
+ {
+ pti->pending_eof = 0;
+ return EOF;
+ }
+
if (pt->read_buf == pt->putback_buf)
{
/* finished reading put-back chars. */
@@ -1665,6 +1685,7 @@ scm_end_input (SCM port)
long offset;
scm_t_port *pt = SCM_PTAB_ENTRY (port);
+ scm_i_clear_pending_eof (port);
if (pt->read_buf == pt->putback_buf)
{
offset = pt->read_end - pt->read_pos;
@@ -1688,6 +1709,7 @@ scm_unget_byte (int c, SCM port)
{
scm_t_port *pt = SCM_PTAB_ENTRY (port);
+ scm_i_clear_pending_eof (port);
if (pt->read_buf == pt->putback_buf)
/* already using the put-back buffer. */
{
@@ -1859,7 +1881,10 @@ SCM_DEFINE (scm_peek_char, "peek-char", 0, 1, 0,
result = SCM_BOOL_F;
}
else if (c == EOF)
- result = SCM_EOF_VAL;
+ {
+ scm_i_set_pending_eof (port);
+ result = SCM_EOF_VAL;
+ }
else
result = SCM_MAKE_CHAR (c);
@@ -1958,7 +1983,10 @@ SCM_DEFINE (scm_seek, "seek", 3, 0, 0,
SCM_MISC_ERROR ("port is not seekable",
scm_cons (fd_port, SCM_EOL));
else
- rv = ptob->seek (fd_port, off, how);
+ {
+ scm_i_clear_pending_eof (fd_port);
+ rv = ptob->seek (fd_port, off, how);
+ }
return scm_from_off_t_or_off64_t (rv);
}
else /* file descriptor?. */
diff --git a/libguile/ports.h b/libguile/ports.h
index 53d5081..5c9334a 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -316,6 +316,7 @@ SCM_API SCM scm_port_column (SCM port);
SCM_API SCM scm_set_port_column_x (SCM port, SCM line);
SCM_API SCM scm_port_filename (SCM port);
SCM_API SCM scm_set_port_filename_x (SCM port, SCM filename);
+SCM_INTERNAL void scm_i_set_pending_eof (SCM port);
SCM_INTERNAL SCM scm_i_port_alist (SCM port);
SCM_INTERNAL void scm_i_set_port_alist_x (SCM port, SCM alist);
SCM_INTERNAL const char *scm_i_default_port_encoding (void);
--
1.7.10.4
This bug report was last modified 12 years and 50 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.