mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Work towards a more complete implementation of `(rnrs io ports)'
* module/rnrs/io/ports.scm: (file-options, buffer-mode, eol-style) (error-handling-mode, make-transcoder, native-transcoder) (latin-1-codec, utf-8-codec, utf-16-codec) (call-with-bytevector-output-port, open-file-input-port) (open-file-output-port, make-custom-textual-output-port) (flush-output-port, put-char, put-datum, put-string, get-char) (get-datum, get-line, get-string-all, lookahead-char) (standard-input-port, standard-output-port, standard-error-port): Define all of these. (call-with-port): Don't use `dynamic-wind', as it is against its specification in R6RS 8.2.6. * module/rnrs.scm: Export procedures added. * module/rnrs/io/simple.scm (call-with-input-file) (call-with-output-file): Define these in terms of R6RS procedures to get correct exception behavior. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
parent
50851f1d18
commit
a5484153b8
3 changed files with 260 additions and 21 deletions
|
@ -160,15 +160,31 @@
|
|||
|
||||
;; (rnrs io ports)
|
||||
|
||||
file-options buffer-mode buffer-mode?
|
||||
eol-style native-eol-style error-handling-mode
|
||||
make-transcoder transcoder-codec native-transcoder
|
||||
latin-1-codec utf-8-codec utf-16-codec
|
||||
|
||||
eof-object? port? input-port? output-port? eof-object port-transcoder
|
||||
binary-port? transcoded-port port-position set-port-position!
|
||||
port-has-port-position? port-has-set-port-position!? call-with-port
|
||||
port-has-port-position? port-has-set-port-position!?
|
||||
close-port call-with-port
|
||||
open-bytevector-input-port make-custom-binary-input-port get-u8
|
||||
lookahead-u8 get-bytevector-n get-bytevector-n! get-bytevector-some
|
||||
get-bytevector-all open-bytevector-output-port
|
||||
make-custom-binary-output-port put-u8 put-bytevector
|
||||
open-string-input-port open-string-output-port
|
||||
|
||||
call-with-bytevector-output-port
|
||||
call-with-string-output-port
|
||||
latin-1-codec utf-8-codec utf-16-codec
|
||||
open-file-input-port open-file-output-port
|
||||
make-custom-textual-output-port
|
||||
call-with-string-output-port
|
||||
flush-output-port put-string
|
||||
get-char get-datum get-line get-string-all lookahead-char
|
||||
put-char put-datum put-string
|
||||
standard-input-port standard-output-port standard-error-port
|
||||
|
||||
;; (rnrs io simple)
|
||||
|
||||
call-with-input-file call-with-output-file current-input-port
|
||||
|
|
|
@ -29,16 +29,23 @@
|
|||
(library (rnrs io ports (6))
|
||||
(export eof-object eof-object?
|
||||
|
||||
;; auxiliary types
|
||||
file-options buffer-mode buffer-mode?
|
||||
eol-style native-eol-style error-handling-mode
|
||||
make-transcoder transcoder-codec native-transcoder
|
||||
latin-1-codec utf-8-codec utf-16-codec
|
||||
|
||||
;; input & output ports
|
||||
port? input-port? output-port?
|
||||
port-transcoder binary-port? transcoded-port
|
||||
port-position set-port-position!
|
||||
port-has-port-position? port-has-set-port-position!?
|
||||
call-with-port
|
||||
call-with-port close-port
|
||||
|
||||
;; input ports
|
||||
open-bytevector-input-port
|
||||
open-string-input-port
|
||||
open-file-input-port
|
||||
make-custom-binary-input-port
|
||||
|
||||
;; binary input
|
||||
|
@ -49,16 +56,129 @@
|
|||
;; output ports
|
||||
open-bytevector-output-port
|
||||
open-string-output-port
|
||||
open-file-output-port
|
||||
make-custom-binary-output-port
|
||||
|
||||
call-with-bytevector-output-port
|
||||
call-with-string-output-port
|
||||
make-custom-textual-output-port
|
||||
flush-output-port
|
||||
|
||||
;; binary output
|
||||
put-u8 put-bytevector)
|
||||
(import (guile))
|
||||
put-u8 put-bytevector
|
||||
|
||||
;; textual input
|
||||
get-char get-datum get-line get-string-all lookahead-char
|
||||
|
||||
;; textual output
|
||||
put-char put-datum put-string
|
||||
|
||||
;; standard ports
|
||||
standard-input-port standard-output-port standard-error-port
|
||||
|
||||
;; condition types
|
||||
&i/o i/o-error? make-i/o-error
|
||||
&i/o-read i/o-read-error? make-i/o-read-error
|
||||
&i/o-write i/o-write-error? make-i/o-write-error
|
||||
&i/o-invalid-position i/o-invalid-position-error?
|
||||
make-i/o-invalid-position-error
|
||||
&i/o-filename i/o-filename-error? make-i/o-filename-error
|
||||
i/o-error-filename
|
||||
&i/o-file-protection i/o-file-protection-error?
|
||||
make-i/o-file-protection-error
|
||||
&i/o-file-is-read-only i/o-file-is-read-only-error?
|
||||
make-i/o-file-is-read-only-error
|
||||
&i/o-file-already-exists i/o-file-already-exists-error?
|
||||
make-i/o-file-already-exists-error
|
||||
&i/o-file-does-not-exist i/o-file-does-not-exist-error?
|
||||
make-i/o-file-does-not-exist-error
|
||||
&i/o-port i/o-port-error? make-i/o-port-error
|
||||
i/o-error-port)
|
||||
(import (only (rnrs base) assertion-violation)
|
||||
(rnrs enums)
|
||||
(rnrs records syntactic)
|
||||
(rnrs exceptions)
|
||||
(rnrs conditions)
|
||||
(rnrs files) ;for the condition types
|
||||
(srfi srfi-8)
|
||||
(ice-9 rdelim)
|
||||
(except (guile) raise))
|
||||
|
||||
(load-extension (string-append "libguile-" (effective-version))
|
||||
"scm_init_r6rs_ports")
|
||||
|
||||
|
||||
|
||||
;;;
|
||||
;;; Auxiliary types
|
||||
;;;
|
||||
|
||||
(define-enumeration file-option
|
||||
(no-create no-fail no-truncate)
|
||||
file-options)
|
||||
|
||||
(define-enumeration buffer-mode
|
||||
(none line block)
|
||||
buffer-modes)
|
||||
|
||||
(define (buffer-mode? symbol)
|
||||
(enum-set-member? symbol (enum-set-universe (buffer-modes))))
|
||||
|
||||
(define-enumeration eol-style
|
||||
(lf cr crlf nel crnel ls)
|
||||
eol-styles)
|
||||
|
||||
(define (native-eol-style)
|
||||
(eol-style lf))
|
||||
|
||||
(define-enumeration error-handling-mode
|
||||
(ignore raise replace)
|
||||
error-handling-modes)
|
||||
|
||||
(define-record-type (transcoder %make-transcoder transcoder?)
|
||||
(fields codec eol-style error-handling-mode))
|
||||
|
||||
(define* (make-transcoder codec
|
||||
#:optional
|
||||
(eol-style (native-eol-style))
|
||||
(handling-mode (error-handling-mode replace)))
|
||||
(%make-transcoder codec eol-style handling-mode))
|
||||
|
||||
(define (native-transcoder)
|
||||
(make-transcoder (or (fluid-ref %default-port-encoding)
|
||||
(latin-1-codec))))
|
||||
|
||||
(define (latin-1-codec)
|
||||
"ISO-8859-1")
|
||||
|
||||
(define (utf-8-codec)
|
||||
"UTF-8")
|
||||
|
||||
(define (utf-16-codec)
|
||||
"UTF-16")
|
||||
|
||||
|
||||
;;;
|
||||
;;; Internal helpers
|
||||
;;;
|
||||
|
||||
(define (with-i/o-filename-conditions filename thunk)
|
||||
(catch 'system-error
|
||||
thunk
|
||||
(lambda args
|
||||
(let ((errno (system-error-errno args)))
|
||||
(let ((construct-condition
|
||||
(cond ((= errno EACCES)
|
||||
make-i/o-file-protection-error)
|
||||
((= errno EEXIST)
|
||||
make-i/o-file-already-exists-error)
|
||||
((= errno ENOENT)
|
||||
make-i/o-file-does-not-exist-error)
|
||||
((= errno EROFS)
|
||||
make-i/o-file-is-read-only-error)
|
||||
(else
|
||||
make-i/o-filename-error))))
|
||||
(raise (construct-condition filename)))))))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Input and output ports.
|
||||
|
@ -100,19 +220,33 @@ read from/written to in @var{port}."
|
|||
(define (call-with-port port proc)
|
||||
"Call @var{proc}, passing it @var{port} and closing @var{port} upon exit of
|
||||
@var{proc}. Return the return values of @var{proc}."
|
||||
(dynamic-wind
|
||||
(lambda ()
|
||||
#t)
|
||||
(lambda ()
|
||||
(proc port))
|
||||
(lambda ()
|
||||
(close-port port))))
|
||||
(call-with-values
|
||||
(lambda () (proc port))
|
||||
(lambda vals
|
||||
(close-port port)
|
||||
(apply values vals))))
|
||||
|
||||
(define* (call-with-bytevector-output-port proc #:optional (transcoder #f))
|
||||
(receive (port extract) (open-bytevector-output-port transcoder)
|
||||
(call-with-port port proc)
|
||||
(extract)))
|
||||
|
||||
(define (open-string-input-port str)
|
||||
"Open an input port that will read from @var{str}."
|
||||
(with-fluids ((%default-port-encoding "UTF-8"))
|
||||
(open-input-string str)))
|
||||
|
||||
(define* (open-file-input-port filename
|
||||
#:optional
|
||||
(file-options (file-options))
|
||||
(buffer-mode (buffer-mode block))
|
||||
maybe-transcoder)
|
||||
(let ((port (with-i/o-filename-conditions filename
|
||||
(lambda () (open filename O_RDONLY)))))
|
||||
(cond (maybe-transcoder
|
||||
(set-port-encoding! port (transcoder-codec maybe-transcoder))))
|
||||
port))
|
||||
|
||||
(define (open-string-output-port)
|
||||
"Return two values: an output port that will collect characters written to it
|
||||
as a string, and a thunk to retrieve the characters associated with that port."
|
||||
|
@ -121,6 +255,88 @@ as a string, and a thunk to retrieve the characters associated with that port."
|
|||
(values port
|
||||
(lambda () (get-output-string port)))))
|
||||
|
||||
(define* (open-file-output-port filename
|
||||
#:optional
|
||||
(file-options (file-options))
|
||||
(buffer-mode (buffer-mode block))
|
||||
maybe-transcoder)
|
||||
(let* ((flags (logior O_WRONLY
|
||||
(if (enum-set-member? 'no-create file-options)
|
||||
0
|
||||
O_CREAT)
|
||||
(if (enum-set-member? 'no-truncate file-options)
|
||||
0
|
||||
O_TRUNC)))
|
||||
(port (with-i/o-filename-conditions filename
|
||||
(lambda () (open filename flags)))))
|
||||
(cond (maybe-transcoder
|
||||
(set-port-encoding! port (transcoder-codec maybe-transcoder))))
|
||||
port))
|
||||
|
||||
(define (call-with-string-output-port proc)
|
||||
"Call @var{proc}, passing it a string output port. When @var{proc} returns,
|
||||
return the characters accumulated in that port."
|
||||
(let ((port (open-output-string)))
|
||||
(proc port)
|
||||
(get-output-string port)))
|
||||
|
||||
(define (make-custom-textual-output-port id
|
||||
write!
|
||||
get-position
|
||||
set-position!
|
||||
close)
|
||||
(make-soft-port (vector (lambda (c) (write! (string c) 0 1))
|
||||
(lambda (s) (write! s 0 (string-length s)))
|
||||
#f ;flush
|
||||
#f ;read character
|
||||
close)
|
||||
"w"))
|
||||
|
||||
(define (flush-output-port port)
|
||||
(force-output port))
|
||||
|
||||
(define (put-char port char)
|
||||
(write-char char port))
|
||||
|
||||
(define (put-datum port datum)
|
||||
(write datum port))
|
||||
|
||||
(define* (put-string port s #:optional start count)
|
||||
(cond ((not (string? s))
|
||||
(assertion-violation 'put-string "expected string" s))
|
||||
((and start count)
|
||||
(display (substring/shared s start (+ start count)) port))
|
||||
(start
|
||||
(display (substring/shared s start (string-length s)) port))
|
||||
(else
|
||||
(display s port))))
|
||||
|
||||
(define (get-char port)
|
||||
(read-char port))
|
||||
|
||||
(define (get-datum port)
|
||||
(read port))
|
||||
|
||||
(define (get-line port)
|
||||
(read-line port 'trim))
|
||||
|
||||
(define (get-string-all port)
|
||||
(read-delimited "" port 'concat))
|
||||
|
||||
(define (lookahead-char port)
|
||||
(peek-char port))
|
||||
|
||||
|
||||
|
||||
(define (standard-input-port)
|
||||
(dup->inport 0))
|
||||
|
||||
(define (standard-output-port)
|
||||
(dup->outport 1))
|
||||
|
||||
(define (standard-error-port)
|
||||
(dup->outport 2))
|
||||
|
||||
)
|
||||
|
||||
;;; ports.scm ends here
|
||||
|
|
|
@ -83,15 +83,16 @@
|
|||
i/o-port-error?
|
||||
i/o-error-port)
|
||||
|
||||
(import (only (rnrs io ports) eof-object
|
||||
eof-object?
|
||||
|
||||
input-port?
|
||||
output-port?)
|
||||
(import (only (rnrs io ports)
|
||||
call-with-port
|
||||
open-file-input-port
|
||||
open-file-output-port
|
||||
eof-object
|
||||
eof-object?
|
||||
|
||||
input-port?
|
||||
output-port?)
|
||||
(only (guile) @@
|
||||
call-with-input-file
|
||||
call-with-output-file
|
||||
|
||||
current-input-port
|
||||
current-output-port
|
||||
current-error-port
|
||||
|
@ -115,5 +116,11 @@
|
|||
(rnrs base (6))
|
||||
(rnrs files (6)) ;for the condition types
|
||||
)
|
||||
|
||||
(define (call-with-input-file filename proc)
|
||||
(call-with-port (open-file-input-port filename) proc))
|
||||
|
||||
(define (call-with-output-file filename proc)
|
||||
(call-with-port (open-file-output-port filename) proc))
|
||||
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue