Refer to official website barectf.org
[deliverable/barectf.git] / barectf / tsdl182gen.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 from barectf import metadata
24 from barectf import codegen
25 import datetime
26 import barectf
27
28
29 _bo_to_string_map = {
30 metadata.ByteOrder.LE: 'le',
31 metadata.ByteOrder.BE: 'be',
32 }
33
34
35 _encoding_to_string_map = {
36 metadata.Encoding.NONE: 'none',
37 metadata.Encoding.ASCII: 'ASCII',
38 metadata.Encoding.UTF8: 'UTF8',
39 }
40
41
42 def _bo_to_string(bo):
43 return _bo_to_string_map[bo]
44
45
46 def _encoding_to_string(encoding):
47 return _encoding_to_string_map[encoding]
48
49
50 def _bool_to_string(b):
51 return 'true' if b else 'false'
52
53
54 def _gen_integer(t, cg):
55 cg.add_line('integer {')
56 cg.indent()
57 cg.add_line('size = {};'.format(t.size))
58 cg.add_line('align = {};'.format(t.align))
59 cg.add_line('signed = {};'.format(_bool_to_string(t.signed)))
60 cg.add_line('byte_order = {};'.format(_bo_to_string(t.byte_order)))
61 cg.add_line('base = {};'.format(t.base))
62 cg.add_line('encoding = {};'.format(_encoding_to_string(t.encoding)))
63
64 if t.property_mappings:
65 clock_name = t.property_mappings[0].object.name
66 cg.add_line('map = clock.{}.value;'.format(clock_name))
67
68 cg.unindent()
69 cg.add_line('}')
70
71
72 def _gen_float(t, cg):
73 cg.add_line('floating_point {')
74 cg.indent()
75 cg.add_line('exp_dig = {};'.format(t.exp_size))
76 cg.add_line('mant_dig = {};'.format(t.mant_size))
77 cg.add_line('align = {};'.format(t.align))
78 cg.add_line('byte_order = {};'.format(_bo_to_string(t.byte_order)))
79 cg.unindent()
80 cg.add_line('}')
81
82
83 def _gen_enum(t, cg):
84 cg.add_line('enum : ')
85 cg.add_glue()
86 _gen_type(t.value_type, cg)
87 cg.append_to_last_line(' {')
88 cg.indent()
89
90 for label, (mn, mx) in t.members.items():
91 if mn == mx:
92 rg = str(mn)
93 else:
94 rg = '{} ... {}'.format(mn, mx)
95
96 line = '"{}" = {},'.format(label, rg)
97 cg.add_line(line)
98
99 cg.unindent()
100 cg.add_line('}')
101
102
103 def _gen_string(t, cg):
104 cg.add_line('string {')
105 cg.indent()
106 cg.add_line('encoding = {};'.format(_encoding_to_string(t.encoding)))
107 cg.unindent()
108 cg.add_line('}')
109
110
111 def _find_deepest_array_element_type(t):
112 if type(t) is metadata.Array:
113 return _find_deepest_array_element_type(t.element_type)
114
115 return t
116
117
118 def _fill_array_lengths(t, lengths):
119 if type(t) is metadata.Array:
120 lengths.append(t.length)
121 _fill_array_lengths(t.element_type, lengths)
122
123
124 def _gen_struct_variant_entry(name, t, cg):
125 real_t = _find_deepest_array_element_type(t)
126 _gen_type(real_t, cg)
127 cg.append_to_last_line(' {}'.format(name))
128
129 # array
130 lengths = []
131 _fill_array_lengths(t, lengths)
132
133 if lengths:
134 for length in reversed(lengths):
135 cg.append_to_last_line('[{}]'.format(length))
136
137 cg.append_to_last_line(';')
138
139
140 def _gen_struct(t, cg):
141 cg.add_line('struct {')
142 cg.indent()
143
144 for field_name, field_type in t.fields.items():
145 _gen_struct_variant_entry(field_name, field_type, cg)
146
147 cg.unindent()
148
149 if not t.fields:
150 cg.add_glue()
151
152 cg.add_line('}} align({})'.format(t.min_align))
153
154
155 def _gen_variant(t, cg):
156 cg.add_line('variant <{}> {{'.format(t.tag))
157 cg.indent()
158
159 for type_name, type_type in t.types.items():
160 _gen_struct_variant_entry(type_name, type_type, cg)
161
162 cg.unindent()
163
164 if not t.types:
165 cg.add_glue()
166
167 cg.add_line('}')
168
169
170 _type_to_gen_type_func = {
171 metadata.Integer: _gen_integer,
172 metadata.FloatingPoint: _gen_float,
173 metadata.Enum: _gen_enum,
174 metadata.String: _gen_string,
175 metadata.Struct: _gen_struct,
176 metadata.Variant: _gen_variant,
177 }
178
179
180 def _gen_type(t, cg):
181 _type_to_gen_type_func[type(t)](t, cg)
182
183
184 def _gen_entity(name, t, cg):
185 cg.add_line('{} := '.format(name))
186 cg.add_glue()
187 _gen_type(t, cg)
188 cg.append_to_last_line(';')
189
190
191 def _gen_start_block(name, cg):
192 cg.add_line('{} {{'.format(name))
193 cg.indent()
194
195
196 def _gen_end_block(cg):
197 cg.unindent()
198 cg.add_line('};')
199 cg.add_empty_line()
200
201
202 def _gen_trace_block(meta, cg):
203 trace = meta.trace
204
205 _gen_start_block('trace', cg)
206 cg.add_line('major = 1;')
207 cg.add_line('minor = 8;')
208 line = 'byte_order = {};'.format(_bo_to_string(trace.byte_order))
209 cg.add_line(line)
210
211 if trace.uuid is not None:
212 line = 'uuid = "{}";'.format(trace.uuid)
213 cg.add_line(line)
214
215 if trace.packet_header_type is not None:
216 _gen_entity('packet.header', trace.packet_header_type, cg)
217
218 _gen_end_block(cg)
219
220
221 def _escape_literal_string(s):
222 esc = s.replace('\\', '\\\\')
223 esc = esc.replace('\n', '\\n')
224 esc = esc.replace('\r', '\\r')
225 esc = esc.replace('\t', '\\t')
226 esc = esc.replace('"', '\\"')
227
228 return esc
229
230
231 def _gen_env_block(meta, cg):
232 env = meta.env
233
234 if not env:
235 return
236
237 _gen_start_block('env', cg)
238
239 for name, value in env.items():
240 if type(value) is int:
241 value_string = str(value)
242 else:
243 value_string = '"{}"'.format(_escape_literal_string(value))
244
245 cg.add_line('{} = {};'.format(name, value_string))
246
247 _gen_end_block(cg)
248
249
250 def _gen_clock_block(clock, cg):
251 _gen_start_block('clock', cg)
252 cg.add_line('name = {};'.format(clock.name))
253
254 if clock.description is not None:
255 desc = _escape_literal_string(clock.description)
256 cg.add_line('description = "{}";'.format(desc))
257
258 if clock.uuid is not None:
259 cg.add_line('uuid = "{}";'.format(clock.uuid))
260
261 cg.add_line('freq = {};'.format(clock.freq))
262 cg.add_line('offset_s = {};'.format(clock.offset_seconds))
263 cg.add_line('offset = {};'.format(clock.offset_cycles))
264 cg.add_line('precision = {};'.format(clock.error_cycles))
265 cg.add_line('absolute = {};'.format(_bool_to_string(clock.absolute)))
266 _gen_end_block(cg)
267
268
269 def _gen_clock_blocks(meta, cg):
270 clocks = meta.clocks
271
272 for clock in clocks.values():
273 _gen_clock_block(clock, cg)
274
275
276 def _gen_stream_block(meta, stream, cg):
277 cg.add_cc_line(stream.name.replace('/', ''))
278 _gen_start_block('stream', cg)
279
280 if meta.trace.packet_header_type is not None:
281 if 'stream_id' in meta.trace.packet_header_type.fields:
282 cg.add_line('id = {};'.format(stream.id))
283
284 if stream.packet_context_type is not None:
285 _gen_entity('packet.context', stream.packet_context_type, cg)
286
287 if stream.event_header_type is not None:
288 _gen_entity('event.header', stream.event_header_type, cg)
289
290 if stream.event_context_type is not None:
291 _gen_entity('event.context', stream.event_context_type, cg)
292
293 _gen_end_block(cg)
294
295
296 def _gen_event_block(meta, stream, ev, cg):
297 _gen_start_block('event', cg)
298 cg.add_line('name = "{}";'.format(ev.name))
299 cg.add_line('id = {};'.format(ev.id))
300
301 if meta.trace.packet_header_type is not None:
302 if 'stream_id' in meta.trace.packet_header_type.fields:
303 cg.add_line('stream_id = {};'.format(stream.id))
304
305 cg.append_cc_to_last_line(stream.name.replace('/', ''))
306
307 if ev.log_level is not None:
308 add_fmt = ''
309
310 if ev.log_level.name is not None:
311 name = ev.log_level.name.replace('*/', '')
312 add_fmt = ' /* {} */'.format(name)
313
314 fmt = 'loglevel = {};' + add_fmt
315 cg.add_line(fmt.format(ev.log_level.value))
316
317 if ev.context_type is not None:
318 _gen_entity('context', ev.context_type, cg)
319
320 if ev.payload_type is not None:
321 _gen_entity('fields', ev.payload_type, cg)
322 else:
323 fake_payload = metadata.Struct()
324 fake_payload.min_align = 8
325 _gen_entity('fields', fake_payload, cg)
326
327 _gen_end_block(cg)
328
329
330 def _gen_streams_events_blocks(meta, cg):
331 for stream in meta.streams.values():
332 _gen_stream_block(meta, stream, cg)
333
334 for ev in stream.events.values():
335 _gen_event_block(meta, stream, ev, cg)
336
337
338 def from_metadata(meta):
339 cg = codegen.CodeGenerator('\t')
340
341 # version/magic
342 cg.add_line('/* CTF 1.8 */')
343 cg.add_empty_line()
344 cg.add_line('''/*
345 * The MIT License (MIT)
346 *
347 * Copyright (c) 2015-2016 Philippe Proulx <pproulx@efficios.com>
348 *
349 * Permission is hereby granted, free of charge, to any person obtaining a copy
350 * of this software and associated documentation files (the "Software"), to deal
351 * in the Software without restriction, including without limitation the rights
352 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
353 * copies of the Software, and to permit persons to whom the Software is
354 * furnished to do so, subject to the following conditions:
355 *
356 * The above copyright notice and this permission notice shall be included in
357 * all copies or substantial portions of the Software.
358 *
359 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
360 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
361 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
362 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
363 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
364 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
365 * THE SOFTWARE.
366 *
367 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
368 *''')
369 v = barectf.__version__
370 line = ' * The following TSDL code was generated by barectf v{}'.format(v)
371 cg.add_line(line)
372 now = datetime.datetime.now()
373 line = ' * on {}.'.format(now)
374 cg.add_line(line)
375 cg.add_line(' *')
376 cg.add_line(' * For more details, see <http://barectf.org>.')
377 cg.add_line(' */')
378 cg.add_empty_line()
379
380 # trace block
381 _gen_trace_block(meta, cg)
382
383 # environment
384 _gen_env_block(meta, cg)
385
386 # clocks
387 _gen_clock_blocks(meta, cg)
388
389 # streams and contained events
390 _gen_streams_events_blocks(meta, cg)
391
392 return cg.code
This page took 0.050453 seconds and 5 git commands to generate.