; 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*))))