diff options
Diffstat (limited to 'ast2json')
-rw-r--r-- | ast2json/decompiler.py | 500 |
1 files changed, 0 insertions, 500 deletions
diff --git a/ast2json/decompiler.py b/ast2json/decompiler.py deleted file mode 100644 index 0a0b916..0000000 --- a/ast2json/decompiler.py +++ /dev/null @@ -1,500 +0,0 @@ -# Copyright (c) 2012 Yuri K. Schlesner -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -import renpy.ast as ast -import renpy.atl as atl -import codegen -import screendecompiler -import code - -DECOMPILE_SCREENS = True - -def pretty_print_ast(out_file, ast): - code.interact(local=locals()) - for stmt in ast: - print_statement(out_file, stmt, 0) - -def indent(f, level): - # Print indentation - f.write(u' ' * level) - -def print_statement(f, statement, indent_level=0): - indent(f, indent_level) - - func = statement_printer_dict.get(type(statement), print_Unknown) - func(f, statement, indent_level) - -def escape_string(s): - s = s.replace('"', '\\"') - s = s.replace('\n', '\\n') - s = s.replace('\t', '\\t') - return s - -# TODO "choice" and "parallel" blocks are greedily combined -# so we need a "pass" statement to separate them if -# multiple of the same block are immediately after -# each other. -def print_atl(f, atl_block, indent_level): - if not atl_block.statements: - indent(f, indent_level) - f.write(u'pass\n') - for stmt in atl_block.statements: - indent(f, indent_level) - - if type(stmt) is atl.RawMultipurpose: - # warper - if stmt.warp_function: - f.write(u"warp %s" % (stmt.warp_function.strip(), )) - f.write(u" %s " % (stmt.duration.strip(), )) - elif stmt.warper: - f.write(stmt.warper) - f.write(u" %s " % (stmt.duration.strip(), )) - elif stmt.duration.strip() != '0': - f.write(u'pause') - f.write(u" %s" % (stmt.duration.strip(), )) - - # revolution - if stmt.revolution: - f.write(u"%s " % (stmt.revolution, )) - - # circles - if stmt.circles != "0": - f.write(u"circles %s " % (stmt.circles.strip(), )) - - # splines - for (name, exprs) in stmt.splines: - f.write(u"%s " % (name, )) - for expr in exprs: - f.write(u"knot %s " % (expr.strip(), )) - - # properties - for (k, v) in stmt.properties: - f.write(u"%s %s " % (k, v.strip())) - - # with - for (expr, with_expr) in stmt.expressions: - f.write(u"%s " % (expr.strip(), )) - if with_expr: - f.write(u"with %s " % (with_expr, )) - - f.write(u"\n") - - elif type(stmt) is atl.RawBlock: - # what does stmt.animation do? - f.write(u"block:\n") - print_atl(f, stmt, indent_level + 1) - - elif type(stmt) is atl.RawChoice: - first = True - for (chance, block) in stmt.choices: - if first: - first = False - else: - indent(f, indent_level) - - f.write(u"choice") - if chance != "1.0": - f.write(u" %s" % (chance, )) - f.write(u":\n") - print_atl(f, block, indent_level + 1) - - elif type(stmt) is atl.RawContainsExpr: - f.write(u"contains %s\n" % (stmt.expression, )) - - elif type(stmt) is atl.RawEvent: - f.write(u"event %s\n" % (stmt.name, )) - - elif type(stmt) is atl.RawFunction: - f.write(u"function %s\n" % (stmt.expr, )) - - elif type(stmt) is atl.RawOn: - first = True - for name, block in stmt.handlers.iteritems(): - if first: - first = False - else: - indent(f, indent_level) - - f.write(u"on %s:\n" % (name, )) - print_atl(f, block, indent_level + 1) - - elif type(stmt) is atl.RawParallel: - first = True - for block in stmt.blocks: - if first: - first = False - else: - indent(f, indent_level) - - f.write(u"parallel:\n") - print_atl(f, block, indent_level + 1) - - elif type(stmt) is atl.RawRepeat: - f.write(u"repeat") - if stmt.repeats: - f.write(u" %s" % (stmt.repeats, )) # not sure if this is even a string - f.write(u"\n") - - elif type(stmt) is atl.RawTime: - f.write(u"time %s\n" % (stmt.time, )) - - else: - f.write(u"TODO atl.%s\n" % type(stmt).__name__) - -def print_imspec(f, imspec): - if imspec[1] is not None: # Expression - f.write(u'expression ') - f.write(imspec[1]) - else: # Image name - f.write(' '.join(imspec[0])) - - # at - if len(imspec[3]) > 0: - f.write(u" at %s" % (', '.join(imspec[3]))) - - # as - if imspec[2] is not None: - f.write(u" as %s" % (imspec[2], )) - - # behind - if len(imspec[6]) > 0: - f.write(u" behind %s" % (', '.join(imspec[6]))) - - # onlayer - if imspec[4] != 'master': - f.write(u" onlayer %s" % (imspec[4], )) - - # zorder - # This isn't in the docs, but it's in the parser - if imspec[5] is not None: - f.write(u" zorder %s" % (imspec[5], )) - -def print_Label(f, stmt, indent_level): - f.write(u"label %s" % (stmt.name, )) - if stmt.parameters is not None: - print_params(f, stmt.parameters) - f.write(u':\n') - - for sub_stmt in stmt.block: - print_statement(f, sub_stmt, indent_level + 1) - -def print_Say(f, stmt, indent_level): - if stmt.who is not None: - f.write(u"%s " % (stmt.who, )) - f.write(u"\"%s\"" % (escape_string(stmt.what), )) - if stmt.with_ is not None: - f.write(u" with %s" % (stmt.with_, )) - f.write(u'\n') - -def print_Jump(f, stmt, indent_level): - f.write(u"jump ") - if stmt.expression: - # TODO expression - f.write(u"expression TODO") - else: - f.write(stmt.target) - f.write(u'\n') - -def print_Scene(f, stmt, indent_level): - f.write(u"scene") - if stmt.imspec is None: - if stmt.layer != 'master': - f.write(u" onlayer %s" % (stmt.layer, )) - else: - f.write(u' ') - print_imspec(f, stmt.imspec) - - # with isn't handled here, but split in several statements - - if stmt.atl is not None: - f.write(u':\n') - print_atl(f, stmt.atl, indent_level+1) - else: - f.write('\n') - -def print_With(f, stmt, indent_level): - f.write(u"with %s\n" % (stmt.expr, )) - -def print_Show(f, stmt, indent_level): - f.write(u"show ") - print_imspec(f, stmt.imspec) - - # with isn't handled here, but split in several statements - - if stmt.atl is not None: - f.write(u':\n') - print_atl(f, stmt.atl, indent_level+1) - else: - f.write('\n') - -def print_Hide(f, stmt, indent_level): - f.write(u"hide ") - print_imspec(f, stmt.imspec) - - # with isn't handled here, but split in several statements - - f.write('\n') - -def print_Python(f, stmt, indent_level, early=False): - code_src = stmt.code.source - - stripped_code = code_src.strip() - - if stripped_code.count('\n') == 0: - f.write(u"$ %s\n" % (stripped_code, )) - else: - f.write(u"python") - if early: - f.write(u" early") - if stmt.hide: - f.write(u" hide") - f.write(u":\n") - - for line in code_src.splitlines(True): - indent(f, indent_level + 1) - f.write(line) - -def print_Return(f, stmt, indent_level): - f.write(u"return") - - if stmt.expression is not None: - f.write(u" %s" % (stmt.expression, )) - - f.write(u'\n') - -def print_UserStatement(f, stmt, indent_level): - f.write(u"%s\n" % (stmt.line, )) - -def print_Init(f, stmt, indent_level): - if len(stmt.block) == 1 and (hasattr(ast, 'Screen') and isinstance(stmt.block[0], ast.Screen)) and stmt.priority == -500: - print_screen(f, stmt.block[0], indent_level) - else: - f.write(u"init") - if stmt.priority != 0: - f.write(u" %d" % (stmt.priority, )) - f.write(u":\n") - for s in stmt.block: - print_statement(f, s, indent_level + 1) - -def print_Image(f, stmt, indent_level): - f.write(u"image %s" % (' '.join(stmt. imgname), )) - if stmt.code is not None: - f.write(u" = %s\n" % (stmt.code.source, )) - else: - f.write(u":\n") - print_atl(f, stmt.atl, indent_level + 1) - -def print_Transform(f, stmt, indent_level): - f.write(u"transform %s" % (stmt.varname, )) - if stmt.parameters is not None: - print_params(f, stmt.parameters) - - f.write(":\n") - print_atl(f, stmt.atl, indent_level + 1) - -def print_Menu(f, stmt, indent_level): - f.write(u"menu:\n") - - if stmt.with_ is not None: - indent(f, indent_level + 1) - f.write(u"with %s\n" % (stmt.with_, )) - - if stmt.set is not None: - indent(f, indent_level + 1) - f.write(u"set %s\n" % (stmt.with_, )) - - for item in stmt.items: - indent(f, indent_level + 1) - - # caption - f.write(u"\"%s\"" % (escape_string(item[0]), )) - - if item[2] is not None: - # condition - if item[1] != 'True': - f.write(u" if %s" % (item[1], )) - - f.write(u':\n') - - for inner_stmt in item[2]: - print_statement(f, inner_stmt, indent_level + 2) - else: - f.write(u'\n') - -def print_Pass(f, stmt, indent_level): - f.write(u"pass\n") - -def print_Call(f, stmt, indent_level): - f.write(u"call ") - if stmt.expression: - f.write(u"expression %s" % (stmt.label, )) - else: - f.write(stmt.label) - - if stmt.arguments is not None: - if stmt.expression: - f.write(u"pass ") - print_args(f, stmt.arguments) - - f.write(u'\n') - -def print_If(f, stmt, indent_level): - f.write(u"if %s:\n" % (stmt.entries[0][0], )) - for inner_stmt in stmt.entries[0][1]: - print_statement(f, inner_stmt, indent_level + 1) - - if len(stmt.entries) >= 2: - if stmt.entries[-1][0].strip() == 'True': - else_entry = stmt.entries[-1] - elif_entries = stmt.entries[1:-1] - else: - else_entry = None - elif_entries = stmt.entries - - for case in elif_entries: - indent(f, indent_level) - f.write(u"elif %s:\n" % (case[0], )) - for inner_stmt in case[1]: - print_statement(f, inner_stmt, indent_level + 1) - - if else_entry is not None: - indent(f, indent_level) - f.write(u"else:\n") - for inner_stmt in else_entry[1]: - print_statement(f, inner_stmt, indent_level + 1) - -def print_EarlyPython(f, stmt, indent_level): - print_Python(f, stmt, indent_level, early=True) - -# TODO extrapos, extrakw? -def print_args(f, arginfo): - if arginfo is None: - return - - f.write(u"(") - - first = True - for (name, val) in arginfo.arguments: - if first: - first = False - else: - f.write(u", ") - - if name is not None: - f.write(u"%s = " % (name, )) - f.write(val) - - f.write(u")") - -# TODO positional? -def print_params(f, paraminfo): - f.write(u"(") - - first = True - for param in paraminfo.parameters: - if first: - first = False - else: - f.write(u", ") - - f.write(param[0]) - - if (param[1] is not None) and ('None' not in param[1]): - f.write(u" = %s" % param[1]) - if paraminfo.extrapos: - f.write(u", ") - f.write(u"*%s" % paraminfo.extrapos) - if paraminfo.extrakw: - f.write(u", ") - f.write(u"**%s" % paraminfo.extrakw) - - f.write(u")") - -# Print while command, from http://forum.cheatengine.org/viewtopic.php?p=5377683 -def print_While(f, stmt, indent_level): - f.write(u"while %s:\n" % (stmt.condition, )) - for inner_stmt in stmt.block: - print_statement(f, inner_stmt, indent_level + 1) - -# Print define command, by iAmGhost -def print_Define(f, stmt, indent_level): - f.write(u"define %s = %s\n" % (stmt.varname, stmt.code.source,)) - -# Print Screen code (or at least code which does exactly the same. can't be picky, don't have source) -# We'll read the ast out here, but leave the decompilation of the resulting python code to screendecompiler.py -# It'd just bloat up this file -def print_screen(f, stmt, indent_level): - screen = stmt.screen - # The creator of the python ast module also created a script to revert it. - sourcecode = codegen.to_source(screen.code.source, u" "*4) - # why suddenly ast in the source code field - f.write(u"screen %s" % screen.name) - if hasattr(screen, 'parameters') and screen.parameters: - print_params(f, screen.parameters) - f.write(u":\n") - if screen.tag: - indent(f, indent_level+1) - f.write(u"tag %s\n" % screen.tag) - if screen.zorder and screen.zorder != '0': - indent(f, indent_level+1) - f.write(u"zorder %s\n" % screen.zorder) - if screen.modal: - indent(f, indent_level+1) - f.write(u"modal %s\n" % screen.modal) - if screen.variant != "None": - indent(f, indent_level+1) - f.write(u"variant %s\n" % screen.variant) - # actual screen decompilation is HARD - if DECOMPILE_SCREENS: - screendecompiler.print_screen(f, sourcecode, indent_level+1) - else: - indent(f, indent_level+1) - f.write('python:\n') - f.write('\n'.join([" "*(indent_level+2)+line for line in sourcecode.splitlines()])) - f.write(u"\n") - -statement_printer_dict = { - ast.Label: print_Label, - ast.Say: print_Say, - ast.Jump: print_Jump, - ast.Scene: print_Scene, - ast.With: print_With, - ast.Show: print_Show, - ast.Hide: print_Hide, - ast.Python: print_Python, - ast.Return: print_Return, - ast.UserStatement: print_UserStatement, - ast.Init: print_Init, - ast.Image: print_Image, - ast.Transform: print_Transform, - ast.Menu: print_Menu, - ast.Pass: print_Pass, - ast.Call: print_Call, - ast.If: print_If, - ast.While: print_While, - ast.Define: print_Define, - ast.EarlyPython: print_EarlyPython, - } -if hasattr(ast, 'Screen'): #backwards compatability - statement_printer_dict.update({ast.Screen: print_screen}) - -def print_Unknown(f, stmt, indent_level): - print "Unknown AST node: %s" % (type(stmt).__name__, ) - f.write(u"<<<UNKNOWN NODE %s>>>\n" % (type(stmt).__name__, )) |