Annotation of 43BSDReno/contrib/emacs-18.55/lisp/disass.el, revision 1.1.1.1

1.1       root        1: ;;; Disassembler for compiled Emacs Lisp code
                      2: ;; Copyright (C) 1986 Free Software Foundation
                      3: ;;; By Doug Cutting ([email protected])
                      4: 
                      5: ;; This file is part of GNU Emacs.
                      6: 
                      7: ;; GNU Emacs is distributed in the hope that it will be useful,
                      8: ;; but WITHOUT ANY WARRANTY.  No author or distributor
                      9: ;; accepts responsibility to anyone for the consequences of using it
                     10: ;; or for whether it serves any particular purpose or works at all,
                     11: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
                     12: ;; License for full details.
                     13: 
                     14: ;; Everyone is granted permission to copy, modify and redistribute
                     15: ;; GNU Emacs, but only under the conditions described in the
                     16: ;; GNU Emacs General Public License.   A copy of this license is
                     17: ;; supposed to have been given to you along with GNU Emacs so you
                     18: ;; can know your rights and responsibilities.  It should be in a
                     19: ;; file named COPYING.  Among other things, the copyright notice
                     20: ;; and this notice must be preserved on all copies.
                     21: 
                     22: 
                     23: (require 'byte-compile "bytecomp")
                     24: 
                     25: (defvar disassemble-column-1-indent 4 "*")
                     26: 
                     27: (defvar disassemble-column-2-indent 9 "*")
                     28: 
                     29: (defvar disassemble-recursive-indent 3 "*")
                     30: 
                     31: ;(defun d (x)
                     32: ;  (interactive "xDiss ")
                     33: ;  (with-output-to-temp-buffer "*Disassemble*"
                     34: ;    (disassemble-internal (list 'lambda '() x ''return-value)
                     35: ;                        standard-output 0 t)))
                     36: 
                     37: (defun disassemble (object &optional stream indent interactive-p)
                     38:   "Print disassembled code for OBJECT on (optional) STREAM.
                     39: OBJECT can be a function name, lambda expression or any function object
                     40: returned by SYMBOL-FUNCTION.  If OBJECT is not already compiled, we will
                     41: compile it (but not redefine it)."
                     42:   (interactive (list (intern (completing-read "Disassemble function: "
                     43:                                              obarray 'fboundp t))
                     44:                     nil 0 t))
                     45:   (or indent (setq indent 0))          ;Default indent to zero
                     46:   (if interactive-p
                     47:       (with-output-to-temp-buffer "*Disassemble*"
                     48:        (disassemble-internal object standard-output indent t))
                     49:     (disassemble-internal object (or stream standard-output) indent nil))
                     50:   nil)
                     51: 
                     52: (defun disassemble-internal (obj stream indent interactive-p)
                     53:   (let ((macro 'nil)
                     54:        (name 'nil)
                     55:        (doc 'nil)
                     56:        args)
                     57:     (while (symbolp obj)
                     58:       (setq name obj
                     59:            obj (symbol-function obj)))
                     60:     (if (subrp obj)
                     61:        (error "Can't disassemble #<subr %s>" name))
                     62:     (if (eq (car obj) 'macro)          ;handle macros
                     63:        (setq macro t
                     64:              obj (cdr obj)))
                     65:     (if (not (eq (car obj) 'lambda))
                     66:        (error "not a function"))
                     67:     (if (assq 'byte-code obj)
                     68:        nil
                     69:       (if interactive-p (message (if name
                     70:                                     "Compiling %s's definition..."
                     71:                                     "Compiling definition...")
                     72:                                 name))
                     73:       (setq obj (byte-compile-lambda obj))
                     74:       (if interactive-p (message "Done compiling.  Disassembling...")))
                     75:     (setq obj (cdr obj))               ;throw lambda away
                     76:     (setq args (car obj))              ;save arg list
                     77:     (setq obj (cdr obj))
                     78:     (write-spaces indent stream)
                     79:     (princ (format "byte code%s%s%s:\n"
                     80:                   (if (or macro name) " for" "")
                     81:                   (if macro " macro" "")
                     82:                   (if name (format " %s" name) ""))
                     83:           stream)
                     84:     (let ((doc (and (stringp (car obj)) (car obj))))
                     85:       (if doc
                     86:          (progn (setq obj (cdr obj))
                     87:                 (write-spaces indent stream)
                     88:                 (princ " doc: " stream)
                     89:                 (princ doc stream)
                     90:                 (terpri stream))))
                     91:     (write-spaces indent stream)
                     92:     (princ " args: " stream)
                     93:     (prin1 args stream)
                     94:     (terpri stream)
                     95:     (let ((interactive (car (cdr (assq 'interactive obj)))))
                     96:       (if interactive
                     97:          (progn (write-spaces indent stream)
                     98:                 (princ " interactive: " stream)
                     99:                 (if (eq (car-safe interactive) 'byte-code)
                    100:                     (disassemble-1 interactive stream
                    101:                       (+ indent disassemble-recursive-indent))
                    102:                   (prin1 interactive stream)
                    103:                   (terpri stream)))))
                    104:     (setq obj (assq 'byte-code obj))   ;obj is now call to byte-code
                    105:     (disassemble-1 obj stream indent))
                    106:   (if interactive-p
                    107:       (message "")))
                    108: 
                    109: (defun disassemble-1 (obj &optional stream indent)
                    110:   "Prints the byte-code call OBJ to (optional) STREAM.
                    111: OBJ should be a call to BYTE-CODE generated by the byte compiler."
                    112:   (or indent (setq indent 0))          ;default indent to 0
                    113:   (or stream (setq stream standard-output))
                    114:   (let ((bytes (car (cdr obj)))                ;the byte code
                    115:        (ptr -1)                        ;where we are in it
                    116:        (constants (car (cdr (cdr obj)))) ;constant vector
                    117:        ;(next-indent indent)
                    118:        offset tmp length)
                    119:     (setq length (length bytes))
                    120:     (terpri stream)
                    121:     (while (< (setq ptr (1+ ptr)) length)
                    122:       ;(setq indent next-indent)
                    123:       (write-spaces indent stream)     ;indent to recursive indent
                    124:       (princ (setq tmp (prin1-to-string ptr)) stream) ;print line #
                    125:       (write-char ?\  stream)
                    126:       (write-spaces (- disassemble-column-1-indent (length tmp) 1)
                    127:                    stream)
                    128:       (setq op (aref bytes ptr))       ;fetch opcode
                    129:       ;; Note: as offsets are either encoded in opcodes or stored as
                    130:       ;; bytes in the code, this function (disassemble-offset)
                    131:       ;; can set OP and/or PTR.
                    132:       (setq offset (disassemble-offset));fetch offset
                    133:       (setq tmp (aref byte-code-vector op))
                    134:       (if (consp tmp)
                    135:          (setq ;next-indent (if (numberp (cdr tmp))
                    136:                ;               (+ indent (cdr tmp))
                    137:                ;             (+ indent (funcall (cdr tmp) offset)))
                    138:                tmp (car tmp)))
                    139:       (setq tmp (symbol-name tmp))
                    140:       (princ tmp stream)               ;print op-name for opcode
                    141:       (if (null offset)
                    142:          nil
                    143:        (write-char ?\  stream)
                    144:        (write-spaces (- disassemble-column-2-indent (length tmp) 1)
                    145:                      stream)           ;indent to col 2
                    146:        (princ                          ;print offset
                    147:         (cond ((or (eq op byte-varref)
                    148:                    (eq op byte-varset)
                    149:                    (eq op byte-varbind))
                    150:                ;; it's a varname (atom)
                    151:                (aref constants offset)) ;fetch it from constants
                    152:               ((or (eq op byte-goto)
                    153:                    (eq op byte-goto-if-nil)
                    154:                    (eq op byte-goto-if-not-nil)
                    155:                    (eq op byte-goto-if-nil-else-pop)
                    156:                    (eq op byte-goto-if-not-nil-else-pop)
                    157:                    (eq op byte-call)
                    158:                    (eq op byte-unbind))
                    159:                ;; it's a number
                    160:                offset)                 ;return it
                    161:               ((or (eq op byte-constant)
                    162:                    (eq op byte-constant2))
                    163:                ;; it's a constant
                    164:                (setq tmp (aref constants offset))
                    165:                ;; but is constant byte code?
                    166:                (cond ((and (eq (car-safe tmp) 'lambda)
                    167:                            (assq 'byte-code tmp))
                    168:                       (princ "<compiled lambda>" stream)
                    169:                       (terpri stream)
                    170:                       (disassemble     ;recurse on compiled lambda
                    171:                         tmp
                    172:                         stream
                    173:                         (+ indent disassemble-recursive-indent))
                    174:                       "")
                    175:                      ((eq (car-safe tmp) 'byte-code)
                    176:                       (princ "<byte code>" stream)
                    177:                       (terpri stream)
                    178:                       (disassemble-1   ;recurse on byte-code object
                    179:                         tmp
                    180:                         stream
                    181:                         (+ indent disassemble-recursive-indent))
                    182:                       "")
                    183:                      ((eq (car-safe (car-safe tmp)) 'byte-code)
                    184:                       (princ "(<byte code>...)" stream)
                    185:                       (terpri stream)
                    186:                       (mapcar          ;recurse on list of byte-code objects
                    187:                         (function (lambda (obj)
                    188:                                     (disassemble-1
                    189:                                       obj
                    190:                                       stream
                    191:                                       (+ indent disassemble-recursive-indent))))
                    192:                         tmp)
                    193:                       "")
                    194:                      ((and (eq tmp 'byte-code) 
                    195:                            (eq (aref bytes (+ ptr 4)) (+ byte-call 3)))
                    196:                       ;; this won't catch cases where args are pushed w/
                    197:                       ;; constant2.
                    198:                       (setq ptr (+ ptr 4))
                    199:                       "<compiled call to byte-code.  compiled code compiled?>")
                    200:                      (t
                    201:                       ;; really just a constant
                    202:                       (let ((print-escape-newlines t))
                    203:                         (prin1-to-string tmp)))))
                    204:               (t "<error in disassembler>"))
                    205:         stream))
                    206:       (terpri stream)))
                    207:   nil)
                    208: 
                    209: 
                    210: (defun disassemble-offset ()
                    211:   "Don't call this!"
                    212:   ;; fetch and return the offset for the current opcode.
                    213:   ;; return NIL if this opcode has no offset
                    214:   ;; OP, PTR and BYTES are used and set dynamically
                    215:   (let (tem)
                    216:     (cond ((< op byte-nth)
                    217:           (setq tem (logand op 7))
                    218:           (setq op (logand op 248))
                    219:           (cond ((eq tem 6)
                    220:                  (setq ptr (1+ ptr))   ;offset in next byte
                    221:                  (aref bytes ptr))
                    222:                 ((eq tem 7)
                    223:                  (setq ptr (1+ ptr))   ;offset in next 2 bytes
                    224:                  (+ (aref bytes ptr)
                    225:                     (progn (setq ptr (1+ ptr))
                    226:                            (lsh (aref bytes ptr) 8))))
                    227:                 (t tem)))      ;offset was in opcode
                    228:          ((>= op byte-constant)
                    229:           (setq tem (- op byte-constant)) ;offset in opcode
                    230:           (setq op byte-constant)
                    231:           tem)
                    232:          ((or (= op byte-constant2)
                    233:               (and (>= op byte-goto)
                    234:                    (<= op byte-goto-if-not-nil-else-pop)))
                    235:           (setq ptr (1+ ptr))          ;offset in next 2 bytes
                    236:           (+ (aref bytes ptr)
                    237:              (progn (setq ptr (1+ ptr))
                    238:                     (lsh (aref bytes ptr) 8))))
                    239:          (t nil))))                    ;no offset
                    240: 
                    241: 
                    242: (defun write-spaces (n &optional stream)
                    243:   "Print N spaces to (optional) STREAM."
                    244:   (or stream (setq stream standard-output))
                    245:   (if (< n 0) (setq n 0))
                    246:   (if (eq stream (current-buffer))
                    247:       (insert-char ?\  n)
                    248:     (while (> n 0)
                    249:       (write-char ?\  stream)
                    250:       (setq n (1- n)))))
                    251: 
                    252: (defconst byte-code-vector
                    253:  '[<not-an-opcode>
                    254:    <not-an-opcode>
                    255:    <not-an-opcode>
                    256:    <not-an-opcode>
                    257:    <not-an-opcode>
                    258:    <not-an-opcode>
                    259:    <not-an-opcode>
                    260:    <not-an-opcode>
                    261:    (varref . 1)
                    262:    <not-an-opcode>
                    263:    <not-an-opcode>
                    264:    <not-an-opcode>
                    265:    <not-an-opcode>
                    266:    <not-an-opcode>
                    267:    <not-an-opcode>
                    268:    <not-an-opcode>
                    269:    (varset . -1)
                    270:    <not-an-opcode>
                    271:    <not-an-opcode>
                    272:    <not-an-opcode>
                    273:    <not-an-opcode>
                    274:    <not-an-opcode>
                    275:    <not-an-opcode>
                    276:    <not-an-opcode>
                    277:    (varbind . 0);Pops a value, "pushes" a binding
                    278:    <not-an-opcode>
                    279:    <not-an-opcode>
                    280:    <not-an-opcode>
                    281:    <not-an-opcode>
                    282:    <not-an-opcode>
                    283:    <not-an-opcode>
                    284:    <not-an-opcode>
                    285:    (call . -); #'-, not -1!
                    286:    <not-an-opcode>
                    287:    <not-an-opcode>
                    288:    <not-an-opcode>
                    289:    <not-an-opcode>
                    290:    <not-an-opcode>
                    291:    <not-an-opcode>
                    292:    <not-an-opcode>
                    293:    (unbind . -);"pops" bindings
                    294:    <not-an-opcode>
                    295:    <not-an-opcode>
                    296:    <not-an-opcode>
                    297:    <not-an-opcode>
                    298:    <not-an-opcode>
                    299:    <not-an-opcode>
                    300:    <not-an-opcode>
                    301:    <not-an-opcode>
                    302:    <not-an-opcode>
                    303:    <not-an-opcode>
                    304:    <not-an-opcode>
                    305:    <not-an-opcode>
                    306:    <not-an-opcode>
                    307:    <not-an-opcode>
                    308:    <not-an-opcode>
                    309:    (nth . -1)
                    310:    symbolp
                    311:    consp
                    312:    stringp
                    313:    listp
                    314:    (eq . -1)
                    315:    (memq . -1)
                    316:    not
                    317:    car
                    318:    cdr
                    319:    (cons . -1)
                    320:    list1
                    321:    (list2 . -1)
                    322:    (list3 . -2)
                    323:    (list4 . -3)
                    324:    length
                    325:    (aref . -1)
                    326:    (aset . -2)
                    327:    symbol-value
                    328:    symbol-function
                    329:    (set . -1)
                    330:    (fset . -1)
                    331:    (get . -1)
                    332:    (substring . -2)
                    333:    (concat2 . -1)
                    334:    (concat3 . -2)
                    335:    (concat4 . -3)
                    336:    sub1
                    337:    add1
                    338:    (eqlsign . -1) ;=
                    339:    (gtr . -1)     ;>
                    340:    (lss . -1)     ;<
                    341:    (leq . -1)     ;<=
                    342:    (geq . -1)     ;>=
                    343:    (diff . -1)    ;-
                    344:    negate         ;unary -
                    345:    (plus . -1)    ;+
                    346:    (max . -1)
                    347:    (min . -1)
                    348:    <not-an-opcode>
                    349:    (point . 1)
                    350:    (mark\(obsolete\) . 1)
                    351:    goto-char 
                    352:    insert
                    353:    (point-max . 1)
                    354:    (point-min . 1)
                    355:    char-after
                    356:    (following-char . 1)
                    357:    (preceding-char . 1)
                    358:    (current-column . 1)
                    359:    (indent-to . 1)
                    360:    (scan-buffer\(obsolete\) . -2)
                    361:    (eolp . 1)
                    362:    (eobp . 1)
                    363:    (bolp . 1)
                    364:    (bobp . 1)
                    365:    (current-buffer . 1)
                    366:    set-buffer
                    367:    (read-char . 1)
                    368:    set-mark\(obsolete\)
                    369:    interactive-p
                    370:    <not-an-opcode>
                    371:    <not-an-opcode>
                    372:    <not-an-opcode>
                    373:    <not-an-opcode>
                    374:    <not-an-opcode>
                    375:    <not-an-opcode>
                    376:    <not-an-opcode>
                    377:    <not-an-opcode>
                    378:    <not-an-opcode>
                    379:    <not-an-opcode>
                    380:    <not-an-opcode>
                    381:    <not-an-opcode>
                    382:    (constant2 . 1)
                    383:    goto;>>>
                    384:    goto-if-nil;>>
                    385:    goto-if-not-nil;>>
                    386:    (goto-if-nil-else-pop . -1)
                    387:    (goto-if-not-nil-else-pop . -1)
                    388:    return
                    389:    (discard . -1)
                    390:    (dup . 1)
                    391:    (save-excursion . 1);Pushes a binding
                    392:    (save-window-excursion . 1);Pushes a binding
                    393:    (save-restriction . 1);Pushes a binding
                    394:    (catch . -1);Takes one argument, returns a value
                    395:    (unwind-protect . 1);Takes one argument, pushes a binding, returns a value
                    396:    (condition-case . -2);Takes three arguments, returns a value
                    397:    (temp-output-buffer-setup . -1)
                    398:    temp-output-buffer-show
                    399:    <not-an-opcode>
                    400:    <not-an-opcode>
                    401:    <not-an-opcode>
                    402:    <not-an-opcode>
                    403:    <not-an-opcode>
                    404:    <not-an-opcode>
                    405:    <not-an-opcode>
                    406:    <not-an-opcode>
                    407:    <not-an-opcode>
                    408:    <not-an-opcode>
                    409:    <not-an-opcode>
                    410:    <not-an-opcode>
                    411:    <not-an-opcode>
                    412:    <not-an-opcode>
                    413:    <not-an-opcode>
                    414:    <not-an-opcode>
                    415:    <not-an-opcode>
                    416:    <not-an-opcode>
                    417:    <not-an-opcode>
                    418:    <not-an-opcode>
                    419:    <not-an-opcode>
                    420:    <not-an-opcode>
                    421:    <not-an-opcode>
                    422:    <not-an-opcode>
                    423:    <not-an-opcode>
                    424:    <not-an-opcode>
                    425:    <not-an-opcode>
                    426:    <not-an-opcode>
                    427:    <not-an-opcode>
                    428:    <not-an-opcode>
                    429:    <not-an-opcode>
                    430:    <not-an-opcode>
                    431:    <not-an-opcode>
                    432:    <not-an-opcode>
                    433:    <not-an-opcode>
                    434:    <not-an-opcode>
                    435:    <not-an-opcode>
                    436:    <not-an-opcode>
                    437:    <not-an-opcode>
                    438:    <not-an-opcode>
                    439:    <not-an-opcode>
                    440:    <not-an-opcode>
                    441:    <not-an-opcode>
                    442:    <not-an-opcode>
                    443:    <not-an-opcode>
                    444:    <not-an-opcode>
                    445:    (constant . 1)
                    446:    ])
                    447: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.