/usr/share/scheme48-1.9/link/transport.scm is in scheme48 1.9-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | ; Part of Scheme 48 1.9. See file COPYING for notices and license.
; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Marcus Crestani
; This is file transport.scm.
; System builder for bootstrapping and debugging.
; Things that have to be written out:
; Made by the compiler
; closures
; templates
; code-vectors
; locations
; Quoted data
; symbols
; pairs
; vectors
; strings
; booleans
; characters
; Convert THING to the Scheme 48 virtual machine's representation and
; return it. Locations and symbols may have multiple references in
; the image. Their transported addresses are kept in a table.
(define (transport thing . stuff)
(let transport ((thing thing))
(cond ((immediate? thing)
(transport-immediate thing))
((closure? thing)
(transport-closure thing))
((code-vector? thing)
(allocate-b-vector thing code-vector-length))
((location? thing)
(let ((address (table-ref *locations* thing)))
(cond (address address)
(else
(let ((desc (transport-location thing)))
(table-set! *locations* thing desc)
desc)))))
((symbol? thing)
(let ((address (table-ref *symbols* thing)))
(cond (address address)
(else
(let ((desc (transport-symbol thing)))
(table-set! *symbols* thing desc)
desc)))))
((pair? thing)
(transport-pair thing))
((template? thing)
(transport-template thing))
((vector? thing)
(transport-vector thing))
((string? thing)
(transport-string thing))
(else
(assertion-violation 'transport
"cannot transport object" thing stuff))))) ; DELETEME stuff
; Transport the things that are not allocated from the heap.
(define (transport-immediate thing)
(cond ((integer? thing)
(make-descriptor (enum tag fixnum) thing))
((char? thing)
(make-immediate (enum imm char) (char->ascii thing)))
((eq? thing '())
vm-null)
((eq? thing #f)
vm-false)
((eq? thing #t)
vm-true)
((eq? thing (unspecific))
vm-unspecific)
(else
(assertion-violation 'transport-immediate "cannot transport literal" thing))))
;==============================================================================
; The heap is a list of transported stored objects, each of which is either a
; string, a code-vector, or a vector of length N+1 representing a stored object
; with N cells. The last slot of the vector is the object's header.
(define *heap* '())
(define *hp* 0) ; Current heap-pointer (in a-units)
(define *symbols* #f) ; Table of already-transported symbols
(define *locations* #f) ; Table of already-transported locations
; We need to preserve sharing of vectors because `syntax-rules' relies on it.
(define *vector-alist* #f) ; Table of already-transported vectors
(define (initialize-memory)
(set! *hp* 0)
(set! *heap* '())
(set! *symbols* (make-table))
(set! *locations* (make-table location-id))
(set! *vector-alist* '()))
; Allocate a new stored object in the heap. DATA is whatever data is
; associated with the object, LEN is the length of the object (not
; including the header) in bytes. A pointer to the new object is
; returned.
(define (allocate-stob data len)
(let ((addr (+ *hp* (cells->a-units 1)))) ; move past header
(set! *hp* (+ addr (bytes->a-units len)))
(set! *heap* (cons data *heap*))
(make-stob-descriptor addr)))
; Allocate a new stored object that contains descriptors. This
; creates a vector to hold the header and the object's tranported
; contents and allocates a stob in the heap. Returns a pair
; containing the stob-pointer and the vector.
(define (allocate-d-vector type cells immutable?)
(let* ((vec (make-vector (+ cells 1) 0))
(ptr (allocate-stob vec (cells->bytes cells)))
(hdr (make-header type (cells->bytes cells))))
(vector-set! vec cells (if immutable? (make-header-immutable hdr) hdr))
(cons ptr vec)))
; Allocate a new stored object that contains data. VEC is either a
; code-vector or a string.
(define (allocate-b-vector vec length)
(let ((len (cells->bytes (bytes->cells (length vec)))))
(allocate-stob vec len)))
;==============================================================================
; Transport an object with two slots. ALLOCATE-D-VECTOR allocates the
; storage and then the two values are transported.
(define (transport-two-slot type accessor1 offset1 accessor2 offset2
immutable?)
(lambda (thing)
(let* ((data (allocate-d-vector type 2 immutable?))
(descriptor (car data))
(vector (cdr data)))
(vector-set! vector offset1 (transport (accessor1 thing)))
(vector-set! vector offset2 (transport (accessor2 thing)))
descriptor)))
; Closures and pairs are transported using TRANSPORT-TWO-SLOT.
(define transport-closure
(transport-two-slot (enum stob closure)
closure-template closure-template-offset
closure-env closure-env-offset
#f))
(define transport-pair
(transport-two-slot (enum stob pair)
car car-offset
cdr cdr-offset
#t)) ; *** ?
; Transporting a location requires some care so as to avoid calling CONTENTS
; when the location is unbound.
(define (transport-location loc)
(let* ((data (allocate-d-vector (enum stob location) 2 #f))
(descriptor (car data))
(vector (cdr data)))
(vector-set! vector
location-contents-offset
(if (location-defined? loc)
(transport (contents loc))
vm-unbound))
(vector-set! vector
location-id-offset
(transport (location-id loc)))
descriptor))
; The characters on the linker system may not be the same as those of Scheme 48
(define (transport-string string)
(allocate-b-vector string
(lambda (x)
(scalar-value-units->bytes (string-length x)))))
; Symbols have two slots, the string containing the symbol's name and a slot
; used in building the symbol table.
; Characters in the symbol name are made to be lower case.
(define (transport-symbol symbol)
(let* ((data (allocate-d-vector (enum stob symbol) 2 #t))
(descriptor (car data))
(vector (cdr data)))
(vector-set! vector
0
(transport-string (symbol-case-converter (symbol->string symbol))))
(vector-set! vector
1
(transport #f))
descriptor))
(define (string-case-converter string)
(let ((new (make-string (string-length string) #\x)))
(do ((i 0 (+ i 1)))
((>= i (string-length new))
new)
(string-set! new i (preferred-case (string-ref string i))))))
;(define preferred-case ;Copied from rts/read.scm
; (if (char=? (string-ref (symbol->string 't) 0) #\T)
; char-upcase
; char-downcase))
(define preferred-case char-downcase)
(define symbol-case-converter
(if (char=? (string-ref (symbol->string 't) 0)
(preferred-case #\t))
(lambda (string) string)
string-case-converter))
; Templates and vectors have an arbitrary number of slots but are otherwise
; the same as pairs and closures.
(define (transport-template template)
(transport-vector-like template
(enum stob template)
(template-length template)
template-ref
#f))
(define (transport-vector vector)
(transport-vector-like vector
(enum stob vector)
(vector-length vector)
vector-ref
#t)) ;***
(define (transport-vector-like vector type length ref immutable?)
(cond
((assq vector *vector-alist*)
=> cdr)
(else
(let* ((data (allocate-d-vector type length immutable?))
(descriptor (car data))
(new (cdr data)))
(do ((i 0 (+ i 1)))
((>= i length))
(vector-set! new i (transport (ref vector i) vector type)))
(set! *vector-alist* (cons (cons vector descriptor) *vector-alist*))
descriptor))))
;==============================================================================
; Writing the heap out to a port.
(define (write-heap port)
(do ((heap (reverse *heap*) (cdr heap)))
((null? heap))
(write-heap-stob (car heap) port)))
; Dispatch on the type of THING and call WRITE-STOB.
(define (write-heap-stob thing port)
(cond ((string? thing)
(let* ((len (string-length thing))
(byte-len (scalar-value-units->bytes len)))
(write-stob (make-header-immutable ; ***
(make-header (enum stob string) byte-len))
thing len string-ref write-char-scalar-value port)
(align-port byte-len port)))
((code-vector? thing)
(let ((len (code-vector-length thing)))
(write-stob (make-header-immutable ; ***
(make-header (enum stob byte-vector) len))
thing len code-vector-ref write-byte port)
(align-port len port)))
((vector? thing)
(let ((len (vector-length thing)))
(write-stob (vector-ref thing (- len 1))
thing (- len 1) vector-ref write-descriptor port)))
(else
(assertion-violation 'write-heap-stob "do not know how to write stob" thing))))
; Write out a transported STOB to PORT. HEADER is the header, LENGTH is the
; number of objects the STOB contains, ACCESSOR and WRITER access the contents
; and write them to the heap.
(define (write-stob header contents length accessor writer port)
(write-descriptor header port)
(do ((i 0 (+ i 1)))
((>= i length))
(writer (accessor contents i) port)))
(define (write-char-scalar-value char port)
(write-scalar-value (char->ascii char) ; ASCII is a subset of Unicode code points
port))
; Write out zeros to align the port on a four-byte boundary.
(define (align-port len port)
(let ((count (- (cells->bytes (bytes->cells len)) len)))
(do ((count count (- count 1)))
((<= count 0))
(write-byte 0 port))))
|