forked from Imagelibrary/seL4
This commit also converts our own copyright headers to directly use SPDX, but leaves all other copyright header intact, only adding the SPDX ident. As far as possible this commit also merges multiple Data61 copyright statements/headers into one for consistency.
135 lines
2.8 KiB
Python
Executable File
135 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
|
|
#
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
#
|
|
|
|
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)
|