1#encoding=utf-8 2 3# Copyright (C) 2016 Intel Corporation 4# Copyright (C) 2016 Broadcom 5# Copyright (C) 2020 Collabora, Ltd. 6# 7# Permission is hereby granted, free of charge, to any person obtaining a 8# copy of this software and associated documentation files (the "Software"), 9# to deal in the Software without restriction, including without limitation 10# the rights to use, copy, modify, merge, publish, distribute, sublicense, 11# and/or sell copies of the Software, and to permit persons to whom the 12# Software is furnished to do so, subject to the following conditions: 13# 14# The above copyright notice and this permission notice (including the next 15# paragraph) shall be included in all copies or substantial portions of the 16# Software. 17# 18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24# IN THE SOFTWARE. 25 26import argparse 27import xml.parsers.expat 28import sys 29import operator 30from functools import reduce 31 32global_prefix = "mali" 33 34v6_format_printer = """ 35 36#define mali_pixel_format_print(fp, format) \\ 37 fprintf(fp, "%*sFormat (v6): %s%s%s %s%s%s%s\\n", indent, "", \\ 38 mali_format_as_str((enum mali_format)((format >> 12) & 0xFF)), \\ 39 (format & (1 << 20)) ? " sRGB" : "", \\ 40 (format & (1 << 21)) ? " big-endian" : "", \\ 41 mali_channel_as_str((enum mali_channel)((format >> 0) & 0x7)), \\ 42 mali_channel_as_str((enum mali_channel)((format >> 3) & 0x7)), \\ 43 mali_channel_as_str((enum mali_channel)((format >> 6) & 0x7)), \\ 44 mali_channel_as_str((enum mali_channel)((format >> 9) & 0x7))); 45 46""" 47 48v7_format_printer = """ 49 50#define mali_pixel_format_print(fp, format) \\ 51 fprintf(fp, "%*sFormat (v7): %s%s %s%s\\n", indent, "", \\ 52 mali_format_as_str((enum mali_format)((format >> 12) & 0xFF)), \\ 53 (format & (1 << 20)) ? " sRGB" : "", \\ 54 mali_rgb_component_order_as_str((enum mali_rgb_component_order)(format & ((1 << 12) - 1))), \\ 55 (format & (1 << 21)) ? " XXX BAD BIT" : ""); 56 57""" 58 59def to_alphanum(name): 60 substitutions = { 61 ' ': '_', 62 '/': '_', 63 '[': '', 64 ']': '', 65 '(': '', 66 ')': '', 67 '-': '_', 68 ':': '', 69 '.': '', 70 ',': '', 71 '=': '', 72 '>': '', 73 '#': '', 74 '&': '', 75 '%': '', 76 '*': '', 77 '"': '', 78 '+': '', 79 '\'': '', 80 } 81 82 for i, j in substitutions.items(): 83 name = name.replace(i, j) 84 85 return name 86 87def safe_name(name): 88 name = to_alphanum(name) 89 if not name[0].isalpha(): 90 name = '_' + name 91 92 return name 93 94def prefixed_upper_name(prefix, name): 95 if prefix: 96 name = prefix + "_" + name 97 return safe_name(name).upper() 98 99def enum_name(name): 100 return "{}_{}".format(global_prefix, safe_name(name)).lower() 101 102MODIFIERS = ["shr", "minus", "align", "log2"] 103 104def parse_modifier(modifier): 105 if modifier is None: 106 return None 107 108 for mod in MODIFIERS: 109 if modifier[0:len(mod)] == mod: 110 if mod == "log2": 111 assert(len(mod) == len(modifier)) 112 return [mod] 113 114 if modifier[len(mod)] == '(' and modifier[-1] == ')': 115 ret = [mod, int(modifier[(len(mod) + 1):-1])] 116 if ret[0] == 'align': 117 align = ret[1] 118 # Make sure the alignment is a power of 2 119 assert(align > 0 and not(align & (align - 1))); 120 121 return ret 122 123 print("Invalid modifier") 124 assert(False) 125 126class Aggregate(object): 127 def __init__(self, parser, name, attrs): 128 self.parser = parser 129 self.sections = [] 130 self.name = name 131 self.explicit_size = int(attrs["size"]) if "size" in attrs else 0 132 self.size = 0 133 self.align = int(attrs["align"]) if "align" in attrs else None 134 135 class Section: 136 def __init__(self, name): 137 self.name = name 138 139 def get_size(self): 140 if self.size > 0: 141 return self.size 142 143 size = 0 144 for section in self.sections: 145 size = max(size, section.offset + section.type.get_length()) 146 147 if self.explicit_size > 0: 148 assert(self.explicit_size >= size) 149 self.size = self.explicit_size 150 else: 151 self.size = size 152 return self.size 153 154 def add_section(self, type_name, attrs): 155 assert("name" in attrs) 156 section = self.Section(safe_name(attrs["name"]).lower()) 157 section.human_name = attrs["name"] 158 section.offset = int(attrs["offset"]) 159 assert(section.offset % 4 == 0) 160 section.type = self.parser.structs[attrs["type"]] 161 section.type_name = type_name 162 self.sections.append(section) 163 164class Field(object): 165 def __init__(self, parser, attrs): 166 self.parser = parser 167 if "name" in attrs: 168 self.name = safe_name(attrs["name"]).lower() 169 self.human_name = attrs["name"] 170 171 if ":" in str(attrs["start"]): 172 (word, bit) = attrs["start"].split(":") 173 self.start = (int(word) * 32) + int(bit) 174 else: 175 self.start = int(attrs["start"]) 176 177 self.end = self.start + int(attrs["size"]) - 1 178 self.type = attrs["type"] 179 180 if self.type == 'bool' and self.start != self.end: 181 print("#error Field {} has bool type but more than one bit of size".format(self.name)); 182 183 if "prefix" in attrs: 184 self.prefix = safe_name(attrs["prefix"]).upper() 185 else: 186 self.prefix = None 187 188 self.default = attrs.get("default") 189 190 # Map enum values 191 if self.type in self.parser.enums and self.default is not None: 192 self.default = safe_name('{}_{}_{}'.format(global_prefix, self.type, self.default)).upper() 193 194 self.modifier = parse_modifier(attrs.get("modifier")) 195 196 def emit_template_struct(self, dim): 197 if self.type == 'address': 198 type = 'uint64_t' 199 elif self.type == 'bool': 200 type = 'bool' 201 elif self.type in ['float', 'ulod', 'slod']: 202 type = 'float' 203 elif self.type in ['uint', 'hex'] and self.end - self.start > 32: 204 type = 'uint64_t' 205 elif self.type == 'int': 206 type = 'int32_t' 207 elif self.type in ['uint', 'hex', 'uint/float', 'padded', 'Pixel Format', 'Component Swizzle']: 208 type = 'uint32_t' 209 elif self.type in self.parser.structs: 210 type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper())) 211 elif self.type in self.parser.enums: 212 type = 'enum ' + enum_name(self.type) 213 else: 214 print("#error unhandled type: %s" % self.type) 215 type = "uint32_t" 216 217 print(" %-36s %s%s;" % (type, self.name, dim)) 218 219 for value in self.values: 220 name = prefixed_upper_name(self.prefix, value.name) 221 print("#define %-40s %d" % (name, value.value)) 222 223 def overlaps(self, field): 224 return self != field and max(self.start, field.start) <= min(self.end, field.end) 225 226class Group(object): 227 def __init__(self, parser, parent, start, count, label): 228 self.parser = parser 229 self.parent = parent 230 self.start = start 231 self.count = count 232 self.label = label 233 self.size = 0 234 self.length = 0 235 self.fields = [] 236 237 def get_length(self): 238 # Determine number of bytes in this group. 239 calculated = max(field.end // 8 for field in self.fields) + 1 if len(self.fields) > 0 else 0 240 if self.length > 0: 241 assert(self.length >= calculated) 242 else: 243 self.length = calculated 244 return self.length 245 246 247 def emit_template_struct(self, dim): 248 if self.count == 0: 249 print(" /* variable length fields follow */") 250 else: 251 if self.count > 1: 252 dim = "%s[%d]" % (dim, self.count) 253 254 if len(self.fields) == 0: 255 print(" int dummy;") 256 257 for field in self.fields: 258 field.emit_template_struct(dim) 259 260 class Word: 261 def __init__(self): 262 self.size = 32 263 self.contributors = [] 264 265 class FieldRef: 266 def __init__(self, field, path, start, end): 267 self.field = field 268 self.path = path 269 self.start = start 270 self.end = end 271 272 def collect_fields(self, fields, offset, path, all_fields): 273 for field in fields: 274 field_path = '{}{}'.format(path, field.name) 275 field_offset = offset + field.start 276 277 if field.type in self.parser.structs: 278 sub_struct = self.parser.structs[field.type] 279 self.collect_fields(sub_struct.fields, field_offset, field_path + '.', all_fields) 280 continue 281 282 start = field_offset 283 end = offset + field.end 284 all_fields.append(self.FieldRef(field, field_path, start, end)) 285 286 def collect_words(self, fields, offset, path, words): 287 for field in fields: 288 field_path = '{}{}'.format(path, field.name) 289 start = offset + field.start 290 291 if field.type in self.parser.structs: 292 sub_fields = self.parser.structs[field.type].fields 293 self.collect_words(sub_fields, start, field_path + '.', words) 294 continue 295 296 end = offset + field.end 297 contributor = self.FieldRef(field, field_path, start, end) 298 first_word = contributor.start // 32 299 last_word = contributor.end // 32 300 for b in range(first_word, last_word + 1): 301 if not b in words: 302 words[b] = self.Word() 303 words[b].contributors.append(contributor) 304 305 def emit_pack_function(self): 306 self.get_length() 307 308 words = {} 309 self.collect_words(self.fields, 0, '', words) 310 311 # Validate the modifier is lossless 312 for field in self.fields: 313 if field.modifier is None: 314 continue 315 316 if field.modifier[0] == "shr": 317 shift = field.modifier[1] 318 mask = hex((1 << shift) - 1) 319 print(" assert(((__unpacked)->{} & {}) == 0); \\".format(field.name, mask)) 320 elif field.modifier[0] == "minus": 321 print(" assert((__unpacked)->{} >= {}); \\".format(field.name, field.modifier[1])) 322 elif field.modifier[0] == "log2": 323 print(" assert(IS_POT_NONZERO((__unpacked)->{})); \\".format(field.name)) 324 325 for index in range(self.length // 4): 326 # Handle MBZ words 327 if not index in words: 328 print(" __tmp_packed.opaque[%2d] = 0; \\" % index) 329 continue 330 331 word = words[index] 332 333 word_start = index * 32 334 335 v = None 336 prefix = " __tmp_packed.opaque[%2d] =" % index 337 338 for contributor in word.contributors: 339 field = contributor.field 340 name = field.name 341 start = contributor.start 342 end = contributor.end 343 contrib_word_start = (start // 32) * 32 344 start -= contrib_word_start 345 end -= contrib_word_start 346 347 value = "(__unpacked)->{}".format(contributor.path) 348 if field.modifier is not None: 349 if field.modifier[0] == "shr": 350 value = "{} >> {}".format(value, field.modifier[1]) 351 elif field.modifier[0] == "minus": 352 value = "{} - {}".format(value, field.modifier[1]) 353 elif field.modifier[0] == "align": 354 value = "ALIGN_POT({}, {})".format(value, field.modifier[1]) 355 elif field.modifier[0] == "log2": 356 value = "util_logbase2({})".format(value) 357 358 if field.type in ["uint", "hex", "uint/float", "address", "Pixel Format", "Component Swizzle"]: 359 s = "util_bitpack_uint(%s, %d, %d)" % \ 360 (value, start, end) 361 elif field.type == "padded": 362 s = "__gen_padded(%s, %d, %d)" % \ 363 (value, start, end) 364 elif field.type in self.parser.enums: 365 s = "util_bitpack_uint(%s, %d, %d)" % \ 366 (value, start, end) 367 elif field.type == "int": 368 s = "util_bitpack_sint(%s, %d, %d)" % \ 369 (value, start, end) 370 elif field.type == "bool": 371 s = "util_bitpack_uint(%s, %d, %d)" % \ 372 (value, start, end) 373 elif field.type == "float": 374 assert(start == 0 and end == 31) 375 s = "util_bitpack_float({})".format(value) 376 elif field.type == "ulod": 377 s = "util_bitpack_ufixed_clamp({}, {}, {}, 8)".format(value, 378 start, 379 end) 380 elif field.type == "slod": 381 s = "util_bitpack_sfixed_clamp({}, {}, {}, 8)".format(value, 382 start, 383 end) 384 else: 385 s = "#error unhandled field {}, type {}".format(contributor.path, field.type) 386 387 if not s == None: 388 shift = word_start - contrib_word_start 389 if shift: 390 s = "%s >> %d" % (s, shift) 391 392 if contributor == word.contributors[-1]: 393 print("%s %s; \\" % (prefix, s)) 394 else: 395 print("%s %s | \\" % (prefix, s)) 396 prefix = " " 397 398 continue 399 400 # Given a field (start, end) contained in word `index`, generate the 32-bit 401 # mask of present bits relative to the word 402 def mask_for_word(self, index, start, end): 403 field_word_start = index * 32 404 start -= field_word_start 405 end -= field_word_start 406 # Cap multiword at one word 407 start = max(start, 0) 408 end = min(end, 32 - 1) 409 count = (end - start + 1) 410 return (((1 << count) - 1) << start) 411 412 def emit_unpack_function(self): 413 # First, verify there is no garbage in unused bits 414 words = {} 415 self.collect_words(self.fields, 0, '', words) 416 417 for index in range(self.length // 4): 418 base = index * 32 419 word = words.get(index, self.Word()) 420 masks = [self.mask_for_word(index, c.start, c.end) for c in word.contributors] 421 mask = reduce(lambda x,y: x | y, masks, 0) 422 423 ALL_ONES = 0xffffffff 424 425 if mask != ALL_ONES: 426 TMPL = ' if (__tmp_packed.opaque[{}] & {}) fprintf(stderr, "XXX: Invalid field of {} unpacked at word {}\\n"); \\' 427 print(TMPL.format(index, hex(mask ^ ALL_ONES), self.label, index)) 428 429 fieldrefs = [] 430 self.collect_fields(self.fields, 0, '', fieldrefs) 431 for fieldref in fieldrefs: 432 field = fieldref.field 433 convert = None 434 435 args = [] 436 args.append('(__unpacked)->{}'.format(fieldref.path)) 437 args.append('&__tmp_packed.opaque[0]') 438 args.append(str(fieldref.start)) 439 args.append(str(fieldref.end)) 440 441 if field.type in set(["uint", "hex", "uint/float", "address", "Pixel Format", "Component Swizzle"]): 442 convert = "__gen_unpack_uint" 443 elif field.type in self.parser.enums: 444 convert = "__gen_unpack_uint" 445 elif field.type == "int": 446 convert = "__gen_unpack_sint" 447 elif field.type == "padded": 448 convert = "__gen_unpack_padded" 449 elif field.type == "bool": 450 convert = "__gen_unpack_uint" 451 elif field.type == "float": 452 convert = "__gen_unpack_float" 453 elif field.type == "ulod": 454 convert = "__gen_unpack_ulod" 455 elif field.type == "slod": 456 convert = "__gen_unpack_slod" 457 else: 458 s = "/* unhandled field %s, type %s */\n" % (field.name, field.type) 459 460 suffix = "" 461 prefix = "" 462 if field.modifier: 463 if field.modifier[0] == "minus": 464 suffix = " + {}".format(field.modifier[1]) 465 elif field.modifier[0] == "shr": 466 suffix = " << {}".format(field.modifier[1]) 467 if field.modifier[0] == "log2": 468 prefix = "1U << " 469 470 print(' {}({}); \\'.format(convert, ', '.join(args))) 471 472 if len(prefix) != 0 or len(suffix) != 0: 473 print(' (__unpacked)->{} = {}(__unpacked)->{}{}; \\'.format(fieldref.path, prefix, fieldref.path, suffix)) 474 475 476 if field.modifier and field.modifier[0] == "align": 477 mask = hex(field.modifier[1] - 1) 478 print(' assert(!((__unpacked)->{} & {})); \\'.format(fieldref.path, mask)) 479 480 def emit_print_function(self): 481 for field in self.fields: 482 convert = None 483 name, val = field.human_name, 'values->{}'.format(field.name) 484 485 if field.type in self.parser.structs: 486 pack_name = self.parser.gen_prefix(safe_name(field.type)).upper() 487 print(' fprintf(fp, "%*s{}:\\n", indent, "");'.format(field.human_name)) 488 print(" {}_print(fp, &values->{}, indent + 2);".format(pack_name, field.name)) 489 elif field.type == "address": 490 # TODO resolve to name 491 print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val)) 492 elif field.type in self.parser.enums: 493 print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {}_as_str({}));'.format(name, enum_name(field.type), val)) 494 elif field.type == "int": 495 print(' fprintf(fp, "%*s{}: %d\\n", indent, "", {});'.format(name, val)) 496 elif field.type == "bool": 497 print(' fprintf(fp, "%*s{}: %s\\n", indent, "", {} ? "true" : "false");'.format(name, val)) 498 elif field.type in ["float", "ulod", "slod"]: 499 print(' fprintf(fp, "%*s{}: %f\\n", indent, "", {});'.format(name, val)) 500 elif field.type in ["uint", "hex"] and (field.end - field.start) >= 32: 501 print(' fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val)) 502 elif field.type == "hex": 503 print(' fprintf(fp, "%*s{}: 0x%x\\n", indent, "", {});'.format(name, val)) 504 elif field.type == "uint/float": 505 print(' fprintf(fp, "%*s{}: 0x%X (%f)\\n", indent, "", {}, uif({}));'.format(name, val, val)) 506 elif field.type == "Pixel Format": 507 print(' mali_pixel_format_print(fp, {});'.format(val)) 508 elif field.type == "Component Swizzle": 509 print(' fprintf(fp, "%*s{}: %u (%s)\\n", indent, "", {}, mali_component_swizzle({}));'.format(name, val, val)) 510 else: 511 print(' fprintf(fp, "%*s{}: %u\\n", indent, "", {});'.format(name, val)) 512 513class Value(object): 514 def __init__(self, attrs): 515 self.name = attrs["name"] 516 self.value = int(attrs["value"], 0) 517 518pack_header = """/* Autogenerated file, do not edit */ 519/* 520 * Copyright 2024 Collabora Ltd. 521 * SPDX-License-Identifier: MIT 522 */ 523 524#ifndef PAN_PACK_H 525#define PAN_PACK_H 526 527#include "genxml/pan_pack_helpers.h" 528""" 529 530class Parser(object): 531 def __init__(self): 532 self.parser = xml.parsers.expat.ParserCreate() 533 self.parser.StartElementHandler = self.start_element 534 self.parser.EndElementHandler = self.end_element 535 536 self.struct = None 537 self.structs = {} 538 # Set of enum names we've seen. 539 self.enums = set() 540 self.aggregate = None 541 self.aggregates = {} 542 543 def gen_prefix(self, name): 544 return '{}_{}'.format(global_prefix.upper(), name) 545 546 def start_element(self, name, attrs): 547 if name == "panxml": 548 print(pack_header) 549 if "arch" in attrs: 550 arch = int(attrs["arch"]) 551 if arch <= 6: 552 print(v6_format_printer) 553 else: 554 print(v7_format_printer) 555 elif name == "struct": 556 name = attrs["name"] 557 self.no_direct_packing = attrs.get("no-direct-packing", False) 558 object_name = self.gen_prefix(safe_name(name.upper())) 559 self.struct = object_name 560 561 self.group = Group(self, None, 0, 1, name) 562 if "size" in attrs: 563 self.group.length = int(attrs["size"]) * 4 564 self.group.align = int(attrs["align"]) if "align" in attrs else None 565 self.structs[attrs["name"]] = self.group 566 elif name == "field": 567 self.group.fields.append(Field(self, attrs)) 568 self.values = [] 569 elif name == "enum": 570 self.values = [] 571 self.enum = safe_name(attrs["name"]) 572 self.enums.add(attrs["name"]) 573 if "prefix" in attrs: 574 self.prefix = attrs["prefix"] 575 else: 576 self.prefix= None 577 elif name == "value": 578 self.values.append(Value(attrs)) 579 elif name == "aggregate": 580 aggregate_name = self.gen_prefix(safe_name(attrs["name"].upper())) 581 self.aggregate = Aggregate(self, aggregate_name, attrs) 582 self.aggregates[attrs['name']] = self.aggregate 583 elif name == "section": 584 type_name = self.gen_prefix(safe_name(attrs["type"].upper())) 585 self.aggregate.add_section(type_name, attrs) 586 587 def end_element(self, name): 588 if name == "struct": 589 self.emit_struct() 590 self.struct = None 591 self.group = None 592 elif name == "field": 593 self.group.fields[-1].values = self.values 594 elif name == "enum": 595 self.emit_enum() 596 self.enum = None 597 elif name == "aggregate": 598 self.emit_aggregate() 599 self.aggregate = None 600 elif name == "panxml": 601 # Include at the end so it can depend on us but not the converse 602 print('#endif') 603 604 def emit_header(self, name): 605 default_fields = [] 606 for field in self.group.fields: 607 if not type(field) is Field: 608 continue 609 if field.default is not None: 610 default_fields.append(" .{} = {}".format(field.name, field.default)) 611 elif field.type in self.structs: 612 default_fields.append(" .{} = {{ {}_header }}".format(field.name, self.gen_prefix(safe_name(field.type.upper())))) 613 614 print('#define %-40s\\' % (name + '_header')) 615 if default_fields: 616 print(", \\\n".join(default_fields)) 617 else: 618 print(' 0') 619 print('') 620 621 def emit_template_struct(self, name, group): 622 print("struct %s {" % name) 623 group.emit_template_struct("") 624 print("};\n") 625 626 def emit_aggregate(self): 627 aggregate = self.aggregate 628 print("struct %s_packed {" % aggregate.name.lower()) 629 print(" uint32_t opaque[{}];".format(aggregate.get_size() // 4)) 630 print("};\n") 631 print('#define {}_PACKED_T struct {}_packed'.format(aggregate.name.upper(), aggregate.name.lower())) 632 print('#define {}_LENGTH {}'.format(aggregate.name.upper(), aggregate.size)) 633 if aggregate.align != None: 634 print('#define {}_ALIGN {}'.format(aggregate.name.upper(), aggregate.align)) 635 for section in aggregate.sections: 636 print('#define {}_SECTION_{}_TYPE struct {}'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 637 print('#define {}_SECTION_{}_PACKED_TYPE {}_PACKED_T'.format(aggregate.name.upper(), section.name.upper(), section.type_name.upper())) 638 print('#define {}_SECTION_{}_header {}_header'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 639 print('#define {}_SECTION_{}_pack {}_pack'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 640 print('#define {}_SECTION_{}_unpack {}_unpack'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 641 print('#define {}_SECTION_{}_print {}_print'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) 642 print('#define {}_SECTION_{}_OFFSET {}'.format(aggregate.name.upper(), section.name.upper(), section.offset)) 643 print("") 644 645 def emit_struct_detail(self, name, group): 646 group.get_length() 647 648 # Should be a whole number of words 649 assert((self.group.length % 4) == 0) 650 651 print('#define {} {}'.format (name + "_LENGTH", self.group.length)) 652 if self.group.align != None: 653 print('#define {} {}'.format (name + "_ALIGN", self.group.align)) 654 print('struct {}_packed {{ uint32_t opaque[{}]; }};'.format(name.lower(), self.group.length // 4)) 655 print('#define {}_PACKED_T struct {}_packed'.format(name.upper(), name.lower())) 656 657 def emit_pack_function(self, name, group): 658 print("#define {}_pack(__packed, __unpacked) \\".format(name)) 659 print("do { \\") 660 print(" {}_PACKED_T __tmp_packed; \\".format(name.upper())) 661 group.emit_pack_function() 662 print(' *(__packed) = __tmp_packed; \\') 663 print("} while (0);\n") 664 665 def emit_unpack_function(self, name, group): 666 print("#define {}_unpack(__packed, __unpacked) \\".format(name)) 667 print("do { \\") 668 print(" {}_PACKED_T __tmp_packed = *(__packed); \\".format(name)) 669 group.emit_unpack_function() 670 print("} while (0);\n") 671 672 def emit_print_function(self, name, group): 673 print("static inline void") 674 print("{}_print(FILE *fp, const struct {} * values, unsigned indent)\n{{".format(name.upper(), name)) 675 676 group.emit_print_function() 677 678 print("}\n") 679 680 def emit_struct(self): 681 name = self.struct 682 683 self.emit_template_struct(self.struct, self.group) 684 self.emit_header(name) 685 if self.no_direct_packing == False: 686 self.emit_struct_detail(self.struct, self.group) 687 self.emit_pack_function(self.struct, self.group) 688 self.emit_unpack_function(self.struct, self.group) 689 self.emit_print_function(self.struct, self.group) 690 691 def enum_prefix(self, name): 692 return 693 694 def emit_enum(self): 695 e_name = enum_name(self.enum) 696 prefix = e_name if self.enum != 'Format' else global_prefix 697 print('enum {} {{'.format(e_name)) 698 699 for value in self.values: 700 name = '{}_{}'.format(prefix, value.name) 701 name = safe_name(name).upper() 702 print(' % -36s = %6d,' % (name, value.value)) 703 print('};\n') 704 705 print("static inline const char *") 706 print("{}_as_str(enum {} imm)\n{{".format(e_name.lower(), e_name)) 707 print(" switch (imm) {") 708 for value in self.values: 709 name = '{}_{}'.format(prefix, value.name) 710 name = safe_name(name).upper() 711 print(' case {}: return "{}";'.format(name, value.name)) 712 print(' default: return "XXX: INVALID";') 713 print(" }") 714 print("}\n") 715 716 def parse(self, filename): 717 file = open(filename, "rb") 718 self.parser.ParseFile(file) 719 file.close() 720 721 722parser = argparse.ArgumentParser() 723parser.add_argument('input_file') 724args = parser.parse_args() 725 726p = Parser() 727p.parse(args.input_file) 728