• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 xml.parsers.expat
27import sys
28import operator
29from functools import reduce
30
31global_prefix = "agx"
32
33pack_header = """
34/* Generated code, see midgard.xml and gen_pack_header.py
35 *
36 * Packets, enums and structures for Panfrost.
37 *
38 * This file has been generated, do not hand edit.
39 */
40
41#ifndef AGX_PACK_H
42#define AGX_PACK_H
43
44#include <stdio.h>
45#include <stdint.h>
46#include <stdbool.h>
47#include <assert.h>
48#include <math.h>
49#include <inttypes.h>
50#include "util/macros.h"
51#include "util/u_math.h"
52
53#define __gen_unpack_float(x, y, z) uif(__gen_unpack_uint(x, y, z))
54
55static inline uint64_t
56__gen_uint(uint64_t v, uint32_t start, uint32_t end)
57{
58#ifndef NDEBUG
59   const int width = end - start + 1;
60   if (width < 64) {
61      const uint64_t max = (1ull << width) - 1;
62      assert(v <= max);
63   }
64#endif
65
66   return v << start;
67}
68
69static inline uint32_t
70__gen_sint(int32_t v, uint32_t start, uint32_t end)
71{
72#ifndef NDEBUG
73   const int width = end - start + 1;
74   if (width < 64) {
75      const int64_t max = (1ll << (width - 1)) - 1;
76      const int64_t min = -(1ll << (width - 1));
77      assert(min <= v && v <= max);
78   }
79#endif
80
81   return (((uint32_t) v) << start) & ((2ll << end) - 1);
82}
83
84static inline uint64_t
85__gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
86{
87   uint64_t val = 0;
88   const int width = end - start + 1;
89   const uint64_t mask = (width == 64 ? ~0 : (1ull << width) - 1 );
90
91   for (unsigned byte = start / 8; byte <= end / 8; byte++) {
92      val |= ((uint64_t) cl[byte]) << ((byte - start / 8) * 8);
93   }
94
95   return (val >> (start % 8)) & mask;
96}
97
98/*
99 * LODs are 4:6 fixed point. We must clamp before converting to integers to
100 * avoid undefined behaviour for out-of-bounds inputs like +/- infinity.
101 */
102static inline uint32_t
103__float_to_lod(float f)
104{
105    return (uint32_t) CLAMP(f * (1 << 6), 0 /* 0.0 */, 0x380 /* 14.0 */);
106}
107
108static inline float
109__gen_unpack_lod(const uint8_t *restrict cl, uint32_t start, uint32_t end)
110{
111    return ((float) __gen_unpack_uint(cl, start, end)) / (1 << 6);
112}
113
114static inline uint64_t
115__gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
116{
117   int size = end - start + 1;
118   int64_t val = __gen_unpack_uint(cl, start, end);
119
120   return util_sign_extend(val, size);
121}
122
123#define agx_prepare(dst, T)                                 \\
124   *(dst) = (struct AGX_ ## T){ AGX_ ## T ## _header }
125
126#define agx_pack(dst, T, name)                              \\
127   for (struct AGX_ ## T name = { AGX_ ## T ## _header }, \\
128        *_loop_terminate = (void *) (dst);                  \\
129        __builtin_expect(_loop_terminate != NULL, 1);       \\
130        ({ AGX_ ## T ## _pack((uint32_t *) (dst), &name);  \\
131           _loop_terminate = NULL; }))
132
133#define agx_unpack(fp, src, T, name)                        \\
134        struct AGX_ ## T name;                         \\
135        AGX_ ## T ## _unpack(fp, (uint8_t *)(src), &name)
136
137#define agx_print(fp, T, var, indent)                   \\
138        AGX_ ## T ## _print(fp, &(var), indent)
139
140#define agx_pixel_format_print(fp, format) do {\\
141   fprintf(fp, "%*sFormat: ", indent, ""); \\
142   \\
143   if (agx_channels_as_str((enum agx_channels)(format & 0x7F))) \\
144      fputs(agx_channels_as_str((enum agx_channels)(format & 0x7F)), fp); \\
145   else \\
146      fprintf(fp, "unknown channels %02X", format & 0x7F); \\
147   \\
148   fputs(" ", fp); \\
149   \\
150   if (agx_texture_type_as_str((enum agx_texture_type)(format >> 7))) \\
151      fputs(agx_texture_type_as_str((enum agx_texture_type)(format >> 7)), fp); \\
152   else \\
153      fprintf(fp, "unknown type %02X", format >> 7); \\
154   \\
155   fputs("\\n", fp); \\
156} while(0) \\
157
158"""
159
160def to_alphanum(name):
161    substitutions = {
162        ' ': '_',
163        '/': '_',
164        '[': '',
165        ']': '',
166        '(': '',
167        ')': '',
168        '-': '_',
169        ':': '',
170        '.': '',
171        ',': '',
172        '=': '',
173        '>': '',
174        '#': '',
175        '&': '',
176        '*': '',
177        '"': '',
178        '+': '',
179        '\'': '',
180    }
181
182    for i, j in substitutions.items():
183        name = name.replace(i, j)
184
185    return name
186
187def safe_name(name):
188    name = to_alphanum(name)
189    if not name[0].isalpha():
190        name = '_' + name
191
192    return name
193
194def prefixed_upper_name(prefix, name):
195    if prefix:
196        name = prefix + "_" + name
197    return safe_name(name).upper()
198
199def enum_name(name):
200    return "{}_{}".format(global_prefix, safe_name(name)).lower()
201
202def num_from_str(num_str):
203    if num_str.lower().startswith('0x'):
204        return int(num_str, base=16)
205    else:
206        assert(not num_str.startswith('0') and 'octals numbers not allowed')
207        return int(num_str)
208
209MODIFIERS = ["shr", "minus", "align", "log2"]
210
211def parse_modifier(modifier):
212    if modifier is None:
213        return None
214
215    for mod in MODIFIERS:
216        if modifier[0:len(mod)] == mod:
217            if mod == "log2":
218                assert(len(mod) == len(modifier))
219                return [mod]
220
221            if modifier[len(mod)] == '(' and modifier[-1] == ')':
222                ret = [mod, int(modifier[(len(mod) + 1):-1])]
223                if ret[0] == 'align':
224                    align = ret[1]
225                    # Make sure the alignment is a power of 2
226                    assert(align > 0 and not(align & (align - 1)));
227
228                return ret
229
230    print("Invalid modifier")
231    assert(False)
232
233class Field(object):
234    def __init__(self, parser, attrs):
235        self.parser = parser
236        if "name" in attrs:
237            self.name = safe_name(attrs["name"]).lower()
238            self.human_name = attrs["name"]
239
240        if ":" in str(attrs["start"]):
241            (word, bit) = attrs["start"].split(":")
242            self.start = (int(word) * 32) + int(bit)
243        else:
244            self.start = int(attrs["start"])
245
246        self.end = self.start + int(attrs["size"]) - 1
247        self.type = attrs["type"]
248
249        if self.type == 'bool' and self.start != self.end:
250            print("#error Field {} has bool type but more than one bit of size".format(self.name));
251
252        if "prefix" in attrs:
253            self.prefix = safe_name(attrs["prefix"]).upper()
254        else:
255            self.prefix = None
256
257        if "exact" in attrs:
258            self.exact = int(attrs["exact"])
259        else:
260            self.exact = None
261
262        self.default = attrs.get("default")
263
264        # Map enum values
265        if self.type in self.parser.enums and self.default is not None:
266            self.default = safe_name('{}_{}_{}'.format(global_prefix, self.type, self.default)).upper()
267
268        self.modifier  = parse_modifier(attrs.get("modifier"))
269
270    def emit_template_struct(self, dim):
271        if self.type == 'address':
272            type = 'uint64_t'
273        elif self.type == 'bool':
274            type = 'bool'
275        elif self.type in ['float', 'lod']:
276            type = 'float'
277        elif self.type in ['uint', 'hex'] and self.end - self.start > 32:
278            type = 'uint64_t'
279        elif self.type == 'int':
280            type = 'int32_t'
281        elif self.type in ['uint', 'uint/float', 'Pixel Format', 'hex']:
282            type = 'uint32_t'
283        elif self.type in self.parser.structs:
284            type = 'struct ' + self.parser.gen_prefix(safe_name(self.type.upper()))
285        elif self.type in self.parser.enums:
286            type = 'enum ' + enum_name(self.type)
287        else:
288            print("#error unhandled type: %s" % self.type)
289            type = "uint32_t"
290
291        print("   %-36s %s%s;" % (type, self.name, dim))
292
293        for value in self.values:
294            name = prefixed_upper_name(self.prefix, value.name)
295            print("#define %-40s %d" % (name, value.value))
296
297    def overlaps(self, field):
298        return self != field and max(self.start, field.start) <= min(self.end, field.end)
299
300class Group(object):
301    def __init__(self, parser, parent, start, count, label):
302        self.parser = parser
303        self.parent = parent
304        self.start = start
305        self.count = count
306        self.label = label
307        self.size = 0
308        self.length = 0
309        self.fields = []
310
311    def get_length(self):
312        # Determine number of bytes in this group.
313        calculated = max(field.end // 8 for field in self.fields) + 1 if len(self.fields) > 0 else 0
314        if self.length > 0:
315            assert(self.length >= calculated)
316        else:
317            self.length = calculated
318        return self.length
319
320
321    def emit_template_struct(self, dim):
322        if self.count == 0:
323            print("   /* variable length fields follow */")
324        else:
325            if self.count > 1:
326                dim = "%s[%d]" % (dim, self.count)
327
328            if len(self.fields) == 0:
329                print("   int dummy;")
330
331            for field in self.fields:
332                if field.exact is not None:
333                    continue
334
335                field.emit_template_struct(dim)
336
337    class Word:
338        def __init__(self):
339            self.size = 32
340            self.contributors = []
341
342    class FieldRef:
343        def __init__(self, field, path, start, end):
344            self.field = field
345            self.path = path
346            self.start = start
347            self.end = end
348
349    def collect_fields(self, fields, offset, path, all_fields):
350        for field in fields:
351            field_path = '{}{}'.format(path, field.name)
352            field_offset = offset + field.start
353
354            if field.type in self.parser.structs:
355                sub_struct = self.parser.structs[field.type]
356                self.collect_fields(sub_struct.fields, field_offset, field_path + '.', all_fields)
357                continue
358
359            start = field_offset
360            end = offset + field.end
361            all_fields.append(self.FieldRef(field, field_path, start, end))
362
363    def collect_words(self, fields, offset, path, words):
364        for field in fields:
365            field_path = '{}{}'.format(path, field.name)
366            start = offset + field.start
367
368            if field.type in self.parser.structs:
369                sub_fields = self.parser.structs[field.type].fields
370                self.collect_words(sub_fields, start, field_path + '.', words)
371                continue
372
373            end = offset + field.end
374            contributor = self.FieldRef(field, field_path, start, end)
375            first_word = contributor.start // 32
376            last_word = contributor.end // 32
377            for b in range(first_word, last_word + 1):
378                if not b in words:
379                    words[b] = self.Word()
380                words[b].contributors.append(contributor)
381
382    def emit_pack_function(self):
383        self.get_length()
384
385        words = {}
386        self.collect_words(self.fields, 0, '', words)
387
388        # Validate the modifier is lossless
389        for field in self.fields:
390            if field.modifier is None:
391                continue
392
393            assert(field.exact is None)
394
395            if field.modifier[0] == "shr":
396                shift = field.modifier[1]
397                mask = hex((1 << shift) - 1)
398                print("   assert((values->{} & {}) == 0);".format(field.name, mask))
399            elif field.modifier[0] == "minus":
400                print("   assert(values->{} >= {});".format(field.name, field.modifier[1]))
401            elif field.modifier[0] == "log2":
402                print("   assert(util_is_power_of_two_nonzero(values->{}));".format(field.name))
403
404        for index in range(self.length // 4):
405            # Handle MBZ words
406            if not index in words:
407                print("   cl[%2d] = 0;" % index)
408                continue
409
410            word = words[index]
411
412            word_start = index * 32
413
414            v = None
415            prefix = "   cl[%2d] =" % index
416
417            for contributor in word.contributors:
418                field = contributor.field
419                name = field.name
420                start = contributor.start
421                end = contributor.end
422                contrib_word_start = (start // 32) * 32
423                start -= contrib_word_start
424                end -= contrib_word_start
425
426                value = str(field.exact) if field.exact is not None else "values->{}".format(contributor.path)
427                if field.modifier is not None:
428                    if field.modifier[0] == "shr":
429                        value = "{} >> {}".format(value, field.modifier[1])
430                    elif field.modifier[0] == "minus":
431                        value = "{} - {}".format(value, field.modifier[1])
432                    elif field.modifier[0] == "align":
433                        value = "ALIGN_POT({}, {})".format(value, field.modifier[1])
434                    elif field.modifier[0] == "log2":
435                        value = "util_logbase2({})".format(value)
436
437                if field.type in ["uint", "hex", "Pixel Format", "address"]:
438                    s = "__gen_uint(%s, %d, %d)" % \
439                        (value, start, end)
440                elif field.type in self.parser.enums:
441                    s = "__gen_uint(%s, %d, %d)" % \
442                        (value, start, end)
443                elif field.type == "int":
444                    s = "__gen_sint(%s, %d, %d)" % \
445                        (value, start, end)
446                elif field.type == "bool":
447                    s = "__gen_uint(%s, %d, %d)" % \
448                        (value, start, end)
449                elif field.type == "float":
450                    assert(start == 0 and end == 31)
451                    s = "__gen_uint(fui({}), 0, 32)".format(value)
452                elif field.type == "lod":
453                    assert(end - start + 1 == 10)
454                    s = "__gen_uint(__float_to_lod(%s), %d, %d)" % (value, start, end)
455                else:
456                    s = "#error unhandled field {}, type {}".format(contributor.path, field.type)
457
458                if not s == None:
459                    shift = word_start - contrib_word_start
460                    if shift:
461                        s = "%s >> %d" % (s, shift)
462
463                    if contributor == word.contributors[-1]:
464                        print("%s %s;" % (prefix, s))
465                    else:
466                        print("%s %s |" % (prefix, s))
467                    prefix = "           "
468
469            continue
470
471    # Given a field (start, end) contained in word `index`, generate the 32-bit
472    # mask of present bits relative to the word
473    def mask_for_word(self, index, start, end):
474        field_word_start = index * 32
475        start -= field_word_start
476        end -= field_word_start
477        # Cap multiword at one word
478        start = max(start, 0)
479        end = min(end, 32 - 1)
480        count = (end - start + 1)
481        return (((1 << count) - 1) << start)
482
483    def emit_unpack_function(self):
484        # First, verify there is no garbage in unused bits
485        words = {}
486        self.collect_words(self.fields, 0, '', words)
487
488        for index in range(self.length // 4):
489            base = index * 32
490            word = words.get(index, self.Word())
491            masks = [self.mask_for_word(index, c.start, c.end) for c in word.contributors]
492            mask = reduce(lambda x,y: x | y, masks, 0)
493
494            ALL_ONES = 0xffffffff
495
496            if mask != ALL_ONES:
497                TMPL = '   if (((const uint32_t *) cl)[{}] & {}) fprintf(fp, "XXX: Unknown field of {} unpacked at word {}: got %X, bad mask %X\\n", ((const uint32_t *) cl)[{}], ((const uint32_t *) cl)[{}] & {});'
498                print(TMPL.format(index, hex(mask ^ ALL_ONES), self.label, index, index, index, hex(mask ^ ALL_ONES)))
499
500        fieldrefs = []
501        self.collect_fields(self.fields, 0, '', fieldrefs)
502        for fieldref in fieldrefs:
503            field = fieldref.field
504            convert = None
505
506            args = []
507            args.append('cl')
508            args.append(str(fieldref.start))
509            args.append(str(fieldref.end))
510
511            if field.type in set(["uint", "uint/float", "address", "Pixel Format", "hex"]) | self.parser.enums:
512                convert = "__gen_unpack_uint"
513            elif field.type == "int":
514                convert = "__gen_unpack_sint"
515            elif field.type == "bool":
516                convert = "__gen_unpack_uint"
517            elif field.type == "float":
518                convert = "__gen_unpack_float"
519            elif field.type == "lod":
520                convert = "__gen_unpack_lod"
521            else:
522                s = "/* unhandled field %s, type %s */\n" % (field.name, field.type)
523
524            suffix = ""
525            prefix = ""
526            if field.modifier:
527                if field.modifier[0] == "minus":
528                    suffix = " + {}".format(field.modifier[1])
529                elif field.modifier[0] == "shr":
530                    suffix = " << {}".format(field.modifier[1])
531                if field.modifier[0] == "log2":
532                    prefix = "1 << "
533
534            if field.type in self.parser.enums:
535                prefix = f"(enum {enum_name(field.type)}) {prefix}"
536
537            decoded = '{}{}({}){}'.format(prefix, convert, ', '.join(args), suffix)
538
539            print('   values->{} = {};'.format(fieldref.path, decoded))
540            if field.modifier and field.modifier[0] == "align":
541                mask = hex(field.modifier[1] - 1)
542                print('   assert(!(values->{} & {}));'.format(fieldref.path, mask))
543
544    def emit_print_function(self):
545        for field in self.fields:
546            convert = None
547            name, val = field.human_name, 'values->{}'.format(field.name)
548
549            if field.type in self.parser.structs:
550                pack_name = self.parser.gen_prefix(safe_name(field.type)).upper()
551                print('   fprintf(fp, "%*s{}:\\n", indent, "");'.format(field.human_name))
552                print("   {}_print(fp, &values->{}, indent + 2);".format(pack_name, field.name))
553            elif field.type == "address":
554                # TODO resolve to name
555                print('   fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val))
556            elif field.type in self.parser.enums:
557                print('   if ({}_as_str({}))'.format(enum_name(field.type), val))
558                print('     fprintf(fp, "%*s{}: %s\\n", indent, "", {}_as_str({}));'.format(name, enum_name(field.type), val))
559                print('    else')
560                print('     fprintf(fp, "%*s{}: unknown %X (XXX)\\n", indent, "", {});'.format(name, val))
561            elif field.type == "int":
562                print('   fprintf(fp, "%*s{}: %d\\n", indent, "", {});'.format(name, val))
563            elif field.type == "bool":
564                print('   fprintf(fp, "%*s{}: %s\\n", indent, "", {} ? "true" : "false");'.format(name, val))
565            elif field.type in ["float", "lod"]:
566                print('   fprintf(fp, "%*s{}: %f\\n", indent, "", {});'.format(name, val))
567            elif field.type in ["uint", "hex"] and (field.end - field.start) >= 32:
568                print('   fprintf(fp, "%*s{}: 0x%" PRIx64 "\\n", indent, "", {});'.format(name, val))
569            elif field.type == "hex":
570                print('   fprintf(fp, "%*s{}: 0x%" PRIx32 "\\n", indent, "", {});'.format(name, val))
571            elif field.type in "Pixel Format":
572                print('   agx_pixel_format_print(fp, {});'.format(val))
573            elif field.type == "uint/float":
574                print('   fprintf(fp, "%*s{}: 0x%X (%f)\\n", indent, "", {}, uif({}));'.format(name, val, val))
575            else:
576                print('   fprintf(fp, "%*s{}: %u\\n", indent, "", {});'.format(name, val))
577
578class Value(object):
579    def __init__(self, attrs):
580        self.name = attrs["name"]
581        self.value = int(attrs["value"], 0)
582
583class Parser(object):
584    def __init__(self):
585        self.parser = xml.parsers.expat.ParserCreate()
586        self.parser.StartElementHandler = self.start_element
587        self.parser.EndElementHandler = self.end_element
588
589        self.struct = None
590        self.structs = {}
591        # Set of enum names we've seen.
592        self.enums = set()
593
594    def gen_prefix(self, name):
595        return '{}_{}'.format(global_prefix.upper(), name)
596
597    def start_element(self, name, attrs):
598        if name == "agxml":
599            print(pack_header)
600        elif name == "struct":
601            name = attrs["name"]
602            self.no_direct_packing = attrs.get("no-direct-packing", False)
603            object_name = self.gen_prefix(safe_name(name.upper()))
604            self.struct = object_name
605
606            self.group = Group(self, None, 0, 1, name)
607            if "size" in attrs:
608                self.group.length = int(attrs["size"])
609            self.group.align = int(attrs["align"]) if "align" in attrs else None
610            self.structs[attrs["name"]] = self.group
611        elif name == "field":
612            self.group.fields.append(Field(self, attrs))
613            self.values = []
614        elif name == "enum":
615            self.values = []
616            self.enum = safe_name(attrs["name"])
617            self.enums.add(attrs["name"])
618            if "prefix" in attrs:
619                self.prefix = attrs["prefix"]
620            else:
621                self.prefix= None
622        elif name == "value":
623            self.values.append(Value(attrs))
624
625    def end_element(self, name):
626        if name == "struct":
627            self.emit_struct()
628            self.struct = None
629            self.group = None
630        elif name  == "field":
631            self.group.fields[-1].values = self.values
632        elif name  == "enum":
633            self.emit_enum()
634            self.enum = None
635        elif name == "agxml":
636            print('#endif')
637
638    def emit_header(self, name):
639        default_fields = []
640        for field in self.group.fields:
641            if not type(field) is Field:
642                continue
643            if field.default is not None:
644                default_fields.append("   .{} = {}".format(field.name, field.default))
645            elif field.type in self.structs:
646                default_fields.append("   .{} = {{ {}_header }}".format(field.name, self.gen_prefix(safe_name(field.type.upper()))))
647
648        print('#define %-40s\\' % (name + '_header'))
649        if default_fields:
650            print(",  \\\n".join(default_fields))
651        else:
652            print('   0')
653        print('')
654
655    def emit_template_struct(self, name, group):
656        print("struct %s {" % name)
657        group.emit_template_struct("")
658        print("};\n")
659
660    def emit_pack_function(self, name, group):
661        print("static inline void\n%s_pack(uint32_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %
662              (name, ' ' * (len(name) + 6), name))
663
664        group.emit_pack_function()
665
666        print("}\n\n")
667
668        print('#define {} {}'.format (name + "_LENGTH", self.group.length))
669        if self.group.align != None:
670            print('#define {} {}'.format (name + "_ALIGN", self.group.align))
671        print('struct {}_packed {{ uint32_t opaque[{}]; }};'.format(name.lower(), self.group.length // 4))
672
673    def emit_unpack_function(self, name, group):
674        print("static inline void")
675        print("%s_unpack(FILE *fp, const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
676              (name.upper(), ' ' * (len(name) + 8), name))
677
678        group.emit_unpack_function()
679
680        print("}\n")
681
682    def emit_print_function(self, name, group):
683        print("static inline void")
684        print("{}_print(FILE *fp, const struct {} * values, unsigned indent)\n{{".format(name.upper(), name))
685
686        group.emit_print_function()
687
688        print("}\n")
689
690    def emit_struct(self):
691        name = self.struct
692
693        self.emit_template_struct(self.struct, self.group)
694        self.emit_header(name)
695        if self.no_direct_packing == False:
696            self.emit_pack_function(self.struct, self.group)
697            self.emit_unpack_function(self.struct, self.group)
698        self.emit_print_function(self.struct, self.group)
699
700    def enum_prefix(self, name):
701        return
702
703    def emit_enum(self):
704        e_name = enum_name(self.enum)
705        prefix = e_name if self.enum != 'Format' else global_prefix
706        print('enum {} {{'.format(e_name))
707
708        for value in self.values:
709            name = '{}_{}'.format(prefix, value.name)
710            name = safe_name(name).upper()
711            print('        % -36s = %6d,' % (name, value.value))
712        print('};\n')
713
714        print("static inline const char *")
715        print("{}_as_str(enum {} imm)\n{{".format(e_name.lower(), e_name))
716        print("    switch (imm) {")
717        for value in self.values:
718            name = '{}_{}'.format(prefix, value.name)
719            name = safe_name(name).upper()
720            print('    case {}: return "{}";'.format(name, value.name))
721        print('    default: break;')
722        print("    }")
723        print("    return NULL;")
724        print("}\n")
725
726    def parse(self, filename):
727        file = open(filename, "rb")
728        self.parser.ParseFile(file)
729        file.close()
730
731if len(sys.argv) < 2:
732    print("No input xml file specified")
733    sys.exit(1)
734
735input_file = sys.argv[1]
736
737p = Parser()
738p.parse(input_file)
739