⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disass.el

📁 早期freebsd实现
💻 EL
字号:
;;; Disassembler for compiled Emacs Lisp code;; Copyright (C) 1986 Free Software Foundation;;; By Doug Cutting (doug@csli.stanford.edu);; This file is part of GNU Emacs.;; GNU Emacs is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 1, or (at your option);; any later version.;; GNU Emacs is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GNU Emacs; see the file COPYING.  If not, write to;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.(require 'byte-compile "bytecomp")(defvar disassemble-column-1-indent 4 "*")(defvar disassemble-column-2-indent 9 "*")(defvar disassemble-recursive-indent 3 "*");(defun d (x);  (interactive "xDiss ");  (with-output-to-temp-buffer "*Disassemble*";    (disassemble-internal (list 'lambda '() x ''return-value);			  standard-output 0 t)))(defun disassemble (object &optional stream indent interactive-p)  "Print disassembled code for OBJECT on (optional) STREAM.OBJECT can be a function name, lambda expression or any function objectreturned by SYMBOL-FUNCTION.  If OBJECT is not already compiled, we willcompile it (but not redefine it)."  (interactive (list (intern (completing-read "Disassemble function: "					      obarray 'fboundp t))		     nil 0 t))  (or indent (setq indent 0))		;Default indent to zero  (if interactive-p      (with-output-to-temp-buffer "*Disassemble*"	(disassemble-internal object standard-output indent t))    (disassemble-internal object (or stream standard-output) indent nil))  nil)(defun disassemble-internal (obj stream indent interactive-p)  (let ((macro 'nil)	(name 'nil)	(doc 'nil)	args)    (while (symbolp obj)      (setq name obj	    obj (symbol-function obj)))    (if (subrp obj)	(error "Can't disassemble #<subr %s>" name))    (if (eq (car obj) 'macro)		;handle macros	(setq macro t	      obj (cdr obj)))    (if (not (eq (car obj) 'lambda))	(error "not a function"))    (if (assq 'byte-code obj)	nil      (if interactive-p (message (if name				     "Compiling %s's definition..."				     "Compiling definition...")				 name))      (setq obj (byte-compile-lambda obj))      (if interactive-p (message "Done compiling.  Disassembling...")))    (setq obj (cdr obj))		;throw lambda away    (setq args (car obj))		;save arg list    (setq obj (cdr obj))    (write-spaces indent stream)    (princ (format "byte code%s%s%s:\n"		   (if (or macro name) " for" "")		   (if macro " macro" "")		   (if name (format " %s" name) ""))	   stream)    (let ((doc (and (stringp (car obj)) (car obj))))      (if doc	  (progn (setq obj (cdr obj))		 (write-spaces indent stream)		 (princ " doc: " stream)		 (princ doc stream)		 (terpri stream))))    (write-spaces indent stream)    (princ " args: " stream)    (prin1 args stream)    (terpri stream)    (let ((interactive (car (cdr (assq 'interactive obj)))))      (if interactive	  (progn (write-spaces indent stream)		 (princ " interactive: " stream)		 (if (eq (car-safe interactive) 'byte-code)		     (disassemble-1 interactive stream		       (+ indent disassemble-recursive-indent))		   (prin1 interactive stream)		   (terpri stream)))))    (setq obj (assq 'byte-code obj))	;obj is now call to byte-code    (disassemble-1 obj stream indent))  (if interactive-p      (message "")))(defun disassemble-1 (obj &optional stream indent)  "Prints the byte-code call OBJ to (optional) STREAM.OBJ should be a call to BYTE-CODE generated by the byte compiler."  (or indent (setq indent 0))		;default indent to 0  (or stream (setq stream standard-output))  (let ((bytes (car (cdr obj)))		;the byte code	(ptr -1)			;where we are in it	(constants (car (cdr (cdr obj)))) ;constant vector	;(next-indent indent)	offset tmp length)    (setq length (length bytes))    (terpri stream)    (while (< (setq ptr (1+ ptr)) length)      ;(setq indent next-indent)      (write-spaces indent stream)	;indent to recursive indent      (princ (setq tmp (prin1-to-string ptr)) stream) ;print line #      (write-char ?\  stream)      (write-spaces (- disassemble-column-1-indent (length tmp) 1)		    stream)      (setq op (aref bytes ptr))	;fetch opcode      ;; Note: as offsets are either encoded in opcodes or stored as      ;; bytes in the code, this function (disassemble-offset)      ;; can set OP and/or PTR.      (setq offset (disassemble-offset));fetch offset      (setq tmp (aref byte-code-vector op))      (if (consp tmp)	  (setq ;next-indent (if (numberp (cdr tmp))		;		(+ indent (cdr tmp))		;	      (+ indent (funcall (cdr tmp) offset)))		tmp (car tmp)))      (setq tmp (symbol-name tmp))      (princ tmp stream)		;print op-name for opcode      (if (null offset)	  nil	(write-char ?\  stream)	(write-spaces (- disassemble-column-2-indent (length tmp) 1)		      stream)		;indent to col 2	(princ				;print offset	 (cond ((or (eq op byte-varref)		    (eq op byte-varset)		    (eq op byte-varbind))		;; it's a varname (atom)		(aref constants offset)) ;fetch it from constants	       ((or (eq op byte-goto)		    (eq op byte-goto-if-nil)		    (eq op byte-goto-if-not-nil)		    (eq op byte-goto-if-nil-else-pop)		    (eq op byte-goto-if-not-nil-else-pop)		    (eq op byte-call)		    (eq op byte-unbind))		;; it's a number		offset)			;return it	       ((or (eq op byte-constant)		    (eq op byte-constant2))		;; it's a constant		(setq tmp (aref constants offset))		;; but is constant byte code?		(cond ((and (eq (car-safe tmp) 'lambda)			    (assq 'byte-code tmp))		       (princ "<compiled lambda>" stream)		       (terpri stream)		       (disassemble	;recurse on compiled lambda			 tmp			 stream			 (+ indent disassemble-recursive-indent))		       "")		      ((eq (car-safe tmp) 'byte-code)		       (princ "<byte code>" stream)		       (terpri stream)		       (disassemble-1	;recurse on byte-code object			 tmp			 stream			 (+ indent disassemble-recursive-indent))		       "")		      ((eq (car-safe (car-safe tmp)) 'byte-code)		       (princ "(<byte code>...)" stream)		       (terpri stream)		       (mapcar		;recurse on list of byte-code objects			 (function (lambda (obj)				     (disassemble-1				       obj				       stream				       (+ indent disassemble-recursive-indent))))			 tmp)		       "")		      ((and (eq tmp 'byte-code) 			    (eq (aref bytes (+ ptr 4)) (+ byte-call 3)))		       ;; this won't catch cases where args are pushed w/		       ;; constant2.		       (setq ptr (+ ptr 4))		       "<compiled call to byte-code.  compiled code compiled?>")		      (t		       ;; really just a constant		       (let ((print-escape-newlines t))			 (prin1-to-string tmp)))))	       (t "<error in disassembler>"))	 stream))      (terpri stream)))  nil)(defun disassemble-offset ()  "Don't call this!"  ;; fetch and return the offset for the current opcode.  ;; return NIL if this opcode has no offset  ;; OP, PTR and BYTES are used and set dynamically  (let (tem)    (cond ((< op byte-nth)	   (setq tem (logand op 7))	   (setq op (logand op 248))	   (cond ((eq tem 6)		  (setq ptr (1+ ptr))	;offset in next byte		  (aref bytes ptr))		 ((eq tem 7)		  (setq ptr (1+ ptr))	;offset in next 2 bytes		  (+ (aref bytes ptr)		     (progn (setq ptr (1+ ptr))			    (lsh (aref bytes ptr) 8))))		 (t tem)))	;offset was in opcode	  ((>= op byte-constant)	   (setq tem (- op byte-constant)) ;offset in opcode	   (setq op byte-constant)	   tem)	  ((or (= op byte-constant2)	       (and (>= op byte-goto)		    (<= op byte-goto-if-not-nil-else-pop)))	   (setq ptr (1+ ptr))		;offset in next 2 bytes	   (+ (aref bytes ptr)	      (progn (setq ptr (1+ ptr))		     (lsh (aref bytes ptr) 8))))	  (t nil))))			;no offset(defun write-spaces (n &optional stream)  "Print N spaces to (optional) STREAM."  (or stream (setq stream standard-output))  (if (< n 0) (setq n 0))  (if (eq stream (current-buffer))      (insert-char ?\  n)    (while (> n 0)      (write-char ?\  stream)      (setq n (1- n)))))(defconst byte-code-vector '[<not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (varref . 1)   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (varset . -1)   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (varbind . 0);Pops a value, "pushes" a binding   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (call . -); #'-, not -1!   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (unbind . -);"pops" bindings   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (nth . -1)   symbolp   consp   stringp   listp   (eq . -1)   (memq . -1)   not   car   cdr   (cons . -1)   list1   (list2 . -1)   (list3 . -2)   (list4 . -3)   length   (aref . -1)   (aset . -2)   symbol-value   symbol-function   (set . -1)   (fset . -1)   (get . -1)   (substring . -2)   (concat2 . -1)   (concat3 . -2)   (concat4 . -3)   sub1   add1   (eqlsign . -1) ;=   (gtr . -1)     ;>   (lss . -1)     ;<   (leq . -1)     ;<=   (geq . -1)     ;>=   (diff . -1)    ;-   negate         ;unary -   (plus . -1)    ;+   (max . -1)   (min . -1)   <not-an-opcode>   (point . 1)   (mark\(obsolete\) . 1)   goto-char    insert   (point-max . 1)   (point-min . 1)   char-after   (following-char . 1)   (preceding-char . 1)   (current-column . 1)   (indent-to . 1)   (scan-buffer\(obsolete\) . -2)   (eolp . 1)   (eobp . 1)   (bolp . 1)   (bobp . 1)   (current-buffer . 1)   set-buffer   (read-char . 1)   set-mark\(obsolete\)   interactive-p   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (constant2 . 1)   goto;>>>   goto-if-nil;>>   goto-if-not-nil;>>   (goto-if-nil-else-pop . -1)   (goto-if-not-nil-else-pop . -1)   return   (discard . -1)   (dup . 1)   (save-excursion . 1);Pushes a binding   (save-window-excursion . 1);Pushes a binding   (save-restriction . 1);Pushes a binding   (catch . -1);Takes one argument, returns a value   (unwind-protect . 1);Takes one argument, pushes a binding, returns a value   (condition-case . -2);Takes three arguments, returns a value   (temp-output-buffer-setup . -1)   temp-output-buffer-show   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   <not-an-opcode>   (constant . 1)   ])

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -