1
# -----------------------------------------
3
# Copyright 2014, Ensoft Ltd.
4
# Author: Patrick Stevens, James Harkin
5
# -----------------------------------------
6
# Convert a program from internal Python representation to various output formats
8
__all__ = "ProgramConverter"
11
class ProgramConverter:
12
# Given our internal program representation, converts it to output formats.
13
# Currently supported: GraphML
16
def get_supported_outputs():
17
return ['graphml', 'yed_graphml', 'dot']
20
def get_display_name(function, suppress_common_nodes=False):
22
Given a Function object, retrieve the label we attach to it.
23
For instance, function-pointers are labelled "(function pointer)",
24
while the `main` function is usually labelled "main".
26
if function.type == "function_pointer":
27
name = "(function pointer)"
31
if suppress_common_nodes and function.is_common:
36
def to_dot(program, suppress_common_nodes=False):
38
Convert the program to DOT output format.
40
output_str = 'digraph "{}" {{\n '.format(program.program_name)
41
output_str += 'overlap=false; \n'
43
font_name = "helvetica"
45
for func in program.get_functions():
46
if func.type == "plt_stub":
47
output_str += ' "{}" [fillcolor=pink, style=filled]\n'.format(func.name)
48
elif func.type == "function_pointer":
49
output_str += ' "{}" [fillcolor=yellow, style=filled]\n'.format(func.name)
51
# in all cases, even if we've specified that we want a filled-in
52
# node already, DOT lets us add more information about that node
53
# so we can insist on turning that same node into a box-shape
54
# and changing its font.
55
output_str += ' "{}" [label="{}", fontname="{}", shape=box]\n'.format(func.name,
56
ProgramConverter.get_display_name(func, suppress_common_nodes),
59
output_str += ' "{}" [fillcolor=lightgreen, style=filled]\n'.format(func.name)
61
for func_called in func.functions_i_call:
62
if not (suppress_common_nodes and func_called.is_common):
63
output_str += ' "{}" -> "{}"\n'.format(func.name, func_called.name)
71
def to_yed_graphml(program, suppress_common_nodes=False):
73
output_str = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
74
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
75
xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" \
76
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
78
output_str += """<key for="graphml" id="d0" yfiles.type="resources"/>
79
<key for="port" id="d1" yfiles.type="portgraphics"/>
80
<key for="port" id="d2" yfiles.type="portgeometry"/>
81
<key for="port" id="d3" yfiles.type="portuserdata"/>
82
<key attr.name="url" attr.type="string" for="node" id="d4"/>
83
<key attr.name="description" attr.type="string" for="node" id="d5"/>
84
<key for="node" id="d6" yfiles.type="nodegraphics"/>
85
<key attr.name="url" attr.type="string" for="edge" id="d7"/>
86
<key attr.name="description" attr.type="string" for="edge" id="d8"/>
87
<key for="edge" id="d9" yfiles.type="edgegraphics"/>\n"""
89
output_str += """<graph id="{}" edgedefault="directed">\n""".format(program.program_name)
91
for func in program.get_functions():
92
display_func = ProgramConverter.get_display_name(func)
93
if func.type == "plt_stub":
95
elif func.type == "function_pointer":
101
output_str += """<node id="{}">
104
<y:Geometry height="{}" width="{}" x="60.0" y="0.0"/>
105
<y:Fill color="{}" transparent="false"/>
106
<y:BorderStyle color="#000000" type="line" width="1.0"/>
107
<y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog"
108
fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false"
109
height="18.701171875" modelName="custom" textColor="#000000" visible="true"
110
width="36.6953125" x="-3.34765625" y="5.6494140625">{}<y:LabelModel>
111
<y:SmartNodeLabelModel distance="4.0"/>
114
<y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0"
115
nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0"
119
<y:Shape type="rectangle"/>
122
</node>\n""".format(func.name, 20, len(display_func)*8, colour, display_func)
123
for callee in func.functions_i_call:
124
if callee not in commonly_called:
125
if not(suppress_common_nodes and callee.is_common):
126
output_str += """<edge source="{}" target="{}"> <data key="d9">
128
<y:LineStyle color="#000000" type="line" width="1.0"/>
129
<y:Arrows source="none" target="standard"/>
130
<y:BendStyle smoothed="false"/>
133
</edge>\n""".format(func.name, callee.name)
135
output_str += '</graph>\n<data key="d0"> <y:Resources/> </data>\n</graphml>'
139
def to_graphml(program):
140
output_str = """<?xml version="1.0" encoding="UTF-8"?>
141
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
142
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
144
output_str += '<graph id="{}" edgedefault="directed">\n'.format(program.program_name)
146
for func in program.get_functions():
147
output_str += '<node id="{}"> <data key="name">{}</data> </node>\n'.format(func.name, ProgramConverter.get_display_name(func))
148
for callee in func.functions_i_call:
149
output_str += '<edge source="{}" target="{}"> <data key="calls">1</data> </edge>\n'.format(func.name, callee.name)
151
output_str += '</graph>\n</graphml>'
b'\\ No newline at end of file'