-
Notifications
You must be signed in to change notification settings - Fork 2
/
code.py
190 lines (167 loc) · 5.55 KB
/
code.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
""" module for constructing the code object """
import opcodes as opc
import utils as utl
# named objects of the form name : object
names = {}
name_cnt = 0
class Code(object):
""" class implementing the code object """
def __init__(self, pyclist, cur=0):
""" initializes the fields of the code object """
self.pyclist = pyclist
self.cur = cur
self.code = self.acq_code()
self.consts = self.acq_consts()
self.names = self.acq_names()
self.varnames = self.acq_varnames()
self.name = self.acq_name()
def get_name(self):
""" returns the name member """
return self.name
def get_cur(self):
""" returns the current position in the pyc_list"""
return self.cur
def get_pyclist(self):
""" returns the pyclist """
return self.pyclist
def get_opcode(self, cur):
""" returns the opcode at self.code[cur] """
return self.code[cur]
def get_oparg(self, cur):
""" returns the oparg of the opcode at cur """
return utl.decimal(self.code, cur)
def is_end(self, cur):
""" True if end of the code reached """
if cur >= len(self.code):
return True
else:
return False
def acq_code(self):
""" constructs co_code field of the code object """
pyclist = self.pyclist
cur = utl.start_of_code(pyclist, self.cur)
end = cur + utl.decimal(pyclist, cur-5, 4)
code = []
while cur < end:
if not utl.is_func_def(cur, pyclist):
if utl.have_arg(pyclist[cur]):
code.extend(pyclist[cur:cur+3])
cur += 3
else:
code.append(pyclist[cur])
cur += 1
else:
code.append(opc.MAKE_FUNCTION)
code.extend([0] * 8)
cur += 9
self.cur = cur
return code
def acq_consts(self):
""" constructs co_consts of the code object """
cur = self.cur
pyclist = self.pyclist
num_co = utl.decimal(pyclist, cur, 4)
cur += 5
consts = []
for dummy in range(num_co):
if pyclist[cur] == opc.TYPE_INTEGER:
consts.append(utl.decimal(pyclist, cur, 4))
cur += 5
elif pyclist[cur] == opc.TYPE_NONE:
consts.append(0)
cur += 1
elif pyclist[cur] == opc.TYPE_CODE:
code_obj = Code(pyclist, cur)
f_idx = code_obj.get_name()
consts.append(code_obj)
names[f_idx][0] = code_obj
cur = utl.end_of_code(pyclist, cur)
self.cur = cur
return consts
def acq_names(self):
""" constructs co_names of the code object """
global name_cnt
cur = self.cur
pyclist = self.pyclist
n_names = utl.decimal(pyclist, cur)
func_idx = 0
cur += 5
co_names = {}
idx = 0
for dummy in range(n_names):
# first occurrence of a name
if (pyclist[cur] == opc.TYPE_INTERN):
names[name_cnt] = [0]
co_names[idx] = names[name_cnt]
name_cnt += 1
idx += 1
cur = utl.skip_element(pyclist, cur)
elif (pyclist[cur] == opc.TYPE_SREF):
func_idx = utl.decimal(pyclist, cur)
co_names[idx] = names[func_idx]
idx += 1
cur += 5
else:
cur += 1
self.cur = cur
return co_names
def acq_varnames(self):
""" constructs co_varnames of the code object """
global name_cnt
cur = self.cur
pyclist = self.pyclist
varnames = []
n_varnames = utl.decimal(pyclist, cur, 4)
cur += 5
for dummy in range(n_varnames):
varnames.append(0)
if pyclist[cur] == opc.TYPE_INTERN:
names[name_cnt] = [0]
name_cnt += 1
cur = utl.skip_element(pyclist, cur)
elif pyclist[cur] == opc.TYPE_SREF:
cur += 5
else:
cur += 1
self.cur = cur
return varnames
def acq_name(self):
""" constructs name of the code object """
global name_cnt
cur = self.cur
pyclist = self.pyclist
n_field = 0
# skip 2 (:28 s that is cellvars and freevars
while True:
if pyclist[cur] == opc.TYPE_TUPLE:
n_field += 1
if n_field == 2:
break
cur += 1
cur += 5
# skip filenmae
cur = utl.skip_element(pyclist, cur)
self.cur = cur
# getting the index of the name of the code
if pyclist[cur] == opc.TYPE_INTERN:
names[name_cnt] = [0]
name_cnt += 1
return name_cnt - 1
else:
return utl.decimal(pyclist, cur, 4)
def view(self):
""" shows the fields of the code object """
print "****************"
print utl.show_pyc(self.code)
print len(self.consts), 'constants'
for idx in range(len(self.consts)):
if type(self.consts[idx]) == int:
print self.consts[idx]
else:
self.consts[idx].view()
print self.names
print self.varnames
print self.name
print 'global names'
print names
print '--------------------------------'