I'm getting strange behavior with input-port-byte-position. When used to read the byte position of an input file, it always returns 0. On the other hand, when used to set the byte position, it works as expected. Here's an example:
% gsi/gsi Gambit Version 4.0 beta 20
(define f (open-input-file "README")) (input-port-byte-position f)
0
(read-char f)
#\R
(read-char f)
#\E
(input-port-byte-position f)
0
(input-port-byte-position f 10)
10
(input-port-byte-position f)
0
(read-char f)
#\e
(input-port-byte-position f)
0
I've tried following the example in the manual to the letter, and it still always returns 0. I've tried this both with 4.0 beta 17 (installed from a deb) and with 4.0 beta 20 (compiled from source, passes all tests in "make check"). I get the same results on two different machines (both i686-gnu-linux).
Does anyone have an explanation for this, or a fix? Aside from this problem, gambit-C is perfect for my project. I noticed that there is a message in the archives from September 2005 asking the same question, but no response was posted. Any help would be most appreciated.
John
Afficher les réponses par date
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 17-Oct-06, at 10:07 AM, John MacFarlane wrote:
I'm getting strange behavior with input-port-byte-position. ...
Thanks for the bug report. The problem is in the function ___device_file_seek_raw_virt in lib/os_io.c (the new position was not being returned). Please update that function as follows and recompile Gambit, and the system will be consistent with the documentation.
Marc
___HIDDEN ___SCMOBJ ___device_file_seek_raw_virt ___P((___device_stream *self, ___stream_index *pos, int whence), (self, pos, whence) ___device_stream *self; ___stream_index *pos; int whence;) { ___device_file *d = ___CAST(___device_file*,self);
if (d->base.base.read_stage == ___STAGE_OPEN || d->base.base.write_stage == ___STAGE_OPEN) { #ifndef USE_POSIX #ifndef USE_WIN32
int new_pos; FILE *stream = d->stream;
if (stream == 0) stream = stdout;
if (fseek (stream, *pos, whence) < 0 || (new_pos = ftell (stream)) < 0) return err_code_from_errno ();
*pos = new_pos; /************** ADD THIS *******************/
#endif #endif
#ifdef USE_POSIX
int new_pos;
if ((new_pos = lseek (d->fd, *pos, whence)) < 0) return err_code_from_errno ();
*pos = new_pos; /************** ADD THIS *******************/
#endif
#ifdef USE_WIN32
...
#endif }
return ___FIX(___NO_ERR); }
Thanks for your quick response. Here's what I'm seeing now, after recompiling with the changes you suggested:
% gsi/gsi Gambit Version 4.0 beta 20
(define f (open-input-file "README")) (input-port-byte-position f)
0
(read-char f)
#\R
(input-port-byte-position f)
1024
(read-char f)
#\E
(input-port-byte-position f)
1024
(read-char f)
#\A
(input-port-byte-position f)
1024
(input-port-byte-position f 0)
0
(read-char f)
#\R
(input-port-byte-position f)
1024
A different problem, but still a problem. Any ideas?
JM
+++ Marc Feeley [Oct 17 06 14:20 ]:
Thanks for the bug report. The problem is in the function ___device_file_seek_raw_virt in lib/os_io.c (the new position was not being returned). Please update that function as follows and recompile Gambit, and the system will be consistent with the documentation.
Marc
___HIDDEN ___SCMOBJ ___device_file_seek_raw_virt ___P((___device_stream *self, ___stream_index *pos, int whence), (self, pos, whence) ___device_stream *self; ___stream_index *pos; int whence;) { ___device_file *d = ___CAST(___device_file*,self);
if (d->base.base.read_stage == ___STAGE_OPEN || d->base.base.write_stage == ___STAGE_OPEN) { #ifndef USE_POSIX #ifndef USE_WIN32
int new_pos; FILE *stream = d->stream; if (stream == 0) stream = stdout; if (fseek (stream, *pos, whence) < 0 || (new_pos = ftell (stream)) < 0) return err_code_from_errno (); *pos = new_pos; /************** ADD THIS *******************/
#endif #endif
#ifdef USE_POSIX
int new_pos; if ((new_pos = lseek (d->fd, *pos, whence)) < 0) return err_code_from_errno (); *pos = new_pos; /************** ADD THIS *******************/
#endif
#ifdef USE_WIN32
...
#endif }
return ___FIX(___NO_ERR); }
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 17-Oct-06, at 7:48 PM, John MacFarlane wrote:
Thanks for your quick response. Here's what I'm seeing now, after recompiling with the changes you suggested:
% gsi/gsi Gambit Version 4.0 beta 20
(define f (open-input-file "README")) (input-port-byte-position f)
0
(read-char f)
#\R
(input-port-byte-position f)
1024
You are witnessing the effect of the buffering. The "byte-position" is the read/write position of the device (a file in this case). At the first read-char, the system will read 1024 bytes into the read buffer. So if you ask for the byte position you will get 1024. The byte position will change after the 1024 bytes have been consumed by a sufficient number of read-chars (or other input operation). The behavior you expected can be obtained by turning the buffering off:
Gambit Version 4.0 beta 20
(define f (open-input-file (list path: "README" buffering: #f))) (input-port-byte-position f)
0
(read-char f)
#\R
(input-port-byte-position f)
1
(read-char f)
#\E
(input-port-byte-position f)
2
(read-char f)
#\A
(input-port-byte-position f)
3
(input-port-byte-position f 0)
0
(read-char f)
#\R
(input-port-byte-position f)
1
Of course the I/O operations will be significantly slower when buffering is off.
It is still not clear to me if this is the proper way of reporting the "byte-position". Gambit has two levels of buffering, a byte buffer and a character buffer. When the byte buffer is empty, an input operation is performed on the device to fill the byte buffer. When the character buffer is empty, the byte buffer is used to fill the character buffer (and a byte to character conversion is performed). The byte position cannot take into account the position in the character buffer because the decoding of bytes to characters may be many to one in general. However the byte position could take into account the position in the byte buffer, which may be more useful than the byte position of the device. I'd appreciate feedback on this issue.
Marc
Many thanks for the clear explanation. That solves my problem. For what it's worth, I do think it would be more useful if input-port-byte-position took into account the position in the byte buffer. I want to be able to store a position in a file and return to it later, and it would be nice if I could do this independently of whether buffering is used.
John
+++ Marc Feeley [Oct 17 06 20:31 ]:
You are witnessing the effect of the buffering. The "byte-position" is the read/write position of the device (a file in this case). At the first read-char, the system will read 1024 bytes into the read buffer. So if you ask for the byte position you will get 1024. The byte position will change after the 1024 bytes have been consumed by a sufficient number of read-chars (or other input operation). The behavior you expected can be obtained by turning the buffering off:
Gambit Version 4.0 beta 20
(define f (open-input-file (list path: "README" buffering: #f))) (input-port-byte-position f)
0
(read-char f)
#\R
(input-port-byte-position f)
1
(read-char f)
#\E
(input-port-byte-position f)
2
(read-char f)
#\A
(input-port-byte-position f)
3
(input-port-byte-position f 0)
0
(read-char f)
#\R
(input-port-byte-position f)
1
Of course the I/O operations will be significantly slower when buffering is off.
It is still not clear to me if this is the proper way of reporting the "byte-position". Gambit has two levels of buffering, a byte buffer and a character buffer. When the byte buffer is empty, an input operation is performed on the device to fill the byte buffer. When the character buffer is empty, the byte buffer is used to fill the character buffer (and a byte to character conversion is performed). The byte position cannot take into account the position in the character buffer because the decoding of bytes to characters may be many to one in general. However the byte position could take into account the position in the byte buffer, which may be more useful than the byte position of the device. I'd appreciate feedback on this issue.
Marc
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.3 (Darwin)
iD8DBQFFNXX///V9Zc2T/v4RAmyrAKC8hTQQ8BlzJ51BUwqc9sS/v4LltQCgvhcJ llsok9oXZ102kblvQcBw0YQ= =eLfQ -----END PGP SIGNATURE-----