#!/usr/bin/env python

import re

machineOpcode = "result"
file = "kerneldecrypt.c"

def SearchEntryPoint(data):
  z = re.search("%s = (.*);" % machineOpcode, data)
  if z != None:
    return z.group(1)
  else:
    return None

def SearchOpcodeTokens(token, data):
  # Search first for switch-case. If not we try other stuff
  b = re.search("case\s%s:(.*?)break"%token, data, re.S)
  if b != None:
    lines = [t.strip() for t in b.group(1).split("\n")]
    tokens = filter(None, [SearchEntryPoint(l) for l in lines])
    return tokens
  # Search secondly for the base token, to see if we have {} or not
  b = re.search("\(\sresult\s==\s%s\s\)\n.*\n" %token, data)
  if b == None:
    return []

  if not "{" in b.group(0):
    # No brackets, single line if
    return filter(None, [ SearchEntryPoint(b.group(0)) ])
  else:
    z = re.search("\(\sresult\s==\s%s\s\).*?\{(.*?)\}" %token, data, re.S)
    if z != None:
      lines = [t.strip() for t in z.group(1).split("\n")]
      tokens = filter(None, [SearchEntryPoint(l) for l in lines])
      return tokens
    else:
      return []

f = open(file, "r")
data = f.read()
f.close()


print "Searching Entry Point"
entryPoint = SearchEntryPoint(data)
print "Entry Point found: %s" %entryPoint

tokenStack = [entryPoint]
processedTokens = []

print "Navigating tree"
while True:
  if len(tokenStack) == 0:
    break
  p = tokenStack.pop(0)
  processedTokens.append(p)
  tokens = SearchOpcodeTokens(p, data)
  for t in tokens:
    if not t in processedTokens and not t in tokenStack:
      tokenStack.append(t)
  print "\"%s\" -> %s" %(p, ",".join(["\"%s\"" % t for t in tokens]))
