LP-295: uncrustify
[librepilot.git] / flight / libraries / PyMite / tools / dismantle.py
blobbf8bcc00335c507a783053cfc17de4f2744acf63
1 #!/usr/bin/env python
3 # This file is Copyright 2003, 2006, 2007, 2009, 2010 Dean Hall.
5 # This file is part of the Python-on-a-Chip program.
6 # Python-on-a-Chip is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1.
8 #
9 # Python-on-a-Chip is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 # A copy of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1
13 # is seen in the file COPYING in this directory.
15 """
16 Dismantles a .py file by compiling it
17 into a code object and recursively dismantling
18 and disassembling the code object.
19 """
21 __usage__ = """Usage:
22 dismantle.py sourcefilename.py
23 """
25 ## @file
26 # @copybrief dismantle
28 ## @package dismantle
29 # @brief Dismantles a .py file by compiling it
30 # into a code object and recursively dismantling
31 # and disassembling the code object.
34 STRINGTOOLONG = 32
37 import dis, sys, types, py_compile, time
40 def dismantle_file(fn):
41 """Dismantles the .py file, fn. Returns the root code object.
42 """
44 #create a code object
45 f = open(fn)
46 source = f.read()
47 f.close()
48 return dismantle(source, fn)
51 def dismantle(source, fn=""):
53 # If no filename given, just dismantle source, skip magic and ignore
54 if fn == "":
55 magic = 0
56 ignore = 0
57 fn = "fn"
58 pyc = ""
60 else:
61 # Compile to .pyc and open
62 py_compile.compile(fn)
63 f = open(fn + 'c','rb')
64 pyc = f.read()
65 f.close()
67 # Check for magic number
68 magic = int((ord(pyc[0]) ) | (ord(pyc[1]) << 8) |
69 (ord(pyc[2]) << 16) | (ord(pyc[3]) << 24))
71 # Grab the next 4 bytes (don't know what they do)
72 ignore = int((ord(pyc[4]) ) | (ord(pyc[5]) << 8) |
73 (ord(pyc[6]) << 16) | (ord(pyc[7]) << 24))
75 code = compile(source, fn, "exec")
77 # Print header
78 print "BEGIN DISMANTLE"
79 print "date: \t", time.ctime(time.time())
80 print "src file: \t", fn
81 print "src file size: \t", len(source), "bytes"
82 print "pyc file size: \t", len(pyc), "bytes"
83 print
84 print "magic: \t0x%08x" % magic
85 print "ignore: \t0x%08x" % ignore
86 print
88 # Recurse into the code object
89 rdismantle(code)
91 print "END DISMANTLE"
92 return code
95 def rdismantle(co, parent = None):
96 """Dismantles the code object, co. Prints the co_* field values and
97 the co_code disassembly for each code object in the file and recurses
98 into any code objects in the constant pool.
99 """
101 # Create full name
102 if parent:
103 fullname = parent + "." + co.co_name
104 else:
105 fullname = co.co_name
107 # Print object fields and values
108 print "fullname: \t", fullname
109 print " co_name: \t", co.co_name
110 print " co_filename: \t", co.co_filename
111 print " co_firstlineno:\t", co.co_firstlineno
112 print " co_flags: \t0x%04x" % co.co_flags
113 print " co_stacksize: \t", co.co_stacksize
114 print " co_lnotab[%3d]:\t%s" % \
115 (len(co.co_lnotab), repr(co.co_lnotab[:8]))
116 print " co_argcount: \t", co.co_argcount
117 print " co_nlocals: \t", co.co_nlocals
118 print " co_freevars: \t", co.co_freevars
119 print " co_cellvars: \t", co.co_cellvars
121 # Print vital compound components
122 tabspacing = "\t\t"
124 print " co_varnames:"
125 i = 0
126 for item in co.co_varnames:
127 print tabspacing, i, ":\t", item
128 i += 1
130 print " co_names: "
131 i = 0
132 for item in co.co_names:
133 print tabspacing, i, ":\t", item
134 i += 1
136 print " co_consts: "
137 i = 0
138 for item in co.co_consts:
139 if type(item) == types.StringType and \
140 len(item) > STRINGTOOLONG:
141 print tabspacing, i, ":\t", repr(item[:STRINGTOOLONG]), "..."
142 else:
143 print tabspacing, i, ":\t", repr(item)
144 i += 1
146 # Print disassembly
147 print " co_code:"
148 dis.dis(co)
149 print "\n"
151 # Dismantle code objects in constant pool
152 for obj in co.co_consts:
153 if type(obj) == types.CodeType:
154 rdismantle(obj, fullname)
155 return
158 def main():
159 """Dismantles the source file given as an arg.
162 if len(sys.argv) == 2:
163 return dismantle_file(sys.argv[1])
164 else:
165 print __usage__
168 if __name__ == "__main__":
169 main()