forked from Imagelibrary/seL4
Update all scripts and build system to call python3, given python2's upcoming doom. Use sys.maxsize instead of sys.maxint in one script (maxint does not exist in python3).
142 lines
3.0 KiB
Python
Executable File
142 lines
3.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
#
|
|
# Copyright 2017, Data61
|
|
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
|
# ABN 41 687 119 230.
|
|
#
|
|
# This software may be distributed and modified according to the terms of
|
|
# the BSD 2-Clause license. Note that NO WARRANTY is provided.
|
|
# See "LICENSE_BSD2.txt" for details.
|
|
#
|
|
# @TAG(DATA61_BSD)
|
|
#
|
|
|
|
from __future__ import print_function
|
|
import sys
|
|
import six
|
|
from functools import reduce
|
|
|
|
# We assume length tp > 0
|
|
|
|
|
|
def parse_type(tps):
|
|
def helper(tps):
|
|
tp = tps[0]
|
|
rest = tps[1:]
|
|
|
|
if tp == 'Word':
|
|
return ('Word', rest[0]), rest[1:]
|
|
|
|
elif tp == 'Ptr':
|
|
tp2, rest = helper(rest)
|
|
return ('Ptr', tp2), rest
|
|
|
|
elif tp == 'Unit':
|
|
return ('Unit',), rest
|
|
|
|
elif tp == 'Array':
|
|
tp2, rest = helper(rest)
|
|
# arrays are Array ... sz
|
|
return ('Array', tp2, rest[0]), rest[1:]
|
|
|
|
else:
|
|
return ('Base', tp), rest
|
|
|
|
return helper(tps)[0]
|
|
|
|
|
|
def splitBy(f, xs):
|
|
def fold(acc, v):
|
|
if f(v):
|
|
acc[0].append(acc[1])
|
|
return (acc[0], [])
|
|
else:
|
|
acc[1].append(v)
|
|
return acc
|
|
|
|
return (reduce(fold, xs, ([], [])))[0]
|
|
|
|
|
|
def handle_one_struct(s):
|
|
def hdl_fld(f):
|
|
fl, tp = f.split(':')
|
|
return (fl.lstrip(), parse_type(tp.split(' ')))
|
|
|
|
name = s[0]
|
|
return (name, map(hdl_fld, s[1:]))
|
|
|
|
|
|
def dict_from_list(ls):
|
|
a = {}
|
|
for k, v in ls:
|
|
a[k] = v
|
|
|
|
return a
|
|
|
|
|
|
def is_base(x):
|
|
return (x[0] == 'Base')
|
|
|
|
|
|
def base_name(x):
|
|
return x[1]
|
|
|
|
# This assumes that membership is a DAG which is the case in C
|
|
# We could memoize, doesn't seem worth it ...
|
|
|
|
|
|
def paths_to_type(mp, f, start):
|
|
def handle_one(fld):
|
|
name, tp = fld
|
|
if f(tp):
|
|
return [([start + '.' + name], tp)]
|
|
elif is_base(tp):
|
|
res = paths_to_type(mp, f, base_name(tp))
|
|
# prepend paths by name (why no Cons in python? grrr)
|
|
map(lambda x: (x[0].insert(0, name)), res)
|
|
return res
|
|
else:
|
|
return []
|
|
|
|
# init case
|
|
start_tp = ('Base', start)
|
|
if f(start_tp):
|
|
return [([], start_tp)]
|
|
else:
|
|
res = map(handle_one, mp[start])
|
|
return (reduce(lambda x, y: x + y, res))
|
|
|
|
|
|
def build_types(file):
|
|
in_file = open(file, 'r')
|
|
|
|
lines = map(lambda x: x.rstrip(), in_file.readlines())
|
|
|
|
in_file.close()
|
|
|
|
grps = splitBy(lambda x: x == '', lines)
|
|
|
|
# the order information will be important if we want _CL for all types
|
|
sts = dict_from_list(map(handle_one_struct, grps))
|
|
|
|
return sts
|
|
|
|
|
|
def print_graph(filename, out_file):
|
|
mp = build_types(filename)
|
|
|
|
print('digraph types {', file=out_file)
|
|
for k, flds in six.iteritems(mp):
|
|
for fld, tp in flds:
|
|
# if is_base(tp):
|
|
print('\t "%s" -> "%s" [label="%s"]' % (k, base_name(tp), fld),
|
|
file=out_file)
|
|
print('}', file=out_file)
|
|
|
|
# Toplevel
|
|
|
|
|
|
if __name__ == '__main__':
|
|
print_graph('umm_types.txt', sys.stdout)
|