1#!/usr/bin/env python3
2# Copyright 2023 The Fuchsia Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import json
7import sys
8
9def usage():
10    print(
11        'Usage:\n'
12        '  regen.py INPUT OUT.in OUT.attrib\n'
13        '    INPUT       json file containing the magma interface definition\n'
14        '    OUT.in      destination path for the magma interface file to generate\n'
15        '    OUT.attrib  destination path for the magma interface file to generate\n'
16        '  Example: ./regen.py ./magma.json ./magma.in ./magma.attrib\n'
17        '  Generates magma interface and attrib files based on a provided json definition.')
18
19# returns a string that will block presubmit
20def dnsstr():
21    return (
22        'DO '
23        'NOT '
24        'SUBMIT'
25    )
26
27def format_export(export):
28    args = [f'{arg["type"]} {arg["name"]}' for arg in export["arguments"]]
29    return f'MAGMA({export["type"]}, {export["name"]}, {", ".join(args)})'
30
31def if_header():
32    return (
33        f'# !!!! {dnsstr()} !!!!\n'
34        '#   This interface file was generated using the magma\n'
35        '#   definition file. Some methods with nested structs must\n'
36        '#   be manually serialized/deserialized and so modifications\n'
37        '#   must be made to those method signatures prior to running\n'
38        '#   emugen!\n'
39        f'# !!!! {dnsstr()} !!!!\n'
40        '\n'
41    )
42
43def attrib_header():
44    return (
45        f'# !!!! {dnsstr()} !!!!\n'
46        '#   This attrib file was generated using HEURISTICS based on\n'
47        '#   the magma definition file. It must be manually verified\n'
48        '#   prior to submission!\n'
49        f'# !!!! {dnsstr()} !!!!\n'
50        '\n'
51        '# For documentation on the .attrib file format, see:\n'
52        '# android/android-emugl/host/tools/emugen/README\n'
53        '\n'
54        'GLOBAL\n'
55	    '\tbase_opcode 100000\n'
56	    '\tencoder_headers <stdint.h>\n'
57    )
58
59def format_attribs(export):
60    out_args = [arg for arg in export["arguments"] if arg["name"].endswith('_out')]
61    if len(out_args) == 0:
62        return None
63    ret = f'{export["name"]}\n'
64    for arg in out_args:
65        ret += f'\tdir {arg["name"]} out\n'
66        ret += f'\tlen {arg["name"]} sizeof({arg["type"][:-1]})\n'
67    return ret
68
69def main():
70    if (len(sys.argv) != 4):
71        usage()
72        return 2
73    try:
74        with open(sys.argv[1], 'r') as file:
75            with open(sys.argv[2], 'w') as dest_in:
76                with open(sys.argv[3], 'w') as dest_attrib:
77                    magma = json.load(file)['magma-interface']
78                    lines = [format_export(e) for e in magma['exports']]
79                    dest_in.write(if_header())
80                    dest_in.write('\n'.join(lines))
81                    dest_attrib.write(attrib_header())
82                    for export in magma['exports']:
83                        attribs = format_attribs(export)
84                        if (attribs):
85                            dest_attrib.write('\n' + attribs)
86
87    except Exception as e:
88        print(f'Error accessing files: {e}')
89        usage()
90        return 1
91
92if __name__ == '__main__':
93    sys.exit(main())
94