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