scsh-0.5/big/external.scm

127 lines
3.4 KiB
Scheme

; Copyright (c) 1993, 1994 Richard Kelsey and Jonathan Rees. See file COPYING.
; Code for keeping external pointers in a table similar to the symbol table.
;
; The entry points for this code are:
;
; (GET-EXTERNAL string) returns an external pointer
; (LOOKUP-ALL-EXTERNALS) looks up new values for all external pointers;
; ideally this should be called automatically
; on startup
(define *the-external-table* #f)
(define (flush-the-external-table!)
(set! *the-external-table* #f))
(define (restore-the-external-table!)
(set! *the-external-table* (make-string-table))
(vector-for-each (lambda (external)
(table-set! *the-external-table*
(external-name external)
external))
(find-all-xs (enum stob external))))
(define (gc-externals)
(flush-the-external-table!)
(collect)
(restore-the-external-table!))
(define (vector-for-each proc vector)
(do ((i 0 (+ i 1)))
((>= i (vector-length vector))
(unspecific))
(proc (vector-ref vector i))))
(restore-the-external-table!)
;------------------------------------------------------------
(define (get-external name)
(cond ((table-ref *the-external-table* name)
=> (lambda (x) x))
(else
(let ((new (maybe-external-lookup
(make-external name (make-code-vector 4 0)))))
(if new
(table-set! *the-external-table* name new)
(warn "External not found" name))
new))))
(define (maybe-external-lookup external)
(call-with-current-continuation
(lambda (lose)
(with-handler
(lambda (c punt)
(cond ((or (not (exception? c))
(not (= op/external-lookup (exception-opcode c))))
(punt))
(else
(lose #f))))
(lambda ()
(external-lookup external)
external)))))
(define op/external-lookup (enum op external-lookup))
(define (null-terminate str)
;; No longer necessary
(string-append str (string (ascii->char 0))))
;------------------------------------------------------------
(define (lookup-all-externals)
(cond ((try-to-lookup-all-externals)
#t)
(else
(display "GCing to try to remove unbound externals")
(newline)
(gc-externals)
(really-lookup-all-externals))))
; Quietly look up all externals, returning #F if unsuccessful
(define (try-to-lookup-all-externals)
(call-with-current-continuation
(lambda (k)
(lookup-all-externals-with-handler
(lambda (external)
(k #f)))
#t)))
; Look up all externals, printing out the names of those that cannot
; be found.
(define (really-lookup-all-externals)
(let ((okay? #t))
(lookup-all-externals-with-handler
(lambda (external)
(cond (okay?
(display "Remaining unbound external(s):")
(newline)
(set! okay? #f)))
(display " ")
(display (external-name external))
(newline)))
okay?))
; Look up all externals, calling PROC on any that cannot be found.
; This assumes that not finding a value for the name is the only reason why
; op/external-lookup would fail, which isn't quite true. Other possible
; reasons are that the name is not a string, or the value is not a
; code vector.
(define (lookup-all-externals-with-handler proc)
(with-handler
(lambda (c punt)
(if (or (not (exception? c))
(not (= op/external-lookup (exception-opcode c))))
(punt)
(proc (car (exception-arguments c)))))
(lambda ()
(table-walk (lambda (name external)
(external-lookup external))
*the-external-table*))))