;;; -*- Mode:LISP; Package:SYSTEM-INTERNALS; Base:10 -*- ;;; to remove a system. ;;; umake it. ;;; then if it has a package that it alone deals with use KILL-PACKAGE on that package. (defun unmake-system (name) (let ((sys (si:find-system-named name nil t))) (let ((files (reverse (system-files-loaded name)))) (format t "~&~D files to unload~%" (length files)) (mapcar #'unload-file files) (setq *SYSTEMS-LIST* (delq sys *SYSTEMS-LIST*)) (let ((psys (ASS #'STRING-EQUAL (SYSTEM-NAME SYS) PATCH-SYSTEMS-LIST))) (when psys (setq PATCH-SYSTEMS-LIST (delq psys PATCH-SYSTEMS-LIST)) (setq frozen-PATCH-SYSTEMS-LIST (delq psys frozen-PATCH-SYSTEMS-LIST)))) sys))) (defun system-files-loaded (name) (apply #'append (mapcar #'transformation-loaded-files (make-system name :print-only :silent :reload :no-reload-system-declaration)))) (defun transformation-loaded-files (z) (let ((type (file-transformation-transformation-type z))) (funcall (or (get (transformation-type-name type) 'transformation-loaded-files) #'(lambda (type system args) system args (format t "~&Warning: unhandled transformation type ~S~%" (transformation-type-name type)) ())) type (file-transformation-system z) (file-transformation-args z)))) (defun (:fasload transformation-loaded-files) (type system args) type system args) (defun (increment-loaded-version transformation-loaded-files) (type system args) type args (multiple-value-bind (major minor) (get-system-version system) (do ((j minor (1- j)) (l nil (cons (patch-system-pathname (system-name system) :patch-file major j :qfasl) l))) ((zerop j) l)))) (defvar *unload-doit* nil) (defun unload-file (name) (let ((pathname (send (fs:parse-pathname name) :generic-pathname))) (format t "~&Unloading ~A~%" pathname) (dolist (dp (get pathname :definitions)) (format t " ~d definition~:*~p in package ~A~%" (length (cdr dp)) (car dp)) (dolist (d (cdr dp)) (unload-definition (cdr d) (car d)))) (if *unload-doit* (setf (get pathname :definitions) nil)) (let ((forms (get pathname :random-forms))) (when forms (format t " ~d random form~:*~p~%" (length forms)) (dolist (form forms) (unload-form form)))) (if *unload-doit* (setf (get pathname :random-forms) nil)))) (defun unload-definition (type def) (let ((handler (get type 'unload-definition))) (cond (handler (and *unload-doit* (funcall handler def))) ('else (format t " Unhandled definition type ~S: ~S~%" type def))))) (defun (defun unload-definition) (def) (when (fdefinedp def) ;; it is possible for a patch file to define something ;; this works for functions, properties, methods. (fundefine def) (or (and (consp def) (eq :property (car def))) (remove-source-file-name def 'defun)) )) (defun (defvar unload-definition) (def) (makunbound def) (remprop def 'special) (remove-documentation def 'VARIABLE) (remove-source-file-name def 'defvar)) (defun (defstruct unload-definition) (def) (remprop def 'defstruct-description) (remove-source-file-name def 'defstruct)) (defun (defflavor unload-definition) (def) (catch-error (undefflavor def)) (remprop def 'si:flavor) (remove-source-file-name def 'defflavor)) (defun (defsignal unload-definition) (def) (remove-source-file-name def 'defsignal) (remove-documentation def 'signal) (remprop def 'make-condition-function)) (defun (defresource unload-definition) (def) (remove-source-file-name def 'DEFRESOURCE) (remove-documentation def 'resource) (when (GET def 'DEFRESOURCE) (clear-resource def) (remprop def 'defresource)) (setq *all-resources* (delq def *all-resources*))) (defun unload-form (f &aux temp) (cond ((atom f)) ((setq temp (find-unload-form f)) (and *unload-doit* (funcall temp f))) ('else (format t " Unhandled form: ~S~%" f)))) (defvar *unload-form-handlers* '(((putprop (? constantp) * (? constantp)) unload-putprop) ((defprop * * *) unload-defprop) ((deff-macro * *) unload-defmacro) ((setq patch-source-file-namestring *) unload-ignored) ((setq * *) unload-setq) ((fasl-record-file-macros-expanded *) unload-ignored) ((set-documentation (? constantp) (? constantp) *) unload-documentation) ((add-initialization (? constantp) *) unload-initialization) ((add-initialization (? constantp) * (? constantp)) unload-initialization) ((add-initialization (? constantp) * (? constantp) (? constantp)) unload-initialization) ((TV:ADD-SYSTEM-KEY (? constantp) . *) unload-system-key) )) (defun unload-putprop (form) (remprop (eval (nth 1 form)) (eval (nth 3 form)))) (defun unload-defprop (form) (remprop (nth 1 form) (nth 3 form))) (defun unload-ignored (form) form) (defun unload-defmacro (form) (let ((f (cadr form))) (remove-source-file-name f 'defun) (fmakunbound f))) (defun unload-setq (form) (makunbound (cadr form))) (defun find-unload-form (f) (do ((l *unload-form-handlers* (cdr l))) ((null l) nil) (when (form-match (caar l) f) (return (cadar l))))) (defun form-match (pattern form) (cond ((atom pattern) (or (eq pattern '*) (eq pattern form))) ((eq (car pattern) '?) (funcall (cadr pattern) form)) ((atom form) nil) ('else (do ((l1 pattern (cdr l1)) (l2 form (cdr l2))) ((atom l1) (form-match l1 l2)) (if (atom l2) (return nil)) (or (form-match (car l1) (car l2)) (return nil)))))) (defun remove-documentation (spec doc-type) (LET* ((S (SYMBOL-NAME DOC-TYPE)) (l (function-spec-GET spec 'DOCUMENTATION-PROPERTY)) (C (ASSOC-EQUAL S l))) (when c (setq l (delq c l)) (cond (l (setf (function-spec-get spec 'DOCUMENTATION-PROPERTY) l)) ('else (function-spec-remprop spec 'DOCUMENTATION-PROPERTY)))))) (defun remove-source-file-name (spec type) (LET* ((S (SYMBOL-NAME TYPE)) (l (function-spec-GET spec ':SOURCE-FILE-NAME))) (cond ((not l)) ((atom l) (function-spec-remprop spec ':SOURCE-FILE-NAME)) ('else (let ((C (ASSOC-EQUAL S l))) (when c (setq l (delq c l)) (cond (l (setf (function-spec-get spec ':SOURCE-FILE-NAME) l)) ('else (function-spec-remprop spec ':SOURCE-FILE-NAME))))))))) (defun unload-initialization (form) ;;(add-initialization name form keywords list-name) (format t "~& Initialization: ~S~%" form) (ecase (length form) (3 (delete-initialization (eval (nth 1 form)))) (4 (delete-initialization (eval (nth 1 form)) (eval (nth 3 form)))) (5 (delete-initialization (eval (nth 1 form)) (eval (nth 3 form)) (eval (nth 4 form)))))) (defun unload-system-key (form) (let ((char (eval (nth 1 form)))) (SETQ *SYSTEM-KEYS* (DELETE-IF #'(LAMBDA (ELT) (CHAR-EQUAL (CAR ELT) CHAR)) *SYSTEM-KEYS*))))