Annotation of GNUtools/emacs/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 free software; you can redistribute it and/or modify
                      8: ;; it under the terms of the GNU General Public License as published by
                      9: ;; the Free Software Foundation; either version 1, or (at your option)
                     10: ;; any later version.
                     11: 
                     12: ;; GNU Emacs is distributed in the hope that it will be useful,
                     13: ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14: ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15: ;; GNU General Public License for more details.
                     16: 
                     17: ;; You should have received a copy of the GNU General Public License
                     18: ;; along with GNU Emacs; see the file COPYING.  If not, write to
                     19: ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     20: 
                     21: 
                     22: (require 'byte-compile "bytecomp")
                     23: 
                     24: (defvar disassemble-column-1-indent 4 "*")
                     25: 
                     26: (defvar disassemble-column-2-indent 9 "*")
                     27: 
                     28: (defvar disassemble-recursive-indent 3 "*")
                     29: 
                     30: ;(defun d (x)
                     31: ;  (interactive "xDiss ")
                     32: ;  (with-output-to-temp-buffer "*Disassemble*"
                     33: ;    (disassemble-internal (list 'lambda '() x ''return-value)
                     34: ;                        standard-output 0 t)))
                     35: 
                     36: (defun disassemble (object &optional stream indent interactive-p)
                     37:   "Print disassembled code for OBJECT on (optional) STREAM.
                     38: OBJECT can be a function name, lambda expression or any function object
                     39: returned by SYMBOL-FUNCTION.  If OBJECT is not already compiled, we will
                     40: compile it (but not redefine it)."
                     41:   (interactive (list (intern (completing-read "Disassemble function: "
                     42:                                              obarray 'fboundp t))
                     43:                     nil 0 t))
                     44:   (or indent (setq indent 0))          ;Default indent to zero
                     45:   (if interactive-p
                     46:       (with-output-to-temp-buffer "*Disassemble*"
                     47:        (disassemble-internal object standard-output indent t))
                     48:     (disassemble-internal object (or stream standard-output) indent nil))
                     49:   nil)
                     50: 
                     51: (defun disassemble-internal (obj stream indent interactive-p)
                     52:   (let ((macro 'nil)
                     53:        (name 'nil)
                     54:        (doc 'nil)
                     55:        args)
                     56:     (while (symbolp obj)
                     57:       (setq name obj
                     58:            obj (symbol-function obj)))
                     59:     (if (subrp obj)
                     60:        (error "Can't disassemble #<subr %s>" name))
                     61:     (if (eq (car obj) 'macro)          ;handle macros
                     62:        (setq macro t
                     63:              obj (cdr obj)))
                     64:     (if (not (eq (car obj) 'lambda))
                     65:        (error "not a function"))
                     66:     (if (assq 'byte-code obj)
                     67:        nil
                     68:       (if interactive-p (message (if name
                     69:                                     "Compiling %s's definition..."
                     70:                                     "Compiling definition...")
                     71:                                 name))
                     72:       (setq obj (byte-compile-lambda obj))
                     73:       (if interactive-p (message "Done compiling.  Disassembling...")))
                     74:     (setq obj (cdr obj))               ;throw lambda away
                     75:     (setq args (car obj))              ;save arg list
                     76:     (setq obj (cdr obj))
                     77:     (write-spaces indent stream)
                     78:     (princ (format "byte code%s%s%s:\n"
                     79:                   (if (or macro name) " for" "")
                     80:                   (if macro " macro" "")
                     81:                   (if name (format " %s" name) ""))
                     82:           stream)
                     83:     (let ((doc (and (stringp (car obj)) (car obj))))
                     84:       (if doc
                     85:          (progn (setq obj (cdr obj))
                     86:                 (write-spaces indent stream)
                     87:                 (princ " doc: " stream)
                     88:                 (princ doc stream)
                     89:                 (terpri stream))))
                     90:     (write-spaces indent stream)
                     91:     (princ " args: " stream)
                     92:     (prin1 args stream)
                     93:     (terpri stream)
                     94:     (let ((interactive (car (cdr (assq 'interactive obj)))))
                     95:       (if interactive
                     96:          (progn (write-spaces indent stream)
                     97:                 (princ " interactive: " stream)
                     98:                 (if (eq (car-safe interactive) 'byte-code)
                     99:                     (disassemble-1 interactive stream
                    100:                       (+ indent disassemble-recursive-indent))
                    101:                   (prin1 interactive stream)
                    102:                   (terpri stream)))))
                    103:     (setq obj (assq 'byte-code obj))   ;obj is now call to byte-code
                    104:     (disassemble-1 obj stream indent))
                    105:   (if interactive-p
                    106:       (message "")))
                    107: 
                    108: (defun disassemble-1 (obj &optional stream indent)
                    109:   "Prints the byte-code call OBJ to (optional) STREAM.
                    110: OBJ should be a call to BYTE-CODE generated by the byte compiler."
                    111:   (or indent (setq indent 0))          ;default indent to 0
                    112:   (or stream (setq stream standard-output))
                    113:   (let ((bytes (car (cdr obj)))                ;the byte code
                    114:        (ptr -1)                        ;where we are in it
                    115:        (constants (car (cdr (cdr obj)))) ;constant vector
                    116:        ;(next-indent indent)
                    117:        offset tmp length)
                    118:     (setq length (length bytes))
                    119:     (terpri stream)
                    120:     (while (< (setq ptr (1+ ptr)) length)
                    121:       ;(setq indent next-indent)
                    122:       (write-spaces indent stream)     ;indent to recursive indent
                    123:       (princ (setq tmp (prin1-to-string ptr)) stream) ;print line #
                    124:       (write-char ?\  stream)
                    125:       (write-spaces (- disassemble-column-1-indent (length tmp) 1)
                    126:                    stream)
                    127:       (setq op (aref bytes ptr))       ;fetch opcode
                    128:       ;; Note: as offsets are either encoded in opcodes or stored as
                    129:       ;; bytes in the code, this function (disassemble-offset)
                    130:       ;; can set OP and/or PTR.
                    131:       (setq offset (disassemble-offset));fetch offset
                    132:       (setq tmp (aref byte-code-vector op))
                    133:       (if (consp tmp)
                    134:          (setq ;next-indent (if (numberp (cdr tmp))
                    135:                ;               (+ indent (cdr tmp))
                    136:                ;             (+ indent (funcall (cdr tmp) offset)))
                    137:                tmp (car tmp)))
                    138:       (setq tmp (symbol-name tmp))
                    139:       (princ tmp stream)               ;print op-name for opcode
                    140:       (if (null offset)
                    141:          nil
                    142:        (write-char ?\  stream)
                    143:        (write-spaces (- disassemble-column-2-indent (length tmp) 1)
                    144:                      stream)           ;indent to col 2
                    145:        (princ                          ;print offset
                    146:         (cond ((or (eq op byte-varref)
                    147:                    (eq op byte-varset)
                    148:                    (eq op byte-varbind))
                    149:                ;; it's a varname (atom)
                    150:                (aref constants offset)) ;fetch it from constants
                    151:               ((or (eq op byte-goto)
                    152:                    (eq op byte-goto-if-nil)
                    153:                    (eq op byte-goto-if-not-nil)
                    154:                    (eq op byte-goto-if-nil-else-pop)
                    155:                    (eq op byte-goto-if-not-nil-else-pop)
                    156:                    (eq op byte-call)
                    157:                    (eq op byte-unbind))
                    158:                ;; it's a number
                    159:                offset)                 ;return it
                    160:               ((or (eq op byte-constant)
                    161:                    (eq op byte-constant2))
                    162:                ;; it's a constant
                    163:                (setq tmp (aref constants offset))
                    164:                ;; but is constant byte code?
                    165:                (cond ((and (eq (car-safe tmp) 'lambda)
                    166:                            (assq 'byte-code tmp))
                    167:                       (princ "<compiled lambda>" stream)
                    168:                       (terpri stream)
                    169:                       (disassemble     ;recurse on compiled lambda
                    170:                         tmp
                    171:                         stream
                    172:                         (+ indent disassemble-recursive-indent))
                    173:                       "")
                    174:                      ((eq (car-safe tmp) 'byte-code)
                    175:                       (princ "<byte code>" stream)
                    176:                       (terpri stream)
                    177:                       (disassemble-1   ;recurse on byte-code object
                    178:                         tmp
                    179:                         stream
                    180:                         (+ indent disassemble-recursive-indent))
                    181:                       "")
                    182:                      ((eq (car-safe (car-safe tmp)) 'byte-code)
                    183:                       (princ "(<byte code>...)" stream)
                    184:                       (terpri stream)
                    185:                       (mapcar          ;recurse on list of byte-code objects
                    186:                         (function (lambda (obj)
                    187:                                     (disassemble-1
                    188:                                       obj
                    189:                                       stream
                    190:                                       (+ indent disassemble-recursive-indent))))
                    191:                         tmp)
                    192:                       "")
                    193:                      ((and (eq tmp 'byte-code) 
                    194:                            (eq (aref bytes (+ ptr 4)) (+ byte-call 3)))
                    195:                       ;; this won't catch cases where args are pushed w/
                    196:                       ;; constant2.
                    197:                       (setq ptr (+ ptr 4))
                    198:                       "<compiled call to byte-code.  compiled code compiled?>")
                    199:                      (t
                    200:                       ;; really just a constant
                    201:                       (let ((print-escape-newlines t))
                    202:                         (prin1-to-string tmp)))))
                    203:               (t "<error in disassembler>"))
                    204:         stream))
                    205:       (terpri stream)))
                    206:   nil)
                    207: 
                    208: 
                    209: (defun disassemble-offset ()
                    210:   "Don't call this!"
                    211:   ;; fetch and return the offset for the current opcode.
                    212:   ;; return NIL if this opcode has no offset
                    213:   ;; OP, PTR and BYTES are used and set dynamically
                    214:   (let (tem)
                    215:     (cond ((< op byte-nth)
                    216:           (setq tem (logand op 7))
                    217:           (setq op (logand op 248))
                    218:           (cond ((eq tem 6)
                    219:                  (setq ptr (1+ ptr))   ;offset in next byte
                    220:                  (aref bytes ptr))
                    221:                 ((eq tem 7)
                    222:                  (setq ptr (1+ ptr))   ;offset in next 2 bytes
                    223:                  (+ (aref bytes ptr)
                    224:                     (progn (setq ptr (1+ ptr))
                    225:                            (lsh (aref bytes ptr) 8))))
                    226:                 (t tem)))      ;offset was in opcode
                    227:          ((>= op byte-constant)
                    228:           (setq tem (- op byte-constant)) ;offset in opcode
                    229:           (setq op byte-constant)
                    230:           tem)
                    231:          ((or (= op byte-constant2)
                    232:               (and (>= op byte-goto)
                    233:                    (<= op byte-goto-if-not-nil-else-pop)))
                    234:           (setq ptr (1+ ptr))          ;offset in next 2 bytes
                    235:           (+ (aref bytes ptr)
                    236:              (progn (setq ptr (1+ ptr))
                    237:                     (lsh (aref bytes ptr) 8))))
                    238:          (t nil))))                    ;no offset
                    239: 
                    240: 
                    241: (defun write-spaces (n &optional stream)
                    242:   "Print N spaces to (optional) STREAM."
                    243:   (or stream (setq stream standard-output))
                    244:   (if (< n 0) (setq n 0))
                    245:   (if (eq stream (current-buffer))
                    246:       (insert-char ?\  n)
                    247:     (while (> n 0)
                    248:       (write-char ?\  stream)
                    249:       (setq n (1- n)))))
                    250: 
                    251: (defconst byte-code-vector
                    252:  '[<not-an-opcode>
                    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:    (varref . 1)
                    261:    <not-an-opcode>
                    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:    (varset . -1)
                    269:    <not-an-opcode>
                    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:    (varbind . 0);Pops a value, "pushes" a binding
                    277:    <not-an-opcode>
                    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:    (call . -); #'-, not -1!
                    285:    <not-an-opcode>
                    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:    (unbind . -);"pops" bindings
                    293:    <not-an-opcode>
                    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:    (nth . -1)
                    309:    symbolp
                    310:    consp
                    311:    stringp
                    312:    listp
                    313:    (eq . -1)
                    314:    (memq . -1)
                    315:    not
                    316:    car
                    317:    cdr
                    318:    (cons . -1)
                    319:    list1
                    320:    (list2 . -1)
                    321:    (list3 . -2)
                    322:    (list4 . -3)
                    323:    length
                    324:    (aref . -1)
                    325:    (aset . -2)
                    326:    symbol-value
                    327:    symbol-function
                    328:    (set . -1)
                    329:    (fset . -1)
                    330:    (get . -1)
                    331:    (substring . -2)
                    332:    (concat2 . -1)
                    333:    (concat3 . -2)
                    334:    (concat4 . -3)
                    335:    sub1
                    336:    add1
                    337:    (eqlsign . -1) ;=
                    338:    (gtr . -1)     ;>
                    339:    (lss . -1)     ;<
                    340:    (leq . -1)     ;<=
                    341:    (geq . -1)     ;>=
                    342:    (diff . -1)    ;-
                    343:    negate         ;unary -
                    344:    (plus . -1)    ;+
                    345:    (max . -1)
                    346:    (min . -1)
                    347:    <not-an-opcode>
                    348:    (point . 1)
                    349:    (mark\(obsolete\) . 1)
                    350:    goto-char 
                    351:    insert
                    352:    (point-max . 1)
                    353:    (point-min . 1)
                    354:    char-after
                    355:    (following-char . 1)
                    356:    (preceding-char . 1)
                    357:    (current-column . 1)
                    358:    (indent-to . 1)
                    359:    (scan-buffer\(obsolete\) . -2)
                    360:    (eolp . 1)
                    361:    (eobp . 1)
                    362:    (bolp . 1)
                    363:    (bobp . 1)
                    364:    (current-buffer . 1)
                    365:    set-buffer
                    366:    (read-char . 1)
                    367:    set-mark\(obsolete\)
                    368:    interactive-p
                    369:    <not-an-opcode>
                    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:    (constant2 . 1)
                    382:    goto;>>>
                    383:    goto-if-nil;>>
                    384:    goto-if-not-nil;>>
                    385:    (goto-if-nil-else-pop . -1)
                    386:    (goto-if-not-nil-else-pop . -1)
                    387:    return
                    388:    (discard . -1)
                    389:    (dup . 1)
                    390:    (save-excursion . 1);Pushes a binding
                    391:    (save-window-excursion . 1);Pushes a binding
                    392:    (save-restriction . 1);Pushes a binding
                    393:    (catch . -1);Takes one argument, returns a value
                    394:    (unwind-protect . 1);Takes one argument, pushes a binding, returns a value
                    395:    (condition-case . -2);Takes three arguments, returns a value
                    396:    (temp-output-buffer-setup . -1)
                    397:    temp-output-buffer-show
                    398:    <not-an-opcode>
                    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:    (constant . 1)
                    445:    ])
                    446: 

unix.superglobalmegacorp.com

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