; Copyright (c) 1993, 1994 Richard Kelsey and Jonathan Rees. See file COPYING. ; Dump and restore ; Unix has special meanings for ; ETX, FS, DEL, ETB, NAK, DC2, EOT, EM (or SUB?), DC3, DC1, SI, SYN, ; 3 28 127 23 21 18 4 25 26 19 17 15 22 ; so avoid using them. (define type/null #\n) (define type/true #\t) (define type/false #\f) (define type/unspecific #\u) (define type/pair #\p) ;obj1 obj2 (define type/string #\s) ;length chars (define type/number #\i) ;#chars rep (define type/symbol #\y) ;length chars (define type/char #\c) ;char (define type/vector #\v) ;length objects (define type/template #\a) ;length objects (define type/code-vector #\k) ;length bytes (each byte is 2 hex digits?) (define type/location #\l) ;uid (define type/closure #\q) ;template-info (define type/ellipsis #\e) (define type/random #\r) ; Recursive entry (define (dump obj write-char depth) (cond ((null? obj) (dump-type type/null write-char)) ((eq? obj #t) (dump-type type/true write-char)) ((eq? obj #f) (dump-type type/false write-char)) ((pair? obj) (dump-pair obj write-char depth)) ;; Template case needs to precede vector case ((template? obj) (dump-template obj write-char depth)) ((vector? obj) (dump-vector obj write-char depth)) ((symbol? obj) (dump-symbol obj write-char)) ((number? obj) (dump-number obj write-char)) ((string? obj) (dump-string obj write-char)) ((char? obj) (dump-char-literal obj write-char)) ((code-vector? obj) (dump-code-vector obj write-char)) ((location? obj) (dump-location obj write-char)) ((unspecific? obj) (dump-type type/unspecific write-char)) ((closure? obj) (dump-closure obj write-char)) (else (dump-random obj write-char depth)))) (define (restore read-char) (let ((type (restore-type read-char))) ((vector-ref restorers (char->ascii type)) type read-char))) (define restorers (make-vector 256 (lambda (type read-char) ;; Invalid type (error "invalid type code" type)))) (define (define-restorer! type proc) (vector-set! restorers (char->ascii type) proc)) ; Particular dumpers & restorers (define-restorer! type/null (lambda (c read-char) '())) (define-restorer! type/false (lambda (c read-char) #f)) (define-restorer! type/true (lambda (c read-char) #t)) (define-restorer! type/unspecific (lambda (c read-char) (if #f #f))) ; Pairs (define (dump-pair obj write-char depth) (if (= depth 0) (dump-ellipsis obj write-char) (let ((depth (- depth 1))) (dump-type type/pair write-char) (dump (car obj) write-char depth) (dump (cdr obj) write-char depth)))) (define-restorer! type/pair (lambda (c write-char) c ;ignored (let ((the-car (restore write-char))) (cons the-car (restore write-char))))) ; Symbols (define (dump-symbol obj write-char) (dump-type type/symbol write-char) (dump-a-string (symbol-case-converter (symbol->string obj)) write-char)) (define-restorer! type/symbol (lambda (c read-char) c ;ignored (string->symbol (symbol-case-converter (restore-a-string read-char))))) ; Numbers ; ... _ represent 0 ... 63, ; { ... {_ represent 64 ... 127, -- { is ascii 123 ; | ... |_ represent 128 ... 191, -- | is ascii 124 ; } ... }_ represent 192 ... 256. -- } is ascii 125 (define (dump-number n write-char) (if (not (communicable-number? n)) (error "can't dump this number" n)) (if (and (integer? n) (>= n 0) (< n 256)) (dump-byte n write-char) (begin (dump-type type/number write-char) ;; Note logarithmic recursion (dump-a-string (number->string n comm-radix) write-char)))) (define (communicable-number? n) #t) ;this gets redefined in client (define (dump-byte n write-char) ;Dump a number between 0 and 255 (if (< n 64) (write-char (ascii->char (+ n ascii-space))) (begin (write-char (ascii->char (+ (arithmetic-shift n -6) 122))) (write-char (ascii->char (+ (bitwise-and n 63) ascii-space)))))) (define ascii-space (char->ascii #\space)) ;32 (define (restore-small-integer c read-char) (- (char->ascii c) ascii-space)) (do ((i (+ ascii-space 63) (- i 1))) ((< i ascii-space)) (define-restorer! (ascii->char i) restore-small-integer)) (define (restore-medium-integer c read-char) (+ (arithmetic-shift (- (char->ascii c) 122) 6) (- (char->ascii (read-char)) ascii-space))) (do ((i 123 (+ i 1))) ((> i 125)) (define-restorer! (ascii->char i) restore-medium-integer)) (define (restore-number read-char) (let ((c (read-char))) (if (char=? c type/number) (string->number (restore-a-string read-char) comm-radix) (let ((n (char->ascii c))) (if (> n 122) (restore-medium-integer c read-char) (- n ascii-space)))))) (define-restorer! type/number (lambda (c read-char) c ;ignored (string->number (restore-a-string read-char) comm-radix))) (define comm-radix 16) ; String literals (define (dump-string obj write-char) (dump-type type/string write-char) (dump-a-string obj write-char)) (define-restorer! type/string (lambda (c read-char) c ;ignored (restore-a-string read-char))) ; Characters (define (dump-char-literal obj write-char) (dump-type type/char write-char) (dump-a-char obj write-char)) (define-restorer! type/char (lambda (c read-char) c ;ignored (restore-a-char read-char))) ; Vectors (define (dump-vector obj write-char depth) (dump-vector-like obj write-char depth type/vector vector-length vector-ref)) (define (dump-template obj write-char depth) (dump-vector-like obj write-char depth type/template template-length template-ref)) (define (dump-vector-like obj write-char depth type vector-length vector-ref) (if (= depth 0) (dump-ellipsis obj write-char) (let ((depth (- depth 1)) (len (vector-length obj))) (dump-type type write-char) (dump-length len write-char) (do ((i 0 (+ i 1))) ((= i len) 'done) (dump (vector-ref obj i) write-char depth))))) (define (restore-vector-like make-vector vector-set!) (lambda (c read-char) c ;ignored (let* ((len (restore-length read-char)) (v (make-vector len #\?))) (do ((i 0 (+ i 1))) ((= i len) v) (vector-set! v i (restore read-char)))))) (define-restorer! type/vector (restore-vector-like make-vector vector-set!)) (define-restorer! type/template (restore-vector-like make-template template-set!)) ; Code vectors (define (dump-code-vector obj write-char) (dump-type type/code-vector write-char) (let ((len (code-vector-length obj))) (dump-length len write-char) (do ((i 0 (+ i 1))) ((= i len) 'done) (dump-byte (code-vector-ref obj i) write-char)))) (define-restorer! type/code-vector (lambda (c read-char) c ;ignored (let* ((len (restore-length read-char)) (cv (make-code-vector len 0))) (do ((i 0 (+ i 1))) ((= i len) cv) (code-vector-set! cv i (restore-number read-char)))))) ; Locations (define (dump-location obj write-char) (dump-type type/location write-char) (dump-number (location->uid obj) write-char)) (define (location->uid obj) (or ((fluid $dump-index) obj) (location-id obj))) (define-restorer! type/location (lambda (c read-char) c ;ignored (uid->location (restore-number read-char)))) (define (uid->location uid) (or ((fluid $restore-index) uid) (table-ref uid->location-table uid) (let ((loc (make-undefined-location uid))) (note-location! loc) loc))) (define $restore-index (make-fluid (lambda (uid) #f))) (define uid->location-table (make-table)) (define (note-location! den) (table-set! uid->location-table (location-id den) den)) (define $dump-index (make-fluid (lambda (loc) #f))) ; For simulation purposes, it's better for location uid's not to ; conflict with any that might be in the base Scheme 48 system. (In the ; real server system there isn't any base Scheme 48 system, so there's ; no danger of conflict.) ; (define location-uid-origin 5000) ; Closure (define (dump-closure obj write-char) (dump-type type/closure write-char) (let ((id (template-info (closure-template obj)))) (dump-number (if (integer? id) id 0) write-char))) (define-restorer! type/closure (lambda (c read-char) c ;ignored (make-random (list 'closure (restore-number read-char))))) ; Random (define random-type (make-record-type 'random '(disclosure))) (define make-random (record-constructor random-type '(disclosure))) (define-record-discloser random-type (let ((d (record-accessor random-type 'disclosure))) (lambda (r) (cons "Remote" (d r))))) (define (dump-random obj write-char depth) (dump-type type/random write-char) (dump (or (disclose obj) (list '?)) write-char depth)) (define-restorer! type/random (lambda (c read-char) (make-random (restore read-char)))) ; Ellipsis (define (dump-ellipsis obj write-char) (dump-type type/ellipsis write-char)) (define-restorer! type/ellipsis (lambda (c read-char) (make-random (list (string->symbol "---"))))) ; Auxiliaries: ; Strings (not necessarily preceded by type code) (define (dump-a-string obj write-char) (let ((len (string-length obj))) (dump-length len write-char) (do ((i 0 (+ i 1))) ((= i len) 'done) (dump-a-char (string-ref obj i) write-char)))) (define (restore-a-string read-char) (let* ((len (restore-length read-char)) (str (make-string len #\?))) (do ((i 0 (+ i 1))) ((= i len) str) (string-set! str i (restore-a-char read-char))))) (define (dump-a-char c write-char) (write-char c)) (define (restore-a-char read-char) (read-char)) ; Type characters (define (dump-type c write-char) (write-char c)) (define (restore-type read-char) (read-char)) (define dump-length dump-number) (define restore-length restore-number) ;(define char->ascii char->integer) -- defined in p-features.scm ;(define ascii->char integer->char) -- ditto ; Miscellaneous support (define (unspecific? obj) (eq? obj *unspecific*)) (define *unspecific* (if #f #f)) ;foo ;(define (integer->digit-char n) ; (ascii->char (+ n (if (< n 10) ascii-zero a-minus-ten)))) ; ;(define (digit-char->integer c) ; (cond ((char-numeric? c) ; (- (char->ascii c) ascii-zero)) ; ((char=? c #\#) 0) ; (else ; (- (char->ascii (char-downcase c)) a-minus-ten)))) ; ;(define ascii-zero (char->ascii #\0)) ; ;(define a-minus-ten (- (char->integer #\a) 10)) ; These modified from s48/boot/transport.scm (define (string-case-converter string) (let ((new (make-string (string-length string) #\?))) (do ((i 0 (+ i 1))) ((>= i (string-length new)) new) (string-set! new i (invert-case (string-ref string i)))))) (define (invert-case c) (cond ((char-upper-case? c) (char-downcase c)) ((char-lower-case? c) (char-upcase c)) (else c))) (define symbol-case-converter (if (char=? (string-ref (symbol->string 't) 0) #\t) (lambda (string) string) string-case-converter)) ; ASCII ; !"#$%&'()*+,-./0123456789:;<=>? ; @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ; `abcdefghijklmnopqrstuvwxyz{|}~ ;(define (tst x) ; (let ((l '())) ; (dump x (lambda (c) (set! l (cons c l))) -1) ; (let ((l (reverse l))) ; (restore (lambda () ; (let ((c (car l))) ; (set! l (cdr l)) ; c)))))) ;(define cwcc call-with-current-continuation) ; ;(define (tst x) ; (letrec ((write-cont (lambda (ignore) ; (dump x ; (lambda (c) ; (cwcc (lambda (k) ; (set! write-cont k) ; (read-cont c)))) ; -1))) ; (read-cont #f)) ; (restore (lambda () ; (cwcc (lambda (k) ; (set! read-cont k) ; (write-cont 'ignore)))))))