diff --git a/scripts/codemapd3.py b/scripts/codemapd3.py
index a277ae02..3132cc5a 100755
--- a/scripts/codemapd3.py
+++ b/scripts/codemapd3.py
@@ -74,8 +74,6 @@ def iself(path):
with open(path, 'rb') as f:
return f.read(4) == b'\x7fELF'
-
-# TODO adopt this default scheme elsewhere?
# parse different data representations
def dat(x, *args):
try:
@@ -105,87 +103,6 @@ def dat(x, *args):
else:
raise
-def collect(csv_paths, defines=[]):
- # collect results from CSV files
- fields = []
- results = []
- for path in csv_paths:
- try:
- with openio(path) as f:
- reader = csv.DictReader(f, restval='')
- fields.extend(
- k for k in reader.fieldnames
- if k not in fields)
- for r in reader:
- # filter by matching defines
- if not all(k in r and r[k] in vs for k, vs in defines):
- continue
-
- results.append(r)
- except FileNotFoundError:
- pass
-
- return fields, results
-
-def fold(results, by=None, fields=None, defines=[]):
- # filter by matching defines
- if defines:
- results_ = []
- for r in results:
- if all(k in r and r[k] in vs for k, vs in defines):
- results_.append(r)
- results = results_
-
- if by:
- # find all 'by' values
- keys = set()
- for r in results:
- keys.add(tuple(r.get(k, '') for k in by))
- keys = sorted(keys)
-
- # collect datasets
- datasets = co.OrderedDict()
- dataattrs = co.OrderedDict()
- for key in (keys if by else [()]):
- for field in fields:
- # organize by 'by' and field
- dataset = []
- dataattr = {}
- for r in results:
- # filter by 'by'
- if by and not all(
- k in r and r[k] == v
- for k, v in zip(by, key)):
- continue
-
- # find field
- if field is not None:
- if field not in r:
- continue
- try:
- v = dat(r[field])
- except ValueError:
- continue
- else:
- v = None
-
- # do _not_ sum v here, it's tempting but risks
- # incorrect and misleading results
- dataset.append(v)
-
- # include all fields in dataattrs in case we use
- # them for % modifiers
- dataattr.update(r)
-
- # hide 'field' if there is only one field
- key_ = key
- if len(fields or []) > 1 or not key_:
- key_ += (field,)
- datasets[key_] = dataset
- dataattrs[key_] = dataattr
-
- return datasets, dataattrs
-
# a representation of optionally key-mapped attrs
class Attr:
def __init__(self, attrs, *,
@@ -283,7 +200,6 @@ class Attr:
return len(self.keyed)
-# TODO adopt this elsewhere (try_dat -> default)
# parse %-escaped strings
def punescape(s, attrs=None):
if attrs is None:
@@ -715,7 +631,6 @@ def main(paths, output, *,
for f in fs:
with f:
- # TODO adopt this rename (json -> is_json) in other scripts
# csv or json? assume json starts with [
is_json = (f.buffer.peek(1)[:1] == b'[')
@@ -780,7 +695,6 @@ def main(paths, output, *,
# ctx things, including any arguments
if 'ctx_size' in r:
functions[r['function']]['ctx'] = dat(r['ctx_size'])
- # TODO, what if not children in ctx? in stack?
if 'children' in r:
if 'args' not in functions[r['function']]:
functions[r['function']]['args'] = []
@@ -795,55 +709,12 @@ def main(paths, output, *,
functions[r['function']]['attrs'] = {}
functions[r['function']]['attrs'].update(r)
-# import pprint
-# pprint.pprint(functions)
-
-# # figure out paths
-# obj_paths = []
-# ci_paths = []
-# for path in paths:
-# if iself(path):
-# obj_paths.append(path)
-# else:
-# ci_paths.append(path)
-#
-# # find code/stack/ctx sizes
-# functions = co.OrderedDict()
-# if obj_paths:
-# for r in collect_code(obj_paths, **args):
-# if r['function'] not in functions:
-# functions[r['function']] = {}
-# functions[r['function']]['code'] = dat(r['code_size'])
-# if ci_paths:
-# for r in collect_stack(ci_paths, **args):
-# if r['function'] not in functions:
-# functions[r['function']] = {}
-# functions[r['function']]['frame'] = dat(r['stack_frame'])
-# functions[r['function']]['stack'] = dat(r['stack_limit'], mt.inf)
-# if 'children' in r:
-# functions[r['function']]['children'] = [
-# r_['function'] for r_ in r['children']]
-# if obj_paths:
-# for r in collect_ctx(obj_paths, **args):
-# if r['function'] not in functions:
-# functions[r['function']] = {}
-# functions[r['function']]['ctx'] = dat(r['ctx_size'])
-# if 'children' in r:
-# functions[r['function']]['args'] = [
-# (r_['function'], dat(r_['ctx_size']))
-# for r_ in r['children']]
-
# stack.py returns infinity for recursive functions, so we need to
# recompute a bounded stack limit to show something useful
def limitof(k, f, seen=set()):
# found a cycle? stop here
if k in seen:
return 0
-# # cached?
-# if not hasattr(limitof, 'cache'):
-# limitof.cache = {}
-# if k in limitof.cache:
-# return limitof.cache[k]
limit = 0
for child in f.get('children', []):
@@ -851,7 +722,6 @@ def main(paths, output, *,
continue
limit = max(limit, limitof(child, functions[child], seen | {k}))
-# limitof.cache[k] = f['frame'] + limit
return f['frame'] + limit
for k, f in functions.items():
@@ -918,96 +788,12 @@ def main(paths, output, *,
for f in functions.values()
for k, v in f['attrs'].items()}
-# import pprint
-# pprint.pprint(functions)
-
# assign colors to subsystems, note this is after sorting, but
# before tile generation, we want code and stack tiles to have the
# same color if they're in the same subsystem
for i, (k, s) in enumerate(subsystems.items()):
s['color'] = punescape(colors_[i, (k,)], s['attrs'] | s)
-# # TODO make this configurable?
-# stack_ratio = 1/5
-
-# # use colors for top of tree
-# for i, t in enumerate(tile.children):
-# for t_ in t.tiles():
-# t_.color = colors_[i, t_.key]
-
-# # build functions
-# datasets = co.OrderedDict()
-# dataattrs = co.OrderedDict()
-# for k, v in functions.items():
-# name = ('_'.join(k.split('_')[:2]), k)
-#
-# try:
-# if 'code' in v:
-# datasets[name] = [dat(v['code'])]
-# except ValueError:
-# pass
-#
-# # bring over everything else
-# if name not in dataattrs:
-# dataattrs[name] = {}
-# dataattrs[name].update(v | {
-# 'subsystem': name[0],
-# 'name': name[1],
-# 'code': datasets[name][0],
-# 'stack': v.get('stack', 0),
-# 'ctx': v.get('ctx', 0)})
-
-# # break down by namespace
-# # TODO namespace depth?
-# results_ = []
-# for r in results:
-# name = (r['function'] if 'function' in r
-# else r['struct'] if 'struct' in r
-# else r['name'] if name in r
-# else '?')
-# results_.append({
-# 'subsystem': '_'.join(name.split('_')[:2]),
-# 'name': name,
-# 'code': r['code'] if 'code' in r
-# else r['size'] if 'size' in r
-# else '0',
-# 'frame': r['frame'] if 'code' in r
-# else '0',
-# 'limit': r['stack'] if 'stack' in r
-# else r['limit'] if 'limit' in r
-# else '0',
-# 'ctx': r['ctx'] if 'ctx' in r
-# else '0'})
-# results = results_
-#
-# by = ['subsystem', 'name']
-# fields = ['code']
-# labels_ = Attr(['%(name)s%ncode %(code)d%nstack %(stack)d%nctx %(ctx)d'])
-#
-# if not by and not fields:
-# print("error: needs --by or --fields to figure out fields",
-# file=sys.stderr)
-# sys.exit(-1)
-#
-# # if by not specified, guess it's anything not in fields/labels/defines
-# if not by:
-# by = [k for k in fields_
-# if k not in (fields or [])
-# and k not in (labels or [])
-# and not any(k == k_ for k_, _ in defines)]
-#
-# # if fields not specified, guess it's anything not in by/labels/defines
-# if not fields:
-# fields = [k for k in fields_
-# if k not in (by or [])
-# and k not in (labels or [])
-# and not any(k == k_ for k_, _ in defines)]
-#
-# # then extract the requested dataset
-# datasets, dataattrs = fold(results, by, fields, defines)
-#
-# import pprint
-# pprint.pprint(datasets)
# build code heirarchy
code = Tile.merge(
@@ -1064,51 +850,6 @@ def main(paths, output, *,
attrs=a)
for a in args)
-# ctxs[k].attrs = {'name': k, 'subsystem': f['subsystem']}
-# print(ctxs[k])
-
-
-# children = []
-# for k, f in functions.items():
-# children.append(Tile(
-# k,
-# f['code'],
-# attrs=f))
-#
-## for key, dataset in datasets.items():
-## for i, v in enumerate(dataset):
-## children.append(Tile(
-## key + ((str(i),) if len(dataset) > 1 else ()),
-## v,
-## attrs=dataattrs[key]))
-#
-# tile = Tile.merge(children)
-#
-# # merge attrs
-# for t in tile.tiles():
-# if t.children:
-# t.attrs = {k: v
-# for t_ in t.leaves()
-# for k, v in t_.attrs.items()}
-# # also sum fields here in case they're used by % modifiers,
-# # note other fields are _not_ summed
-# for k in fields:
-# t.attrs[k] = sum(t_.value
-# for t_ in t.leaves()
-# if len(fields) == 1 or t_.key[len(by)] == k)
-#
-# # assign colors/labels before sorting to keep things reproducible
-#
-# # use colors for top of tree
-# for i, t in enumerate(tile.children):
-# for t_ in t.tiles():
-# t_.color = colors_[i, t_.key]
-#
-# # and labels everywhere
-# for i, t in enumerate(tile.tiles()):
-# if (i, t.key) in labels_:
-# t.label = punescape(labels_[i, t.key], t.attrs)
-
# scale width/height if requested now that we have our data
if (to_scale is not None
and (width is None or height is None)):
@@ -1275,6 +1016,7 @@ def main(paths, output, *,
# align to pixel boundaries
stack.align()
+
# create svg file
with openio(output, 'w') as f:
def writeln(s=''):
@@ -1293,9 +1035,6 @@ def main(paths, output, *,
'font: %(font_size)dpx %(font)s; '
'background-color: %(background)s; '
'user-select: %(user_select)s;">' % dict(
-# 'pointer-events="none" '
-# 'onkeydown="keydown(this,event)" '
-# 'onkeyup="keydown(this,event)" '
width=width_,
height=height_,
font=','.join(font),
@@ -1344,21 +1083,6 @@ def main(paths, output, *,
f.write('')
f.write('')
-# # put all our tiles in a big group to catch clicks
-# f.write('')
-# # add an invisible rect to make things more clickable
-# f.write('' % dict(
-# x=0,
-# y=y__,
-# width=width_,
-# height=height_ - y__))
-# f.write('')
-
# create code tiles
for i, t in enumerate(code.leaves()):
# skip anything with zero weight/height after aligning things
@@ -1394,7 +1118,6 @@ def main(paths, output, *,
'data-y="%(y)d" '
'data-width="%(width)d" '
'data-height="%(height)d" '
- # 'cursor="pointer" '
'onmouseenter="enter_tile(this,event)" '
'onmouseleave="leave_tile(this,event)" '
'onclick="click_tile(this,event)">' % dict(
@@ -1450,10 +1173,6 @@ def main(paths, output, *,
f.write('')
f.write('')
-# # show the deepest stack/ctx by default
-# default = max(functions.values(),
-# key=lambda f: f.get('stack', 0) + f.get('ctx', 0))
-
# create stack/ctx tiles
if not no_stack and (not no_ctx or not no_frames):
for i, k in enumerate(functions.keys()):
@@ -1496,24 +1215,6 @@ def main(paths, output, *,
- code.y - padding))
f.write('')
-# # create a group to catch stack-enter events
-# f.write('' % dict(
-# func=k))
-# # add an invisible rect to make things more clickable
-# f.write('' % dict(
-# x=code.x + code.width + 2,
-# y=y__,
-# width=width_ - (code.x + code.width + 2),
-# height=height_ - y__))
-# f.write('')
-
# create ctx tiles
if not no_ctx:
for j, t in enumerate(ctxs[k].leaves()):
@@ -1521,7 +1222,6 @@ def main(paths, output, *,
if t.width == 0 or t.height == 0:
continue
-# print(ctx)
label__ = labels_[j, (t.attrs['name'],)]
if label__ is not None:
label__ = punescape(label__, t.attrs['attrs'] | t.attrs)
@@ -1547,7 +1247,6 @@ def main(paths, output, *,
'data-y="%(y)d" '
'data-width="%(width)d" '
'data-height="%(height)d" '
- # 'cursor="pointer" '
'onmouseenter="enter_tile(this,event)" '
'onmouseleave="leave_tile(this,event)" '
'onclick="click_tile(this,event)">' % dict(
@@ -1651,7 +1350,6 @@ def main(paths, output, *,
'data-y="%(y)d" '
'data-width="%(width)d" '
'data-height="%(height)d" '
-# 'cursor="pointer" '
'onmouseenter="enter_tile(this,event)" '
'onmouseleave="leave_tile(this,event)" '
'onclick="click_tile(this,event)"' % dict(
@@ -1711,10 +1409,6 @@ def main(paths, output, *,
f.write('')
-# f.write('')
-
-# f.write('')
-
if not no_javascript:
# arrowhead for arrows
f.write('')
@@ -1731,32 +1425,12 @@ def main(paths, output, *,
f.write('')
f.write('')
- # TODO why are we running into NaNs? for v1?
-
# javascript for arrows
#
# why tf does svg support javascript?
f.write('')
f.write('')
@@ -2764,7 +2055,6 @@ if __name__ == "__main__":
v.strip())
)(*x.split('=', 1))
if '=' in x else x.strip(),
- # TODO % modifiers in color everywhere? chars? formats? etc?
help="Add a color to use. Can be assigned to a specific "
"function/subsystem. Accepts %% modifiers.")
parser.add_argument(
@@ -2874,7 +2164,6 @@ if __name__ == "__main__":
tuple(float(v) for v in x.split(':', 1))
if ':' in x else (float(x), 1)),
help="Aspect ratio to use with --to-scale. Defaults to 1:1.")
- # TODO add tiny to treemap.py / codemap.py?
parser.add_argument(
'-t', '--tiny',
action='store_true',