
sizes of pathnames produced by expansion of tilde (home-directory) prefixes by replacing S_pathname, S_pathname_impl, and S_homedir with S_malloc_pathname, which always mallocs space for the result. one thread-safety issue involved the use of static strings for expanded pathnames and affected various file-system operations. the other affected the file open routines and involved use of the incoming pathname while deactivated. the incoming pathname is sometimes if not always a pointer into a Scheme bytevector, which can be overwritten if a collection occurs while the thread is deactivated. the size limitation corresponded to the use of the static strings, which were limited to PATH_MAX bytes. (PATH_MAX typically isn't actually the maximum path length in contemporary operating systems.) eliminated similar issues for wide pathnames under Windows by adding S_malloc_wide_pathname. consumers of the old routines have been modified to use the new routines and to free the result strings. the various file operations now consistently treat a pathname with an unresolvable home directory as a pathname that happens to start with a tilde. eliminated unused foreign-symbol binding of "(cs)pathname" to S_pathname. io.c, externs.h, new_io.c, prim5.c, scheme.c, prim.c - various places where a call to close or gzclose was retried when the close operation was interrupted no longer do so, since this can cause problems when another thread has reallocated the same file descriptor. new_io.c - now using vcvarsall type x86_amd64 rather than amd64 when the former appears to supported and the latter does not, as is the case with VS Express 2015. c/Mf-a6nt, c/Mf-ta6nt - commented out one of the thread mats that consistently causes indefinite delays under Windows and OpenBSD due to starvation. thread.ms - increased wait time for a couple of subprocess responses 6.ms - added call to collector to close files opened during iconv mats specifically for when mats are run under Windows with no iconv dll. io.ms original commit: ad44924307c576eb2fc92e7958afe8b615a7f48b
3478 lines
176 KiB
Scheme
3478 lines
176 KiB
Scheme
;;; 6.ms
|
||
;;; Copyright 1984-2016 Cisco Systems, Inc.
|
||
;;;
|
||
;;; Licensed under the Apache License, Version 2.0 (the "License");
|
||
;;; you may not use this file except in compliance with the License.
|
||
;;; You may obtain a copy of the License at
|
||
;;;
|
||
;;; http://www.apache.org/licenses/LICENSE-2.0
|
||
;;;
|
||
;;; Unless required by applicable law or agreed to in writing, software
|
||
;;; distributed under the License is distributed on an "AS IS" BASIS,
|
||
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
;;; See the License for the specific language governing permissions and
|
||
;;; limitations under the License.
|
||
|
||
;;; sections 6-1 and 6-2:
|
||
|
||
(mat current-input-port
|
||
(port? (current-input-port))
|
||
(input-port? (current-input-port))
|
||
(eq? (current-input-port) (console-input-port))
|
||
)
|
||
|
||
(mat current-output-port
|
||
(port? (current-output-port))
|
||
(output-port? (current-output-port))
|
||
(eq? (current-output-port) (console-output-port))
|
||
)
|
||
|
||
(mat port-operations
|
||
(error? (open-input-file "nonexistent file"))
|
||
(error? (open-input-file "nonexistent file" 'compressed))
|
||
(error? (open-output-file "/nonexistent/directory/nonexistent/file"))
|
||
(error? (open-output-file "/nonexistent/directory/nonexistent/file" 'replace))
|
||
(error? (open-input-output-file "/nonexistent/directory/nonexistent/file"))
|
||
(error? (open-input-output-file "/nonexistent/directory/nonexistent/file" 'truncate))
|
||
; the following several clauses test various open-output-file options
|
||
(let ([p (open-output-file "testfile.ss" 'truncate)])
|
||
(and (port? p) (output-port? p) (begin (close-output-port p) #t)))
|
||
(error? (open-output-file "testfile.ss"))
|
||
(error? (open-output-file "testfile.ss" 'error))
|
||
(let ([p (open-output-file "testfile.ss" 'replace)])
|
||
(and (port? p) (output-port? p) (begin (close-output-port p) #t)))
|
||
(let ([p (open-output-file "testfile.ss" 'truncate)])
|
||
(and (port? p) (output-port? p) (begin (close-output-port p) #t)))
|
||
(let ([p (open-output-file "testfile.ss" 'truncate)])
|
||
(display "\"hello" p)
|
||
(close-output-port p)
|
||
(let ([p (open-output-file "testfile.ss" 'append)])
|
||
(display " there\"" p)
|
||
(close-output-port p)
|
||
(let ([p (open-input-file "testfile.ss")])
|
||
(and (equal? (read p) "hello there")
|
||
(eof-object? (read p))
|
||
(begin (close-input-port p) #t)))))
|
||
; the following tests open-output-file, close-output-port, write,
|
||
; display, and newline---and builds testfile.ss for the next test
|
||
(let ([p (let loop () (if (file-exists? "testfile.ss")
|
||
(begin (delete-file "testfile.ss" #f) (loop))
|
||
(open-output-file "testfile.ss")))])
|
||
(for-each (lambda (x) (write x p) (display " " p))
|
||
'(a b c d e))
|
||
(newline p)
|
||
(close-output-port p)
|
||
#t)
|
||
; the following tests open-input-file, close-input-port, read,
|
||
; and eof-object?
|
||
(equal? (let ([p (open-input-file "testfile.ss")])
|
||
(let f ([x (read p)])
|
||
(if (eof-object? x)
|
||
(begin (close-input-port p) '())
|
||
(cons x (f (read p))))))
|
||
'(a b c d e))
|
||
; the following tests with-output-to-file, close-port,
|
||
; and write-char---and builds testfile.ss for the next test
|
||
(equal? (call-with-values
|
||
(lambda ()
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda ()
|
||
(for-each (lambda (c) (write-char c))
|
||
(string->list "a b c d e"))
|
||
(values 1 2 3))
|
||
'replace))
|
||
list)
|
||
'(1 2 3))
|
||
; the following tests with-input-from-file, close-port,
|
||
; read-char, unread-char, and eof-object?
|
||
(equal? (with-input-from-file "testfile.ss"
|
||
(lambda ()
|
||
(list->string
|
||
(let f ()
|
||
(let ([c (read-char)])
|
||
(if (eof-object? c)
|
||
'()
|
||
(begin (unread-char c)
|
||
(let ([c (read-char)])
|
||
(cons c (f))))))))))
|
||
"a b c d e")
|
||
; the following tests call-with-output-file, close-port,
|
||
; and write-char---and builds testfile.ss for the next test
|
||
(equal? (call-with-values
|
||
(lambda ()
|
||
(call-with-output-file "testfile.ss"
|
||
(lambda (p)
|
||
(for-each (lambda (c) (write-char c p))
|
||
(string->list "a b c d e"))
|
||
(close-port p)
|
||
(values 1 2 3))
|
||
'replace))
|
||
list)
|
||
'(1 2 3))
|
||
; the following tests call-with-input-file, close-port,
|
||
; read-char, unread-char, and eof-object?
|
||
(equal? (call-with-input-file "testfile.ss"
|
||
(lambda (p)
|
||
(list->string
|
||
(let f ()
|
||
(let ([c (read-char p)])
|
||
(if (eof-object? c)
|
||
(begin (close-port p) '())
|
||
(begin (unread-char c p)
|
||
(let ([c (read-char p)])
|
||
(cons c (f))))))))))
|
||
"a b c d e")
|
||
; the following tests call-with-input-file, close-port,
|
||
; read-char, unread-char, and eof-object?
|
||
(equal? (call-with-values
|
||
(lambda ()
|
||
(call-with-input-file "testfile.ss"
|
||
(lambda (p)
|
||
(apply values
|
||
(let f ()
|
||
(let ([c (read-char p)])
|
||
(if (eof-object? c)
|
||
(begin (close-port p) '())
|
||
(begin (unread-char c p)
|
||
(let ([c (read-char p)])
|
||
(cons c (f)))))))))))
|
||
(lambda ls (list->string ls)))
|
||
"a b c d e")
|
||
; the following tests call-with-input-file, close-input-port,
|
||
; read-char, peek-char, and eof-object?
|
||
(equal? (call-with-input-file "testfile.ss"
|
||
(lambda (p)
|
||
(list->string
|
||
(let f ()
|
||
(let ([c (peek-char p)])
|
||
(if (eof-object? c)
|
||
(begin (close-input-port p) '())
|
||
(let ([c (read-char p)])
|
||
(cons c (f)))))))))
|
||
"a b c d e")
|
||
; test various errors related to input ports
|
||
(begin (set! ip (open-input-file "testfile.ss"))
|
||
(and (port? ip) (input-port? ip)))
|
||
(error? (unread-char #\a ip))
|
||
(eqv? (read-char ip) #\a)
|
||
(begin (unread-char #\a ip) (eqv? (read-char ip) #\a))
|
||
(begin (clear-input-port ip) #t)
|
||
(error? (unread-char #\a ip))
|
||
(error? (write-char #\a ip))
|
||
(error? (write 'a ip))
|
||
(error? (display 'a ip))
|
||
(error? (newline ip))
|
||
(error? (fprintf ip "hi"))
|
||
(error? (flush-output-port ip))
|
||
(error? (clear-output-port ip))
|
||
(begin (close-input-port ip) #t)
|
||
(error? (read-char ip))
|
||
(error? (read ip))
|
||
(error? (char-ready? ip))
|
||
; test various errors related to output ports
|
||
(begin (set! op (open-output-file "testfile.ss" 'replace))
|
||
(and (port? op) (output-port? op)))
|
||
(error? (char-ready? op))
|
||
(error? (peek-char op))
|
||
(error? (read-char op))
|
||
(error? (unread-char #\a op))
|
||
(error? (read op))
|
||
(error? (clear-input-port op))
|
||
(begin (close-output-port op) #t)
|
||
(error? (write-char #\a op))
|
||
(error? (write 'a op))
|
||
(error? (display 'a op))
|
||
(error? (newline op))
|
||
(error? (fprintf op "hi"))
|
||
(error? (flush-output-port op))
|
||
(error? (clear-output-port op))
|
||
(error? (current-output-port 'a))
|
||
(error? (current-input-port 'a))
|
||
(begin (current-output-port (console-output-port)) #t)
|
||
(begin (current-input-port (console-input-port)) #t)
|
||
|
||
; the following tests open-input-string, open-output-string, read-char,
|
||
; eof-object?, unread-char, write-char, and get-ouptut-string
|
||
(let ([s "hi there, mom!"])
|
||
(let ([ip (open-input-string s)] [op (open-output-string)])
|
||
(do ([c (read-char ip) (read-char ip)])
|
||
((eof-object? c)
|
||
(equal? (get-output-string op) s))
|
||
(unread-char c ip)
|
||
(write-char (read-char ip) op))))
|
||
|
||
(error? (with-input-from-string))
|
||
(error? (with-input-from-string "a"))
|
||
(error? (with-input-from-string 'a (lambda () 3)))
|
||
(error? (with-input-from-string "a" 'foo))
|
||
(error? (with-input-from-string (lambda () 3) "a"))
|
||
(error? (with-input-from-string '(this too?) values))
|
||
(error? (with-input-from-string "a" (lambda () 3) 'compressed))
|
||
(error? (with-output-to-string))
|
||
(error? (with-output-to-string "a"))
|
||
(error? (with-output-to-string 'a (lambda () 3)))
|
||
(error? (with-output-to-string '(this too?)))
|
||
(error? (eof-object #!eof))
|
||
(eq? (with-input-from-string "" read) #!eof)
|
||
(eq? (with-input-from-string "" read) (eof-object))
|
||
(eq? (eof-object) #!eof)
|
||
(error? (with-input-from-string "'" read))
|
||
; the following tests with-input-from-string, with-output-to-string,
|
||
; read-char, eof-object?, unread-char, and write-char
|
||
(let ([s "hi there, mom!"])
|
||
(equal?
|
||
(with-input-from-string s
|
||
(lambda ()
|
||
(with-output-to-string
|
||
(lambda ()
|
||
(do ([c (read-char) (read-char)])
|
||
((eof-object? c))
|
||
(unread-char c)
|
||
(write-char (read-char)))))))
|
||
s))
|
||
|
||
; the following makes sure that call-with-{in,out}put-file close the
|
||
; port (from Dave Boyer)---at least on systems which restrict the
|
||
; number of open ports to less than 20
|
||
(let loop ((i 20))
|
||
(or (zero? i)
|
||
(begin (call-with-output-file "testfile.ss"
|
||
(lambda (p) (write i p))
|
||
'replace)
|
||
(and (eq? (call-with-input-file "testfile.ss"
|
||
(lambda (p) (read p)))
|
||
i)
|
||
(loop (- i 1))))))
|
||
|
||
; test source information in error messages from read
|
||
(error?
|
||
(begin
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display "(cons 1 2 . 3 4)"))
|
||
'replace)
|
||
(let ([ip (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (read ip))
|
||
(lambda () (close-input-port ip))))))
|
||
|
||
; test source information in error messages from read
|
||
(error?
|
||
(begin
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display "(cons 1 2 ] 3 4)"))
|
||
'replace)
|
||
(let ([ip (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (read ip))
|
||
(lambda () (close-input-port ip))))))
|
||
)
|
||
|
||
(mat port-operations1
|
||
(error? (open-input-output-file))
|
||
(error? (open-input-output-file 'furball))
|
||
(error? (open-input-output-file "/probably/not/a/good/path"))
|
||
(error? (open-input-output-file "testfile.ss" 'compressed))
|
||
(error? (open-input-output-file "testfile.ss" 'uncompressed))
|
||
(begin
|
||
(define $ppp (open-input-output-file "testfile.ss"))
|
||
(and (input-port? $ppp) (output-port? $ppp) (port? $ppp)))
|
||
(error? (truncate-file $ppp -3))
|
||
(error? (truncate-file $ppp 'all-the-way))
|
||
(eof-object?
|
||
(begin
|
||
(truncate-file $ppp)
|
||
(display "hello" $ppp)
|
||
(flush-output-port $ppp)
|
||
(read $ppp)))
|
||
(eq? (begin (file-position $ppp 0) (read $ppp)) 'hello)
|
||
(eqv? (begin
|
||
(display "goodbye\n" $ppp)
|
||
(truncate-file $ppp 9)
|
||
(file-position $ppp))
|
||
9)
|
||
(eof-object? (read $ppp))
|
||
(eqv? (begin (file-position $ppp 0) (file-position $ppp)) 0)
|
||
(eq? (read $ppp) 'hellogood)
|
||
(eqv? (begin
|
||
(display "byebye\n" $ppp)
|
||
(truncate-file $ppp 0)
|
||
(file-position $ppp))
|
||
0)
|
||
(eof-object? (read $ppp))
|
||
(eof-object?
|
||
(begin
|
||
(close-port $ppp)
|
||
(let ([ip (open-input-file "testfile.ss")])
|
||
(let ([c (read-char ip)])
|
||
(close-input-port ip)
|
||
c))))
|
||
(error?
|
||
(let ([ip (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (truncate-file ip))
|
||
(lambda () (close-input-port ip)))))
|
||
(error? (truncate-file 'animal-crackers))
|
||
(error? (truncate-file))
|
||
(error? (truncate-file $ppp))
|
||
(let ([op (open-output-string)])
|
||
(and (= (file-position op) 0)
|
||
(= (file-length op) 0)
|
||
(begin (fresh-line op) #t)
|
||
(= (file-length op) 0)
|
||
(= (file-position op) 0)
|
||
(do ([i 4000 (fx- i 1)])
|
||
((fx= i 0) #t)
|
||
(display "hello" op))
|
||
(= (file-length op) 20000)
|
||
(= (file-position op) 20000)
|
||
(begin (file-position op 5000) #t)
|
||
(= (file-position op) 5000)
|
||
(= (file-length op) 20000)
|
||
(begin (truncate-file op) #t)
|
||
(= (file-length op) 0)
|
||
(= (file-position op) 0)
|
||
(begin (truncate-file op 17) #t)
|
||
(= (file-length op) 17)
|
||
(= (file-position op) 17)
|
||
(begin (display "okay" op) #t)
|
||
(= (file-length op) 21)
|
||
(= (file-position op) 21)
|
||
(equal? (substring (get-output-string op) 17 21) "okay")
|
||
(= (file-length op) 0)
|
||
(= (file-position op) 0)
|
||
(begin (fresh-line op) #t)
|
||
(= (file-length op) 0)
|
||
(= (file-position op) 0)
|
||
(begin
|
||
(write-char #\a op)
|
||
(fresh-line op)
|
||
#t)
|
||
(= (file-position op) 2)
|
||
(begin (fresh-line op) #t)
|
||
(= (file-position op) 2)
|
||
(equal? (get-output-string op) "a\n")))
|
||
(let ([ip (open-input-string "beam me up, scotty!")]
|
||
[s (make-string 10)])
|
||
(and (= (file-position ip) 0)
|
||
(= (file-length ip) 19)
|
||
(not (eof-object? (peek-char ip)))
|
||
(equal? (read ip) 'beam)
|
||
(= (file-position ip) 4)
|
||
(not (eof-object? (peek-char ip)))
|
||
(equal? (block-read ip s 10) 10)
|
||
(equal? s " me up, sc")
|
||
(= (file-position ip) 14)
|
||
(equal? (block-read ip s 10) 5)
|
||
(equal? s "otty!p, sc")
|
||
(= (file-position ip) 19)
|
||
(eof-object? (peek-char ip))
|
||
(eof-object? (read-char ip))
|
||
(eof-object? (block-read ip s 10))
|
||
(eof-object? (block-read ip s 0))
|
||
(begin
|
||
(file-position ip 10)
|
||
(= (file-position ip) 10))
|
||
(equal? (block-read ip s 10) 9)
|
||
(equal? s ", scotty!c")))
|
||
(error? ; unhandled message
|
||
(get-output-string (open-input-string "oops")))
|
||
(error? ; unhandled message
|
||
(let ([op (open-output-file "testfile.ss" 'replace)])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (get-output-string op))
|
||
(lambda () (close-output-port op)))))
|
||
)
|
||
|
||
(mat compression
|
||
(let ()
|
||
(define cp
|
||
(lambda (mode src dst)
|
||
(define buf-size 4096)
|
||
(let ([buf (make-string buf-size)])
|
||
(call-with-output-file dst
|
||
(lambda (op)
|
||
(call-with-input-file src
|
||
(lambda (ip)
|
||
(let lp ()
|
||
(let ([n (block-read ip buf buf-size)])
|
||
(unless (eof-object? n) (block-write op buf n) (lp)))))))
|
||
mode))))
|
||
(define cmp
|
||
(lambda (mode1 src1 mode2 src2)
|
||
(define buf-size 4096)
|
||
(let ([buf1 (make-string buf-size)]
|
||
[buf2 (make-string buf-size)])
|
||
(call-with-input-file src1
|
||
(lambda (ip1)
|
||
(call-with-input-file src2
|
||
(lambda (ip2)
|
||
(let lp ()
|
||
(let ([n1 (block-read ip1 buf1 buf-size)]
|
||
[n2 (block-read ip2 buf2 buf-size)])
|
||
(if (eof-object? n1)
|
||
(eof-object? n2)
|
||
(and (eqv? n1 n2)
|
||
(string=? (substring buf1 0 n1)
|
||
(substring buf2 0 n2))
|
||
(lp))))))
|
||
mode2))
|
||
mode1))))
|
||
(and
|
||
(cmp '() "prettytest.ss" '() "prettytest.ss")
|
||
(cmp '(compressed) "prettytest.ss" '() "prettytest.ss")
|
||
(cmp '() "prettytest.ss" '(compressed) "prettytest.ss")
|
||
(cmp '(compressed) "prettytest.ss" '(compressed) "prettytest.ss")
|
||
(begin
|
||
(cp '(replace compressed) "prettytest.ss" "testfile.ss")
|
||
#t)
|
||
(cmp '(compressed) "testfile.ss" '() "prettytest.ss")
|
||
(not (= (call-with-input-file "testfile.ss" file-length) (call-with-input-file "prettytest.ss" file-length)))
|
||
; the following test could cause an error with anything but latin-1 codec
|
||
#;(not (cmp '() "testfile.ss" '() "prettytest.ss"))
|
||
(begin
|
||
(cp '(compressed append) "prettytest.ss" "testfile.ss")
|
||
#t)
|
||
(not (cmp '(compressed) "testfile.ss" '() "prettytest.ss"))
|
||
))
|
||
(error? (open-output-file "testfile.ss" '(replace append)))
|
||
(error? (open-output-file "testfile.ss" '(append truncate)))
|
||
; test workaround for bogus gzclose error return for empty input files
|
||
(and
|
||
(eqv? (with-output-to-file "testfile.ss" void 'replace) (void))
|
||
(eof-object? (with-input-from-file "testfile.ss" read 'compressed)))
|
||
)
|
||
|
||
(mat read-comment
|
||
(equal? '; this is the first comment
|
||
(a ; second comment
|
||
#;(third ; comment in comment
|
||
comment #;(comment #1=e in
|
||
. #;(comment in comment in comment)
|
||
comment)) b ; fourth comment
|
||
c #| fifth comment #| more
|
||
nesting here |# |# d
|
||
; sixth and final comment
|
||
#1#)
|
||
'(a b c d e))
|
||
(equal? (read (open-input-string "; this is the first comment
|
||
(a ; second comment
|
||
#;(third ; comment in comment
|
||
comment #;(comment #1=e in
|
||
. #;(comment in comment in comment)
|
||
comment)) b ; fourth comment
|
||
c #| fifth comment #| more
|
||
nesting here |# |# d
|
||
; sixth and final comment
|
||
#1#)"))
|
||
'(a b c d e))
|
||
(equal? (read (open-input-string "(#|##|# |#|#1
|
||
#||#2
|
||
#|||#3
|
||
#|#||#|#4
|
||
#|| hello ||#5
|
||
#| ; rats |#)"))
|
||
'(1 2 3 4 5))
|
||
)
|
||
|
||
(mat read-graph
|
||
(begin
|
||
(define read-test-graph
|
||
(case-lambda
|
||
[(s) (read-test-graph s s)]
|
||
[(s1 s2)
|
||
(string=?
|
||
(parameterize ((print-graph #t))
|
||
(format "~s" (read (open-input-string s1))))
|
||
s2)]))
|
||
#t)
|
||
(error? ; verify that the error message is NOT "invalid memory reference"
|
||
(let ((ip (open-input-string "(cons 0 #0#)")))
|
||
((#%$make-read ip #t #f) #t)))
|
||
(let ()
|
||
(define-record foo ((immutable x) (immutable y)))
|
||
(record-reader 'foo (record-rtd (make-foo 3 4)))
|
||
(and
|
||
(read-test-graph "#0=#[foo (#0#) 0]")
|
||
(read-test-graph "#0=(#[foo #0# 0])")
|
||
(read-test-graph "#[foo #0=(a b c) #0#]")))
|
||
(error? (read-test-graph "#0=#[foo #0# #0#]"))
|
||
(read-test-graph "#(123 #[foo #0=(a b c) #0#])")
|
||
(read-test-graph "#(#0=#[foo #1=(a b c) #1#] 0 #0#)")
|
||
(read-test-graph "#(#1# 0 #1=#[foo #0=(a b c) #0#])"
|
||
"#(#0=#[foo #1=(a b c) #1#] 0 #0#)")
|
||
(read-test-graph "#(123 #0=(#0#))")
|
||
(read-test-graph "#(123 #0=(#0#))")
|
||
(let ()
|
||
(define-record r1 ((mutable a) (immutable b)))
|
||
(define-record r2 ((immutable a)))
|
||
(let* ((x2 (make-r2 (make-r1 '* '(a b c)))) (x1 (r2-a x2)))
|
||
(set-r1-a! x1 x2)
|
||
(record-reader 'r1 (record-rtd (make-r1 3 4)))
|
||
(record-reader 'r2 (record-rtd (make-r2 3)))
|
||
(read-test-graph
|
||
(parameterize ((print-graph #t))
|
||
(format "~s" (list (r1-b x1) x1))))))
|
||
(read-test-graph "(#0=(a b c) #1=#[r1 #[r2 #1#] #0#])")
|
||
)
|
||
|
||
(mat block-io
|
||
; test block-write and build testfile.ss for the following test
|
||
(let ([p (open-output-file "testfile.ss" 'truncate)])
|
||
(block-write p "hi there")
|
||
(display " mom" p)
|
||
(block-write p ", how are you?xxxx" (string-length ", how are you?"))
|
||
(newline p)
|
||
(let ([s (make-string 100 #\X)])
|
||
(string-set! s 99 #\newline)
|
||
(let ([s (apply string-append (make-list 10 s))])
|
||
(let ([s (apply string-append (make-list 10 s))])
|
||
(block-write p s)
|
||
(block-write p s 5000))))
|
||
(close-output-port p)
|
||
#t)
|
||
; test block-read
|
||
(let ([random-read-up
|
||
(lambda (p n)
|
||
(let f ([n n] [ls '()])
|
||
(if (fx= n 0)
|
||
(apply string-append (reverse ls))
|
||
(if (fxodd? n)
|
||
(f (- n 1) (cons (string (read-char p)) ls))
|
||
(let ([s (make-string (random (fx+ n 1)))])
|
||
(let ([i (if (fx= (random 2) 0)
|
||
(block-read p s)
|
||
(block-read p s (string-length s)))])
|
||
(f (- n i) (cons (substring s 0 i) ls))))))))])
|
||
(let ([s (make-string 100 #\X)])
|
||
(string-set! s 99 #\newline)
|
||
(let ([s (apply string-append (make-list 10 s))])
|
||
(let ([s (apply string-append (make-list 10 s))])
|
||
(let ([s (string-append "hi there mom, how are you?"
|
||
(string #\newline)
|
||
s
|
||
(substring s 0 5000))])
|
||
(let ([p (open-input-file "testfile.ss")])
|
||
(let ([t (random-read-up p (string-length s))])
|
||
(and (eof-object? (read-char p))
|
||
(string=? t s)
|
||
(eqv? (close-input-port p) (void))))))))))
|
||
; test for bug: block-read complained when handler returned eof
|
||
(eof-object?
|
||
(let ((p (make-input-port (lambda args #!eof) "")))
|
||
(block-read p (make-string 100))))
|
||
)
|
||
|
||
(mat file-length-and-file-position
|
||
(procedure? file-length)
|
||
(procedure? file-position)
|
||
(let ([s "hi there"])
|
||
(let ([n (string-length s)]
|
||
[p (open-output-file "testfile.ss" 'replace)])
|
||
(and (eqv? (file-length p) 0)
|
||
(begin (display s p)
|
||
(= (file-position p) (file-length p) n))
|
||
(begin (display #\space p)
|
||
(= (file-position p) (file-length p) (+ n 1)))
|
||
(eqv? (file-position p 1) (void))
|
||
(write-char #\o p)
|
||
(eqv? (file-position p 2000) (void))
|
||
(begin (display s p)
|
||
(= (file-length p) (file-position p) (+ 2000 n)))
|
||
(eqv? (close-output-port p) (void)))))
|
||
;;; no error is reported, which isn't serious
|
||
; (error? (file-position (open-input-file "testfile.ss") 10000))
|
||
(error?
|
||
(let ((p (open-input-file "testfile.ss")))
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (file-position p -1))
|
||
(lambda () (close-input-port p)))))
|
||
(guard (c [(i/o-invalid-position-error? c)])
|
||
(let ([p (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
void
|
||
(lambda ()
|
||
(file-position p (if (fixnum? (expt 2 32)) (- (expt 2 63) 1) (- (expt 2 31) 1)))
|
||
#t)
|
||
(lambda () (close-input-port p)))))
|
||
(error?
|
||
(let ([p (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (file-position p (expt 2 64)))
|
||
(lambda () (close-input-port p)))))
|
||
(error? (file-position 1))
|
||
(error? (file-length 1))
|
||
(let ([s "hi there"])
|
||
(let ([n (string-length s)] [p (open-input-file "testfile.ss")])
|
||
(and (eqv? (file-length p) (+ 2000 n))
|
||
(eq? (read p) 'ho)
|
||
(eq? (read p) 'there)
|
||
(eqv? (file-position p) n)
|
||
(eqv? (file-position p 2000) (void))
|
||
(eq? (read p) 'hi)
|
||
(eq? (read p) 'there)
|
||
(= (file-position p) (file-length p) (+ 2000 n))
|
||
(eqv? (close-input-port p) (void)))))
|
||
)
|
||
|
||
(mat string-port-file-position
|
||
(let ([ip (open-input-string "hit me")])
|
||
(and (eq? (read ip) 'hit)
|
||
(eq? (file-position ip) 3)
|
||
(begin
|
||
(file-position ip 1)
|
||
(eq? (read ip) 'it))
|
||
(begin
|
||
(file-position ip 6)
|
||
(eof-object? (read ip)))
|
||
(begin
|
||
(file-position ip 0)
|
||
(eq? (read ip) 'hit))))
|
||
(error? (file-position (open-input-string "hi") 3))
|
||
(error? (file-position (open-input-string "hi") -1))
|
||
(let ()
|
||
(define f
|
||
(lambda (n)
|
||
(let ([op (open-output-string)])
|
||
(and (begin
|
||
(write 'ab op)
|
||
(eq? (file-position op) 2))
|
||
(begin
|
||
(file-position op 4)
|
||
(write 'ef op)
|
||
(eq? (file-position op) 6))
|
||
(begin
|
||
(file-position op 2)
|
||
(write 'cd op)
|
||
(eq? (file-position op) 4))
|
||
(begin
|
||
(set-port-length! op n)
|
||
(get-output-string op))))))
|
||
(and (equal? (f 6) "abcdef")
|
||
(equal? (f 4) "abcd")
|
||
(equal? (f 2) "ab")
|
||
(equal? (f 0) "")
|
||
(equal? (f 5) "abcde")
|
||
(let ((s (f 2000)))
|
||
(and s (= (string-length s) 2000)))))
|
||
(error? (file-position (open-output-string) -1))
|
||
)
|
||
|
||
(mat fresh-line
|
||
(procedure? fresh-line)
|
||
(error? (fresh-line 3))
|
||
(error? (fresh-line (open-input-string "hello")))
|
||
(equal?
|
||
(with-output-to-string
|
||
(lambda ()
|
||
(fresh-line)
|
||
(fresh-line)
|
||
(display "hello")
|
||
(fresh-line)
|
||
(fresh-line)))
|
||
"hello\n")
|
||
(begin
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda ()
|
||
(fresh-line)
|
||
(fresh-line)
|
||
(display "hello")
|
||
(fresh-line)
|
||
(fresh-line))
|
||
'replace)
|
||
#t)
|
||
(call-with-input-file "testfile.ss"
|
||
(lambda (p)
|
||
(let ([s (make-string 100)])
|
||
(and
|
||
(= (block-read p s (string-length s)) 6)
|
||
(string=? (substring s 0 6) "hello\n")
|
||
(eof-object? (read-char p))))))
|
||
(begin
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda ()
|
||
(write-char #\a)
|
||
(fresh-line)
|
||
(flush-output-port)
|
||
(set-port-bol! (current-output-port) #f)
|
||
(fresh-line)
|
||
(write-char #\b)
|
||
(flush-output-port)
|
||
(set-port-bol! (current-output-port) #t)
|
||
(fresh-line)
|
||
(fresh-line)
|
||
(write-char #\c)
|
||
(fresh-line)
|
||
(fresh-line))
|
||
'replace)
|
||
#t)
|
||
(call-with-input-file "testfile.ss"
|
||
(lambda (p)
|
||
(let ([s (make-string 100)])
|
||
(and
|
||
(= (block-read p s (string-length s)) 6)
|
||
(string=? (substring s 0 6) "a\n\nbc\n")
|
||
(eof-object? (read-char p))))))
|
||
)
|
||
|
||
(mat char-ready?
|
||
(procedure? char-ready?)
|
||
(let ([x (open-input-string "a")])
|
||
(and (char-ready? x)
|
||
(eqv? (read-char x) #\a)
|
||
(char-ready? x)
|
||
(eof-object? (read-char x))))
|
||
)
|
||
|
||
(mat clear-input-port ; test interactively
|
||
(procedure? clear-input-port)
|
||
)
|
||
|
||
;;; pretty-equal? is like equal? except that it considers gensyms
|
||
;;; with equal print names to be equal and any two nans to be equal.
|
||
(define pretty-equal?
|
||
(rec equal?
|
||
(lambda (x y) ; mostly snarfed from 5_1.ss
|
||
(or (cond
|
||
[(eq? x y) #t]
|
||
[(pair? x)
|
||
(and (pair? y)
|
||
(equal? (car x) (car y))
|
||
(equal? (cdr x) (cdr y)))]
|
||
[(symbol? x)
|
||
(and (gensym? x)
|
||
(gensym? y)
|
||
(string=? (symbol->string x) (symbol->string y)))]
|
||
[(or (null? x) (null? y)) #f]
|
||
[(or (char? x) (char? y)) #f]
|
||
[(flonum? x)
|
||
(and (flonum? y)
|
||
(or (let ([nan? (lambda (x) (not (fl= x x)))])
|
||
(and (nan? x) (nan? y)))
|
||
(fl= x y)))]
|
||
[(number? x)
|
||
(and (number? y)
|
||
(if (exact? x)
|
||
(and (exact? y) (= x y))
|
||
(and (equal? (real-part x) (real-part y))
|
||
(equal? (imag-part x) (imag-part y)))))]
|
||
[(string? x) (and (string? y) (string=? x y))]
|
||
[(box? x) (and (box? y) (equal? (unbox x) (unbox y)))]
|
||
[(vector? x)
|
||
(and (vector? y)
|
||
(= (vector-length x) (vector-length y))
|
||
(let f ([i (- (vector-length x) 1)])
|
||
(or (< i 0)
|
||
(and (equal? (vector-ref x i) (vector-ref y i))
|
||
(f (1- i))))))]
|
||
[(fxvector? x)
|
||
(and (fxvector? y)
|
||
(= (fxvector-length x) (fxvector-length y))
|
||
(let f ([i (- (fxvector-length x) 1)])
|
||
(or (< i 0)
|
||
(and (fx= (fxvector-ref x i) (fxvector-ref y i))
|
||
(f (1- i))))))]
|
||
[(bytevector? x)
|
||
(and (bytevector? y)
|
||
(bytevector=? x y))]
|
||
[else #f])
|
||
(parameterize ([print-length 6] [print-level 3])
|
||
(display "----------------------\n")
|
||
(pretty-print x)
|
||
(pretty-print '=/=)
|
||
(pretty-print y)
|
||
(display "----------------------\n")
|
||
#f)))))
|
||
|
||
(mat pretty-print
|
||
(let ([pretty-copy
|
||
(lambda (ifn ofn)
|
||
(let ([ip (open-input-file ifn)]
|
||
[op (open-output-file ofn 'replace)])
|
||
(dynamic-wind
|
||
(lambda () #f)
|
||
(rec loop
|
||
(lambda ()
|
||
(let ([x (read ip)])
|
||
(or (eof-object? x)
|
||
(parameterize ([print-unicode #f])
|
||
(pretty-print x op)
|
||
(newline op)
|
||
(loop))))))
|
||
(lambda ()
|
||
(close-input-port ip)
|
||
(close-output-port op)))))])
|
||
(pretty-copy "prettytest.ss" "testfile.ss"))
|
||
(let ([p1 (open-input-file "prettytest.ss")]
|
||
[p2 (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
(lambda () #f)
|
||
(rec loop
|
||
(lambda ()
|
||
(let ([x1 (read p1)] [x2 (read p2)])
|
||
(unless (pretty-equal? x1 x2)
|
||
(errorf 'pretty-equal "~s is not equal to ~s" x1 x2))
|
||
(or (eof-object? x1) (loop)))))
|
||
(lambda ()
|
||
(close-input-port p1)
|
||
(close-input-port p2))))
|
||
(error? (pretty-format))
|
||
(error? (pretty-format 'foo 'x 'x))
|
||
(error? (pretty-format 3 'x))
|
||
(error? (pretty-format 'foo '(bad 0 ... ... 0 format)))
|
||
(list? (pretty-format 'let))
|
||
(let ([x (pretty-format 'let)])
|
||
(pretty-format 'let x)
|
||
(equal? x (pretty-format 'let)))
|
||
(string=?
|
||
(parameterize ([pretty-standard-indent 2] [pretty-one-line-limit 1])
|
||
(pretty-format 'frob '(frob (x 1 ...) 3 (x #f ...) 4 (x y 3 ...) ...))
|
||
(with-output-to-string
|
||
(lambda ()
|
||
(pretty-print '(frob (alpha b c d)
|
||
(peter o n m)
|
||
(zero 1 2 3)
|
||
(nine 8 7 6))))))
|
||
"(frob (alpha\n b\n c\n d)\n (peter\n o\n n\n m)\n (zero 1\n 2\n 3)\n (nine 8\n 7\n 6))\n")
|
||
(eqv? (begin (pretty-format 'frob #f) (pretty-format 'frob)) #f)
|
||
(equal?
|
||
(with-output-to-string
|
||
(lambda ()
|
||
(pretty-print ''#'#`#,#,@,,@`(a b c))))
|
||
"'#'#`#,#,@,,@`(a b c)\n")
|
||
)
|
||
|
||
(mat write
|
||
(let ([unpretty-copy
|
||
(lambda (ifn ofn)
|
||
(let ([ip (open-input-file ifn)]
|
||
[op (open-output-file ofn 'replace)])
|
||
(dynamic-wind
|
||
(lambda () #f)
|
||
(rec loop
|
||
(lambda ()
|
||
(let ([x (read ip)])
|
||
(or (eof-object? x)
|
||
(parameterize ([print-unicode #f])
|
||
(write x op)
|
||
(newline op)
|
||
(loop))))))
|
||
(lambda ()
|
||
(close-input-port ip)
|
||
(close-output-port op)))))])
|
||
(unpretty-copy "prettytest.ss" "testfile.ss"))
|
||
(let ([p1 (open-input-file "prettytest.ss")]
|
||
[p2 (open-input-file "testfile.ss")])
|
||
(dynamic-wind
|
||
(lambda () #f)
|
||
(rec loop
|
||
(lambda ()
|
||
(let ([x1 (read p1)] [x2 (read p2)])
|
||
(unless (pretty-equal? x1 x2)
|
||
(errorf 'pretty-equal "~s is not equal to ~s" x1 x2))
|
||
(or (eof-object? x1) (loop)))))
|
||
(lambda ()
|
||
(close-input-port p1)
|
||
(close-input-port p2))))
|
||
)
|
||
|
||
(mat fasl
|
||
(pretty-equal?
|
||
(begin
|
||
(call-with-port
|
||
(open-file-output-port "testfile.ss" (file-options replace))
|
||
(lambda (p) (fasl-write +nan.0 p)))
|
||
(call-with-port (open-file-input-port "testfile.ss") fasl-read))
|
||
(/ 0.0 0.0))
|
||
(let ([ls (with-input-from-file "prettytest.ss"
|
||
(rec f
|
||
(lambda ()
|
||
(let ([x (read)])
|
||
(if (eof-object? x) '() (cons x (f)))))))])
|
||
(define-record frob (x1 (uptr x2) (fixnum x3) (float x4) (double x5) (wchar_t x6) (integer-64 x7) (char x8) (unsigned-64 x9)))
|
||
(let ([x (make-frob '#(#&3+4i 3.456+723i 3/4) 7500000 (most-negative-fixnum) +nan.0 3.1415 #\x3d0
|
||
(- (expt 2 63) 5) #\$ (- (expt 2 64) 5))])
|
||
(define put-stuff
|
||
(lambda (p)
|
||
(fasl-write (cons x x) p)
|
||
(fasl-write (list +nan.0 +inf.0 -inf.0 -0.0) p)
|
||
(for-each (lambda (x) (fasl-write x p)) ls)))
|
||
(define (get-stuff fasl-read)
|
||
(lambda (p)
|
||
(let ([y (fasl-read p)])
|
||
(and (equal? ($record->vector (car y)) ($record->vector x))
|
||
(eq? (cdr y) (car y))
|
||
(pretty-equal? (fasl-read p) (list +nan.0 +inf.0 -inf.0 -0.0))
|
||
(let loop ([ls ls])
|
||
(let ([x1 (fasl-read p)] [x2 (if (null? ls) #!eof (car ls))])
|
||
(unless (pretty-equal? x1 x2)
|
||
(errorf #f "~s is not equal to ~s" x1 x2))
|
||
(or (eof-object? x1) (loop (cdr ls)))))))))
|
||
(call-with-port
|
||
(open-file-output-port "testfile.ss" (file-options replace))
|
||
put-stuff)
|
||
(and
|
||
(call-with-port
|
||
(open-file-input-port "testfile.ss")
|
||
(get-stuff fasl-read))
|
||
(call-with-port
|
||
(open-file-input-port "testfile.ss" (file-options compressed))
|
||
(get-stuff fasl-read))
|
||
(call-with-port
|
||
(open-file-input-port "testfile.ss" (file-options compressed))
|
||
(get-stuff (lambda (p)
|
||
(when (eof-object? (lookahead-u8 p)) (printf "done\n"))
|
||
(fasl-read p))))
|
||
(begin
|
||
(call-with-port
|
||
(open-file-output-port "testfile.ss" (file-options compressed replace))
|
||
put-stuff)
|
||
(call-with-port
|
||
(open-file-input-port "testfile.ss" (file-options compressed))
|
||
(get-stuff fasl-read)))
|
||
(call-with-port
|
||
(open-bytevector-input-port
|
||
(call-with-bytevector-output-port put-stuff))
|
||
(get-stuff fasl-read)))))
|
||
(eqv? (fasl-file "prettytest.ss" "testfile.ss") (void))
|
||
(let ([ls (with-input-from-file "prettytest.ss"
|
||
(rec f
|
||
(lambda ()
|
||
(let ([x (read)])
|
||
(if (eof-object? x) '() (cons x (f)))))))])
|
||
(call-with-port
|
||
(open-file-input-port "testfile.ss")
|
||
(lambda (p)
|
||
(let loop ([ls ls])
|
||
(let ([x1 (fasl-read p)] [x2 (if (null? ls) #!eof (car ls))])
|
||
(unless (pretty-equal? x1 x2)
|
||
(errorf #f "~s is not equal to ~s" x1 x2))
|
||
(or (eof-object? x1) (loop (cdr ls))))))))
|
||
(equal?
|
||
(with-interrupts-disabled
|
||
(let ([ls (cons (weak-cons 'a 'b) (weak-cons 'c (cons 'd (weak-cons 'e #f))))])
|
||
(call-with-port
|
||
(open-file-output-port "testfile.ss" (file-options replace))
|
||
(lambda (p) (fasl-write ls p))))
|
||
(let ([ls (call-with-port (open-file-input-port "testfile.ss") fasl-read)])
|
||
(list
|
||
(equal? ls '((a . b) c d e . #f))
|
||
(weak-pair? ls)
|
||
(weak-pair? (car ls))
|
||
(weak-pair? (cdr ls))
|
||
(weak-pair? (cddr ls))
|
||
(weak-pair? (cdddr ls)))))
|
||
'(#t #f #t #t #f #t))
|
||
)
|
||
|
||
(mat clear-output-port ; test interactively
|
||
(procedure? clear-output-port)
|
||
)
|
||
|
||
(mat flush-output-port ; test interactively
|
||
(procedure? flush-output-port)
|
||
)
|
||
|
||
;;; section 6-3:
|
||
|
||
(mat format
|
||
(equal? (format "abcde") "abcde")
|
||
(equal? (format "~s ~a ~c ~~ ~%" "hi" "there" #\X)
|
||
(string-append "\"hi\" there X ~ " (string #\newline)))
|
||
(equal? (format "~s" car) "#<procedure car>")
|
||
(equal? (format "~s" (lambda () #f)) "#<procedure>")
|
||
)
|
||
|
||
(mat printf
|
||
(let ([p (open-output-string)])
|
||
(parameterize ([current-output-port p])
|
||
(printf "~s:~s" 3 4))
|
||
(equal? (get-output-string p) "3:4"))
|
||
)
|
||
|
||
(mat fprintf
|
||
(let ([p (open-output-string)])
|
||
(fprintf p "~s.~s:~s" 'abc 345 "xyz")
|
||
(equal? (get-output-string p) "abc.345:\"xyz\""))
|
||
)
|
||
|
||
(mat cp1in-verify-format-warnings
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(lambda () (import scheme) (format "~a~~~s" 5)))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(lambda () (import scheme) (format "~a~a~a~s" 1 2 3 4 5 6)))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(mat/cf (lambda () (import scheme) (format "~a~~~s" 5))))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(mat/cf (lambda () (import scheme) (format "~a~a~a~s" 1 2 3 4 5 6))))))
|
||
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(lambda () (import scheme) (printf "abc~s")))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(lambda () (import scheme) (printf "~%~abc~adef~ag~s~~~%" 1 2 3 4 5)))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(mat/cf (lambda () (import scheme) (printf "abc~s"))))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(mat/cf (lambda () (import scheme) (printf "~%~abc~adef~ag~s~~~%" 1 2 3 4 5))))))
|
||
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(lambda (p) (import scheme) (fprintf p "abc~s")))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(lambda (p) (import scheme) (fprintf p "~%~abc~adef~ag~s~~~%" 1 2 3 4 5)))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(mat/cf (lambda (p) (import scheme) (fprintf p "abc~s"))))))
|
||
(warning? (parameterize ([#%$suppress-primitive-inlining #f])
|
||
(eval '(mat/cf (lambda (p) (import scheme) (fprintf p "~%~abc~adef~ag~s~~~%" 1 2 3 4 5))))))
|
||
)
|
||
|
||
(mat print-parameters
|
||
(equal? (parameterize ([print-level 3])
|
||
(format "~s" (let ([x (list 'a)]) (set-car! x x) x)))
|
||
"((((...))))")
|
||
(equal? (parameterize ([print-length 3])
|
||
(format "~s" (let ([x (list 'a)]) (set-cdr! x x) x)))
|
||
"(a a a ...)")
|
||
(equal? (parameterize ([print-graph #t])
|
||
(format "~s" (let ([x (list 'a)]) (set-car! x x) x)))
|
||
"#0=(#0#)")
|
||
(equal? (parameterize ([print-graph #t])
|
||
(format "~s" (let ([x (list 'a)]) (set-cdr! x x) x)))
|
||
"#0=(a . #0#)")
|
||
(equal? (parameterize ([print-graph #t])
|
||
(format "~s" (let ([x (list 'a)] [y (list 'b)])
|
||
(list x y y x))))
|
||
"(#0=(a) #1=(b) #1# #0#)")
|
||
(equal? (parameterize ([print-graph #t])
|
||
(format "~s" (let ([x (list 'a)] [y (list 'b)])
|
||
(vector x y y x))))
|
||
"#(#0=(a) #1=(b) #1# #0#)")
|
||
(equal? (parameterize ([print-graph #t])
|
||
(format "~s" '(#2# #2=#{a b})))
|
||
"(#0=#{a b} #0#)")
|
||
(error? (guard (c [(and (warning? c) (format-condition? c))
|
||
(apply errorf (condition-who c) (condition-message c) (condition-irritants c))])
|
||
(format "~s"
|
||
(let ([x (list '*)])
|
||
(set-car! x x)
|
||
(set-cdr! x x)
|
||
x))))
|
||
(equal? (parameterize ([print-vector-length #f])
|
||
(format "~s ~s" '#5(1 2 3) '#8vfx(5 7 9 8 8 9 -1)))
|
||
"#(1 2 3 3 3) #vfx(5 7 9 8 8 9 -1 -1)")
|
||
(equal? (parameterize ([print-vector-length #t])
|
||
(format "~s ~s" '#(1 2 3 3 3) '#vfx(5 7 9 8 8 9 -1 -1)))
|
||
"#5(1 2 3) #8vfx(5 7 9 8 8 9 -1)")
|
||
(equal? (parameterize ([print-vector-length #f])
|
||
(format "~a ~a" '#5(1 2 3) '#8vfx(5 7 9 8 8 9 -1)))
|
||
"#(1 2 3 3 3) #vfx(5 7 9 8 8 9 -1 -1)")
|
||
(equal? (parameterize ([print-vector-length #t])
|
||
(format "~a ~a" '#(1 2 3 3 3) '#vfx(5 7 9 8 8 9 -1 -1)))
|
||
"#(1 2 3 3 3) #vfx(5 7 9 8 8 9 -1 -1)")
|
||
(equal? (parameterize ([print-vector-length #f])
|
||
(with-output-to-string
|
||
(lambda ()
|
||
(pretty-print '#5(1 2 3))
|
||
(pretty-print '#8vfx(5 7 9 8 8 9 -1)))))
|
||
"#(1 2 3 3 3)\n#vfx(5 7 9 8 8 9 -1 -1)\n")
|
||
(equal? (parameterize ([print-vector-length #t])
|
||
(with-output-to-string
|
||
(lambda ()
|
||
(pretty-print '#(1 2 3 3 3))
|
||
(pretty-print '#vfx(5 7 9 8 8 9 -1 -1)))))
|
||
"#5(1 2 3)\n#8vfx(5 7 9 8 8 9 -1)\n")
|
||
(equal? (parameterize ([print-gensym #f])
|
||
(format "~s" '(#3# #3=#{g0 fool})))
|
||
"(g0 g0)")
|
||
(equal? (parameterize ([print-graph #t] [print-gensym #f])
|
||
(format "~s" '(#4# #4=#{g0 fool})))
|
||
"(#0=g0 #0#)")
|
||
(equal? (parameterize ([print-gensym 'pretty])
|
||
(format "~s" '(#5# #5=#{g0 fool})))
|
||
"(#:g0 #:g0)")
|
||
(equal? (parameterize ([print-graph #t] [print-gensym 'pretty])
|
||
(format "~s" '(#6# #6=#{g0 fool})))
|
||
"(#0=#:g0 #0#)")
|
||
(equal? (parameterize ([print-gensym 'pretty])
|
||
(format "~s" '(#7# #7=#:g0)))
|
||
"(#:g0 #:g0)")
|
||
(let ([g (gensym "x")])
|
||
(parameterize ([print-gensym 'pretty/suffix])
|
||
(equal? (format "~s" g) (format "~s" g))))
|
||
(do ([i 100 (fx- i 1)])
|
||
((fx= i 0) #t)
|
||
(let ([g (gensym "x")])
|
||
(unless (< (string-length (parameterize ([print-gensym 'pretty/suffix])
|
||
(format "~s" g)))
|
||
(string-length (parameterize ([print-gensym #t])
|
||
(format "~s" g))))
|
||
(error #f "failed"))))
|
||
(let ([g (gensym "x")])
|
||
(let ([x (with-input-from-string
|
||
(parameterize ([print-gensym 'pretty/suffix])
|
||
(format "~s" g))
|
||
read)])
|
||
(and (symbol? x) (not (gensym? x)))))
|
||
(equal? (parameterize ([print-gensym 'pretty/suffix])
|
||
(format "~s" '#{g0 cfdhkxfnlo6opm0x-c}))
|
||
"g0.cfdhkxfnlo6opm0x-c")
|
||
(equal? (parameterize ([print-graph #t] [print-gensym 'pretty])
|
||
(format "~s" '(#8# #8=#:g0)))
|
||
"(#0=#:g0 #0#)")
|
||
(equal? (parameterize ([print-brackets #t])
|
||
(let ([p (open-output-string)])
|
||
(pretty-print '(let ((x 3)) x) p)
|
||
(get-output-string p)))
|
||
(format "~a~%" "(let ([x 3]) x)"))
|
||
(equal? (parameterize ([print-brackets #f])
|
||
(let ([p (open-output-string)])
|
||
(pretty-print '(let ((x 3)) x) p)
|
||
(get-output-string p)))
|
||
(format "~a~%" "(let ((x 3)) x)"))
|
||
(equal? (parameterize ([case-sensitive #t])
|
||
(format "~s" (string->symbol "AbcDEfg")))
|
||
"AbcDEfg")
|
||
(equal? (format "~s" (read (open-input-string "abCdEfG")))
|
||
"abCdEfG")
|
||
(equal? (parameterize ([case-sensitive #f])
|
||
(format "~s" (read (open-input-string "abCdEfG"))))
|
||
"abcdefg")
|
||
(equal? (parameterize ([print-radix 36])
|
||
(format "~s" 35))
|
||
"#36rZ")
|
||
(equal? (parameterize ([print-radix 36])
|
||
(format "~a" 35))
|
||
"Z")
|
||
)
|
||
|
||
(mat general-port
|
||
(<= (port-input-index (console-input-port))
|
||
(port-input-size (console-input-port))
|
||
(string-length (port-input-buffer (console-input-port))))
|
||
(<= (port-input-count (console-input-port))
|
||
(string-length (port-input-buffer (console-input-port))))
|
||
(<= (port-output-index (console-output-port))
|
||
(port-output-size (console-output-port))
|
||
(string-length (port-output-buffer (console-output-port))))
|
||
(<= (port-output-count (console-output-port))
|
||
(string-length (port-output-buffer (console-output-port))))
|
||
(equal?
|
||
(let ([sip (open-string-input-port "hello")])
|
||
(let ([n1 (port-input-count sip)])
|
||
(read-char sip)
|
||
(list n1 (port-input-count sip))))
|
||
'(5 4))
|
||
(equal?
|
||
(let ([op (make-output-port (lambda args (error #f "oops")) (make-string 10))])
|
||
(let ([n1 (port-output-count op)])
|
||
(display "hey!" op)
|
||
(list n1 (port-output-count op))))
|
||
'(10 6))
|
||
(let ()
|
||
(define make-two-way-port
|
||
; no local buffering
|
||
; close-port passed through
|
||
(lambda (ip op)
|
||
(define handler
|
||
(lambda (msg . args)
|
||
(record-case (cons msg args)
|
||
[block-read (p s n) (block-read ip s n)]
|
||
[block-write (p s n) (block-write op s n)]
|
||
[char-ready? (p) (char-ready? ip)]
|
||
[clear-input-port (p) (clear-input-port ip)]
|
||
[clear-output-port (p) (clear-output-port op)]
|
||
[close-port (p)
|
||
(close-port ip)
|
||
(close-port op)
|
||
(mark-port-closed! p)]
|
||
; [file-length (p) #f]
|
||
[file-position (p . pos)
|
||
(if (null? pos)
|
||
(most-negative-fixnum)
|
||
(errorf 'two-way-port "cannot reposition"))]
|
||
[flush-output-port (p) (flush-output-port op)]
|
||
[peek-char (p) (peek-char ip)]
|
||
[port-name (p) "two-way port"]
|
||
[read-char (p) (read-char ip)]
|
||
[unread-char (c p) (unread-char c ip)]
|
||
[write-char (c p) (write-char c op)]
|
||
[else (errorf 'two-way-port "operation ~s not handled"
|
||
msg)])))
|
||
(make-input/output-port handler "" "")))
|
||
(let ([sip (open-input-string "far out")]
|
||
[sop (open-output-string)])
|
||
(let ([p1 (make-two-way-port sip sop)])
|
||
(and (port? p1)
|
||
(begin (write (read p1) p1)
|
||
(string=? (get-output-string sop) "far"))
|
||
(char-ready? p1)
|
||
(char=? (read-char p1) #\space)
|
||
(char=? (read-char p1) #\o)
|
||
(begin (unread-char #\o p1)
|
||
(char=? (read-char p1) #\o))
|
||
; can't count on clear-output-port doing anything for
|
||
; string output ports, so next two checks are bogus
|
||
#;(begin (write-char #\a p1)
|
||
(clear-output-port p1)
|
||
(string=? (get-output-string sop) ""))
|
||
(begin
|
||
(file-position sip (file-length sip))
|
||
(char-ready? p1))
|
||
(eof-object? (peek-char p1))
|
||
; make sure these don't error out
|
||
(eq? (clear-input-port p1) (void))
|
||
(eq? (clear-output-port p1) (void))
|
||
(begin (close-port p1) (port-closed? p1))
|
||
(port-closed? sip)
|
||
(port-closed? sop)))))
|
||
(let ()
|
||
(define make-broadcast-port
|
||
; local buffering
|
||
; closed-port not passed through
|
||
; critical sections used where necessary to protect against interrupts
|
||
; uses block-write to dump buffers to subordinate ports
|
||
; check cltl2 to see what it says about local buffering,
|
||
; and about passing through flush, clear, and close
|
||
; size set so that buffer always has room for character to be written,
|
||
; allowing buffer to be flushed as soon as it becomes full
|
||
(lambda ports
|
||
(define handler
|
||
(lambda (msg . args)
|
||
(record-case (cons msg args)
|
||
; [block-read (p s n) #f]
|
||
[block-write (p s n)
|
||
(unless (null? ports)
|
||
(with-interrupts-disabled
|
||
(flush-output-port p)
|
||
(for-each (lambda (p) (block-write p s n))
|
||
ports)))]
|
||
; [char-ready? (p) (char-ready? ip)]
|
||
; [clear-input-port (p) (clear-input-port ip)]
|
||
[clear-output-port (p) (set-port-output-index! p 0)]
|
||
[close-port (p)
|
||
(set-port-output-size! p 0)
|
||
(mark-port-closed! p)]
|
||
; [file-length (p) #f]
|
||
[file-position (p . pos)
|
||
(if (null? pos)
|
||
(most-negative-fixnum)
|
||
(errorf 'broadcast-port "cannot reposition"))]
|
||
[flush-output-port (p)
|
||
(with-interrupts-disabled
|
||
(unless (null? ports)
|
||
(let ([b (port-output-buffer p)]
|
||
[i (port-output-index p)])
|
||
(for-each (lambda (p) (block-write p b i))
|
||
ports)))
|
||
(set-port-output-index! p 0))]
|
||
; [peek-char (p) (peek-char ip)]
|
||
[port-name (p) "broadcast port"]
|
||
; [read-char (p) (read-char ip)]
|
||
; [unread-char (c p) (unread-char c ip)]
|
||
[write-char (c p)
|
||
(with-interrupts-disabled
|
||
(unless (null? ports)
|
||
(let ([b (port-output-buffer p)]
|
||
[i (port-output-index p)])
|
||
; could check here to be sure that we really need
|
||
; to flush
|
||
(string-set! b i c)
|
||
(for-each (lambda (p)
|
||
(block-write p b (fx+ i 1)))
|
||
ports)))
|
||
(set-port-output-index! p 0))]
|
||
[else (errorf 'broadcast-port "operation ~s not handled"
|
||
msg)])))
|
||
(let ([len 1024])
|
||
(let ([p (make-output-port handler (make-string len))])
|
||
(set-port-output-size! p (fx- len 1))
|
||
p))))
|
||
(let ([p (make-broadcast-port)])
|
||
(and (port? p)
|
||
(let ([x (make-string 1000 #\a)])
|
||
(let loop ([i 1000])
|
||
(if (fx= i 0)
|
||
(fx<= (port-output-index p)
|
||
(port-output-size p)
|
||
(string-length (port-output-buffer p)))
|
||
(begin (display x p)
|
||
(loop (fx- i 1))))))
|
||
(begin (close-port p) (port-closed? p))))
|
||
(let ([sop (open-output-string)])
|
||
(let ([p (make-broadcast-port sop sop)])
|
||
(and (port? p)
|
||
(let ([x "abcde"])
|
||
(display x p)
|
||
(and (string=? (get-output-string sop) "")
|
||
(begin (flush-output-port p)
|
||
(string=? (get-output-string sop)
|
||
(string-append x x)))))
|
||
(begin (close-output-port p) (port-closed? p))))))
|
||
|
||
(let ()
|
||
(define make-transcript-port
|
||
; local buffering; run into problems with unread-char and
|
||
; clear-output-port otherwise
|
||
; close-port passed through to tp only
|
||
(lambda (ip op tp)
|
||
(define handler
|
||
(lambda (msg . args)
|
||
(record-case (cons msg args)
|
||
[block-read (p str cnt)
|
||
(with-interrupts-disabled
|
||
(let ([b (port-input-buffer p)]
|
||
[i (port-input-index p)]
|
||
[s (port-input-size p)])
|
||
(if (< i s)
|
||
(let ([cnt (fxmin cnt (fx- s i))])
|
||
(do ([i i (fx+ i 1)]
|
||
[j 0 (fx+ j 1)])
|
||
((fx= j cnt)
|
||
(set-port-input-index! p i)
|
||
cnt)
|
||
(string-set! str j (string-ref b i))))
|
||
(let ([cnt (block-read ip str cnt)])
|
||
(unless (eof-object? cnt)
|
||
(block-write tp str cnt))
|
||
cnt))))]
|
||
[char-ready? (p)
|
||
(or (< (port-input-index p) (port-input-size p))
|
||
(char-ready? ip))]
|
||
[clear-input-port (p)
|
||
; set size to zero rather than index to size
|
||
; in order to invalidate unread-char
|
||
(set-port-input-size! p 0)]
|
||
[clear-output-port (p) (set-port-output-index! p 0)]
|
||
[close-port (p)
|
||
(flush-output-port p)
|
||
(close-port tp)
|
||
(set-port-output-size! p 0)
|
||
(set-port-input-size! p 0)
|
||
(mark-port-closed! p)]
|
||
; [file-length (p) #f]
|
||
[file-position (p . pos)
|
||
(if (null? pos)
|
||
(most-negative-fixnum)
|
||
(errorf 'transcript-port "cannot reposition"))]
|
||
[flush-output-port (p)
|
||
(with-interrupts-disabled
|
||
(let ([b (port-output-buffer p)]
|
||
[i (port-output-index p)])
|
||
(block-write op b i)
|
||
(block-write tp b i)
|
||
(set-port-output-index! p 0)
|
||
(flush-output-port op)
|
||
(flush-output-port tp)))]
|
||
[peek-char (p)
|
||
(with-interrupts-disabled
|
||
(let ([b (port-input-buffer p)]
|
||
[i (port-input-index p)]
|
||
[s (port-input-size p)])
|
||
(if (fx< i s)
|
||
(string-ref b i)
|
||
(begin (flush-output-port p)
|
||
(let ([s (block-read ip b)])
|
||
(if (eof-object? s)
|
||
s
|
||
(begin (block-write tp b s)
|
||
(set-port-input-size! p s)
|
||
(string-ref b 0))))))))]
|
||
[port-name (p) "transcript"]
|
||
[read-char (p)
|
||
(with-interrupts-disabled
|
||
(let ([c (peek-char p)])
|
||
(unless (eof-object? c)
|
||
(set-port-input-index! p
|
||
(fx+ (port-input-index p) 1)))
|
||
c))]
|
||
[unread-char (c p)
|
||
(with-interrupts-disabled
|
||
(let ([b (port-input-buffer p)]
|
||
[i (port-input-index p)]
|
||
[s (port-input-size p)])
|
||
(when (fx= i 0)
|
||
(errorf 'unread-char
|
||
"tried to unread too far on ~s"
|
||
p))
|
||
(set-port-input-index! p (fx- i 1))
|
||
; following could be skipped; supposed to be
|
||
; same character
|
||
(string-set! b (fx- i 1) c)))]
|
||
[write-char (c p)
|
||
(with-interrupts-disabled
|
||
(let ([b (port-output-buffer p)]
|
||
[i (port-output-index p)]
|
||
[s (port-output-size p)])
|
||
(string-set! b i c)
|
||
; could check here to be sure that we really need
|
||
; to flush
|
||
(block-write op b (fx+ i 1))
|
||
(block-write tp b (fx+ i 1))
|
||
(set-port-output-index! p 0)))]
|
||
[block-write (p str cnt)
|
||
(with-interrupts-disabled
|
||
(let ([b (port-output-buffer p)]
|
||
[i (port-output-index p)])
|
||
; flush buffered data
|
||
(when (fx> i 0)
|
||
(block-write op b i)
|
||
(block-write tp b i))
|
||
; write new data
|
||
(block-write op str cnt)
|
||
(block-write tp str cnt)
|
||
(set-port-output-index! p 0)))]
|
||
[else (errorf 'transcript-port "operation ~s not handled"
|
||
msg)])))
|
||
(let ([ib (make-string 100)] [ob (make-string 100)])
|
||
(let ([p (make-input/output-port handler ib ob)])
|
||
(if (char-ready? ip)
|
||
; kludge so that old input doesn't show up after later
|
||
; output (e.g., input newline after output prompt)
|
||
(let ((n (block-read ip ib (string-length ib))))
|
||
(if (eof-object? n)
|
||
(set-port-input-size! p 0)
|
||
(set-port-input-size! p n)))
|
||
(set-port-input-size! p 0))
|
||
(set-port-output-size! p (fx- (string-length ob) 1))
|
||
p))))
|
||
; (define-record tp-frame (cip cop tp))
|
||
; (define tp-stack '())
|
||
; (define transcript-on
|
||
; (lambda (fn)
|
||
; (with-interrupts-disabled
|
||
; (let ((cip (console-input-port))
|
||
; (cop (console-output-port)))
|
||
; (let ((tp (make-transcript-port cip cop
|
||
; (open-output-file fn 'replace))))
|
||
; (set! tp-stack (cons (make-tp-frame cip cop tp) tp-stack))
|
||
; (console-output-port tp)
|
||
; (console-input-port tp)
|
||
; (when (eq? (current-input-port) cip)
|
||
; (current-input-port tp))
|
||
; (when (eq? (current-output-port) cop)
|
||
; (current-output-port tp)))))))
|
||
; (define transcript-off
|
||
; (lambda ()
|
||
; (with-interrupts-disabled
|
||
; (when (null? tp-stack) (errorf 'transcript-off "no transcript running"))
|
||
; (let ((frame (car tp-stack)))
|
||
; (let ((cip (tp-frame-cip frame))
|
||
; (cop (tp-frame-cop frame))
|
||
; (tp (tp-frame-tp frame)))
|
||
; (console-input-port cip)
|
||
; (console-output-port cop)
|
||
; (when (eq? (current-input-port) tp) (current-input-port cip))
|
||
; (when (eq? (current-output-port) tp) (current-output-port cop))
|
||
; (set! tp-stack (cdr tp-stack))
|
||
; (close-port tp))))))
|
||
(let ([ip (open-input-string (format "2"))]
|
||
[op (open-output-string)]
|
||
[tp (open-output-string)])
|
||
(let ([p (make-transcript-port ip op tp)])
|
||
(and (begin (display "1" p) (eq? (read p) 2))
|
||
(begin (display "3" p)
|
||
(flush-output-port p)
|
||
(and (string=? (get-output-string op) "13")
|
||
; 2 doesn't show up since we scan past available
|
||
; input (see "kludge" above)
|
||
(string=? (get-output-string tp) "13")))
|
||
(begin (close-port p)
|
||
(and (port-closed? p) (port-closed? tp)))))))
|
||
)
|
||
|
||
(mat port-handler
|
||
(begin (set! ph (port-handler (current-output-port)))
|
||
(procedure? ph))
|
||
(string? (ph 'port-name (current-output-port)))
|
||
(error? (ph))
|
||
(error? (ph 'foo))
|
||
(error? (ph 'foo (current-output-port)))
|
||
(error? (ph 'read-char))
|
||
(error? (ph 'write-char))
|
||
(error? (ph 'write-char 3))
|
||
(error? (ph 'write-char (current-input-port)))
|
||
(error? (ph 'write-char 'a (current-output-port)))
|
||
(error? (ph 'write-char #\a 'a))
|
||
(error? (ph 'write-char #\a (open-input-string "hello")))
|
||
(error? (ph 'write-char #\a (current-output-port) 'a))
|
||
(boolean? (ph 'char-ready? (current-input-port)))
|
||
)
|
||
|
||
(mat char-name
|
||
(eqv? (char-name 'space) #\space)
|
||
(eqv? (char-name #\space) 'space)
|
||
(eqv? (char-name 'tab) #\tab)
|
||
(eqv? (char-name #\tab) 'tab)
|
||
(eqv? (char-name 'return) #\return)
|
||
(eqv? (char-name #\return) 'return)
|
||
(eqv? (char-name 'page) #\page)
|
||
(eqv? (char-name #\page) 'page)
|
||
(eqv? (char-name 'linefeed) #\linefeed)
|
||
(eqv? (char-name #\linefeed) 'newline)
|
||
(eqv? (char-name 'newline) #\newline)
|
||
(eqv? (char-name #\newline) 'newline)
|
||
(eqv? (char-name #\backspace) 'backspace)
|
||
(eqv? (char-name 'backspace) #\backspace)
|
||
(eqv? (char-name #\rubout) 'delete)
|
||
(eqv? (char-name 'rubout) #\rubout)
|
||
(eqv? (char-name #\nul) 'nul)
|
||
(eqv? (char-name 'nul) #\nul)
|
||
(eqv? (char-name 'foo) #f)
|
||
(eqv? (char-name 'delete) #\delete)
|
||
(eqv? (char-name #\delete) 'delete)
|
||
(eqv? (char-name 'vtab) #\vtab)
|
||
(eqv? (char-name #\vtab) 'vtab)
|
||
(eqv? (char-name 'alarm) #\alarm)
|
||
(eqv? (char-name #\alarm) 'alarm)
|
||
(eqv? (char-name 'esc) #\esc)
|
||
(eqv? (char-name #\esc) 'esc)
|
||
(error? (read (open-input-string "#\\foo")))
|
||
(and (eqv? (char-name 'foo #\003) (void))
|
||
(eqv? (char-name 'foo) #\003)
|
||
(eqv? (char-name #\003) 'foo)
|
||
(eqv? (read (open-input-string "#\\foo")) #\003))
|
||
(equal?
|
||
(begin
|
||
(char-name 'foo #f)
|
||
(list (char-name 'foo) (char-name #\003)))
|
||
'(#f #f))
|
||
(error? (read (open-input-string "#\\new\\line")))
|
||
(error? (read (open-input-string "#\\new\\x6c;ine")))
|
||
)
|
||
|
||
(mat string-escapes
|
||
(eqv? (string-ref "ab\b" 2) #\backspace)
|
||
(eqv? (string-ref "\n" 0) #\newline)
|
||
(eqv? (string-ref "a\fb" 1) #\page)
|
||
(eqv? (string-ref "ab\r" 2) #\return)
|
||
(eqv? (string-ref "\t" 0) #\tab)
|
||
(eqv? (string-ref "\a\v" 0) #\bel)
|
||
(eqv? (string-ref "\a\v" 1) #\vt)
|
||
(eqv? (string-ref "\000" 0) #\nul)
|
||
(eqv? (string-ref "\x00;" 0) #\nul)
|
||
(eqv? (string-ref "a\x20;b" 1) #\space)
|
||
(eqv? (string-ref "\\\"\'" 0) #\\)
|
||
(eqv? (string-ref "\\\"\'" 1) #\")
|
||
(eqv? (string-ref "\\\"\'" 2) #\')
|
||
(= (char->integer (string-ref "a\012" 1)) #o12 10)
|
||
(= (char->integer (string-ref "a\015" 1)) #o15 13)
|
||
(= (char->integer (string-ref "a\177" 1)) #o177 127)
|
||
(= (char->integer (string-ref "a\377" 1)) #o377 255)
|
||
(error? (read (open-input-string "\"ab\\\"")))
|
||
(error? (read (open-input-string "\"ab\\0\"")))
|
||
(error? (read (open-input-string "\"ab\\01\"")))
|
||
(error? (read (open-input-string "\"ab\\*\"")))
|
||
(error? (read (open-input-string "\"ab\\x\"")))
|
||
(error? (read (open-input-string "\"ab\\x*\"")))
|
||
(error? (read (open-input-string "\"ab\\xg\"")))
|
||
(equal? (format "~s" "\bab\nc\f\rd\t\v\a") "\"\\bab\\nc\\f\\rd\\t\\v\\a\"")
|
||
)
|
||
|
||
(mat read-token
|
||
(let ([ip (open-input-string "(cons 33 #;hello \"rot\")")])
|
||
(and (let-values ([vals (read-token ip)])
|
||
(equal? vals '(lparen #f 0 1)))
|
||
(let-values ([vals (read-token ip)])
|
||
(equal? vals '(atomic cons 1 5)))
|
||
(let-values ([vals (read-token ip)])
|
||
(equal? vals '(atomic 33 6 8)))
|
||
(let-values ([vals (read-token ip)])
|
||
(equal? vals '(quote datum-comment 9 11)))
|
||
(let-values ([vals (read-token ip)])
|
||
(equal? vals '(atomic hello 11 16)))
|
||
(let-values ([vals (read-token ip)])
|
||
(equal? vals '(atomic "rot" 17 22)))
|
||
(let-values ([vals (read-token ip)])
|
||
(equal? vals '(rparen #f 22 23)))))
|
||
(let ()
|
||
(define with-input-from-string
|
||
(lambda (s p)
|
||
(parameterize ([current-input-port (open-input-string s)])
|
||
(p))))
|
||
(with-input-from-string "\n#17#\n"
|
||
(lambda ()
|
||
(let-values ([vals (read-token)])
|
||
(equal? vals '(insert 17 1 5))))))
|
||
(let ()
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display "\n#eat\n"))
|
||
'replace)
|
||
#t)
|
||
(error?
|
||
(let* ([ip (open-file-input-port "testfile.ss")]
|
||
[sfd (#%$source-file-descriptor "testfile.ss" ip)]
|
||
[ip (transcoded-port ip (native-transcoder))])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (read-token ip sfd))
|
||
(lambda () (close-input-port ip)))))
|
||
(let ()
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display "\neat\n"))
|
||
'replace)
|
||
#t)
|
||
; $transcoded-source-port is no more
|
||
#;(equal?
|
||
(let-values ([vals (let* ([ip (open-file-input-port "testfile.ss")]
|
||
[sfd (#%$source-file-descriptor "testfile.ss" ip)]
|
||
[ip (#%$transcoded-source-port ip (native-transcoder))])
|
||
(dynamic-wind
|
||
void
|
||
(lambda () (read-token ip sfd))
|
||
(lambda () (close-input-port ip))))])
|
||
vals)
|
||
'(atomic eat 1 4))
|
||
)
|
||
|
||
(define read-test
|
||
(lambda (s)
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display s))
|
||
'replace)
|
||
(load "testfile.ss" values)
|
||
#t))
|
||
(define load-test
|
||
(lambda (s)
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display s))
|
||
'replace)
|
||
(load "testfile.ss")
|
||
#t))
|
||
(define compile-test
|
||
(lambda (s)
|
||
(with-output-to-file "testfile.ss"
|
||
(lambda () (display s))
|
||
'replace)
|
||
(compile-file "testfile.ss")
|
||
(load "testfile.so")
|
||
#t))
|
||
|
||
(define-syntax xmat
|
||
(syntax-rules ()
|
||
[(_ string ...)
|
||
(begin
|
||
(mat read-test (error? (read-test string)) ...)
|
||
(mat load-test (error? (load-test string)) ...)
|
||
(mat compile-test (error? (compile-test string)) ...))]))
|
||
|
||
(begin (define-record f800 (a b)) (record-reader "zinjanthropus" (type-descriptor f800)))
|
||
(begin (define-record $acyclic ((immutable notme))) (record-reader '$acyclic (type-descriptor $acyclic)))
|
||
|
||
(xmat
|
||
"; Test error \"fasl object created by different release\"\n; This one is the list (a b c d) created by version 5.9b\n\n#@ |