;;; -*- Mode:LISP; Package:USER; Base:10; Readtable:CL -*- (defun k-unfasl-file (filename) (let ((pathname (parse-namestring filename))) (with-open-file (kfasl-stream pathname :direction :input :element-type '(unsigned-byte 8)) (with-open-file (output-stream (format nil "ed-buffer: unkfasl of ~a" (namestring pathname)) :direction :output) (unkfasl-loop kfasl-stream output-stream))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; For some objects we can just bullshit our way through to describe them ;;; but for some things like fixnums ans strings, we need to represent them ;;; on the lambda because they are used in the fasl file to describe other ;;; fasl file entries. (defstruct (unkfasl-object :named (:constructor make-unkfasl-object-internal) (:print-function print-unkfasl-object)) type print-function) (defun make-unkfasl-object (type print-function) (make-unkfasl-object-internal :type type :print-function print-function)) (defun print-unkfasl-object (obj stream &rest ignore) (funcall (unkfasl-object-print-function obj) obj stream)) ;(defun unkfasl-object-value (object &optional &key (error-p t)) ; (if (typep object 'unkfasl-object) ; (if (unkfasl-object-value-p object) ; (if error-p ; (error nil "K unfasl doesn't understand values of ~a's" (unkfasl-object-type object)) ; object) ; (unkfasl-object-value object)) ; object)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun unkfasl-loop (kfasl-stream output-stream) (do ((something (unkfasl-something kfasl-stream output-stream) (unkfasl-something kfasl-stream output-stream))) ((and (typep something 'unkfasl-object) (eq :end-of-file (unkfasl-object-type something)))) (print something output-stream))) (defstruct (unkfasl-desc (:conc-name) (:constructor make-unkfasl-desc (unkfasl-name unkfasl-opcode unkfasl-function))) unkfasl-name unkfasl-opcode unkfasl-function) (defmacro make-unkfasl-table (&rest descriptors) `(defconstant unkfasl-table (mapcar #'(lambda (thing) (let ((opcode-name (first thing)) (unfasl-function (second thing))) (make-unkfasl-desc opcode-name (symbol-value opcode-name) unfasl-function))) ',descriptors))) ;;; for objects that can be exactly represented on the lambda, a LISP object of the correct type ;;; is returned. For other objects, a named structure of thpe 'UNKFASL-OBJECT is created. (make-unkfasl-table (k2:$$fasl-op-bignum unkfasl-bignum) (K2:$$fasl-op-compiled-function unkfasl-compiled-function) ; OBJECT (K2:$$fasl-op-cons unkfasl-cons) ; VALUE (K2:$$fasl-op-create-table unkfasl-create-table) (K2:$$fasl-op-defafun unkfasl-defafun) ; OBJECT (K2:$$fasl-op-defconstant unkfasl-defconstant) ; OBJECT (K2:$$fasl-op-defmacro unkfasl-defmacro) ; OBJECT (K2:$$fasl-op-defsubst unkfasl-defsubst) ; OBJECT (K2:$$fasl-op-defun unkfasl-defun) ; OBJECT (K2:$$fasl-op-end-of-object unkfasl-end-of-object) (K2:$$fasl-op-end-of-file unkfasl-end-of-file) ; OBJECT (K2:$$fasl-op-escape unkfasl-escape) (K2:$$fasl-op-eval unkfasl-eval) ; OBJECT (K2:$$fasl-op-fixnum unkfasl-fixnum) ; VALUE (K2:$$fasl-op-in-package unkfasl-in-package) (K2:$$fasl-op-nil unkfasl-nil) ; VALUE (K2:$$fasl-op-reference-table-index unkfasl-ref-table-index) (K2:$$fasl-op-store-table-index unkfasl-store-table-index) (K2:$$fasl-op-string unkfasl-string) ; VALUE (K2:$$fasl-op-string-character unkfasl-string-character) ; VALUE (K2:$$fasl-op-symbol unkfasl-symbol) ; OBJECT (K2:$$fasl-op-short-float unkfasl-short-float) ; OBJECT (K2:$$fasl-op-single-float unkfasl-single-float) ; OBJECT (K2:$$fasl-op-double-float unkfasl-double-float) ; OBJECT (K2:$$fasl-op-defvar unkfasl-defvar) ; OBJECT (K2:$$fasl-op-defparameter unkfasl-defparameter) ; OBJECT (K2:$$fasl-op-unbound unkfasl-unbound) ; OBJECT (K2:$$fasl-op-simple-vector unkfasl-simple-vector) ) (defun unkfasl-something (kfasl-stream output-stream) (let* ((fasl-opcode (read-byte kfasl-stream)) (unfasl (car (member fasl-opcode unkfasl-table :test #'= :key #'unkfasl-opcode)))) (if unfasl (funcall (unkfasl-function unfasl) kfasl-stream output-stream) (error nil "Unknown fasl opcode #x~x" fasl-opcode)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Now deal with the fasl opcodes ; (defun unkfasl-nil (kfasl-stream output-stream) (declare (ignore kfasl-stream output-stream)) nil) (defun unkfasl-fixnum (kfasl-stream output-stream) (declare (ignore output-stream)) (let ((low-bits (read-byte kfasl-stream)) (medium-bits (read-byte kfasl-stream)) (high-bits (read-byte kfasl-stream))) (dpb high-bits (byte 8. 16.) (dpb medium-bits (byte 8. 8.) low-bits)))) (defun unkfasl-short-float (kfasl-stream output-stream) (declare (ignore output-stream)) (make-unkfasl-object :short-float (let ((b1 (read-byte kfasl-stream)) (b2 (read-byte kfasl-stream)) (b3 (read-byte kfasl-stream)) (b4 (read-byte kfasl-stream))) #'(lambda (object stream) (declare (ignore object)) (format stream "<>" b1 b2 b3 b4))))) (defun unkfasl-single-float (kfasl-stream output-stream) (declare (ignore output-stream)) (make-unkfasl-object :single-float (let ((b1 (read-byte kfasl-stream)) (b2 (read-byte kfasl-stream)) (b3 (read-byte kfasl-stream)) (b4 (read-byte kfasl-stream))) #'(lambda (object stream) (declare (ignore object)) (format stream "<>" b1 b2 b3 b4))))) (defun unkfasl-double-float (kfasl-stream output-stream) (declare (ignore output-stream)) (make-unkfasl-object :double-float (let ((b1 (read-byte kfasl-stream)) (b2 (read-byte kfasl-stream)) (b3 (read-byte kfasl-stream)) (b4 (read-byte kfasl-stream)) (b5 (read-byte kfasl-stream)) (b6 (read-byte kfasl-stream)) (b7 (read-byte kfasl-stream)) (b8 (read-byte kfasl-stream))) #'(lambda (object stream) (declare (ignore object)) (format stream "<>" b1 b2 b3 b4 b5 b6 b7 b8))))) (defun unkfasl-string-character (kfasl-stream output-stream) (declare (ignore output-stream)) (int-char (read-byte kfasl-stream))) (defun unkfasl-string (kfasl-stream output-stream) (let* ((length (unkfasl-fixnum kfasl-stream output-stream)) (string (make-string length))) (dotimes (i length) (aset (unkfasl-string-character kfasl-stream output-stream) string i)) string)) (defun unkfasl-symbol (kfasl-stream output-stream) (declare (unspecial package)) (let ((symbol (unkfasl-something kfasl-stream output-stream)) (package (unkfasl-something kfasl-stream output-stream))) (unless (and (stringp symbol) (stringp package)) (error nil "FASL-OP-SYMBOL not followed by two strings")) (make-unkfasl-object :symbol #'(lambda (object stream) (declare (ignore object)) (format stream "~a:~a" package symbol))))) (defun unkfasl-unbound (kfasl-stream output-stream) (declare (ignore kfasl-stream output-stream)) (make-unkfasl-object :unbound-token #'(lambda (object stream) (declare (ignore object)) (format stream "[unbound]")))) (defun unkfasl-defvar (kfasl-stream output-stream) (let ((symbol (unkfasl-something kfasl-stream output-stream)) (value (unkfasl-something kfasl-stream output-stream)) (doc (unkfasl-something kfasl-stream output-stream))) (unless (eq :symbol (unkfasl-object-type symbol)) (error nil "defvar of other than a symbol")) (make-unkfasl-object :defvar #'(lambda (object stream) (declare (ignore object)) (format stream "{defvar ~a ~s ~s}" symbol value doc))))) (defun unkfasl-defparameter (kfasl-stream output-stream) (let ((symbol (unkfasl-something kfasl-stream output-stream)) (value (unkfasl-something kfasl-stream output-stream)) (doc (unkfasl-something kfasl-stream output-stream))) (unless (eq :symbol (unkfasl-object-type symbol)) (error nil "defvar of other than a symbol")) (make-unkfasl-object :defparameter #'(lambda (object stream) (declare (ignore object)) (format stream "{defparameter ~a ~s ~s}" symbol value doc))))) (defun unkfasl-defconstant (kfasl-stream output-stream) (let ((symbol (unkfasl-something kfasl-stream output-stream)) (value (unkfasl-something kfasl-stream output-stream)) (doc (unkfasl-something kfasl-stream output-stream))) (unless (eq :symbol (unkfasl-object-type symbol)) (error nil "defvar of other than a symbol")) (make-unkfasl-object :defconstant #'(lambda (object stream) (declare (ignore object)) (format stream "{defconstant ~a ~s ~s}" symbol value doc))))) (defun unkfasl-cons (kfasl-stream output-stream) (cons (unkfasl-something kfasl-stream output-stream) (unkfasl-something kfasl-stream output-stream))) (defun unkfasl-defun-like (type kfasl-stream output-stream) (let ((name (unkfasl-something kfasl-stream output-stream)) (function (unkfasl-something kfasl-stream output-stream))) (make-unkfasl-object :defun #'(lambda (object stream) (declare (ignore object)) (format stream "{~a ~a ~a}" type name function))))) (defun unkfasl-defmacro (kfasl-stream output-stream) (unkfasl-defun-like "defmacro" kfasl-stream output-stream)) (defun unkfasl-defun (kfasl-stream output-stream) (unkfasl-defun-like "defun" kfasl-stream output-stream)) (defun unkfasl-defafun (kfasl-stream output-stream) (unkfasl-defun-like "defafun" kfasl-stream output-stream)) (defun unkfasl-defsubst (kfasl-stream output-stream) (let ((defsubst-stuff (unkfasl-something kfasl-stream output-stream))) (declare (ignore defsubst-stuff)) (unkfasl-defun-like "defsubst" kfasl-stream output-stream))) (defun unkfasl-compiled-function (kfasl-stream output-stream) (let ((symbol (unkfasl-something kfasl-stream output-stream)) (local-refs (unkfasl-cf-local-refs kfasl-stream output-stream)) (refs (unkfasl-cf-refs kfasl-stream output-stream)) (entry-points (unkfasl-cf-entry-points kfasl-stream output-stream)) (length (unkfasl-fixnum kfasl-stream output-stream))) (declare (ignore symbol local-refs refs entry-points)) (dotimes (i length) (let ((*standard-output* output-stream) (lo (unkfasl-read-unboxed-word kfasl-stream output-stream)) (hi (unkfasl-read-unboxed-word kfasl-stream output-stream))) (format t "~&~8,48x ~8,48x " hi lo) (k-kbug:kbug2-print-instruction (dpb (ldb (byte 16 16) hi) (byte 16 48) (dpb (ldb (byte 16 0) hi) (byte 16 32) lo)) i))) (make-unkfasl-object :compiled-code #'(lambda (object stream) (declare (ignore object)) (format stream "[compiled-code]"))))) (defun unkfasl-cf-local-refs (kfasl-stream output-stream) (let* ((n (unkfasl-fixnum kfasl-stream output-stream)) (refs nil)) (dotimes (i n) (push (cons (unkfasl-fixnum kfasl-stream output-stream) (unkfasl-fixnum kfasl-stream output-stream)) refs)) (cons :local-refs (nreverse refs)))) (defun unkfasl-cf-refs (kfasl-stream output-stream) (let* ((n (unkfasl-fixnum kfasl-stream output-stream)) (refs nil)) (dotimes (i n) (push (list (unkfasl-fixnum kfasl-stream output-stream) (unkfasl-symbol kfasl-stream output-stream) (unkfasl-fixnum kfasl-stream output-stream)) refs)) (cons :refs (nreverse refs)))) (defun unkfasl-cf-entry-points (kfasl-stream output-stream) (let ((n (unkfasl-fixnum kfasl-stream output-stream)) (ent nil)) (dotimes (i n) (push (list :args (unkfasl-fixnum kfasl-stream output-stream) :offset (unkfasl-fixnum kfasl-stream output-stream)) ent)) (cons :entry-points (nreverse ent)))) (defun unkfasl-read-16-bits (kfasl-stream output-stream) (declare (ignore output-stream)) (let ((low-half (read-byte kfasl-stream)) (high-half (read-byte kfasl-stream))) (dpb high-half (byte 8. 8.) low-half))) (defun unkfasl-read-unboxed-word (kfasl-stream output-stream) (let ((low-half (unkfasl-read-16-bits kfasl-stream output-stream)) (high-half (unkfasl-read-16-bits kfasl-stream output-stream))) (dpb high-half (byte 16. 16.) low-half))) (defun unkfasl-end-of-file (kfasl-stream output-stream) (declare (ignore kfasl-stream output-stream)) (make-unkfasl-object :end-of-file #'(lambda (object stream) (declare (ignore object)) (format stream "[end-of-file]")))) (defun unkfasl-eval (kfasl-stream output-stream) (let ((form (unkfasl-something kfasl-stream output-stream))) (make-unkfasl-object :eval #'(lambda (object stream) (declare (ignore object)) (format stream "{eval ~s}" form)))))