411 lines
14 KiB
ArmAsm
411 lines
14 KiB
ArmAsm
|
; -*- Mode: Lisp -*- Filename: pdebug.s
|
|||
|
|
|||
|
;--------------------------------------------------------------------------;
|
|||
|
; ;
|
|||
|
; TI SCHEME -- PCS Compiler ;
|
|||
|
; Copyright 1985 (c) Texas Instruments ;
|
|||
|
; ;
|
|||
|
; David Bartley ;
|
|||
|
; ;
|
|||
|
; System Debugger and Error Handlers ;
|
|||
|
; ;
|
|||
|
;--------------------------------------------------------------------------;
|
|||
|
|
|||
|
; Revision history:
|
|||
|
; db 10/18/85 - ??
|
|||
|
; tc 03/13/87 - Extended errors for DOS I/O errors
|
|||
|
|
|||
|
|
|||
|
; The following definitions are used only at compile time for readability
|
|||
|
; and understanding. They will not be written out to the .so file.
|
|||
|
; See pboot.s and compile.all.
|
|||
|
|
|||
|
(compile-time-alias IO-ERRORS-START 21)
|
|||
|
(compile-time-alias IO-ERRORS-END 108)
|
|||
|
(compile-time-alias DOS-IO-ERROR 21)
|
|||
|
(compile-time-alias FILE-NOT-FOUND 22)
|
|||
|
(compile-time-alias PATH-NOT-FOUND 23)
|
|||
|
(compile-time-alias TOO-MANY-FILES 24)
|
|||
|
|
|||
|
(define assert-procedure)
|
|||
|
(define breakpoint-procedure)
|
|||
|
(define error-procedure)
|
|||
|
(define *error-handler*)
|
|||
|
|
|||
|
(letrec
|
|||
|
((uv-msg
|
|||
|
'(1 2 3 4))
|
|||
|
(msg-codes
|
|||
|
'((0 . "Unspecified VM error")
|
|||
|
(1 . "Variable not defined in current environment")
|
|||
|
(2 . "SET! of an unbound variable")
|
|||
|
(3 . "Variable not defined in lexical environment")
|
|||
|
(4 . "SET! of an unbound lexical variable")
|
|||
|
(5 . "Variable not defined in fluid environment")
|
|||
|
(6 . "SET-FLUID! of an unbound fluid variable")
|
|||
|
(7 . "Vector index out of range")
|
|||
|
(8 . "String index out of range")
|
|||
|
(9 . "Invalid substring range") ; not generated
|
|||
|
(10 . "Invalid operand to VM instruction")
|
|||
|
(11 . "User keyboard interrupt")
|
|||
|
(12 . "Attempt to call a non-procedural object")
|
|||
|
;; (13 . "Engine Timer Interrupt")
|
|||
|
(14 . "I/O attempted to a de-exposed window")
|
|||
|
;; 14 is a trap for a window handler, not a real error
|
|||
|
(15 . "FLONUM overflow or underflow")
|
|||
|
(16 . "Divide by zero")
|
|||
|
(17 . "Non-numeric operand to arithmetic operation")
|
|||
|
(18 . "Register overflow--Too many arguments to closure")
|
|||
|
(19 . "MAKE-VECTOR size limit exceeded")
|
|||
|
(20 . "MAKE-STRING size limit exceeded")
|
|||
|
(21 . "DOS I/O error number ")
|
|||
|
(22 . "DOS I/O error - File not found")
|
|||
|
(23 . "DOS I/O error - Path not found")
|
|||
|
(24 . "DOS I/O error - Too many open files")
|
|||
|
(25 . "DOS I/O error - Access denied")
|
|||
|
(32 . "DOS I/O error - Invalid access")
|
|||
|
(36 . "DOS I/O error - Invalid disk drive")
|
|||
|
(39 . "DOS I/O error - Disk write protected")
|
|||
|
(41 . "DOS I/O error - Drive not ready")
|
|||
|
(48 . "DOS I/O error - Printer out of paper")
|
|||
|
(200 . "DOS I/O error - Disk Full")
|
|||
|
))
|
|||
|
(oops
|
|||
|
(lambda (msg irritant env stk-index kind error-code)
|
|||
|
(fluid-let ((input-port standard-input)
|
|||
|
(output-port standard-output))
|
|||
|
(let* ((si (if (negative? stk-index)
|
|||
|
(%reify-stack (+ (%reify-stack -1) 6))
|
|||
|
stk-index))
|
|||
|
(env (if (null? env)
|
|||
|
(%reify-stack (+ si 9))
|
|||
|
env)))
|
|||
|
(newline)
|
|||
|
(display kind)
|
|||
|
(when msg (display msg))
|
|||
|
(newline)
|
|||
|
(write irritant)
|
|||
|
(newline)
|
|||
|
(pcs-kill-engine)
|
|||
|
|
|||
|
(if (unbound? compile)
|
|||
|
;; see if compiler auto-loadable
|
|||
|
(when (not (pcs-autoload-binding 'compile))
|
|||
|
;; Cant find compiler, punt
|
|||
|
(display (integer->char 7)) ;beep
|
|||
|
(display "Press a key to return to toplevel, escape to exit to DOS")
|
|||
|
(let ((ch (read-char)))
|
|||
|
(if (char=? ch #\escape)
|
|||
|
(exit)
|
|||
|
(scheme-reset))))
|
|||
|
;else
|
|||
|
(if (null? (%env-lu '%inspector user-initial-environment))
|
|||
|
;; check to see if we can load the inspector
|
|||
|
(when (or (eqv? *error-message* TOO-MANY-FILES)
|
|||
|
(null? (pcs-autoload-binding '%inspector)))
|
|||
|
(display "Unable to autoload the inspector - file PINSPECT.FSL")
|
|||
|
(reset))))
|
|||
|
|
|||
|
(%inspector msg kind irritant env si error-code)
|
|||
|
|
|||
|
))))
|
|||
|
(envoke-handler
|
|||
|
(lambda (number msg irritant stk-index err-code)
|
|||
|
(let ((handler (lambda ()
|
|||
|
(oops msg
|
|||
|
irritant
|
|||
|
'()
|
|||
|
stk-index
|
|||
|
"[VM ERROR encountered!] "
|
|||
|
err-code))))
|
|||
|
(if (closure? *user-error-handler*)
|
|||
|
(*user-error-handler* number
|
|||
|
msg
|
|||
|
irritant
|
|||
|
handler)
|
|||
|
(handler)))))
|
|||
|
(decipher-error
|
|||
|
(lambda (stk-index)
|
|||
|
(let ((err-code *error-code*)
|
|||
|
(irritant *irritant*)
|
|||
|
(err-num (and (number? *error-message*) *error-message*))
|
|||
|
(msg (apply-if (assv *error-message* msg-codes)
|
|||
|
cdr
|
|||
|
*error-message*)))
|
|||
|
(cond ((eqv? err-num 11) ; Shift Break
|
|||
|
(set! err-num 100))
|
|||
|
((and err-num ; I/O Errors
|
|||
|
(>= err-num IO-ERRORS-START)
|
|||
|
(<= err-num IO-ERRORS-END))
|
|||
|
(if (and (or (=? err-num FILE-NOT-FOUND)
|
|||
|
(=? err-num PATH-NOT-FOUND))
|
|||
|
(fluid-bound? *file-exists-open*))
|
|||
|
((fluid *file-exists-open*) #!false)) ; error continuation
|
|||
|
|
|||
|
(set! err-num (- err-num (-1+ DOS-IO-ERROR)))
|
|||
|
(if (number? msg)
|
|||
|
(set! msg (string-append (cdr (assv DOS-IO-ERROR msg-codes))
|
|||
|
(integer->string err-num 10))))))
|
|||
|
(envoke-handler err-num msg irritant stk-index err-code))))
|
|||
|
) ; letrec vars
|
|||
|
|
|||
|
(begin
|
|||
|
(set! assert-procedure ; ASSERT-PROCEDURE
|
|||
|
(lambda (msgs env)
|
|||
|
(oops '() (cons 'ASSERT (cons '() msgs)) env -1 "[ASSERT failure!] " 0)))
|
|||
|
|
|||
|
(set! breakpoint-procedure ; BREAKPOINT-PROCEDURE
|
|||
|
(lambda (msg irritant env . rest)
|
|||
|
(let* ((stk-index (if (or (null? rest)
|
|||
|
(not (integer? (car rest))))
|
|||
|
-1
|
|||
|
(car rest))))
|
|||
|
(oops msg irritant env stk-index "[BKPT encountered!] " 0))))
|
|||
|
|
|||
|
(set! error-procedure ; ERROR-PROCEDURE
|
|||
|
(lambda (msg irritant env)
|
|||
|
(let ((system-error-handler
|
|||
|
(lambda ()
|
|||
|
(oops msg irritant env -1 "[ERROR encountered!] " 0))))
|
|||
|
(if (closure? *user-error-handler*)
|
|||
|
(begin
|
|||
|
(*user-error-handler* '() msg irritant system-error-handler))
|
|||
|
;else
|
|||
|
(system-error-handler)))))
|
|||
|
|
|||
|
(set! *error-handler* ; *ERROR-HANDLER*
|
|||
|
(lambda ()
|
|||
|
(cond ((and (zero? *error-code*) ; resumable
|
|||
|
(memv *error-message* uv-msg)) ; unbound symbol
|
|||
|
(if (pcs-autoload-binding *irritant*)
|
|||
|
'() ; autoload worked!
|
|||
|
;else
|
|||
|
(let ((info (getprop *irritant* 'PCS*PRIMOP-HANDLER))
|
|||
|
(compiler-present (or (not (unbound? compile))
|
|||
|
(pcs-autoload-binding 'compile))))
|
|||
|
(cond ((and compiler-present
|
|||
|
(integer? info)
|
|||
|
(getprop *irritant* 'PCS*OPCODE))
|
|||
|
(let* ((vars '(J I H G F E D C B A))
|
|||
|
(bvl (list-tail vars (- (length vars) info)))
|
|||
|
(form `(define ,*irritant*
|
|||
|
(lambda ,bvl
|
|||
|
(,*irritant* . ,bvl))))
|
|||
|
(dw pcs-display-warnings)
|
|||
|
(ip pcs-integrate-primitives))
|
|||
|
(set! pcs-display-warnings #!false)
|
|||
|
(set! pcs-integrate-primitives #!true)
|
|||
|
(eval form user-global-environment)
|
|||
|
(set! pcs-display-warnings dw)
|
|||
|
(set! pcs-integrate-primitives ip)
|
|||
|
'()))
|
|||
|
((and compiler-present
|
|||
|
(pair? info)
|
|||
|
(eq? (car info) 'DEFINE-INTEGRABLE))
|
|||
|
(let ((form `(define ,*irritant* ,(cdr info)))
|
|||
|
(dw pcs-display-warnings)
|
|||
|
(ip pcs-integrate-primitives))
|
|||
|
(set! pcs-display-warnings #!false)
|
|||
|
(set! pcs-integrate-primitives #!true)
|
|||
|
(eval form user-initial-environment)
|
|||
|
(set! pcs-display-warnings dw)
|
|||
|
(set! pcs-integrate-primitives ip)
|
|||
|
'()))
|
|||
|
(else
|
|||
|
(set! *error-message*
|
|||
|
(cdr (assv *error-message* msg-codes)))
|
|||
|
(*error-handler*))))))
|
|||
|
((eqv? *error-message* 13)
|
|||
|
(pcs-engine-timeout)) ; Engine Timeout
|
|||
|
(else
|
|||
|
(decipher-error (%reify-stack
|
|||
|
(+ (%reify-stack
|
|||
|
(+ (%reify-stack -1) 6)) 6)))))
|
|||
|
) ;lambda
|
|||
|
) ;set!
|
|||
|
) ;begin
|
|||
|
) ;letrec
|
|||
|
|
|||
|
(define autoload-from-file ; AUTOLOAD-FROM-FILE
|
|||
|
(lambda (file names . rest)
|
|||
|
(let ((env (if rest (car rest) user-initial-environment)))
|
|||
|
(putprop 'PCS-AUTOLOAD-INFO
|
|||
|
(cons (list file names env)
|
|||
|
(getprop 'PCS-AUTOLOAD-INFO
|
|||
|
'PCS-AUTOLOAD-INFO))
|
|||
|
'PCS-AUTOLOAD-INFO)
|
|||
|
'())))
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(define pcs-autoload-binding '()) ; PCS-AUTOLOAD-BINDING
|
|||
|
(define remove-autoload-info '()) ; REMOVE-AUTOLOAD-INFO
|
|||
|
|
|||
|
(letrec
|
|||
|
((find-entry
|
|||
|
(lambda (name info)
|
|||
|
(and info
|
|||
|
(or (symbol? name) (string? name))
|
|||
|
(find-item name (caar info)(cadar info) info))))
|
|||
|
(find-item
|
|||
|
(lambda (name file symbols info)
|
|||
|
(cond ((string? name)
|
|||
|
(if (string-ci=? name file)
|
|||
|
(car info)
|
|||
|
(find-entry name (cdr info))))
|
|||
|
((null? symbols)
|
|||
|
(find-entry name (cdr info)))
|
|||
|
((eq? name (car symbols))
|
|||
|
(car info))
|
|||
|
(else
|
|||
|
(find-item name file (cdr symbols) info))))))
|
|||
|
(set! pcs-autoload-binding
|
|||
|
(lambda (name)
|
|||
|
(let* ((info (getprop 'PCS-AUTOLOAD-INFO 'PCS-AUTOLOAD-INFO))
|
|||
|
(entry (find-entry name info)))
|
|||
|
(and entry
|
|||
|
(let ((file (car entry))
|
|||
|
(env (caddr entry)))
|
|||
|
(and (string? file)
|
|||
|
(file-exists? file)
|
|||
|
(let ((saved-env (%set-global-environment env)))
|
|||
|
(load file)
|
|||
|
(%set-global-environment saved-env)
|
|||
|
(not (null? (%env-lu name env)))
|
|||
|
)))))))
|
|||
|
(set! remove-autoload-info
|
|||
|
(lambda (filename)
|
|||
|
(let* ((info (getprop 'PCS-AUTOLOAD-INFO 'PCS-AUTOLOAD-INFO))
|
|||
|
(entry (find-entry (%system-file-name filename) info)))
|
|||
|
(and entry
|
|||
|
(putprop 'PCS-AUTOLOAD-INFO
|
|||
|
(delq! entry
|
|||
|
(getprop 'PCS-AUTOLOAD-INFO
|
|||
|
'PCS-AUTOLOAD-INFO))
|
|||
|
'PCS-AUTOLOAD-INFO)))))
|
|||
|
)
|
|||
|
|
|||
|
(define environment-bindings ; ENVIRONMENT-BINDINGS
|
|||
|
(letrec
|
|||
|
((linked-bindings
|
|||
|
(lambda (a-list names values)
|
|||
|
(if (null? names)
|
|||
|
(reverse! a-list)
|
|||
|
(linked-bindings (cons (cons (car names)(cdr values))
|
|||
|
a-list)
|
|||
|
(cdr names)
|
|||
|
(car values)))))
|
|||
|
(hashed-bindings
|
|||
|
(lambda (a-list index env)
|
|||
|
(if (zero? index)
|
|||
|
a-list
|
|||
|
(let ((bucket (%reify env index)))
|
|||
|
(hashed-bindings (if (null? bucket)
|
|||
|
a-list
|
|||
|
(bucket-bindings a-list bucket))
|
|||
|
(- index 1)
|
|||
|
env)))))
|
|||
|
(bucket-bindings
|
|||
|
(lambda (a-list bucket)
|
|||
|
(if (null? bucket)
|
|||
|
a-list
|
|||
|
(bucket-bindings (cons (car bucket) a-list)
|
|||
|
(cdr bucket))))))
|
|||
|
(lambda (obj)
|
|||
|
(if (null? obj)
|
|||
|
obj
|
|||
|
(let* ((env (cond ((environment? obj) ; environment?
|
|||
|
obj)
|
|||
|
((or (closure? obj) ; closure?
|
|||
|
(delayed-object? obj)) ; delayed object?
|
|||
|
(procedure-environment obj))
|
|||
|
(else
|
|||
|
(%error-invalid-operand 'ENVIRONMENT-BINDINGS
|
|||
|
obj))))
|
|||
|
(size (%reify env -1)))
|
|||
|
(if (= size 12)
|
|||
|
(linked-bindings '() (%reify env 1) (%reify env 2))
|
|||
|
(hashed-bindings '() (- (quotient size 3) 2) env)))))))
|
|||
|
|
|||
|
|
|||
|
;;;
|
|||
|
;;; UNBIND is a function which will remove a variable's binding from a given
|
|||
|
;;; environment. It will work for either of the 2 global environments
|
|||
|
;;; (USER-GLOBAL-ENVIRONMENT and USER-INITIAL-ENVIRONMENT) or for any other
|
|||
|
;;; heap allocated environments. Removing the binding from the environment
|
|||
|
;;; will allow the garbage collector to reclaim that space. Also, once
|
|||
|
;;; unbound, the autoloader may reload the variable whenever that variable
|
|||
|
;;; is referenced again.
|
|||
|
;;;
|
|||
|
|
|||
|
|
|||
|
(define unbind
|
|||
|
(letrec
|
|||
|
((remove-hashed-binding!
|
|||
|
(lambda (key alist)
|
|||
|
(cond ((null? (cadr alist))
|
|||
|
'())
|
|||
|
((eq? key (caadr alist))
|
|||
|
(set-cdr! alist (cddr alist)))
|
|||
|
(else
|
|||
|
(remove-hashed-binding! key (cdr alist))))))
|
|||
|
|
|||
|
(modify-hashed-env!
|
|||
|
(lambda (symbol env)
|
|||
|
(let* ((hash-val (1+ (%esc2 9 (symbol->string symbol))))
|
|||
|
(sym-list (%reify env hash-val)))
|
|||
|
|
|||
|
(if (null? sym-list)
|
|||
|
'()
|
|||
|
;else
|
|||
|
(begin
|
|||
|
(if (eq? symbol (caar sym-list))
|
|||
|
(set! sym-list (cdr sym-list))
|
|||
|
;else
|
|||
|
(remove-hashed-binding! symbol sym-list))
|
|||
|
(%reify! env hash-val sym-list)
|
|||
|
env)))))
|
|||
|
|
|||
|
(remove-linked-binding!
|
|||
|
(lambda (key names values)
|
|||
|
(cond ((null? (cadr names))
|
|||
|
'())
|
|||
|
((eq? key (cadr names))
|
|||
|
(set-cdr! names (cddr names))
|
|||
|
(set-car! values (caar values)))
|
|||
|
(else
|
|||
|
(remove-linked-binding! key (cdr names) (car values))))))
|
|||
|
|
|||
|
(modify-linked-env!
|
|||
|
(lambda (symbol env names values)
|
|||
|
(if (eq? symbol (car names))
|
|||
|
(begin
|
|||
|
(set! names (cdr names))
|
|||
|
(set! values (car values)))
|
|||
|
;else
|
|||
|
(remove-linked-binding! symbol names values))
|
|||
|
(%reify! env 1 names)
|
|||
|
(%reify! env 2 values)))
|
|||
|
)
|
|||
|
|
|||
|
(lambda (symbol env)
|
|||
|
(cond ((not (symbol? symbol))
|
|||
|
(%error-invalid-operand 'UNBIND symbol))
|
|||
|
((not (environment? env))
|
|||
|
(%error-invalid-operand 'UNBIND env))
|
|||
|
(else
|
|||
|
(if (= (%reify env -1) 12)
|
|||
|
(modify-linked-env! symbol env (%reify env 1) (%reify env 2))
|
|||
|
;
|
|||
|
(modify-hashed-env! symbol env)))))))
|
|||
|
|
|||
|
|
|||
|
(define (procedure-environment obj) ; PROCEDURE-ENVIRONMENT
|
|||
|
(cond ((closure? obj)
|
|||
|
(%reify obj 1))
|
|||
|
((delayed-object? obj)
|
|||
|
(procedure-environment (vector-ref obj 1)))
|
|||
|
(else
|
|||
|
(%error-invalid-operand 'PROCEDURE-ENVIRONMENT obj))))
|
|||
|
|
|||
|
|