decomplie.py


SUBMITTED BY: Guest

DATE: July 15, 2013, 9:57 p.m.

FORMAT: Python

SIZE: 63.8 kB

HITS: 895

  1. #
  2. # decompile.py - decompile Python code objects
  3. #
  4. # Copyright (c) 2001 Jonathan Patrick Giddy
  5. #
  6. # Permission is hereby granted, free of charge, to any person obtaining
  7. # a copy of this software and associated documentation files (the
  8. # "Software"), to deal in the Software without restriction, including
  9. # without limitation the rights to use, copy, modify, merge, publish,
  10. # distribute, sublicense, and/or sell copies of the Software, and to
  11. # permit persons to whom the Software is furnished to do so, subject to
  12. # the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be
  15. # included in all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  21. # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  22. # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  23. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. # Send comments to:
  25. # Jonathan Giddy, jongiddy@pobox.co.uk
  26. # version 0.9
  27. # Date 21 January 2005
  28. # - no code changes, added MIT licence, updated email address
  29. # - there will be no v1.0 - try decompyle instead
  30. # version 0.8
  31. # Date 25 January 2001
  32. __version__ = '0.9'
  33. import dis, string, sys, types
  34. VARARGS = 4
  35. KWARGS = 8
  36. PRECEDENCE_ATOM = 24
  37. PRECEDENCE_POWER = 17
  38. PRECEDENCE_UNARY = 16
  39. PRECEDENCE_MULT = 15
  40. PRECEDENCE_ADD = 14
  41. PRECEDENCE_SHIFT = 13
  42. PRECEDENCE_BAND = 12
  43. PRECEDENCE_BXOR = 11
  44. PRECEDENCE_BOR = 10
  45. PRECEDENCE_CMP = 9
  46. PRECEDENCE_IS = 8
  47. PRECEDENCE_IN = 7
  48. PRECEDENCE_NOT = 6
  49. PRECEDENCE_AND = 5
  50. PRECEDENCE_OR = 4
  51. PRECEDENCE_LAMBDA = 3
  52. PRECEDENCE_ARG = PRECEDENCE_LAMBDA
  53. PRECEDENCE_COMMA = 1
  54. PRECEDENCE_NONE = 0
  55. def current_line(code, i):
  56. tab = code.co_lnotab
  57. line = code.co_firstlineno
  58. stopat = i
  59. addr = 0
  60. for i in range(0, len(tab), 2):
  61. addr = addr + ord(tab[i])
  62. if addr > stopat:
  63. break
  64. line = line + ord(tab[i+1])
  65. return line
  66. class Expression:
  67. def __init__(self, value, precedence):
  68. self.value = value
  69. self.precedence = precedence
  70. def __repr__(self):
  71. return 'Expression(%s, %s)' % (`self.value`, `self.precedence`)
  72. def __str__(self):
  73. return str(self.value)
  74. def Precedence(self):
  75. return self.precedence
  76. def Value(self):
  77. return self.value
  78. def GetString(self, precedence):
  79. if self.Precedence() < precedence:
  80. return '(%s)' % self
  81. else:
  82. return str(self)
  83. class Atom(Expression):
  84. def __init__(self, value):
  85. Expression.__init__(self, value, PRECEDENCE_ATOM)
  86. class Constant(Atom):
  87. def __str__(self):
  88. if self.value is Ellipsis:
  89. return '...'
  90. else:
  91. return repr(self.value)
  92. class Local(Atom):
  93. pass
  94. class Global(Atom):
  95. pass
  96. class Map(Atom):
  97. def __init__(self):
  98. Atom.__init__(self, [])
  99. def __str__(self):
  100. return '{%s}' % string.join(self.value, ', ')
  101. def SetAttr(self, name, value):
  102. self.value.append("%s: %s" % (name, value))
  103. class Tuple(Atom):
  104. def __init__(self, values):
  105. Atom.__init__(self, values)
  106. def __str__(self):
  107. values = self.Value()
  108. if len(values) == 0:
  109. return '()'
  110. elif len(values) == 1:
  111. # This doesn't need the parens immediately, but
  112. # it emphasises the prescence of the comma, and
  113. # confirms that it is a 1-tuple
  114. return '(%s,)' % values[0]
  115. else:
  116. return string.join(values, ', ')
  117. def Precedence(self):
  118. if len(self.value) <= 1:
  119. return PRECEDENCE_ATOM
  120. else:
  121. return PRECEDENCE_COMMA
  122. def Value(self):
  123. return tuple(self.value)
  124. class CodeCursor:
  125. def __init__(self, code):
  126. self.code = code # code object
  127. self.i = 0 # instruction pointer
  128. self.extend = 0 # extended opcodes
  129. self.lineno = 1 # minimum possible line number
  130. self.lastop = 0 # pointer to last operator read
  131. self.stopi = [len(code.co_code)]
  132. def GetPosition(self):
  133. return self.i
  134. def AtEnd(self):
  135. return self.i == self.stopi[0]
  136. def GetLine(self):
  137. return max(self.lineno, current_line(self.code, self.lastop))
  138. def SetLine(self, lineno):
  139. assert lineno >= self.lineno, `lineno, self.lineno`
  140. self.lineno = lineno
  141. def PushStop(self, i):
  142. self.stopi.append(i)
  143. def PopStop(self):
  144. return self.stopi.pop()
  145. def NextOpcode(self):
  146. if self.i < self.stopi[-1]:
  147. c = self.code.co_code[self.i]
  148. op = ord(c)
  149. opcode = dis.opname[op]
  150. if opcode == 'EXTENDED_ARG':
  151. self.i = self.i + 1
  152. self.extend = self.ReadOperand()
  153. return self.NextOpcode()
  154. else:
  155. opcode = None
  156. return opcode
  157. def ReadOpcode(self, *args):
  158. opcode = self.NextOpcode()
  159. assert opcode is not None
  160. if args:
  161. assert opcode in args, `self.i, opcode`
  162. self.lastop = self.i
  163. self.i = self.i + 1
  164. return opcode
  165. def ReadOperand(self):
  166. assert self.i + 1 < self.stopi[-1], `self.i, self.stopi`
  167. co_code = self.code.co_code
  168. operand = ord(co_code[self.i]) + ord(co_code[self.i+1])*256 + \
  169. (self.extend << 16)
  170. self.extend = 0
  171. self.i = self.i + 2
  172. return operand
  173. def GetConstant(self, n):
  174. return self.code.co_consts[n]
  175. def GetLocal(self, n):
  176. assert n < len(self.code.co_varnames), `n, self.code.co_varnames`
  177. return self.code.co_varnames[n]
  178. def GetName(self, n):
  179. assert n < len(self.code.co_names), `n, self.code.co_names`
  180. return self.code.co_names[n]
  181. class Decompiler:
  182. def __init__(self, version):
  183. self.version = version
  184. self.stack = []
  185. self.lines = {}
  186. self.global_decl = {}
  187. self.loop = None
  188. def decompile(self, code, *termop):
  189. try:
  190. self.code = code
  191. opcode = code.NextOpcode()
  192. while opcode is not None and opcode not in termop:
  193. opcode = string.replace(opcode, '+', '_')
  194. method = getattr(self, opcode)
  195. apply(method, (code,))
  196. opcode = code.NextOpcode()
  197. except:
  198. dis.dis(code.code)
  199. print
  200. raise
  201. def getstack(self):
  202. return self.stack
  203. def getsource(self, indent):
  204. assert not self.stack, `self.stack`
  205. lines = {}
  206. if not self.lines:
  207. self.lines[self.code.GetLine()] = 'pass'
  208. for key, value in self.lines.items():
  209. lines[key] = ' ' * indent + value
  210. return lines
  211. def addline(self, lineno, line):
  212. assert type(line) == type(''), `line`
  213. prev = self.lines.get(lineno)
  214. if prev is None:
  215. self.lines[lineno] = line
  216. else:
  217. self.lines[lineno] = '%s; %s' % (prev, line)
  218. def addclause(self, lineno, head, body):
  219. if body.has_key(lineno):
  220. if 0:
  221. assert len(body) == 1, `body`
  222. self.addline(lineno, "%s %s" % (head, string.strip(body[lineno])))
  223. else:
  224. line = body[lineno]
  225. self.addline(lineno, "%s %s" % (head, string.strip(line)))
  226. del body[lineno]
  227. self.lines.update(body)
  228. body[lineno] = line
  229. else:
  230. self.addline(lineno, head)
  231. self.lines.update(body)
  232. self.code.SetLine(max(body.keys()) + 1)
  233. def SET_LINENO(self, code):
  234. code.ReadOpcode('SET_LINENO')
  235. code.ReadOperand()
  236. def BINARY_ADD(self, code):
  237. code.ReadOpcode('BINARY_ADD')
  238. y = self.stack.pop().GetString(PRECEDENCE_ADD+1)
  239. x = self.stack.pop().GetString(PRECEDENCE_ADD)
  240. self.stack.append(Expression('%s + %s' % (x, y), PRECEDENCE_ADD))
  241. def BINARY_AND(self, code):
  242. code.ReadOpcode('BINARY_AND')
  243. y = self.stack.pop().GetString(PRECEDENCE_BAND+1)
  244. x = self.stack.pop().GetString(PRECEDENCE_BAND)
  245. self.stack.append(Expression('%s & %s' % (x, y), PRECEDENCE_BAND))
  246. def BINARY_DIVIDE(self, code):
  247. code.ReadOpcode('BINARY_DIVIDE')
  248. y = self.stack.pop().GetString(PRECEDENCE_MULT+1)
  249. x = self.stack.pop().GetString(PRECEDENCE_MULT)
  250. self.stack.append(Expression('%s / %s' % (x, y), PRECEDENCE_MULT))
  251. def BINARY_LSHIFT(self, code):
  252. code.ReadOpcode('BINARY_LSHIFT')
  253. y = self.stack.pop().GetString(PRECEDENCE_SHIFT+1)
  254. x = self.stack.pop().GetString(PRECEDENCE_SHIFT)
  255. self.stack.append(Expression('%s << %s' % (x, y), PRECEDENCE_SHIFT))
  256. def BINARY_MODULO(self, code):
  257. code.ReadOpcode('BINARY_MODULO')
  258. y = self.stack.pop().GetString(PRECEDENCE_MULT+1)
  259. x = self.stack.pop().GetString(PRECEDENCE_MULT)
  260. self.stack.append(Expression('%s %% %s' % (x, y), PRECEDENCE_MULT))
  261. def BINARY_MULTIPLY(self, code):
  262. code.ReadOpcode('BINARY_MULTIPLY')
  263. y = self.stack.pop().GetString(PRECEDENCE_MULT+1)
  264. x = self.stack.pop().GetString(PRECEDENCE_MULT)
  265. self.stack.append(Expression('%s * %s' % (x, y), PRECEDENCE_MULT))
  266. def BINARY_OR(self, code):
  267. code.ReadOpcode('BINARY_OR')
  268. y = self.stack.pop().GetString(PRECEDENCE_BOR+1)
  269. x = self.stack.pop().GetString(PRECEDENCE_BOR)
  270. self.stack.append(Expression('%s | %s' % (x, y), PRECEDENCE_BOR))
  271. def BINARY_POWER(self, code):
  272. code.ReadOpcode('BINARY_POWER')
  273. y = self.stack.pop()
  274. if y.Precedence() == PRECEDENCE_POWER:
  275. # include ** in parentheses because the correct order is poorly
  276. # understood, and is the opposite of the other binary operators
  277. y = y.GetString(PRECEDENCE_ATOM)
  278. else:
  279. y = y.GetString(PRECEDENCE_UNARY)
  280. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  281. self.stack.append(Expression('%s ** %s' % (x, y), PRECEDENCE_POWER))
  282. def BINARY_RSHIFT(self, code):
  283. code.ReadOpcode()
  284. y = self.stack.pop().GetString(PRECEDENCE_SHIFT+1)
  285. x = self.stack.pop().GetString(PRECEDENCE_SHIFT)
  286. self.stack.append(Expression('%s >> %s' % (x, y), PRECEDENCE_SHIFT))
  287. def BINARY_SUBSCR(self, code):
  288. code.ReadOpcode()
  289. y = self.stack.pop().GetString(PRECEDENCE_NONE)
  290. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  291. self.stack.append(Expression('%s[%s]' % (x, y), PRECEDENCE_ATOM))
  292. def BINARY_SUBTRACT(self, code):
  293. code.ReadOpcode()
  294. y = self.stack.pop().GetString(PRECEDENCE_ADD+1)
  295. x = self.stack.pop().GetString(PRECEDENCE_ADD)
  296. self.stack.append(Expression('%s - %s' % (x, y), PRECEDENCE_ADD))
  297. def BINARY_XOR(self, code):
  298. code.ReadOpcode()
  299. y = self.stack.pop().GetString(PRECEDENCE_BXOR+1)
  300. x = self.stack.pop().GetString(PRECEDENCE_BXOR)
  301. self.stack.append(Expression('%s ^ %s' % (x, y), PRECEDENCE_BXOR))
  302. def BREAK_LOOP(self, code):
  303. code.ReadOpcode('BREAK_LOOP')
  304. self.addline(code.GetLine(), 'break')
  305. def BUILD_LIST(self, code):
  306. code.ReadOpcode('BUILD_LIST')
  307. oparg = code.ReadOperand()
  308. values = []
  309. for i in range(oparg):
  310. value = self.stack.pop()
  311. if value.Precedence() < PRECEDENCE_ARG:
  312. value = '(%s)' % value
  313. values.append(str(value))
  314. values.reverse()
  315. valuelist = string.join(values, ', ')
  316. self.stack.append(Expression('[%s]' % valuelist, PRECEDENCE_ATOM))
  317. def BUILD_MAP(self, code):
  318. code.ReadOpcode('BUILD_MAP')
  319. code.ReadOperand()
  320. self.stack.append(Map())
  321. def BUILD_SLICE(self, code):
  322. code.ReadOpcode()
  323. code.ReadOperand()
  324. z = self.stack.pop()
  325. if isinstance(z, Constant) and z.Value() is None:
  326. z = ''
  327. else:
  328. z = z.GetString(PRECEDENCE_ARG)
  329. y = self.stack.pop()
  330. if isinstance(y, Constant) and y.Value() is None:
  331. y = ''
  332. else:
  333. y = y.GetString(PRECEDENCE_ARG)
  334. x = self.stack.pop()
  335. if isinstance(x, Constant) and x.Value() is None:
  336. x = ''
  337. else:
  338. x = x.GetString(PRECEDENCE_ARG)
  339. # always goes into BINARY_SUBSCR, so precedence is irrelevant
  340. self.stack.append(Expression('%s:%s:%s' % (x, y, z), PRECEDENCE_NONE))
  341. def BUILD_TUPLE(self, code):
  342. code.ReadOpcode()
  343. oparg = code.ReadOperand()
  344. values = []
  345. for i in range(oparg):
  346. value = self.stack.pop().GetString(PRECEDENCE_ARG)
  347. values.append(value)
  348. values.reverse()
  349. self.stack.append(Tuple(values))
  350. def CALL_FUNCTION(self, code):
  351. opcode = code.ReadOpcode('CALL_FUNCTION', 'CALL_FUNCTION_VAR',
  352. 'CALL_FUNCTION_KW', 'CALL_FUNCTION_VAR_KW')
  353. oparg = code.ReadOperand()
  354. nkw, nargs = divmod(oparg, 256)
  355. args = []
  356. if opcode in ('CALL_FUNCTION_KW', 'CALL_FUNCTION_VAR_KW'):
  357. name = self.stack.pop()
  358. args.append('**%s' % name)
  359. if opcode in ('CALL_FUNCTION_VAR', 'CALL_FUNCTION_VAR_KW'):
  360. name = self.stack.pop()
  361. args.append('*%s' % name)
  362. for i in range(nkw):
  363. value = self.stack.pop().GetString(PRECEDENCE_ARG)
  364. name = self.stack.pop().Value()
  365. args.append('%s=%s' % (name, value))
  366. for i in range(nargs):
  367. arg = self.stack.pop().GetString(PRECEDENCE_ARG)
  368. args.append(str(arg))
  369. args.reverse()
  370. arglist = string.join(args, ', ')
  371. func = self.stack.pop().GetString(PRECEDENCE_ATOM)
  372. self.stack.append(Expression('%s(%s)' % (func, arglist),
  373. PRECEDENCE_ATOM))
  374. CALL_FUNCTION_VAR = CALL_FUNCTION
  375. CALL_FUNCTION_KW = CALL_FUNCTION
  376. CALL_FUNCTION_VAR_KW = CALL_FUNCTION
  377. def COMPARE_OP(self, code):
  378. code.ReadOpcode()
  379. oparg = code.ReadOperand()
  380. if len(self.stack) == 1:
  381. y = self.stack.pop()
  382. x = None
  383. else:
  384. y = self.stack.pop()
  385. x = self.stack.pop()
  386. op = dis.cmp_op[oparg]
  387. if op[0] in '!<=>':
  388. prec = PRECEDENCE_CMP
  389. elif op[-2:] == 'in':
  390. prec = PRECEDENCE_IN
  391. else:
  392. assert op[:2] == 'is', `op`
  393. prec = PRECEDENCE_IS
  394. if y.Precedence() <= prec:
  395. y = '(%s)' % y
  396. if x is None:
  397. self.stack.append(Chain('%s %s' % (op, y)))
  398. else:
  399. if x.Precedence() < prec:
  400. x = '(%s)' % x
  401. self.stack.append(Expression('%s %s %s' % (x, op, y), prec))
  402. def DELETE_ATTR(self, code):
  403. code.ReadOpcode()
  404. oparg = code.ReadOperand()
  405. attr = code.GetName(oparg)
  406. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  407. self.addline(code.GetLine(), 'del %s.%s' % (x, attr))
  408. def DELETE_FAST(self, code):
  409. names = []
  410. lastlineno = -1
  411. while code.NextOpcode() in ('DELETE_FAST', 'DELETE_GLOBAL',
  412. 'DELETE_NAME'):
  413. opcode = code.ReadOpcode()
  414. if lastlineno == -1:
  415. lineno = lastlineno = code.GetLine()
  416. else:
  417. lineno = code.GetLine()
  418. if lineno != lastlineno:
  419. self.addline(lastlineno, 'del %s' % string.join(names, ', '))
  420. names = []
  421. lastlineno = lineno
  422. oparg = code.ReadOperand()
  423. if opcode == 'DELETE_FAST':
  424. names.append(code.GetLocal(oparg))
  425. elif opcode == 'DELETE_GLOBAL':
  426. names.append(code.GetName(oparg))
  427. else:
  428. assert opcode == 'DELETE_NAME', `opcode`
  429. names.append(code.GetName(oparg))
  430. self.addline(lastlineno, 'del %s' % string.join(names, ', '))
  431. DELETE_GLOBAL = DELETE_FAST
  432. DELETE_NAME = DELETE_FAST
  433. def DELETE_SLICE_0(self, code):
  434. code.ReadOpcode()
  435. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  436. self.addline(code.GetLine(), 'del %s[:]' % x)
  437. def DELETE_SLICE_1(self, code):
  438. code.ReadOpcode()
  439. y = self.stack.pop().GetString(PRECEDENCE_ARG)
  440. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  441. self.addline(code.GetLine(), 'del %s[%s:]' % (x, y))
  442. def DELETE_SLICE_2(self, code):
  443. code.ReadOpcode()
  444. z = self.stack.pop().GetString(PRECEDENCE_ARG)
  445. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  446. self.addline(code.GetLine(), 'del %s[:%s]' % (x, z))
  447. def DELETE_SLICE_3(self, code):
  448. code.ReadOpcode()
  449. z = self.stack.pop().GetString(PRECEDENCE_ARG)
  450. y = self.stack.pop().GetString(PRECEDENCE_ARG)
  451. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  452. self.addline(code.GetLine(), 'del %s[%s:%s]' % (x, y, z))
  453. def DELETE_SUBSCR(self, code):
  454. code.ReadOpcode()
  455. y = self.stack.pop().GetString(PRECEDENCE_NONE)
  456. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  457. self.addline(code.GetLine(), 'del %s[%s]' % (x, y))
  458. def DUP_TOP(self, code):
  459. code.ReadOpcode('DUP_TOP')
  460. self.stack.append(self.stack[-1])
  461. def DUP_TOPX(self, code):
  462. code.ReadOpcode('DUP_TOPX')
  463. n = code.ReadOperand()
  464. self.stack = self.stack + self.stack[-n:]
  465. def EXEC_STMT(self, code):
  466. code.ReadOpcode('EXEC_STMT')
  467. lineno = code.GetLine()
  468. locals = self.stack.pop()
  469. globals = self.stack.pop()
  470. stmt = self.stack.pop().GetString(PRECEDENCE_IN)
  471. if isinstance(globals, Constant) and globals.Value() is None:
  472. self.addline(lineno, 'exec %s' % stmt)
  473. else:
  474. if locals is globals:
  475. globals = globals.GetString(PRECEDENCE_ARG)
  476. self.addline(lineno, 'exec %s in %s' % (stmt, globals))
  477. else:
  478. globals = globals.GetString(PRECEDENCE_ARG)
  479. locals = locals.GetString(PRECEDENCE_ARG)
  480. self.addline(lineno,
  481. 'exec %s in %s, %s' % (stmt, globals, locals))
  482. def FOR_LOOP(self, code):
  483. code.ReadOpcode('FOR_LOOP')
  484. leap = code.ReadOperand()
  485. loopcleanup = code.GetPosition() + leap
  486. self.stack.pop() # sequence index
  487. forlist = self.stack.pop()
  488. forvar = self.build_target(code).GetString(PRECEDENCE_NONE)
  489. head = "for %s in %s:" % (forvar, forlist)
  490. lineno = code.GetLine()
  491. d = Decompiler(self.version)
  492. d.decompile(code, 'JUMP_ABSOLUTE')
  493. self.addclause(lineno, head, d.getsource(1))
  494. code.ReadOpcode('JUMP_ABSOLUTE')
  495. oparg = code.ReadOperand() # to FOR_LOOP (or SET_LINENO)
  496. assert code.GetPosition() == loopcleanup
  497. code.ReadOpcode('POP_BLOCK')
  498. end = self.loop[1]
  499. self.loop = None
  500. if code.GetPosition() < end:
  501. lineno = code.GetLine()
  502. code.PushStop(end)
  503. d = Decompiler(self.version)
  504. d.decompile(code)
  505. code.PopStop()
  506. self.addclause(lineno, "else:", d.getsource(1))
  507. assert code.GetPosition() == end
  508. def IMPORT_NAME(self, code):
  509. names = []
  510. while code.NextOpcode() == 'IMPORT_NAME':
  511. code.ReadOpcode('IMPORT_NAME')
  512. if self.version >= (2, 0):
  513. self.stack.pop()
  514. oparg = code.ReadOperand()
  515. module = code.GetName(oparg)
  516. opname = code.ReadOpcode('IMPORT_FROM', 'IMPORT_STAR',
  517. 'STORE_FAST', 'STORE_NAME')
  518. if opname in ('IMPORT_FROM', 'IMPORT_STAR'):
  519. if names:
  520. self.addline('import %s' % string.join(names, ', '))
  521. names = []
  522. if opname == 'IMPORT_STAR':
  523. objs = '*'
  524. else:
  525. while opname == 'IMPORT_FROM':
  526. oparg = code.ReadOperand()
  527. name1 = code.GetName(oparg)
  528. if self.version >= (2, 0):
  529. opname = code.ReadOpcode('STORE_FAST', 'STORE_NAME')
  530. oparg = code.ReadOperand()
  531. if opname == 'STORE_FAST':
  532. name2 = code.GetLocal(oparg)
  533. else:
  534. name2 = code.GetName(oparg)
  535. else:
  536. name2 = name1
  537. if name1 == name2:
  538. names.append(name1)
  539. else:
  540. names.append('%s as %s' % (name1, name2))
  541. opname = code.ReadOpcode('IMPORT_FROM', 'POP_TOP')
  542. objs = string.join(names, ', ')
  543. self.addline(code.GetLine(),
  544. 'from %s import %s' %
  545. (module, objs))
  546. names = []
  547. else:
  548. assert opname in ('STORE_FAST', 'STORE_NAME'), `opname`
  549. oparg = code.ReadOperand()
  550. if opname == 'STORE_FAST':
  551. name = code.GetLocal(oparg)
  552. else:
  553. name = code.GetName(oparg)
  554. if module == name:
  555. names.append(module)
  556. else:
  557. names.append("%s as %s" % (module, name))
  558. if names:
  559. self.addline(code.GetLine(),
  560. 'import %s' % string.join(names, ', '))
  561. def INPLACE_ADD(self, code):
  562. opcode = code.ReadOpcode(
  563. 'INPLACE_ADD', 'INPLACE_AND', 'INPLACE_DIVIDE', 'INPLACE_LSHIFT',
  564. 'INPLACE_MODULO', 'INPLACE_MULTIPLY', 'INPLACE_OR', 'INPLACE_POWER',
  565. 'INPLACE_RSHIFT', 'INPLACE_SUBTRACT', 'INPLACE_XOR')
  566. if opcode == 'INPLACE_ADD':
  567. op = '+='
  568. elif opcode == 'INPLACE_AND':
  569. op = '&='
  570. elif opcode == 'INPLACE_DIVIDE':
  571. op = '/='
  572. elif opcode == 'INPLACE_LSHIFT':
  573. op = '<<='
  574. elif opcode == 'INPLACE_MODULO':
  575. op = '%='
  576. elif opcode == 'INPLACE_MULTIPLY':
  577. op = '*='
  578. elif opcode == 'INPLACE_OR':
  579. op = '|='
  580. elif opcode == 'INPLACE_POWER':
  581. op = '**='
  582. elif opcode == 'INPLACE_RSHIFT':
  583. op = '>>='
  584. elif opcode == 'INPLACE_SUBTRACT':
  585. op = '-='
  586. else:
  587. assert opcode == 'INPLACE_XOR', `opcode`
  588. op = '^='
  589. y = self.stack.pop().GetString(PRECEDENCE_NONE)
  590. x = self.stack.pop().GetString(PRECEDENCE_NONE)
  591. opcode = code.ReadOpcode('ROT_THREE', 'ROT_TWO', 'STORE_FAST',
  592. 'STORE_GLOBAL')
  593. if opcode == 'STORE_FAST':
  594. code.ReadOperand()
  595. elif opcode == 'STORE_GLOBAL':
  596. code.ReadOperand()
  597. elif opcode == 'STORE_NAME':
  598. code.ReadOperand()
  599. elif opcode == 'ROT_THREE':
  600. code.ReadOpcode('STORE_SUBSCR')
  601. self.stack.pop()
  602. self.stack.pop()
  603. elif opcode == 'ROT_TWO':
  604. code.ReadOpcode('STORE_ATTR')
  605. code.ReadOperand()
  606. self.stack.pop()
  607. self.addline(code.GetLine(), '%s %s %s' % (x, op, y))
  608. INPLACE_AND = INPLACE_ADD
  609. INPLACE_DIVIDE = INPLACE_ADD
  610. INPLACE_LSHIFT = INPLACE_ADD
  611. INPLACE_MODULO = INPLACE_ADD
  612. INPLACE_MULTIPLY = INPLACE_ADD
  613. INPLACE_OR = INPLACE_ADD
  614. INPLACE_POWER = INPLACE_ADD
  615. INPLACE_RSHIFT = INPLACE_ADD
  616. INPLACE_SUBTRACT = INPLACE_ADD
  617. INPLACE_XOR = INPLACE_ADD
  618. def JUMP_ABSOLUTE(self, code):
  619. code.ReadOpcode('JUMP_ABSOLUTE')
  620. code.ReadOperand()
  621. self.addline(code.GetLine(), 'continue')
  622. def JUMP_IF_FALSE(self, code):
  623. code.ReadOpcode('JUMP_IF_FALSE')
  624. leap = code.ReadOperand()
  625. endcond = code.GetPosition() + leap
  626. opcode = code.ReadOpcode('POP_TOP')
  627. assert opcode == 'POP_TOP', `opcode`
  628. lineno = code.GetLine()
  629. code.PushStop(endcond)
  630. d = Decompiler(self.version)
  631. if self.loop is None:
  632. d.decompile(code, 'JUMP_FORWARD')
  633. else:
  634. d.decompile(code, 'JUMP_ABSOLUTE')
  635. code.PopStop()
  636. stack = d.getstack()
  637. if stack:
  638. if len(stack) == 1:
  639. assert code.GetPosition() == endcond
  640. # and
  641. x = self.stack.pop().GetString(PRECEDENCE_AND+1)
  642. y = stack.pop().GetString(PRECEDENCE_AND)
  643. self.stack.append(
  644. Expression('%s and %s' % (x, y), PRECEDENCE_AND))
  645. else:
  646. # assert
  647. self.stack.pop()
  648. test = stack.pop().GetString(PRECEDENCE_ARG)
  649. value = stack.pop()
  650. if value is None:
  651. self.addline(lineno, 'assert %s' % test)
  652. else:
  653. value = value.GetString(PRECEDENCE_ARG)
  654. self.addline(lineno, 'assert %s, %s' % (test, value))
  655. code.ReadOpcode('POP_TOP')
  656. else:
  657. condition = self.stack.pop()
  658. body = d.getsource(1)
  659. if self.loop is None:
  660. # if
  661. self.addclause(lineno, 'if %s:' % condition, body)
  662. code.ReadOpcode('JUMP_FORWARD')
  663. leap = code.ReadOperand()
  664. end = code.GetPosition() + leap
  665. code.ReadOpcode('POP_TOP')
  666. while code.GetPosition() < end:
  667. lineno = code.GetLine()
  668. code.PushStop(end)
  669. d = Decompiler(self.version)
  670. d.decompile(code, 'JUMP_FORWARD')
  671. code.PopStop()
  672. body = d.getsource(1)
  673. if body.has_key(lineno):
  674. if body[lineno][-1] == ':':
  675. # elif
  676. body = d.getsource(0)
  677. body[lineno] = 'el' + body[lineno]
  678. self.lines.update(body)
  679. else:
  680. #assert len(body) == 1, `body`
  681. line = body[lineno]
  682. self.addline(lineno, "else: %s" %
  683. string.strip(line))
  684. del body[lineno]
  685. self.lines.update(body)
  686. body[lineno] = line
  687. else:
  688. self.addline(lineno, "else:")
  689. self.lines.update(body)
  690. code.SetLine(max(body.keys()) + 1)
  691. else:
  692. # while
  693. self.addclause(lineno, "while %s:" % condition, body)
  694. code.ReadOpcode('JUMP_ABSOLUTE')
  695. oparg = code.ReadOperand()
  696. assert oparg == self.loop[0], `(oparg, self.loop)`
  697. code.ReadOpcode('POP_TOP')
  698. code.ReadOpcode('POP_BLOCK')
  699. end = self.loop[1]
  700. self.loop = None
  701. if code.GetPosition() < end:
  702. lineno = code.GetLine()
  703. code.PushStop(end)
  704. d = Decompiler(self.version)
  705. d.decompile(code)
  706. code.PopStop()
  707. self.addclause(lineno, "else:", d.getsource(1))
  708. assert code.GetPosition() == end
  709. def JUMP_IF_TRUE(self, code):
  710. code.ReadOpcode('JUMP_IF_TRUE')
  711. leap = code.ReadOperand()
  712. end = code.GetPosition() + leap
  713. code.ReadOpcode('POP_TOP')
  714. code.PushStop(end)
  715. d = Decompiler(self.version)
  716. d.decompile(code, 'RAISE_VARARGS')
  717. code.PopStop()
  718. stack = d.getstack()
  719. assert stack
  720. if code.GetPosition() == end:
  721. # or expression
  722. x = self.stack.pop().GetString(PRECEDENCE_OR+1)
  723. y = stack.pop().GetString(PRECEDENCE_OR)
  724. self.stack.append(Expression('%s or %s' % (x, y), PRECEDENCE_OR))
  725. else:
  726. # raise AssertionError, exp
  727. test = self.stack.pop()
  728. code.ReadOpcode('RAISE_VARARGS')
  729. oparg = code.ReadOperand()
  730. if oparg == 1:
  731. self.stack.append(None)
  732. else:
  733. value = stack.pop()
  734. self.stack.append(value)
  735. self.stack.append(test)
  736. assert len(self.stack) == 2, `self.stack`
  737. assert code.GetPosition() == end
  738. def LOAD_ATTR(self, code):
  739. code.ReadOpcode('LOAD_ATTR')
  740. oparg = code.ReadOperand()
  741. attr = code.GetName(oparg)
  742. x = self.stack.pop()
  743. if x.Precedence() < PRECEDENCE_ATOM:
  744. x = '(%s)' % x
  745. self.stack.append(Expression('%s.%s' % (x, attr), PRECEDENCE_ATOM))
  746. def LOAD_CONST(self, code):
  747. code.ReadOpcode('LOAD_CONST')
  748. oparg = code.ReadOperand()
  749. self.stack.append(Constant(code.GetConstant(oparg)))
  750. def LOAD_FAST(self, code):
  751. code.ReadOpcode('LOAD_FAST')
  752. oparg = code.ReadOperand()
  753. self.stack.append(Local(code.GetLocal(oparg)))
  754. def LOAD_GLOBAL(self, code):
  755. code.ReadOpcode('LOAD_GLOBAL')
  756. oparg = code.ReadOperand()
  757. self.stack.append(Global(code.GetName(oparg)))
  758. def LOAD_LOCALS(self, code):
  759. code.ReadOpcode('LOAD_LOCALS')
  760. self.stack.append(Constant(None))
  761. def LOAD_NAME(self, code):
  762. code.ReadOpcode('LOAD_NAME')
  763. oparg = code.ReadOperand()
  764. self.stack.append(Local(code.GetName(oparg)))
  765. def MAKE_FUNCTION(self, code):
  766. code.ReadOpcode('MAKE_FUNCTION')
  767. defaultcount = code.ReadOperand()
  768. co = self.stack.pop().Value()
  769. if co.co_name == '<lambda>':
  770. # lambda
  771. # Get the function def part
  772. params = []
  773. argcount = co.co_argcount
  774. while argcount:
  775. argcount = argcount - 1
  776. name = co.co_varnames[argcount]
  777. if defaultcount:
  778. defaultcount = defaultcount - 1
  779. default = self.stack.pop().GetString(PRECEDENCE_ARG)
  780. params.append('%s=%s' % (name, default))
  781. else:
  782. params.append(name)
  783. params.reverse()
  784. argcount = co.co_argcount
  785. if co.co_flags & VARARGS:
  786. params.append('*' + co.co_varnames[argcount])
  787. argcount = argcount + 1
  788. if co.co_flags & KWARGS:
  789. params.append('**' + co.co_varnames[argcount])
  790. paramlist = string.join(params, ', ')
  791. # get the function body
  792. d = Decompiler(self.version)
  793. d.decompile(CodeCursor(co), 'RETURN_VALUE')
  794. stack = d.getstack()
  795. assert len(stack) == 1, `stack`
  796. y = stack.pop().GetString(PRECEDENCE_LAMBDA)
  797. self.stack.append(
  798. Expression('lambda %s: %s' % (paramlist, y), PRECEDENCE_LAMBDA))
  799. else:
  800. opcode = code.ReadOpcode('CALL_FUNCTION', 'STORE_FAST',
  801. 'STORE_NAME')
  802. if opcode == 'CALL_FUNCTION':
  803. # class
  804. oparg = code.ReadOperand()
  805. assert oparg == 0, `oparg`
  806. code.ReadOpcode('BUILD_CLASS')
  807. super = self.stack.pop().Value()
  808. name = self.stack.pop().Value()
  809. opcode = code.ReadOpcode('STORE_FAST', 'STORE_NAME')
  810. oparg = code.ReadOperand()
  811. if opcode == 'STORE_FAST':
  812. classname = code.GetLocal(oparg)
  813. else:
  814. classname = code.GetName(oparg)
  815. assert name == classname, `name, classname`
  816. if super:
  817. classname = '%s(%s)' % (classname, string.join(super, ', '))
  818. lineno = code.GetLine()
  819. d = Decompiler(self.version)
  820. d.decompile(CodeCursor(co))
  821. body = d.getsource(1)
  822. if body.has_key(lineno):
  823. if len(body) == 1:
  824. self.addline(lineno, "class %s: %s" % (classname,
  825. string.strip(body[lineno])))
  826. else:
  827. assert 0
  828. # __doc__ string appears in 0th row
  829. assert not body.has_key(lineno+1), `body`
  830. body[lineno+1] = body[lineno]
  831. del body[lineno]
  832. self.addline(lineno, "class %s:" % classname)
  833. self.lines.update(body)
  834. else:
  835. self.addline(lineno, "class %s:" % classname)
  836. self.lines.update(body)
  837. code.SetLine(max(body.keys()) + 1)
  838. else:
  839. assert opcode in ('STORE_FAST', 'STORE_NAME'), `opcode`
  840. # def
  841. oparg = code.ReadOperand()
  842. if opcode == 'STORE_FAST':
  843. funcname = code.GetLocal(oparg)
  844. else:
  845. funcname = code.GetName(oparg)
  846. # Get the function def part
  847. params = []
  848. argcount = co.co_argcount
  849. while argcount:
  850. argcount = argcount - 1
  851. name = co.co_varnames[argcount]
  852. if defaultcount:
  853. defaultcount = defaultcount - 1
  854. default = self.stack.pop()
  855. if default.Precedence() < PRECEDENCE_ARG:
  856. default = '(%s)' % default
  857. params.append('%s=%s' % (name, default))
  858. else:
  859. params.append(name)
  860. params.reverse()
  861. argcount = co.co_argcount
  862. if co.co_flags & VARARGS:
  863. params.append('*' + co.co_varnames[argcount])
  864. argcount = argcount + 1
  865. if co.co_flags & KWARGS:
  866. params.append('**' + co.co_varnames[argcount])
  867. paramlist = string.join(params, ', ')
  868. head = "def %s(%s):" % (funcname, paramlist)
  869. # get the function body
  870. lineno = code.GetLine()
  871. d = Decompiler(self.version)
  872. d.decompile(CodeCursor(co))
  873. self.addclause(lineno, head, d.getsource(1))
  874. def PRINT_ITEM(self, code):
  875. code.ReadOpcode('PRINT_ITEM')
  876. x = self.stack.pop().GetString(PRECEDENCE_ARG)
  877. if code.NextOpcode() == 'PRINT_NEWLINE':
  878. code.ReadOpcode('PRINT_NEWLINE')
  879. self.addline(code.GetLine(), 'print %s' % x)
  880. else:
  881. self.addline(code.GetLine(), 'print %s,' % x)
  882. def PRINT_ITEM_TO(self, code):
  883. # XXX - if file is an expression, it gets evaluated multiple times.
  884. code.ReadOpcode('PRINT_ITEM_TO')
  885. file = self.stack.pop()
  886. x = self.stack.pop().GetString(PRECEDENCE_ARG)
  887. if code.NextOpcode() == 'PRINT_NEWLINE_TO' and self.stack[-1] is file:
  888. code.ReadOpcode('PRINT_NEWLINE_TO')
  889. self.stack.pop()
  890. if file.Precedence() < PRECEDENCE_ARG:
  891. file = '(%s)' % file
  892. self.addline('print >> %s, %s' % (file, x))
  893. else:
  894. if file.Precedence() < PRECEDENCE_ARG:
  895. file = '(%s)' % file
  896. self.addline('print >> %s, %s,' % (file, x))
  897. def PRINT_NEWLINE(self, code):
  898. code.ReadOpcode('PRINT_NEWLINE')
  899. self.addline(code.GetLine(), 'print')
  900. def PRINT_NEWLINE_TO(self, code):
  901. code.ReadOpcode('PRINT_NEWLINE')
  902. file = self.stack.pop().GetString(PRECEDENCE_ARG)
  903. self.addline(code.GetLine(), 'print >> %s' % file)
  904. def POP_TOP(self, code):
  905. code.ReadOpcode('POP_TOP')
  906. self.addline(code.GetLine(),
  907. self.stack.pop().GetString(PRECEDENCE_NONE))
  908. def RAISE_VARARGS(self, code):
  909. code.ReadOpcode('RAISE_VARARGS')
  910. argcount = code.ReadOperand()
  911. args = []
  912. for i in range(argcount):
  913. arg = self.stack.pop().GetString(PRECEDENCE_ARG)
  914. args.append(arg)
  915. args.reverse()
  916. self.addline(code.GetLine(), 'raise %s' % string.join(args, ', '))
  917. def RETURN_VALUE(self, code):
  918. code.ReadOpcode()
  919. y = self.stack.pop()
  920. if isinstance(y, Constant) and y.Value() is None:
  921. if not code.AtEnd():
  922. self.addline(code.GetLine(), 'return')
  923. else:
  924. value = y.GetString(PRECEDENCE_NONE)
  925. self.addline(code.GetLine(), 'return %s' % value)
  926. def ROT_THREE(self, code):
  927. code.ReadOpcode('ROT_THREE')
  928. assert len(self.stack) >= 3, `code.GetPosition(), self.stack`
  929. self.stack.pop() # duplicate of y
  930. y = self.stack.pop().GetString(PRECEDENCE_CMP+1)
  931. x = self.stack.pop().GetString(PRECEDENCE_CMP+1)
  932. code.ReadOpcode('COMPARE_OP')
  933. oparg = code.ReadOperand()
  934. op = dis.cmp_op[oparg]
  935. chain = '%s %s %s' % (x, op, y)
  936. opcode = code.ReadOpcode('JUMP_IF_FALSE')
  937. leap = code.ReadOperand()
  938. stop1 = code.GetPosition() + leap
  939. while opcode == 'JUMP_IF_FALSE':
  940. assert code.GetPosition() + leap == stop1, \
  941. `code.GetPosition(), leap, stop1`
  942. code.ReadOpcode('POP_TOP')
  943. code.PushStop(stop1 - 6)
  944. d = Decompiler(self.version)
  945. d.decompile(code, 'ROT_THREE')
  946. code.PopStop()
  947. stack = d.getstack()
  948. y = stack.pop().GetString(PRECEDENCE_CMP+1)
  949. opcode = code.ReadOpcode('COMPARE_OP', 'ROT_THREE')
  950. if opcode == 'ROT_THREE':
  951. opcode = code.ReadOpcode('COMPARE_OP')
  952. oparg = code.ReadOperand()
  953. op = dis.cmp_op[oparg]
  954. chain = '%s %s %s' % (chain, op, y)
  955. opcode = code.ReadOpcode('JUMP_IF_FALSE', 'JUMP_FORWARD')
  956. leap = code.ReadOperand()
  957. assert leap == 2, `leap`
  958. assert code.GetPosition() == stop1, `code.GetPosition(), stop1`
  959. code.ReadOpcode('ROT_TWO')
  960. code.ReadOpcode('POP_TOP')
  961. self.stack.append(Expression(chain, PRECEDENCE_CMP))
  962. def ROT_TWO(self, code):
  963. code.ReadOpcode('ROT_TWO')
  964. n1 = self.stack.pop()
  965. n2 = self.stack.pop()
  966. self.stack.append(n1)
  967. self.stack.append(n2)
  968. def handle_except_clause(self, code):
  969. opcode = code.ReadOpcode('DUP_TOP', 'POP_TOP', 'SET_LINENO')
  970. if opcode == 'SET_LINENO':
  971. code.ReadOperand()
  972. opcode = code.ReadOpcode('DUP_TOP', 'POP_TOP')
  973. lineno = code.GetLine()
  974. if opcode == 'DUP_TOP':
  975. d = Decompiler(self.version)
  976. d.decompile(code, 'COMPARE_OP')
  977. stack = d.getstack()
  978. exc_type = stack.pop().GetString(PRECEDENCE_ARG)
  979. code.ReadOpcode('COMPARE_OP')
  980. oparg = code.ReadOperand()
  981. assert oparg == 10, `oparg` # 10 -> exception match
  982. code.ReadOpcode('JUMP_IF_FALSE')
  983. leap = code.ReadOperand()
  984. nextclause = code.GetPosition() + leap
  985. code.ReadOpcode('POP_TOP') # result of test
  986. code.ReadOpcode('POP_TOP') # exc_type
  987. opcode = code.NextOpcode()
  988. if opcode == 'POP_TOP': # exc_value
  989. code.ReadOpcode('POP_TOP')
  990. head = 'except %s:' % exc_type
  991. else:
  992. exc_value = self.build_target(code).GetString(PRECEDENCE_ARG)
  993. head = 'except %s, %s:' % (exc_type, exc_value)
  994. else:
  995. code.ReadOpcode('POP_TOP') # exc_value
  996. head = 'except:'
  997. nextclause = None
  998. code.ReadOpcode('POP_TOP') # exc_tb
  999. d = Decompiler(self.version)
  1000. d.decompile(code, 'JUMP_FORWARD')
  1001. self.addclause(lineno, head, d.getsource(1))
  1002. code.ReadOpcode('JUMP_FORWARD')
  1003. leap = code.ReadOperand()
  1004. end = code.GetPosition() + leap
  1005. if nextclause is not None:
  1006. assert code.GetPosition() == nextclause
  1007. code.ReadOpcode('POP_TOP')
  1008. return end
  1009. def SETUP_EXCEPT(self, code):
  1010. code.ReadOpcode('SETUP_EXCEPT')
  1011. leap = code.ReadOperand()
  1012. firstexceptclause = code.GetPosition() + leap
  1013. lineno = code.GetLine()
  1014. d = Decompiler(self.version)
  1015. d.decompile(code, 'POP_BLOCK')
  1016. self.addclause(lineno, "try:", d.getsource(1))
  1017. code.ReadOpcode('POP_BLOCK')
  1018. code.ReadOpcode('JUMP_FORWARD')
  1019. leap = code.ReadOperand()
  1020. elseclause = code.GetPosition() + leap
  1021. assert code.GetPosition() == firstexceptclause
  1022. end = self.handle_except_clause(code)
  1023. while code.NextOpcode() != 'END_FINALLY':
  1024. end1 = self.handle_except_clause(code)
  1025. assert end1 == end, `end1, end`
  1026. code.ReadOpcode('END_FINALLY')
  1027. assert code.GetPosition() == elseclause, \
  1028. `code.GetPosition(), elseclause`
  1029. if elseclause < end:
  1030. lineno = code.GetLine()
  1031. code.PushStop(end)
  1032. d = Decompiler(self.version)
  1033. d.decompile(code)
  1034. code.PopStop()
  1035. self.addclause(lineno, "else:", d.getsource(1))
  1036. assert code.GetPosition() == end
  1037. def SETUP_FINALLY(self, code):
  1038. code.ReadOpcode('SETUP_FINALLY')
  1039. leap = code.ReadOperand()
  1040. finallyclause = code.GetPosition() + leap
  1041. lineno = code.GetLine()
  1042. d = Decompiler(self.version)
  1043. d.decompile(code, 'POP_BLOCK')
  1044. body = d.getsource(1)
  1045. self.addclause(lineno, "try:", body)
  1046. code.ReadOpcode('POP_BLOCK')
  1047. code.ReadOpcode('LOAD_CONST')
  1048. oparg = code.ReadOperand()
  1049. assert oparg == 0, `oparg`
  1050. assert code.GetPosition() == finallyclause
  1051. lineno = code.GetLine()
  1052. d = Decompiler(self.version)
  1053. d.decompile(code, 'END_FINALLY')
  1054. body = d.getsource(1)
  1055. self.addclause(lineno, "finally:", body)
  1056. code.ReadOpcode('END_FINALLY')
  1057. def SETUP_LOOP(self, code):
  1058. code.ReadOpcode('SETUP_LOOP')
  1059. leap = code.ReadOperand()
  1060. assert self.loop is None, `self.loop`
  1061. i = code.GetPosition()
  1062. self.loop = i, i + leap
  1063. def SLICE_0(self, code):
  1064. code.ReadOpcode()
  1065. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1066. self.stack.append(Expression('%s[:]' % x, PRECEDENCE_ATOM))
  1067. def SLICE_1(self, code):
  1068. code.ReadOpcode()
  1069. y = self.stack.pop().GetString(PRECEDENCE_ARG)
  1070. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1071. self.stack.append(Expression('%s[%s:]' % (x, y), PRECEDENCE_ATOM))
  1072. def SLICE_2(self, code):
  1073. code.ReadOpcode()
  1074. z = self.stack.pop().GetString(PRECEDENCE_ARG)
  1075. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1076. self.stack.append(Expression('%s[:%s]' % (x, z), PRECEDENCE_ATOM))
  1077. def SLICE_3(self, code):
  1078. code.ReadOpcode()
  1079. z = self.stack.pop().GetString(PRECEDENCE_ARG)
  1080. y = self.stack.pop().GetString(PRECEDENCE_ARG)
  1081. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1082. self.stack.append(Expression('%s[%s:%s]' % (x, y, z), PRECEDENCE_ATOM))
  1083. def STORE_ATTR(self, code):
  1084. code.ReadOpcode()
  1085. oparg = code.ReadOperand()
  1086. attr = code.GetName(oparg)
  1087. name = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1088. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1089. self.addline(code.GetLine(), '%s.%s = %s' % (name, attr, value))
  1090. def STORE_FAST(self, code):
  1091. code.ReadOpcode()
  1092. oparg = code.ReadOperand()
  1093. name = code.GetLocal(oparg)
  1094. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1095. self.addline(code.GetLine(), '%s = %s' % (name, value))
  1096. def STORE_GLOBAL(self, code):
  1097. # XXX - need to put in global statement
  1098. code.ReadOpcode()
  1099. oparg = code.ReadOperand()
  1100. name = code.GetName(oparg)
  1101. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1102. self.addline(code.GetLine(), '%s = %s' % (name, value))
  1103. def STORE_NAME(self, code):
  1104. code.ReadOpcode()
  1105. oparg = code.ReadOperand()
  1106. name = code.GetName(oparg)
  1107. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1108. self.addline(code.GetLine(), '%s = %s' % (name, value))
  1109. def STORE_SLICE_0(self, code):
  1110. code.ReadOpcode()
  1111. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1112. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1113. self.addline(code.GetLine(), '%s[:] = %s' % (x, value))
  1114. def STORE_SLICE_1(self, code):
  1115. code.ReadOpcode()
  1116. y = self.stack.pop().GetString(PRECEDENCE_ARG)
  1117. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1118. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1119. self.addline(code.GetLine(), '%s[%s:] = %s' % (x, y, value))
  1120. def STORE_SLICE_2(self, code):
  1121. code.ReadOpcode()
  1122. z = self.stack.pop().GetString(PRECEDENCE_ARG)
  1123. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1124. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1125. self.addline(code.GetLine(), '%s[:%s] = %s' % (x, z, value))
  1126. def STORE_SLICE_3(self, code):
  1127. code.ReadOpcode()
  1128. z = self.stack.pop().GetString(PRECEDENCE_ARG)
  1129. y = self.stack.pop().GetString(PRECEDENCE_ARG)
  1130. x = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1131. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1132. self.addline(code.GetLine(), '%s[%s:%s] = %s' % (x, y, z, value))
  1133. def STORE_SUBSCR(self, code):
  1134. code.ReadOpcode()
  1135. key = self.stack.pop()
  1136. obj = self.stack.pop()
  1137. if isinstance(obj, Map):
  1138. value = self.stack.pop().GetString(PRECEDENCE_ARG)
  1139. if key.Precedence() < PRECEDENCE_ARG:
  1140. key = '(%s)' % key
  1141. obj.SetAttr(key, value)
  1142. else:
  1143. obj = obj.GetString(PRECEDENCE_ATOM)
  1144. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1145. self.addline(code.GetLine(),
  1146. '%s[%s] = %s' % (obj, key, value))
  1147. def UNARY_CONVERT(self, code):
  1148. code.ReadOpcode()
  1149. value = self.stack.pop().GetString(PRECEDENCE_NONE)
  1150. self.stack.append(Expression('`%s`' % value, PRECEDENCE_ATOM))
  1151. def UNARY_INVERT(self, code):
  1152. code.ReadOpcode()
  1153. # only requires PRECEDENCE_UNARY, but both powers and other
  1154. # unary operators are confusing without parentheses
  1155. y = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1156. self.stack.append(Expression('~%s' % y, PRECEDENCE_UNARY))
  1157. def UNARY_NEGATIVE(self, code):
  1158. code.ReadOpcode()
  1159. # only requires PRECEDENCE_UNARY, but both powers and other
  1160. # unary operators are confusing without parentheses
  1161. y = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1162. self.stack.append(Expression('-%s' % y, PRECEDENCE_UNARY))
  1163. def UNARY_NOT(self, code):
  1164. code.ReadOpcode()
  1165. y = self.stack.pop().GetString(PRECEDENCE_NOT)
  1166. self.stack.append(Expression('not %s' % y, PRECEDENCE_NOT))
  1167. def UNARY_POSITIVE(self, code):
  1168. code.ReadOpcode()
  1169. # only requires PRECEDENCE_UNARY, but both powers and other
  1170. # unary operators are confusing without parentheses
  1171. y = self.stack.pop().GetString(PRECEDENCE_ATOM)
  1172. self.stack.append(Expression('+%s' % y, PRECEDENCE_UNARY))
  1173. def build_target(self, code):
  1174. if code.NextOpcode() not in ('STORE_FAST', 'STORE_GLOBAL', 'STORE_NAME',
  1175. 'UNPACK_SEQUENCE', 'UNPACK_TUPLE'):
  1176. d = Decompiler(self.version)
  1177. d.decompile(code, 'STORE_ATTR', 'STORE_SLICE+0', 'STORE_SLICE+1',\
  1178. 'STORE_SLICE+2', 'STORE_SLICE+3', 'STORE_SUBSCR')
  1179. opcode = code.ReadOpcode()
  1180. if opcode == 'STORE_ATTR':
  1181. stack = d.getstack()
  1182. assert len(stack) == 1, `stack`
  1183. name = stack.pop().GetString(PRECEDENCE_ATOM)
  1184. oparg = code.ReadOperand()
  1185. attr = code.GetName(oparg)
  1186. target = Expression('%s.%s' % (name, attr), PRECEDENCE_ATOM)
  1187. elif opcode == 'STORE_FAST':
  1188. oparg = code.ReadOperand()
  1189. target = Local(code.GetLocal(oparg))
  1190. elif opcode == 'STORE_GLOBAL':
  1191. oparg = code.ReadOperand()
  1192. target = Global(code.GetName(oparg))
  1193. elif opcode == 'STORE_NAME':
  1194. oparg = code.ReadOperand()
  1195. target = Local(code.GetName(oparg))
  1196. elif opcode == 'STORE_SLICE+0':
  1197. stack = d.getstack()
  1198. assert len(stack) == 1, `stack`
  1199. x = stack.pop().GetString(PRECEDENCE_ATOM)
  1200. target = Expression('%s[:]' % x, PRECEDENCE_ATOM)
  1201. elif opcode == 'STORE_SLICE+1':
  1202. stack = d.getstack()
  1203. assert len(stack) == 2, `stack`
  1204. y = stack.pop().GetString(PRECEDENCE_ARG)
  1205. x = stack.pop().GetString(PRECEDENCE_ATOM)
  1206. target = Expression('%s[%s:]' % (x, y), PRECEDENCE_ATOM)
  1207. elif opcode == 'STORE_SLICE+2':
  1208. stack = d.getstack()
  1209. assert len(stack) == 2, `stack`
  1210. z = stack.pop().GetString(PRECEDENCE_ARG)
  1211. x = stack.pop().GetString(PRECEDENCE_ATOM)
  1212. target = Expression('%s[:%s]' % (x, z), PRECEDENCE_ATOM)
  1213. elif opcode == 'STORE_SLICE+3':
  1214. stack = d.getstack()
  1215. assert len(stack) == 3, `stack`
  1216. z = stack.pop().GetString(PRECEDENCE_ARG)
  1217. y = stack.pop().GetString(PRECEDENCE_ARG)
  1218. x = stack.pop().GetString(PRECEDENCE_ATOM)
  1219. target = Expression('%s[%s:%s]' % (x, y, z), PRECEDENCE_ATOM)
  1220. elif opcode == 'STORE_SUBSCR':
  1221. stack = d.getstack()
  1222. assert len(stack) == 2, `stack`
  1223. key = stack.pop().GetString(PRECEDENCE_NONE)
  1224. name = stack.pop().GetString(PRECEDENCE_ATOM)
  1225. target = Expression('%s[%s]' % (name, key), PRECEDENCE_ATOM)
  1226. else:
  1227. assert opcode in ('UNPACK_SEQUENCE', 'UNPACK_TUPLE'), `opcode`
  1228. count = code.ReadOperand()
  1229. values = []
  1230. while count > 0:
  1231. value = self.build_target(code).GetString(PRECEDENCE_ARG)
  1232. values.append(value)
  1233. count = count - 1
  1234. target = Tuple(values)
  1235. return target
  1236. def UNPACK_SEQUENCE(self, code):
  1237. seq = self.build_target(code).GetString(PRECEDENCE_NONE)
  1238. rhs = self.stack.pop().GetString(PRECEDENCE_NONE)
  1239. self.addline(code.GetLine(), '%s = %s' % (seq, rhs))
  1240. UNPACK_TUPLE = UNPACK_SEQUENCE
  1241. # These tests need to be more complete, however, the things that are
  1242. # known to be broken are represented
  1243. tests = [
  1244. '3\n' # constant expression
  1245. 'a\n' # name expression
  1246. 'a[3][4]\n' # subscr expression
  1247. 'a.b.c\n' # attr expression
  1248. 'a(b, c, d=3, e="d")\n', # function call
  1249. 'a = b\n', # simple assignment
  1250. 'a.b.c.d = 2\n', # attr target
  1251. 'a[b][c][d] = 3\n', # subscr target
  1252. 'a[:] = 4\n', # slice targets
  1253. 'a[b:] = 5\n',
  1254. 'a[:b] = 6\n',
  1255. 'a[b:c] = 7\n',
  1256. 'a, b, c.d, e[f], g[:], h[i:], j[:k], l[m:n] = z\n', # tuple target
  1257. '(a, b), (c, (d, e)) = t\n', # nested tuple target
  1258. 'import spam',
  1259. 'import string, spam as ham, sys',
  1260. 'from spam import ham, eggs',
  1261. 'import spam.ham', # BROKEN: this type of import
  1262. 'from package.spam import ham, eggs as milk',
  1263. 'from string import *',
  1264. 'def f(a, (b, c)):\n del f\n', # BROKEN: tuple func args
  1265. 'a = b.d = c[3] = a, b = f()', # BROKEN: chained assignment
  1266. 'print >> file, a, b',
  1267. 'a = [2*i for i in x]', # BROKEN: list comprehension
  1268. 'if 1:\n pass\nelif 2: pass\nelse: 3', # BROKEN, swap conditions JUMP_IF_FALSE
  1269. ## for i in r:
  1270. ## print
  1271. ## print hello, b
  1272. ## a &= 3; b^=9
  1273. ## c|=8 ; d <<=2
  1274. ## def g(a, b, c=5, d=10, *args, **kw):
  1275. ## pass
  1276. ## class G(foo):
  1277. ## def __init__(self, b=5):
  1278. ## "hello"
  1279. ## x.k = x.k & (7 * (3 + 4))
  1280. ## return x
  1281. ## x, y[5][g+4], z.x = 1, 2, 3
  1282. ## f(a, b, x=1, **args)
  1283. ## try: 1
  1284. ## finally: 2
  1285. ## if a < b*2 <= c > d:
  1286. ## print
  1287. ## x = lambda y: (2 * y, 3)
  1288. ## class C: pass
  1289. ## if 3:
  1290. ## print
  1291. ## elif 5:
  1292. ## del e
  1293. ## else:
  1294. ## print
  1295. ## import sys
  1296. ## if 3:
  1297. ## print
  1298. ## else:
  1299. ## i = j + -2 ** -3 ** -2
  1300. ## if stuff[0] == '!':
  1301. ## stuff = '[^' + stuff[1:] + ']'
  1302. ## elif stuff == 'g':
  1303. ## stuff = '\\^'
  1304. ## else:
  1305. ## while stuff[0] == '^':
  1306. ## stuff = stuff[1:] + stuff[0]
  1307. ## stuff = ('[' + stuff + ']'),
  1308. ##
  1309. ## a, b, c.b, a[p] = c
  1310. ## x = 1 - 2 + 3 - (4 + 5) - 6, 6
  1311. ## try:
  1312. ## print 2
  1313. ## except RuntimeError, exc:
  1314. ## del a
  1315. ## except IOError:
  1316. ## del g
  1317. ## except:
  1318. ## del b
  1319. ## else:
  1320. ## del elses
  1321. ## if a and b and c:
  1322. ## del a
  1323. ## if (a and b) and c:
  1324. ## del b
  1325. ## if a and (b and c):
  1326. ## del c
  1327. ]
  1328. def test():
  1329. import traceback
  1330. for osrc in tests:
  1331. code1 = compile(osrc, '<string>', 'exec')
  1332. d = Decompiler((2, 0))
  1333. try:
  1334. d.decompile(CodeCursor(code1))
  1335. except:
  1336. print osrc
  1337. print 'FAILS'
  1338. traceback.print_exc(file=sys.stdout)
  1339. print '---'
  1340. continue
  1341. source = d.getsource(0)
  1342. lastline = max(source.keys())
  1343. lines = []
  1344. for lineno in range(1, lastline+2):
  1345. lines.append(source.get(lineno, ''))
  1346. dsrc = string.join(lines, '\n')
  1347. if dsrc == osrc:
  1348. continue
  1349. try:
  1350. code2 = compile(dsrc, '<string>', 'exec')
  1351. except SyntaxError:
  1352. code2 = None
  1353. if code2 and code2.co_code == code1.co_code:
  1354. continue
  1355. print osrc
  1356. print 'BECOMES'
  1357. print dsrc
  1358. print '---'
  1359. def f():
  1360. a(b=3, d=3)
  1361. a[x:], b[:] = 1
  1362. # don't work:
  1363. ## import spam.ham
  1364. ## def f(a, (b, c)):
  1365. ## del f
  1366. ## a = b.d = c[3] = a, b = f()
  1367. ## a = [2*i for i in x]
  1368. ## import string, x as y
  1369. ## from spam.ham import eggs, foo as bar
  1370. ## from d import *
  1371. ## for i in r:
  1372. ## print
  1373. print hello, b
  1374. ## a &= 3; b^=9
  1375. ## c|=8 ; d <<=2
  1376. ## def g(a, b, c=5, d=10, *args, **kw):
  1377. ## pass
  1378. ## class G(foo):
  1379. ## def __init__(self, b=5):
  1380. ## "hello"
  1381. ## x.k = x.k & (7 * (3 + 4))
  1382. ## return x
  1383. ## x, y[5][g+4], z.x = 1, 2, 3
  1384. ## f(a, b, x=1, **args)
  1385. ## try: 1
  1386. ## finally: 2
  1387. ## if a < b*2 <= c > d:
  1388. ## print
  1389. ## x = lambda y: (2 * y, 3)
  1390. ## class C: pass
  1391. ## if 3:
  1392. ## print
  1393. ## elif 5:
  1394. ## del e
  1395. ## else:
  1396. ## print
  1397. ## import sys
  1398. ## if 3:
  1399. ## print
  1400. ## else:
  1401. ## i = j + -2 ** -3 ** -2
  1402. ## if stuff[0] == '!':
  1403. ## stuff = '[^' + stuff[1:] + ']'
  1404. ## elif stuff == 'g':
  1405. ## stuff = '\\^'
  1406. ## else:
  1407. ## while stuff[0] == '^':
  1408. ## stuff = stuff[1:] + stuff[0]
  1409. ## stuff = ('[' + stuff + ']'),
  1410. ##
  1411. ## a, b, c.b, a[p] = c
  1412. ## x = 1 - 2 + 3 - (4 + 5) - 6, 6
  1413. ## try:
  1414. ## print 2
  1415. ## except RuntimeError, exc:
  1416. ## del a
  1417. ## except IOError:
  1418. ## del g
  1419. ## except:
  1420. ## del b
  1421. ## else:
  1422. ## del elses
  1423. ## if a and b and c:
  1424. ## del a
  1425. ## if (a and b) and c:
  1426. ## del b
  1427. ## if a and (b and c):
  1428. ## del c
  1429. if __name__ == '__main__':
  1430. if 1:
  1431. test()
  1432. else:
  1433. out = open(r'E:\output.txt', 'wt')
  1434. try:
  1435. stdout = sys.stdout
  1436. sys.stdout = out
  1437. if 1:
  1438. import marshal
  1439. m = open(r'C:\Python20\Lib\code.pyc', 'rb')
  1440. magic = m.read(4)
  1441. if magic == '\207\306\015\012':
  1442. version = (2, 0)
  1443. elif magic == '\231N\015\012':
  1444. version = (1, 5, 2)
  1445. else:
  1446. raise RuntimeError, 'unrecognised magic: %s' % `magic`
  1447. timestamp = m.read(4)
  1448. s = m.read()
  1449. code = marshal.loads(s)
  1450. m.close()
  1451. else:
  1452. version = (2, 0)
  1453. print f.func_code.co_names
  1454. print f.func_code.co_varnames
  1455. print f.func_code.co_consts
  1456. code = f.func_code
  1457. c = CodeCursor(code)
  1458. d = Decompiler(version)
  1459. d.decompile(c)
  1460. lines = d.getsource(0)
  1461. keys = lines.keys()
  1462. keys.sort()
  1463. for lineno in range(keys[0], keys[-1] + 1):
  1464. print '%4d %s' % (lineno, lines.get(lineno, ''))
  1465. print
  1466. sys.stdout = stdout
  1467. finally:
  1468. out.close()
  1469. sys.stderr.write('DONE\n')

comments powered by Disqus