2007-12-10 08:08:50 -05:00
|
|
|
;;; Ikarus Scheme -- A compiler for R6RS Scheme.
|
2008-01-29 00:34:34 -05:00
|
|
|
;;; Copyright (C) 2006,2007,2008 Abdulaziz Ghuloum
|
2007-12-10 08:08:50 -05:00
|
|
|
;;;
|
|
|
|
;;; This program is free software: you can redistribute it and/or modify
|
|
|
|
;;; it under the terms of the GNU General Public License version 3 as
|
|
|
|
;;; published by the Free Software Foundation.
|
|
|
|
;;;
|
|
|
|
;;; This program is distributed in the hope that it will be useful, but
|
|
|
|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
;;; General Public License for more details.
|
|
|
|
;;;
|
|
|
|
;;; You should have received a copy of the GNU General Public License
|
|
|
|
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2007-12-05 05:33:31 -05:00
|
|
|
|
2008-06-09 04:36:27 -04:00
|
|
|
(library (ikarus.io)
|
2007-12-08 14:52:35 -05:00
|
|
|
|
2007-12-06 05:05:26 -05:00
|
|
|
(export
|
2007-12-09 17:13:09 -05:00
|
|
|
port? input-port? output-port? textual-port? binary-port?
|
|
|
|
open-file-input-port open-input-file
|
|
|
|
call-with-input-file with-input-from-file
|
|
|
|
standard-input-port current-input-port
|
2007-12-06 05:05:26 -05:00
|
|
|
open-bytevector-input-port
|
2008-05-06 15:38:05 -04:00
|
|
|
open-string-input-port open-string-input-port/id
|
|
|
|
with-input-from-string
|
2007-12-06 05:05:26 -05:00
|
|
|
make-custom-binary-input-port
|
2007-12-10 10:36:10 -05:00
|
|
|
make-custom-binary-output-port
|
2007-12-10 11:11:59 -05:00
|
|
|
make-custom-textual-input-port
|
|
|
|
make-custom-textual-output-port
|
2007-12-08 14:52:35 -05:00
|
|
|
transcoded-port port-transcoder
|
2007-12-23 22:28:48 -05:00
|
|
|
close-port port-closed? close-input-port close-output-port
|
2007-12-08 14:52:35 -05:00
|
|
|
port-eof?
|
2007-12-09 12:20:13 -05:00
|
|
|
get-char lookahead-char read-char peek-char
|
2008-12-06 12:40:18 -05:00
|
|
|
get-string-n get-string-n! get-string-all get-line read-line
|
2007-12-08 14:52:35 -05:00
|
|
|
get-u8 lookahead-u8
|
|
|
|
get-bytevector-n get-bytevector-n!
|
|
|
|
get-bytevector-some get-bytevector-all
|
2008-12-09 03:00:44 -05:00
|
|
|
port-position port-has-port-position?
|
|
|
|
set-port-position! port-has-set-port-position!?
|
2007-12-08 14:52:35 -05:00
|
|
|
call-with-port
|
2008-12-09 04:46:43 -05:00
|
|
|
flush-output-port
|
2008-01-20 20:30:37 -05:00
|
|
|
put-u8 put-bytevector
|
2007-12-10 07:28:03 -05:00
|
|
|
put-char write-char
|
|
|
|
put-string
|
|
|
|
open-bytevector-output-port
|
|
|
|
call-with-bytevector-output-port
|
2007-12-23 15:12:22 -05:00
|
|
|
open-string-output-port with-output-to-string
|
2008-04-29 00:20:29 -04:00
|
|
|
with-output-to-port
|
2007-12-26 02:16:02 -05:00
|
|
|
call-with-string-output-port
|
|
|
|
open-output-string get-output-string
|
2007-12-10 07:28:03 -05:00
|
|
|
standard-output-port standard-error-port
|
|
|
|
current-output-port current-error-port
|
2007-12-23 15:18:40 -05:00
|
|
|
open-file-output-port open-output-file
|
|
|
|
call-with-output-file with-output-to-file
|
2007-12-10 07:28:03 -05:00
|
|
|
console-output-port
|
2007-12-10 07:40:34 -05:00
|
|
|
console-error-port
|
2007-12-10 07:28:03 -05:00
|
|
|
console-input-port
|
|
|
|
newline
|
|
|
|
port-mode set-port-mode!
|
2008-12-09 04:46:43 -05:00
|
|
|
output-port-buffer-mode
|
2007-12-10 07:28:03 -05:00
|
|
|
reset-input-port!
|
2008-04-06 10:57:56 -04:00
|
|
|
reset-output-port!
|
2007-12-10 10:18:52 -05:00
|
|
|
port-id
|
2007-12-18 17:25:48 -05:00
|
|
|
input-port-byte-position
|
2008-04-30 22:55:59 -04:00
|
|
|
process process-nonblocking
|
2007-12-26 17:35:58 -05:00
|
|
|
|
2007-12-27 22:08:27 -05:00
|
|
|
tcp-connect tcp-connect-nonblocking
|
2008-03-22 19:29:41 -04:00
|
|
|
udp-connect udp-connect-nonblocking
|
2008-03-23 05:02:12 -04:00
|
|
|
tcp-server-socket tcp-server-socket-nonblocking
|
|
|
|
accept-connection accept-connection-nonblocking
|
|
|
|
close-tcp-server-socket
|
|
|
|
register-callback
|
2008-05-21 02:21:37 -04:00
|
|
|
input-socket-buffer-size output-socket-buffer-size)
|
|
|
|
|
2007-12-08 14:52:35 -05:00
|
|
|
|
|
|
|
|
2007-12-05 05:33:31 -05:00
|
|
|
(import
|
2007-12-12 19:18:57 -05:00
|
|
|
(ikarus system $io)
|
2007-12-06 05:05:26 -05:00
|
|
|
(except (ikarus)
|
2007-12-09 17:13:09 -05:00
|
|
|
port? input-port? output-port? textual-port? binary-port?
|
|
|
|
open-file-input-port open-input-file
|
|
|
|
call-with-input-file with-input-from-file
|
|
|
|
standard-input-port current-input-port
|
2007-12-06 05:05:26 -05:00
|
|
|
open-bytevector-input-port
|
2007-12-23 14:44:55 -05:00
|
|
|
open-string-input-port with-input-from-string
|
2007-12-06 05:05:26 -05:00
|
|
|
make-custom-binary-input-port
|
2007-12-10 10:36:10 -05:00
|
|
|
make-custom-binary-output-port
|
2007-12-10 11:11:59 -05:00
|
|
|
make-custom-textual-input-port
|
|
|
|
make-custom-textual-output-port
|
2007-12-08 14:52:35 -05:00
|
|
|
transcoded-port port-transcoder
|
2007-12-23 22:28:48 -05:00
|
|
|
close-port port-closed? close-input-port close-output-port
|
2007-12-08 14:52:35 -05:00
|
|
|
port-eof?
|
2007-12-09 12:20:13 -05:00
|
|
|
get-char lookahead-char read-char peek-char
|
2008-12-06 12:40:18 -05:00
|
|
|
get-string-n get-string-n! get-string-all get-line read-line
|
2007-12-08 14:52:35 -05:00
|
|
|
get-u8 lookahead-u8
|
|
|
|
get-bytevector-n get-bytevector-n!
|
|
|
|
get-bytevector-some get-bytevector-all
|
2008-12-09 03:00:44 -05:00
|
|
|
port-position port-has-port-position?
|
|
|
|
set-port-position! port-has-set-port-position!?
|
2007-12-08 14:52:35 -05:00
|
|
|
call-with-port
|
2007-12-09 17:13:09 -05:00
|
|
|
flush-output-port
|
2008-01-20 20:30:37 -05:00
|
|
|
put-u8 put-bytevector
|
2007-12-10 07:28:03 -05:00
|
|
|
put-char write-char
|
|
|
|
put-string
|
|
|
|
open-bytevector-output-port
|
|
|
|
call-with-bytevector-output-port
|
2007-12-23 15:12:22 -05:00
|
|
|
open-string-output-port with-output-to-string
|
2007-12-10 07:28:03 -05:00
|
|
|
call-with-string-output-port
|
2007-12-26 02:16:02 -05:00
|
|
|
open-output-string get-output-string
|
2007-12-10 07:28:03 -05:00
|
|
|
standard-output-port standard-error-port
|
|
|
|
current-output-port current-error-port
|
2007-12-23 15:18:40 -05:00
|
|
|
open-file-output-port open-output-file
|
|
|
|
call-with-output-file with-output-to-file
|
2008-04-29 00:20:29 -04:00
|
|
|
with-output-to-port
|
2007-12-10 07:28:03 -05:00
|
|
|
console-output-port
|
|
|
|
console-input-port
|
2007-12-10 07:40:34 -05:00
|
|
|
console-error-port
|
2007-12-10 07:28:03 -05:00
|
|
|
newline
|
|
|
|
port-mode set-port-mode!
|
2008-12-09 04:46:43 -05:00
|
|
|
output-port-buffer-mode
|
2007-12-10 07:28:03 -05:00
|
|
|
reset-input-port!
|
2008-04-06 10:57:56 -04:00
|
|
|
reset-output-port!
|
2007-12-10 10:18:52 -05:00
|
|
|
port-id
|
2008-04-30 22:55:59 -04:00
|
|
|
process process-nonblocking
|
2008-03-22 19:29:41 -04:00
|
|
|
tcp-connect tcp-connect-nonblocking
|
|
|
|
udp-connect udp-connect-nonblocking
|
2008-03-23 05:02:12 -04:00
|
|
|
tcp-server-socket tcp-server-socket-nonblocking
|
|
|
|
accept-connection accept-connection-nonblocking
|
|
|
|
close-tcp-server-socket
|
|
|
|
register-callback
|
2008-04-11 14:02:43 -04:00
|
|
|
input-socket-buffer-size output-socket-buffer-size
|
2008-03-22 19:29:41 -04:00
|
|
|
))
|
2007-12-08 14:52:35 -05:00
|
|
|
|
2008-10-18 15:42:11 -04:00
|
|
|
;(define-syntax assert* (identifier-syntax assert))
|
|
|
|
(define-syntax assert* (syntax-rules () [(_ . x) (void)]))
|
|
|
|
|
2007-12-14 01:58:55 -05:00
|
|
|
(module UNSAFE
|
|
|
|
(fx< fx<= fx> fx>= fx= fx+ fx-
|
|
|
|
fxior fxand fxsra fxsll
|
|
|
|
integer->char char->integer
|
|
|
|
string-ref string-set! string-length
|
2008-10-19 23:10:34 -04:00
|
|
|
bytevector-u8-ref bytevector-u8-set!
|
|
|
|
bytevector-u16-ref)
|
2007-12-12 21:22:05 -05:00
|
|
|
(import
|
|
|
|
(rename (ikarus system $strings)
|
|
|
|
($string-length string-length)
|
|
|
|
($string-ref string-ref)
|
|
|
|
($string-set! string-set!))
|
|
|
|
(rename (ikarus system $chars)
|
|
|
|
($char->fixnum char->integer)
|
|
|
|
($fixnum->char integer->char))
|
|
|
|
(rename (ikarus system $bytevectors)
|
|
|
|
($bytevector-set! bytevector-u8-set!)
|
|
|
|
($bytevector-u8-ref bytevector-u8-ref))
|
|
|
|
(rename (ikarus system $fx)
|
|
|
|
($fxsra fxsra)
|
|
|
|
($fxsll fxsll)
|
|
|
|
($fxlogor fxior)
|
|
|
|
($fxlogand fxand)
|
|
|
|
($fx+ fx+)
|
|
|
|
($fx- fx-)
|
|
|
|
($fx< fx<)
|
|
|
|
($fx> fx>)
|
|
|
|
($fx>= fx>=)
|
|
|
|
($fx<= fx<=)
|
2008-10-19 23:10:34 -04:00
|
|
|
($fx= fx=)))
|
|
|
|
(define (bytevector-u16-ref x i endianness)
|
|
|
|
(case endianness
|
|
|
|
[(little)
|
|
|
|
(fxlogor (bytevector-u8-ref x i)
|
|
|
|
(fxsll (bytevector-u8-ref x (fx+ i 1)) 8))]
|
|
|
|
[else
|
|
|
|
(fxlogor (bytevector-u8-ref x (fx+ i 1))
|
|
|
|
(fxsll (bytevector-u8-ref x i) 8))])))
|
|
|
|
|
2007-12-12 21:22:05 -05:00
|
|
|
|
|
|
|
(define (port? x)
|
|
|
|
(import (only (ikarus) port?))
|
|
|
|
(port? x))
|
|
|
|
|
2007-12-08 14:52:35 -05:00
|
|
|
(define-syntax define-rrr
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ name)
|
|
|
|
(define (name . args)
|
2007-12-15 08:22:49 -05:00
|
|
|
(apply die 'name "not implemented" args))]))
|
2007-12-12 19:18:57 -05:00
|
|
|
|
2007-12-12 21:22:05 -05:00
|
|
|
(define-syntax u8?
|
|
|
|
(let ()
|
|
|
|
(import (ikarus system $fx))
|
|
|
|
(syntax-rules ()
|
|
|
|
[(_ x)
|
|
|
|
($fxzero? ($fxlogand x -256))])))
|
|
|
|
|
|
|
|
;(define (u8? x) (and (fixnum? x) (fx>= x 0) (fx< x 256)))
|
2007-12-12 18:59:19 -05:00
|
|
|
|
|
|
|
(define (textual-port? x)
|
|
|
|
(fx= (fxand ($port-tag x) textual-port-tag) textual-port-tag))
|
2007-12-05 05:33:31 -05:00
|
|
|
|
2007-12-12 18:59:19 -05:00
|
|
|
(define (binary-port? x)
|
|
|
|
(fx= (fxand ($port-tag x) binary-port-tag) binary-port-tag))
|
2007-12-10 10:18:52 -05:00
|
|
|
|
2007-12-12 18:59:19 -05:00
|
|
|
(define (output-port? x)
|
|
|
|
(fx= (fxand ($port-tag x) output-port-tag) output-port-tag))
|
2007-12-10 10:18:52 -05:00
|
|
|
|
2007-12-12 18:59:19 -05:00
|
|
|
(define (input-port? x)
|
|
|
|
(fx= (fxand ($port-tag x) input-port-tag) input-port-tag))
|
2007-12-10 10:18:52 -05:00
|
|
|
|
2007-12-12 18:59:19 -05:00
|
|
|
;;; everything above this line will turn into primitive
|
|
|
|
;;; ----------------------------------------------------------
|
|
|
|
|
2007-12-12 19:47:03 -05:00
|
|
|
(define input-port-tag #b00000000000001)
|
|
|
|
(define output-port-tag #b00000000000010)
|
|
|
|
(define textual-port-tag #b00000000000100)
|
|
|
|
(define binary-port-tag #b00000000001000)
|
|
|
|
(define fast-char-text-tag #b00000000010000)
|
|
|
|
(define fast-u7-text-tag #b00000000100000)
|
|
|
|
(define fast-u8-text-tag #b00000001100000)
|
2008-10-19 18:43:42 -04:00
|
|
|
(define fast-u16be-text-tag #b00000010000000)
|
|
|
|
(define fast-u16le-text-tag #b00000100000000)
|
2008-10-21 03:31:44 -04:00
|
|
|
(define init-u16-text-tag #b00000110000000)
|
2007-12-12 19:47:03 -05:00
|
|
|
(define r6rs-mode-tag #b01000000000000)
|
|
|
|
(define closed-port-tag #b10000000000000)
|
|
|
|
|
|
|
|
(define port-type-mask #b00000000001111)
|
|
|
|
(define binary-input-port-bits #b00000000001001)
|
|
|
|
(define binary-output-port-bits #b00000000001010)
|
|
|
|
(define textual-input-port-bits #b00000000000101)
|
|
|
|
(define textual-output-port-bits #b00000000000110)
|
|
|
|
|
|
|
|
(define fast-get-byte-tag #b00000000001001)
|
|
|
|
(define fast-get-char-tag #b00000000010101)
|
|
|
|
(define fast-get-utf8-tag #b00000000100101)
|
|
|
|
(define fast-get-latin-tag #b00000001100101)
|
2008-10-19 18:43:42 -04:00
|
|
|
(define fast-get-utf16be-tag #b00000010000101)
|
|
|
|
(define fast-get-utf16le-tag #b00000100000101)
|
2007-12-12 19:47:03 -05:00
|
|
|
|
|
|
|
(define fast-put-byte-tag #b00000000001010)
|
|
|
|
(define fast-put-char-tag #b00000000010110)
|
|
|
|
(define fast-put-utf8-tag #b00000000100110)
|
|
|
|
(define fast-put-latin-tag #b00000001100110)
|
2008-10-21 03:31:44 -04:00
|
|
|
(define fast-put-utf16be-tag #b00000010000110)
|
|
|
|
(define fast-put-utf16le-tag #b00000100000110)
|
|
|
|
(define init-put-utf16-tag #b00000110000110)
|
2007-12-10 10:18:52 -05:00
|
|
|
|
2008-10-19 18:43:42 -04:00
|
|
|
(define fast-attrs-mask #b111111111111)
|
2008-01-19 13:50:53 -05:00
|
|
|
(define-syntax $port-fast-attrs
|
|
|
|
(identifier-syntax
|
|
|
|
(lambda (x)
|
|
|
|
(import (ikarus system $fx))
|
|
|
|
($fxlogand ($port-tag x) fast-attrs-mask))))
|
2007-12-12 21:22:05 -05:00
|
|
|
|
2007-12-10 10:18:52 -05:00
|
|
|
(define (port-id p)
|
|
|
|
(if (port? p)
|
|
|
|
($port-id p)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die 'port-id "not a port" p)))
|
2007-12-10 10:18:52 -05:00
|
|
|
|
2007-12-18 17:25:48 -05:00
|
|
|
(define (input-port-byte-position p)
|
|
|
|
(if (input-port? p)
|
2008-06-18 00:05:01 -04:00
|
|
|
(let ([pos-vec ($port-position p)])
|
|
|
|
(+ (vector-ref pos-vec 0) (fx+ ($port-index p) 1)))
|
2007-12-18 17:25:48 -05:00
|
|
|
(error 'input-port-byte-position "not an input port" p)))
|
|
|
|
|
2008-06-20 00:49:24 -04:00
|
|
|
(define (port-position p)
|
|
|
|
(define who 'port-position)
|
|
|
|
(if (port? p)
|
|
|
|
(let ([pos-vec ($port-position p)]
|
|
|
|
[index ($port-index p)]
|
|
|
|
[get-position ($port-get-position p)])
|
|
|
|
(cond
|
|
|
|
[(procedure? get-position)
|
|
|
|
(let ([pos (get-position)])
|
|
|
|
(if (or (fixnum? pos) (bignum? pos))
|
2008-07-25 01:30:21 -04:00
|
|
|
(if (input-port? p)
|
|
|
|
(- pos (- ($port-size p) index))
|
|
|
|
(+ pos index))
|
|
|
|
(die who "invalid returned value from get-position" p)))]
|
2008-11-11 16:31:35 -05:00
|
|
|
[(eqv? get-position #t)
|
2008-06-20 00:49:24 -04:00
|
|
|
(+ (vector-ref pos-vec 0) index)]
|
|
|
|
[else
|
2008-11-11 16:31:35 -05:00
|
|
|
(die who "port does not support port-position operation" p)]))
|
2008-06-20 00:49:24 -04:00
|
|
|
(die who "not a port" p)))
|
|
|
|
|
2008-12-09 03:00:44 -05:00
|
|
|
|
|
|
|
(define (set-port-position! p pos)
|
|
|
|
(define who 'set-port-position!)
|
2008-12-09 03:41:59 -05:00
|
|
|
(define (set-position! p pos flush?)
|
2008-12-09 03:00:44 -05:00
|
|
|
(let ([setpos! ($port-set-position! p)])
|
2008-12-09 05:27:50 -05:00
|
|
|
(cond
|
|
|
|
[(procedure? setpos!)
|
|
|
|
(when flush? (flush-output-port p))
|
|
|
|
(setpos! pos)
|
|
|
|
($set-port-index! p 0)
|
|
|
|
($set-port-size! p 0)
|
|
|
|
(let ([pos-vec ($port-position p)])
|
|
|
|
(vector-set! pos-vec 0 pos))]
|
|
|
|
[(eqv? setpos! #t)
|
|
|
|
(if (<= pos ($port-size p))
|
|
|
|
($set-port-index! p pos)
|
|
|
|
(die who "position out of range" pos))]
|
|
|
|
[else
|
|
|
|
(die who "port does not support port position" p)])))
|
2008-12-09 03:00:44 -05:00
|
|
|
(unless (and (or (fixnum? pos) (bignum? pos)) (>= pos 0))
|
|
|
|
(die who "position must be a nonnegative exact integer" pos))
|
|
|
|
(cond
|
2008-12-09 03:41:59 -05:00
|
|
|
[(output-port? p) (set-position! p pos #t)]
|
|
|
|
[(input-port? p) (set-position! p pos #f)]
|
2008-12-09 03:00:44 -05:00
|
|
|
[else (die who "not a port" p)]))
|
|
|
|
|
|
|
|
|
2008-06-20 00:49:24 -04:00
|
|
|
(define (port-has-port-position? p)
|
|
|
|
(define who 'port-has-port-position?)
|
|
|
|
(if (port? p)
|
2008-11-11 16:31:35 -05:00
|
|
|
(and ($port-get-position p) #t)
|
2008-06-20 00:49:24 -04:00
|
|
|
(die who "not a port" p)))
|
2008-12-09 03:00:44 -05:00
|
|
|
|
|
|
|
(define (port-has-set-port-position!? p)
|
|
|
|
(define who 'port-has-set-port-position!?)
|
|
|
|
(if (port? p)
|
|
|
|
(and ($port-set-position! p) #t)
|
|
|
|
(die who "not a port" p)))
|
|
|
|
|
2008-12-09 02:06:46 -05:00
|
|
|
|
2007-12-12 01:32:55 -05:00
|
|
|
(define guarded-port
|
|
|
|
(let ([G (make-guardian)])
|
|
|
|
(define (clean-up)
|
|
|
|
(cond
|
|
|
|
[(G) =>
|
|
|
|
(lambda (p)
|
|
|
|
(close-port p)
|
|
|
|
(clean-up))]))
|
|
|
|
(lambda (p)
|
|
|
|
(clean-up)
|
2008-01-12 17:32:43 -05:00
|
|
|
(when (fixnum? ($port-cookie p))
|
2007-12-12 01:32:55 -05:00
|
|
|
(G p))
|
|
|
|
p)))
|
|
|
|
|
2007-12-11 03:25:51 -05:00
|
|
|
(define ($make-custom-binary-port attrs init-size id
|
2007-12-10 10:36:10 -05:00
|
|
|
read! write! get-position set-position! close buffer-size)
|
2007-12-06 05:05:26 -05:00
|
|
|
(let ([bv (make-bytevector buffer-size)])
|
2008-03-23 05:02:12 -04:00
|
|
|
($make-port attrs 0 init-size bv #f id read! write!
|
2008-06-20 00:49:24 -04:00
|
|
|
get-position set-position! close #f (vector 0))))
|
2007-12-06 05:05:26 -05:00
|
|
|
|
2007-12-11 03:25:51 -05:00
|
|
|
(define ($make-custom-textual-port attrs init-size id
|
2007-12-10 11:11:59 -05:00
|
|
|
read! write! get-position set-position! close buffer-size)
|
|
|
|
(let ([bv (make-string buffer-size)])
|
2008-03-23 05:02:12 -04:00
|
|
|
($make-port attrs 0 init-size bv #t id read! write!
|
2008-06-20 00:49:24 -04:00
|
|
|
get-position set-position! close #f (vector 0))))
|
2007-12-10 11:11:59 -05:00
|
|
|
|
2007-12-06 05:05:26 -05:00
|
|
|
(define (make-custom-binary-input-port id
|
|
|
|
read! get-position set-position! close)
|
|
|
|
;;; FIXME: get-position and set-position! are ignored for now
|
|
|
|
(define who 'make-custom-binary-input-port)
|
|
|
|
(unless (string? id)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "id is not a string" id))
|
2007-12-06 05:05:26 -05:00
|
|
|
(unless (procedure? read!)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "read! is not a procedure" read!))
|
2007-12-06 05:05:26 -05:00
|
|
|
(unless (or (procedure? close) (not close))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "close should be either a procedure or #f" close))
|
2008-06-20 00:49:24 -04:00
|
|
|
(unless (or (procedure? get-position)
|
|
|
|
(not get-position))
|
|
|
|
(die who "get-position is not a procedure or #f"
|
|
|
|
get-position))
|
2007-12-10 10:56:10 -05:00
|
|
|
($make-custom-binary-port
|
2007-12-12 18:59:19 -05:00
|
|
|
binary-input-port-bits
|
2007-12-11 03:25:51 -05:00
|
|
|
0
|
2008-06-20 00:49:24 -04:00
|
|
|
id read! #f
|
|
|
|
get-position
|
|
|
|
set-position!
|
|
|
|
close 256))
|
2007-12-10 10:36:10 -05:00
|
|
|
|
|
|
|
(define (make-custom-binary-output-port id
|
|
|
|
write! get-position set-position! close)
|
|
|
|
;;; FIXME: get-position and set-position! are ignored for now
|
|
|
|
(define who 'make-custom-binary-output-port)
|
|
|
|
(unless (string? id)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "id is not a string" id))
|
2007-12-10 10:36:10 -05:00
|
|
|
(unless (procedure? write!)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "write! is not a procedure" write!))
|
2007-12-10 10:36:10 -05:00
|
|
|
(unless (or (procedure? close) (not close))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "close should be either a procedure or #f" close))
|
2008-06-20 00:49:24 -04:00
|
|
|
(unless (or (procedure? get-position)
|
|
|
|
(not get-position))
|
|
|
|
(die who "get-position is not a procedure or #f"
|
|
|
|
get-position))
|
2007-12-10 10:53:17 -05:00
|
|
|
($make-custom-binary-port
|
2007-12-12 18:59:19 -05:00
|
|
|
binary-output-port-bits
|
2007-12-11 03:25:51 -05:00
|
|
|
256
|
2008-06-20 00:49:24 -04:00
|
|
|
id #f write!
|
|
|
|
get-position
|
|
|
|
set-position!
|
|
|
|
close 256))
|
2007-12-06 05:05:26 -05:00
|
|
|
|
2007-12-10 11:11:59 -05:00
|
|
|
(define (make-custom-textual-input-port id
|
|
|
|
read! get-position set-position! close)
|
|
|
|
;;; FIXME: get-position and set-position! are ignored for now
|
|
|
|
(define who 'make-custom-textual-input-port)
|
|
|
|
(unless (string? id)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "id is not a string" id))
|
2007-12-10 11:11:59 -05:00
|
|
|
(unless (procedure? read!)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "read! is not a procedure" read!))
|
2007-12-10 11:11:59 -05:00
|
|
|
(unless (or (procedure? close) (not close))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "close should be either a procedure or #f" close))
|
2008-06-20 00:49:24 -04:00
|
|
|
(unless (or (procedure? get-position)
|
|
|
|
(not get-position))
|
|
|
|
(die who "get-position is not a procedure or #f"
|
|
|
|
get-position))
|
2007-12-10 11:11:59 -05:00
|
|
|
($make-custom-textual-port
|
2007-12-14 19:42:00 -05:00
|
|
|
(fxior textual-input-port-bits fast-char-text-tag)
|
2007-12-11 03:25:51 -05:00
|
|
|
0
|
2007-12-10 11:11:59 -05:00
|
|
|
id read! #f get-position
|
|
|
|
set-position! close 256))
|
|
|
|
|
|
|
|
(define (make-custom-textual-output-port id
|
|
|
|
write! get-position set-position! close)
|
|
|
|
;;; FIXME: get-position and set-position! are ignored for now
|
|
|
|
(define who 'make-custom-textual-output-port)
|
|
|
|
(unless (string? id)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "id is not a string" id))
|
2007-12-10 11:11:59 -05:00
|
|
|
(unless (procedure? write!)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "write! is not a procedure" write!))
|
2007-12-10 11:11:59 -05:00
|
|
|
(unless (or (procedure? close) (not close))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "close should be either a procedure or #f" close))
|
2008-06-20 00:49:24 -04:00
|
|
|
(unless (or (procedure? get-position)
|
|
|
|
(not get-position))
|
|
|
|
(die who "get-position is not a procedure or #f"
|
|
|
|
get-position))
|
2007-12-10 11:11:59 -05:00
|
|
|
($make-custom-textual-port
|
2007-12-14 19:42:00 -05:00
|
|
|
(fxior textual-output-port-bits fast-char-text-tag)
|
2007-12-11 03:25:51 -05:00
|
|
|
256
|
2007-12-10 11:11:59 -05:00
|
|
|
id #f write! get-position
|
|
|
|
set-position! close 256))
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-01-22 03:30:52 -05:00
|
|
|
(define (input-transcoder-attrs x who)
|
2007-12-06 05:05:26 -05:00
|
|
|
(cond
|
2007-12-06 08:14:05 -05:00
|
|
|
[(not x) ;;; binary input port
|
2007-12-12 18:59:19 -05:00
|
|
|
binary-input-port-bits]
|
2008-01-22 03:30:52 -05:00
|
|
|
[(not (eq? 'none (transcoder-eol-style x)))
|
|
|
|
(die who "unsupported transcoder eol-style"
|
|
|
|
(transcoder-eol-style x))]
|
|
|
|
[(eq? 'latin-1-codec (transcoder-codec x))
|
2007-12-12 18:59:19 -05:00
|
|
|
(fxior textual-input-port-bits fast-u8-text-tag)]
|
2007-12-14 19:45:50 -05:00
|
|
|
;;; attrs for utf-8-codec are set as part of the
|
|
|
|
;;; bom-reading dance when the first char is read.
|
2007-12-12 18:59:19 -05:00
|
|
|
[else textual-input-port-bits]))
|
2007-12-06 05:05:26 -05:00
|
|
|
|
2008-01-22 03:30:52 -05:00
|
|
|
(define (output-transcoder-attrs x who)
|
2007-12-10 07:28:03 -05:00
|
|
|
(cond
|
|
|
|
[(not x) ;;; binary input port
|
2007-12-12 18:59:19 -05:00
|
|
|
binary-output-port-bits]
|
2008-01-22 03:30:52 -05:00
|
|
|
[(not (eq? 'none (transcoder-eol-style x)))
|
|
|
|
(die who "unsupported transcoder eol-style"
|
|
|
|
(transcoder-eol-style x))]
|
|
|
|
[(eq? 'latin-1-codec (transcoder-codec x))
|
2007-12-12 18:59:19 -05:00
|
|
|
(fxior textual-output-port-bits fast-u8-text-tag)]
|
2008-01-22 03:30:52 -05:00
|
|
|
[(eq? 'utf-8-codec (transcoder-codec x))
|
2007-12-12 18:59:19 -05:00
|
|
|
(fxior textual-output-port-bits fast-u7-text-tag)]
|
2008-10-21 03:31:44 -04:00
|
|
|
[(eq? 'utf-16-codec (transcoder-codec x))
|
2008-10-21 23:00:10 -04:00
|
|
|
(fxior textual-output-port-bits fast-u16be-text-tag)]
|
2008-07-30 20:28:33 -04:00
|
|
|
[else (die who "unsupported codec" (transcoder-codec x))]))
|
2007-12-06 05:05:26 -05:00
|
|
|
|
|
|
|
(define open-bytevector-input-port
|
|
|
|
(case-lambda
|
|
|
|
[(bv) (open-bytevector-input-port bv #f)]
|
|
|
|
[(bv maybe-transcoder)
|
|
|
|
(unless (bytevector? bv)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die 'open-bytevector-input-port
|
2007-12-06 05:05:26 -05:00
|
|
|
"not a bytevector" bv))
|
|
|
|
(when (and maybe-transcoder
|
2007-12-06 08:14:05 -05:00
|
|
|
(not (transcoder? maybe-transcoder)))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die 'open-bytevector-input-port
|
2007-12-06 05:05:26 -05:00
|
|
|
"not a transcoder" maybe-transcoder))
|
2007-12-12 19:18:57 -05:00
|
|
|
($make-port
|
2008-01-22 03:30:52 -05:00
|
|
|
(input-transcoder-attrs maybe-transcoder
|
|
|
|
'open-bytevector-output-port)
|
2007-12-12 19:59:10 -05:00
|
|
|
0 (bytevector-length bv) bv
|
2007-12-06 05:05:26 -05:00
|
|
|
maybe-transcoder
|
|
|
|
"*bytevector-input-port*"
|
|
|
|
(lambda (bv i c) 0) ;;; read!
|
|
|
|
#f ;;; write!
|
2008-11-11 16:31:35 -05:00
|
|
|
#t ;;; get-position
|
2008-12-09 05:27:50 -05:00
|
|
|
#t ;;; set-position!
|
2007-12-06 05:05:26 -05:00
|
|
|
#f ;;; close
|
2008-06-18 00:05:01 -04:00
|
|
|
#f
|
|
|
|
(vector 0))]))
|
2007-12-06 05:05:26 -05:00
|
|
|
|
2007-12-10 07:28:03 -05:00
|
|
|
(define open-bytevector-output-port
|
|
|
|
(case-lambda
|
|
|
|
[() (open-bytevector-output-port #f)]
|
|
|
|
[(transcoder)
|
|
|
|
(define who 'open-bytevector-output-port)
|
|
|
|
(unless (or (not transcoder) (transcoder? transcoder))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "invalid transcoder value" transcoder))
|
2007-12-10 07:28:03 -05:00
|
|
|
(let ([buf* '()] [buffer-size 256])
|
|
|
|
(let ([p
|
2007-12-12 19:18:57 -05:00
|
|
|
($make-port
|
2008-01-22 03:30:52 -05:00
|
|
|
(output-transcoder-attrs transcoder
|
|
|
|
'open-bytevector-output-port)
|
2007-12-12 19:59:10 -05:00
|
|
|
0 buffer-size (make-bytevector buffer-size)
|
2007-12-10 07:28:03 -05:00
|
|
|
transcoder
|
|
|
|
"*bytevector-output-port*"
|
|
|
|
#f
|
|
|
|
(lambda (bv i c)
|
|
|
|
(unless (= c 0)
|
|
|
|
(let ([x (make-bytevector c)])
|
|
|
|
(bytevector-copy! bv i x 0 c)
|
|
|
|
(set! buf* (cons x buf*))))
|
|
|
|
c)
|
2008-11-11 16:31:35 -05:00
|
|
|
#t ;;; get-position
|
|
|
|
#f ;;; set-position!
|
|
|
|
#f ;;; close
|
|
|
|
#f ;;; cookie
|
2008-06-18 00:05:01 -04:00
|
|
|
(vector 0))])
|
2007-12-10 07:28:03 -05:00
|
|
|
(values
|
|
|
|
p
|
|
|
|
(lambda ()
|
|
|
|
(define (append-bv-buf* ls)
|
|
|
|
(let f ([ls ls] [i 0])
|
|
|
|
(cond
|
|
|
|
[(null? ls)
|
|
|
|
(values (make-bytevector i) 0)]
|
|
|
|
[else
|
|
|
|
(let* ([a (car ls)]
|
|
|
|
[n (bytevector-length a)])
|
|
|
|
(let-values ([(bv i) (f (cdr ls) (fx+ i n))])
|
|
|
|
(bytevector-copy! a 0 bv i n)
|
|
|
|
(values bv (fx+ i n))))])))
|
|
|
|
(unless ($port-closed? p)
|
|
|
|
(flush-output-port p))
|
|
|
|
(let-values ([(bv len) (append-bv-buf* buf*)])
|
|
|
|
(set! buf* '())
|
|
|
|
bv)))))]))
|
|
|
|
|
|
|
|
(define call-with-bytevector-output-port
|
|
|
|
(case-lambda
|
|
|
|
[(proc) (call-with-bytevector-output-port proc #f)]
|
|
|
|
[(proc transcoder)
|
|
|
|
(define who 'call-with-bytevector-output-port)
|
|
|
|
(unless (procedure? proc)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "not a procedure" proc))
|
2007-12-10 07:28:03 -05:00
|
|
|
(unless (or (not transcoder) (transcoder? transcoder))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "invalid transcoder argument" transcoder))
|
2007-12-10 07:28:03 -05:00
|
|
|
(let-values ([(p extract)
|
|
|
|
(open-bytevector-output-port transcoder)])
|
|
|
|
(proc p)
|
|
|
|
(extract))]))
|
|
|
|
|
|
|
|
(define (call-with-string-output-port proc)
|
|
|
|
(define who 'call-with-string-output-port)
|
|
|
|
(unless (procedure? proc)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "not a procedure" proc))
|
2007-12-10 07:28:03 -05:00
|
|
|
(let-values ([(p extract) (open-string-output-port)])
|
|
|
|
(proc p)
|
|
|
|
(extract)))
|
2007-12-23 15:12:22 -05:00
|
|
|
|
|
|
|
(define (with-output-to-string proc)
|
|
|
|
(define who 'with-output-to-string)
|
|
|
|
(unless (procedure? proc)
|
|
|
|
(die who "not a procedure" proc))
|
|
|
|
(let-values ([(p extract) (open-string-output-port)])
|
2008-11-15 11:21:00 -05:00
|
|
|
(parameterize ([current-output-port p])
|
2007-12-23 15:12:22 -05:00
|
|
|
(proc))
|
|
|
|
(extract)))
|
2008-04-29 00:20:29 -04:00
|
|
|
|
|
|
|
(define (with-output-to-port p proc)
|
|
|
|
(define who 'with-output-to-port)
|
|
|
|
(unless (procedure? proc)
|
|
|
|
(die who "not a procedure" proc))
|
|
|
|
(unless (output-port? p)
|
|
|
|
(die who "not an output port" p))
|
|
|
|
(unless (textual-port? p)
|
|
|
|
(die who "not a textual port" p))
|
2008-11-15 11:21:00 -05:00
|
|
|
(parameterize ([current-output-port p])
|
2008-04-29 00:20:29 -04:00
|
|
|
(proc)))
|
|
|
|
|
2007-12-26 02:16:02 -05:00
|
|
|
(define-struct output-string-cookie (strings))
|
|
|
|
|
|
|
|
|
|
|
|
(define (open-output-string)
|
|
|
|
(define who 'open-output-string)
|
|
|
|
(let ([cookie (make-output-string-cookie '())]
|
|
|
|
[buffer-size 256])
|
|
|
|
($make-port
|
|
|
|
(fxior textual-output-port-bits fast-char-text-tag)
|
|
|
|
0 buffer-size (make-string buffer-size)
|
|
|
|
#t ;;; transcoder
|
|
|
|
"*string-output-port*"
|
|
|
|
#f
|
|
|
|
(lambda (str i c)
|
|
|
|
(unless (= c 0)
|
|
|
|
(let ([x (make-string c)])
|
|
|
|
(string-copy! str i x 0 c)
|
|
|
|
(set-output-string-cookie-strings! cookie
|
|
|
|
(cons x (output-string-cookie-strings cookie)))))
|
|
|
|
c)
|
2008-11-11 16:31:35 -05:00
|
|
|
#t ;;; get-position
|
|
|
|
#f ;;; set-position!
|
|
|
|
#f ;;; close!
|
2008-06-18 00:05:01 -04:00
|
|
|
cookie
|
|
|
|
(vector 0))))
|
2007-12-26 02:16:02 -05:00
|
|
|
|
2007-12-10 07:28:03 -05:00
|
|
|
(define (open-string-output-port)
|
2007-12-26 02:16:02 -05:00
|
|
|
(let ([p (open-output-string)])
|
|
|
|
(values
|
|
|
|
p
|
|
|
|
(lambda ()
|
|
|
|
(let ([str (get-output-string p)])
|
|
|
|
(set-output-string-cookie-strings! ($port-cookie p) '())
|
|
|
|
str)))))
|
|
|
|
|
|
|
|
(define (get-output-string-cookie-data cookie)
|
|
|
|
(define (append-str-buf* ls)
|
|
|
|
(let f ([ls ls] [i 0])
|
|
|
|
(cond
|
|
|
|
[(null? ls)
|
|
|
|
(values (make-string i) 0)]
|
|
|
|
[else
|
|
|
|
(let* ([a (car ls)]
|
|
|
|
[n (string-length a)])
|
|
|
|
(let-values ([(bv i) (f (cdr ls) (fx+ i n))])
|
|
|
|
(string-copy! a 0 bv i n)
|
|
|
|
(values bv (fx+ i n))))])))
|
|
|
|
(let ([buf* (output-string-cookie-strings cookie)])
|
|
|
|
(let-values ([(bv len) (append-str-buf* buf*)])
|
|
|
|
bv)))
|
|
|
|
|
|
|
|
(define (get-output-string p)
|
|
|
|
(if (port? p)
|
|
|
|
(let ([cookie ($port-cookie p)])
|
|
|
|
(cond
|
|
|
|
[(output-string-cookie? cookie)
|
|
|
|
(unless ($port-closed? p)
|
|
|
|
(flush-output-port p))
|
|
|
|
(get-output-string-cookie-data cookie)]
|
|
|
|
[else
|
|
|
|
(die 'get-output-string "not an output-string port" p)]))
|
|
|
|
(die 'get-output-string "not a port" p)))
|
2007-12-10 07:28:03 -05:00
|
|
|
|
2008-05-06 15:38:05 -04:00
|
|
|
|
|
|
|
|
|
|
|
(define (open-string-input-port/id str id)
|
2007-12-07 07:39:17 -05:00
|
|
|
(unless (string? str)
|
2008-01-23 02:17:25 -05:00
|
|
|
(die 'open-string-input-port "not a string" str))
|
2007-12-12 19:18:57 -05:00
|
|
|
($make-port
|
|
|
|
(fxior textual-input-port-bits fast-char-text-tag)
|
2007-12-12 19:59:10 -05:00
|
|
|
0 (string-length str) str
|
2007-12-11 17:41:48 -05:00
|
|
|
#t ;;; transcoder
|
2008-05-06 15:38:05 -04:00
|
|
|
id
|
2007-12-07 07:39:17 -05:00
|
|
|
(lambda (str i c) 0) ;;; read!
|
|
|
|
#f ;;; write!
|
2008-11-11 16:31:35 -05:00
|
|
|
#t ;;; get-position
|
2008-12-09 05:27:50 -05:00
|
|
|
#t ;;; set-position!
|
2007-12-07 07:39:17 -05:00
|
|
|
#f ;;; close
|
2008-11-11 16:31:35 -05:00
|
|
|
#f ;;; cookie
|
2008-06-18 00:05:01 -04:00
|
|
|
(vector 0)))
|
2008-05-06 15:38:05 -04:00
|
|
|
|
|
|
|
(define (open-string-input-port str)
|
|
|
|
(open-string-input-port/id str "*string-input-port*"))
|
2007-12-07 07:39:17 -05:00
|
|
|
|
2007-12-06 08:14:05 -05:00
|
|
|
(define (transcoded-port p transcoder)
|
|
|
|
(define who 'transcoded-port)
|
|
|
|
(unless (transcoder? transcoder)
|
2007-12-15 08:22:49 -05:00
|
|
|
(die who "not a transcoder" transcoder))
|
|
|
|
(unless (port? p) (die who "not a port" p))
|
|
|
|
(when ($port-transcoder p) (die who "not a binary port" p))
|
|
|
|
(when ($port-closed? p) (die who "cannot transcode closed port" p))
|
2007-12-06 08:14:05 -05:00
|
|
|
(let ([read! ($port-read! p)]
|
2007-12-12 19:34:28 -05:00
|
|
|
[write! ($port-write! p)])
|
|
|
|
($mark-port-closed! p)
|
2007-12-12 01:32:55 -05:00
|
|
|
(guarded-port
|
|
|
|
($make-port
|
|
|
|
(cond
|
2008-01-22 03:30:52 -05:00
|
|
|
[read! (input-transcoder-attrs transcoder
|
|
|
|
'transcoded-port)]
|
|
|
|
[write! (output-transcoder-attrs transcoder
|
|
|
|
'transcoded-port)]
|
2007-12-12 01:32:55 -05:00
|
|
|
[else
|
2007-12-15 08:22:49 -05:00
|
|
|
(die 'transcoded-port
|
2007-12-12 01:32:55 -05:00
|
|
|
"port is neither input nor output!")])
|
2007-12-12 19:18:57 -05:00
|
|
|
($port-index p)
|
|
|
|
($port-size p)
|
|
|
|
($port-buffer p)
|
|
|
|
transcoder
|
2007-12-12 01:32:55 -05:00
|
|
|
($port-id p)
|
|
|
|
read!
|
|
|
|
write!
|
|
|
|
($port-get-position p)
|
|
|
|
($port-set-position! p)
|
|
|
|
($port-close p)
|
2008-06-18 00:05:01 -04:00
|
|
|
($port-cookie p)
|
|
|
|
(vector 0)))))
|
2007-12-06 08:14:05 -05:00
|
|
|
|
2007-12-10 07:28:03 -05:00
|
|
|
(define (reset-input-port! p)
|
|
|
|
(if (input-port? p)
|
2008-04-02 20:28:45 -04:00
|
|
|
(begin
|
|
|
|
($set-port-index! p ($port-size p))
|
|
|
|
(unregister-callback p))
|
2007-12-15 08:22:49 -05:00
|
|
|
(die 'reset-input-port! "not an input port" p)))
|
2007-12-10 07:28:03 -05:00
|
|
|
|
2008-04-06 10:57:56 -04:00
|
|
|
(define (reset-output-port! p)
|
|
|
|
(if (output-port? p)
|
|
|
|
(begin
|
|
|
|
($set-port-index! p 0)
|
|
|
|
(unregister-callback p))
|
|
|
|
(die 'reset-output-port! "not an output port" p)))
|
|
|
|
|
|
|
|
|
2007-12-08 14:52:35 -05:00
|
|
|
(define (port-transcoder p)
|
|