From ee3d35336bb21a6aba50674f6623b74537c8c775 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Thu, 3 Apr 2014 15:32:10 -0400 Subject: stuff --- Makefile | 2 + Modernizr | 2 +- README.rst | 6 +- ast2json/decompiler.py | 500 ------------------------------------------------- configure | 77 +++++--- fastclick | 2 +- 6 files changed, 56 insertions(+), 533 deletions(-) delete mode 100644 ast2json/decompiler.py diff --git a/Makefile b/Makefile index 5e45486..0b7e65d 100644 --- a/Makefile +++ b/Makefile @@ -68,12 +68,14 @@ $(IJSON): www/json/%.json: ast2json/imachine2json.py ast2json/%.json.i $^ $@ %.json.gz: %.json +ifdef GZIP ifdef DEFLUFF $(GZIP) -c $< | $(DEFLUFF) > $@ else $(GZIP) -c $< > $@ endif touch $< $@ +endif # === VIDEO === diff --git a/Modernizr b/Modernizr index 608d906..3b56e73 160000 --- a/Modernizr +++ b/Modernizr @@ -1 +1 @@ -Subproject commit 608d9069ef615aa35d6430e10bf938002074e418 +Subproject commit 3b56e7309de3a301ac69987ac3d5d7055d0fb048 diff --git a/README.rst b/README.rst index f149277..bfd538b 100644 --- a/README.rst +++ b/README.rst @@ -55,11 +55,9 @@ Build steps Disabling unused conversions ---------------------------- -To reduce programs and build time required, some conversions can be disabled. -Passing --minimal to configure will disable the safe ones. +To reduce programs and build time required, some conversions can be disabled by passing ``CONVERSION=`` on the command line, e.g. ``ZOPFLIPNG= ./configure``. -Alternatively, specific conversions can be disabled by passing --disable-conversion on the command line. -See ``./configure --help`` for more information. +Alternatively, just don't install those programs. Conversions that are safe to disable are labeled as such in ``configure``. If a required conversion is disabled, configure will print a big error. Reducing disk usage =================== 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"<<>>\n" % (type(stmt).__name__, )) diff --git a/configure b/configure index 291ce68..a039e8c 100755 --- a/configure +++ b/configure @@ -5,9 +5,9 @@ import re import shlex import shutil import subprocess -from sys import stderr cmds = {} +warnings = [] class CheckError(Exception): pass @@ -16,15 +16,31 @@ def checking(thing): stderr.write("checking %s... " % thing) stderr.flush() -def check(name, flags=[], optional=False, var=None, run=True): +def warn(string): + warnings.append(string) + stderr.write("WARNING: %s\n" % string) + +def check(name, why, flags=[], optional=False, var=None, run=True): + global warn checking("for %s" % name) var = var or name.upper() - split = shlex.split(os.getenv(var) or name) + varvalue = os.getenv(var) + if varvalue == '': + stderr.write("skipping\n") + if not optional: + warn("%s is required to %s, the code will not fall back gracefully without it!" % (name, why)) + return + elif varvalue is None: + varvalue = name + split = shlex.split(varvalue) exe = shutil.which(split[0]) if not exe: stderr.write("not found\n") if not optional: raise CheckError() + else: + warn("%s is recommended to %s." % (name, why)) + return stderr.write("%s\n" % exe) cmd = [exe] + split[1:] + flags + shlex.split(os.getenv(var + "FLAGS") or "") if run: @@ -51,27 +67,34 @@ def ffmpeg_check(name, regex, checks, output): stderr.write("no\n") raise CheckError() -try: - check("zopfli", var="GZIP") -except CheckError: - check("gzip", ["-9"]) - -check("apngasm", run=False) -check("convert") -check("cwebp", ["-quiet", "-alpha_cleanup", "-m", "6"]) -ffmpeg = check("ffmpeg", ["-v", "warning", "-y"], run=False) -ffmpeg_formats = run_ffmpeg("-formats") -ffmpeg_check("demuxing", "D.", ["matroska,webm", "ogg", "wav", "yuv4mpegpipe"], ffmpeg_formats) -ffmpeg_check("muxing", ".E", ["ipod", "mp4", "ogg", "wav", "webm", "yuv4mpegpipe"], ffmpeg_formats) -ffmpeg_check("decoding", ".{6}", ["mpeg4", "rawvideo", "pcm_s16le", "vorbis"], run_ffmpeg("-decoders")) -ffmpeg_check("encoding", ".{6}", ["libx264", "rawvideo", "libtheora", "libvpx", "libvpx-vp9", "libfdk_aac", "libopus", "pcm_s16le"], run_ffmpeg("-encoders")) -check("npm", ["--quiet"]) -check("webpmux") -check("defluff", optional=True, run=False) -check("pngquant", optional=True) -check("zopflipng", optional=True) - -stderr.write("creating Makefile.inc\n") - -with open("Makefile.inc", "w") as f: - f.write(''.join('%s := %s\n' % (k, subprocess.list2cmdline(cmds[k])) for k in cmds)) +if __name__ == "__main__": + # no, this line isn't bugged. really. examine check() and Makefile + if not check("zopfli", "compress gzip files better than gzip -9", optional=True, var="GZIP"): + check("gzip", "pre-compress the JSON files", ["-9"]) + + check("apngasm", "assemble the click-to-continue image", run=False) + check("convert", "perform miscellaneous actions on the images") + check("cwebp", "convert all images to WebP for webkit browsers", ["-quiet", "-alpha_cleanup", "-m", "6"]) + ffmpeg = check("ffmpeg", "convert audio and video to HTML5 formats", ["-v", "warning", "-y"], run=False) + if ffmpeg: + ffmpeg_formats = run_ffmpeg("-formats") + ffmpeg_check("demuxing", "D.", ["matroska,webm", "ogg", "wav", "yuv4mpegpipe"], ffmpeg_formats) + ffmpeg_check("muxing", ".E", ["ipod", "mp4", "ogg", "wav", "webm", "yuv4mpegpipe"], ffmpeg_formats) + ffmpeg_check("decoding", ".{6}", ["mpeg4", "rawvideo", "pcm_s16le", "vorbis"], run_ffmpeg("-decoders")) + ffmpeg_check("encoding", ".{6}", ["libx264", "rawvideo", "libtheora", "libvpx", "libvpx-vp9", "libfdk_aac", "libopus", "pcm_s16le"], run_ffmpeg("-encoders")) + check("npm", "install uglifyjs", ["--quiet"]) + check("webpmux", "assemble the WebP click-to-continue image") + check("defluff", "decrease the size of DEFLATE files including gzip and PNG files", optional=True, run=False) + check("pngquant", "quantize PNG images, improving compatibility and dramatically decreasing size", optional=True) + check("zopflipng", "recompress DEFLATE files including gzip and PNG files", optional=True) + + stderr.write("creating Makefile.inc\n") + + with open("Makefile.inc", "w") as f: + f.write(''.join('%s := %s\n' % (k, subprocess.list2cmdline(cmds[k])) for k in cmds)) + + if len(warnings): + stderr.write("Warnings during configuration:\n") + stderr.write('\n'.join(warnings) + '\n') + + stderr.write("Run `make' now to build HTML5KS.\n") diff --git a/fastclick b/fastclick index d7727a1..3497d2e 160000 --- a/fastclick +++ b/fastclick @@ -1 +1 @@ -Subproject commit d7727a10e538da46ce7a7ed86dc6f4be466dc06c +Subproject commit 3497d2e92ccc8a959c7efb326c0fc437302d5bcf -- cgit v1.2.3-54-g00ecf