diff --git a/collects/mzlib/port.ss b/collects/mzlib/port.ss index d9d5ec5..6b017a0 100644 --- a/collects/mzlib/port.ss +++ b/collects/mzlib/port.ss @@ -4,6 +4,7 @@ (lib "contract.ss")) (provide open-output-nowhere + make-pipe-with-specials make-input-port/read-to-peek merge-input copy-port @@ -74,11 +75,12 @@ (unless (output-port? dest) (raise-type-error 'copy-port "output-port" dest))) (cons dest dests)) - (let ([dests (cons dest dests)] - [s (make-bytes 4096)]) + (let ([s (make-bytes 4096)] + [dests (cons dest dests)]) (let loop () (let ([c (read-bytes-avail! s src)]) - (unless (eof-object? c) + (cond + [(number? c) (for-each (lambda (dest) (let loop ([start 0]) @@ -86,7 +88,17 @@ (let ([c2 (write-bytes-avail s dest start c)]) (loop (+ start c2)))))) dests) - (loop)))))) + (loop)] + [(procedure? c) + (let ([v (let-values ([(l col p) (port-next-location src)]) + (c (object-name src) l col p))]) + (for-each + (lambda (dest) (write-special v dest)) + dests)) + (loop)] + [else + ;; Must be EOF + (void)]))))) (define merge-input (case-lambda @@ -182,12 +194,13 @@ #f] [(null? special-peeked) ;; Empty special queue, so read through the original proc - (let ([r (read s)]) + (let* ([t (make-bytes (min 4096 (+ skip (bytes-length s))))] + [r (read t)]) (cond [(number? r) ;; The nice case --- reading gave us more bytes (set! peeked-end (+ r peeked-end)) - (write-bytes s peeked-w 0 r) + (write-bytes t peeked-w 0 r) ;; Now try again (peek-bytes-avail!* s skip #f peeked-r)] [(evt? r) @@ -195,7 +208,7 @@ ;; Technically, there's a race condition here. ;; We might choose r (and return 0) even when ;; unless-evt becomes available first. However, - ;; this race is not detectable only by the inside + ;; this race is detectable only by the inside ;; of `read'. (choice-evt r (wrap-evt unless-evt (lambda (x) #f))) r)] @@ -230,7 +243,9 @@ [else (let ([v (if (number? r) (subbytes t 0 r) r)]) - (set-cdr! special-peeked-tail (cons v null)) + (let ([pr (cons v null)]) + (set-cdr! special-peeked-tail pr) + (set! special-peeked-tail pr)) ;; Got something; now try again (do-peek-it s skip unless-evt))]))] [(eof-object? (car l)) @@ -319,10 +334,14 @@ [(more) null] [(more-last) #f] [(more-sema) #f] + [(close-w?) #f] [(sema-semaphore) (make-semaphore 1)]) (define (flush-more) (if (null? more) - (set! more-last #f) + (begin + (set! more-last #f) + (when close-w? + (close-output-port w))) (when (bytes? (car more)) (write-bytes (car more) w) (set! more (cdr more)) @@ -331,7 +350,7 @@ (make-input-port/read-to-peek in-name (lambda (s) - (let ([v (read-bytes-avail! r)]) + (let ([v (read-bytes-avail!* s r)]) (if (eq? v 0) (if more-last ;; Return a special @@ -347,7 +366,8 @@ (unless more-sema (set! more-sema (make-semaphore))) (wrap-evt (semaphore-peek-evt more-sema) - (lambda (x) 0)))))))) + (lambda (x) 0))))) + v))) #f void) (make-output-port @@ -358,22 +378,24 @@ (call-with-semaphore sema-semaphore (lambda () - (if more-last - (let ([p (cons (subbytes str start end) null)]) - (set-cdr! more-last p) - (set! more-last p)) - (write-bytes str w start end)) - (when more-sema - (semaphore-post more-sema) - (set! more-sema #f))))) + (begin0 + (if more-last + (let ([p (cons (subbytes str start end) null)]) + (set-cdr! more-last p) + (set! more-last p) + (- end start)) + (write-bytes str w start end)) + (when more-sema + (semaphore-post more-sema) + (set! more-sema #f)))))) ;; close (lambda () (call-with-semaphore sema-semaphore (lambda () - (close-output-port w) - (set! more null) - (set! more-last #f) + (if more-last + (set! close-w? #t) + (close-output-port w)) (when more-sema (semaphore-post more-sema))))) ;; write-special @@ -439,26 +461,31 @@ (lambda () (let loop ([got 0]) (let ([n (read-bytes-avail! in from-port got)]) - (let ([got (+ got (if (eof-object? n) - 0 - n))]) + (let ([got (+ got (if (number? n) + n + 0))]) (let-values ([(wrote used status) (bytes-convert c in 0 got out)]) (when (eq? status 'error) (error 'convert-stream "conversion error")) (unless (zero? wrote) (write-bytes out to-port 0 wrote)) (bytes-copy! in 0 in used got) - (if (eof-object? n) + (if (not (number? n)) (begin (unless (= got used) - (error 'convert-stream "input stream ended with a partial conversion")) + (error 'convert-stream "input stream ~a with a partial conversion" + (if (eof-object? n) "ended" "hit a special value"))) (let-values ([(wrote status) (bytes-convert-end c out)]) (when (eq? status 'error) (error 'convert-stream "conversion-end error")) (unless (zero? wrote) (write-bytes out to-port 0 wrote)) - ;; Success - (void))) + (if (eof-object? n) + ;; Success + (void) + (begin + (write-special n to-port) + (loop 0))))) (loop (- got used)))))))) (lambda () (bytes-close-converter c))))) @@ -490,6 +517,7 @@ (cond [(eq? n 0) (wrap-evt port (lambda (x) 0))] [(number? n) (set! got (+ got n)) n] + [(procedure? n) (set! got (add1 got)) n] [else n]))))) (lambda (str skip progress-evt) (let ([count (max 0 (min (- limit got skip) (bytes-length str)))]) diff --git a/collects/mzlib/private/package-helper.ss b/collects/mzlib/private/package-helper.ss index 08d7651..94747d7 100644 --- a/collects/mzlib/private/package-helper.ss +++ b/collects/mzlib/private/package-helper.ss @@ -46,9 +46,14 @@ ((bound-identifier=? id (caar renames)) (car renames)) (else (stx-assoc id (cdr renames))))) + (define insp (current-code-inspector)) + (define (rebuild ctxt val) (if (syntax? ctxt) - (datum->syntax-object ctxt val ctxt ctxt) + (syntax-recertify (datum->syntax-object ctxt val ctxt ctxt) + ctxt + insp + #f) val)) (define (rebuild-cons car cdr stx)