101 lines
3 KiB
Python
101 lines
3 KiB
Python
|
#! /usr/bin/python
|
||
|
|
||
|
import sys
|
||
|
import yaml
|
||
|
import array
|
||
|
|
||
|
class Call(object):
|
||
|
def __init__(self, call):
|
||
|
self.func, = call
|
||
|
args = dict(call[self.func])
|
||
|
self.output = array.array("B", args.pop("output")).tostring()
|
||
|
self.inputs = {
|
||
|
name: array.array("B", args[name]).tostring()
|
||
|
for name in args
|
||
|
if not name.endswith("_length")
|
||
|
}
|
||
|
self.bind = {}
|
||
|
|
||
|
def expr(self, stream, indent=" ", level=""):
|
||
|
stream.write(self.func + "(\n")
|
||
|
for name, value in self.inputs.items():
|
||
|
stream.write(level + indent + name + "=")
|
||
|
self.bind.get(name, Literal(value)).expr(
|
||
|
stream, indent, level + indent
|
||
|
)
|
||
|
stream.write(",\n")
|
||
|
stream.write(level + ")")
|
||
|
|
||
|
|
||
|
class Literal(str):
|
||
|
def expr(self, stream, indent, level):
|
||
|
stream.write("\"" + self.encode("hex") + "\"")
|
||
|
|
||
|
|
||
|
class Slice(object):
|
||
|
def __init__(self, thing, start, end):
|
||
|
self.thing = thing
|
||
|
self.start = start
|
||
|
self.end = end
|
||
|
|
||
|
def expr(self, stream, indent=" ", level=""):
|
||
|
self.thing.expr(stream, indent, level)
|
||
|
stream.write("[%d:%d]" % (self.start, self.end))
|
||
|
|
||
|
|
||
|
class Concat(list):
|
||
|
def expr(self, stream, indent=" ", level=""):
|
||
|
stream.write("concat(\n")
|
||
|
for thing in self:
|
||
|
stream.write(level + indent)
|
||
|
thing.expr(stream, indent, level + indent)
|
||
|
stream.write(",\n")
|
||
|
stream.write(level + ")")
|
||
|
|
||
|
|
||
|
calls = [Call(c) for c in yaml.load(sys.stdin)]
|
||
|
|
||
|
outputs = {}
|
||
|
|
||
|
for call in calls:
|
||
|
for i in range(8, len(call.output)):
|
||
|
outputs.setdefault(call.output[i - 8: i], []).append(call)
|
||
|
|
||
|
for call in calls:
|
||
|
for name, value in call.inputs.items():
|
||
|
for bind in outputs.get(value[:8], ()):
|
||
|
if value == bind.output:
|
||
|
call.bind[name] = bind
|
||
|
else:
|
||
|
for end in range(len(value), len(bind.output) + 1):
|
||
|
start = end - len(value)
|
||
|
if value == bind.output[start:end]:
|
||
|
call.bind[name] = Slice(bind, start, end)
|
||
|
if not name in call.bind:
|
||
|
i = 0
|
||
|
j = 1
|
||
|
k = 0
|
||
|
concat = Concat()
|
||
|
while i < len(value):
|
||
|
for bind in outputs.get(value[i:i+8], ()):
|
||
|
if value[i:].startswith(bind.output):
|
||
|
if k != i:
|
||
|
concat.append(Literal(value[k:i]))
|
||
|
concat.append(bind)
|
||
|
j = len(bind.output)
|
||
|
k = i + j
|
||
|
break
|
||
|
i += j
|
||
|
j = 1
|
||
|
if concat:
|
||
|
if k != i:
|
||
|
concat.append(Literal(value[k:i]))
|
||
|
call.bind[name] = concat
|
||
|
|
||
|
for call in calls:
|
||
|
if call.func.startswith("h"):
|
||
|
sys.stdout.write("\"" + call.output.encode("hex") + "\" = ")
|
||
|
call.expr(sys.stdout)
|
||
|
sys.stdout.write("\n")
|
||
|
|