xref: /aosp_15_r20/external/mesa3d/src/nouveau/headers/class_parser.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#! /usr/bin/env python3
2*61046927SAndroid Build Coastguard Worker
3*61046927SAndroid Build Coastguard Worker# script to parse nvidia CL headers and generate inlines to be used in pushbuffer encoding.
4*61046927SAndroid Build Coastguard Worker# probably needs python3.9
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Workerimport argparse
7*61046927SAndroid Build Coastguard Workerimport os.path
8*61046927SAndroid Build Coastguard Workerimport sys
9*61046927SAndroid Build Coastguard Workerimport re
10*61046927SAndroid Build Coastguard Workerimport subprocess
11*61046927SAndroid Build Coastguard Worker
12*61046927SAndroid Build Coastguard Workerfrom mako.template import Template
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard WorkerMETHOD_ARRAY_SIZES = {
15*61046927SAndroid Build Coastguard Worker    'BIND_GROUP_CONSTANT_BUFFER'                        : 16,
16*61046927SAndroid Build Coastguard Worker    'CALL_MME_DATA'                                     : 256,
17*61046927SAndroid Build Coastguard Worker    'CALL_MME_MACRO'                                    : 256,
18*61046927SAndroid Build Coastguard Worker    'LOAD_CONSTANT_BUFFER'                              : 16,
19*61046927SAndroid Build Coastguard Worker    'LOAD_INLINE_QMD_DATA'                              : 64,
20*61046927SAndroid Build Coastguard Worker    'SET_ANTI_ALIAS_SAMPLE_POSITIONS'                   : 4,
21*61046927SAndroid Build Coastguard Worker    'SET_BLEND'                                         : 8,
22*61046927SAndroid Build Coastguard Worker    'SET_BLEND_PER_TARGET_*'                            : 8,
23*61046927SAndroid Build Coastguard Worker    'SET_COLOR_TARGET_*'                                : 8,
24*61046927SAndroid Build Coastguard Worker    'SET_COLOR_COMPRESSION'                             : 8,
25*61046927SAndroid Build Coastguard Worker    'SET_COLOR_CLEAR_VALUE'                             : 4,
26*61046927SAndroid Build Coastguard Worker    'SET_CT_WRITE'                                      : 8,
27*61046927SAndroid Build Coastguard Worker    'SET_MME_SHADOW_SCRATCH'                            : 256,
28*61046927SAndroid Build Coastguard Worker    'SET_PIPELINE_*'                                    : 6,
29*61046927SAndroid Build Coastguard Worker    'SET_SCG_COMPUTE_SCHEDULING_PARAMETERS'             : 16,
30*61046927SAndroid Build Coastguard Worker    'SET_SCISSOR_*'                                     : 16,
31*61046927SAndroid Build Coastguard Worker    'SET_SHADER_PERFORMANCE_SNAPSHOT_COUNTER_VALUE*'    : 8,
32*61046927SAndroid Build Coastguard Worker    'SET_SHADER_PERFORMANCE_COUNTER_VALUE*'             : 8,
33*61046927SAndroid Build Coastguard Worker    'SET_SHADER_PERFORMANCE_COUNTER_EVENT'              : 8,
34*61046927SAndroid Build Coastguard Worker    'SET_SHADER_PERFORMANCE_COUNTER_CONTROL_A'          : 8,
35*61046927SAndroid Build Coastguard Worker    'SET_SHADER_PERFORMANCE_COUNTER_CONTROL_B'          : 8,
36*61046927SAndroid Build Coastguard Worker    'SET_STREAM_OUT_BUFFER_*'                           : 4,
37*61046927SAndroid Build Coastguard Worker    'SET_STREAM_OUT_CONTROL_*'                          : 4,
38*61046927SAndroid Build Coastguard Worker    'SET_VIEWPORT_*'                                    : 16,
39*61046927SAndroid Build Coastguard Worker    'SET_VERTEX_ATTRIBUTE_*'                            : 16,
40*61046927SAndroid Build Coastguard Worker    'SET_VERTEX_STREAM_*'                               : 16,
41*61046927SAndroid Build Coastguard Worker}
42*61046927SAndroid Build Coastguard Worker
43*61046927SAndroid Build Coastguard WorkerMETHOD_IS_FLOAT = [
44*61046927SAndroid Build Coastguard Worker    'SET_BLEND_CONST_*',
45*61046927SAndroid Build Coastguard Worker    'SET_DEPTH_BIAS',
46*61046927SAndroid Build Coastguard Worker    'SET_SLOPE_SCALE_DEPTH_BIAS',
47*61046927SAndroid Build Coastguard Worker    'SET_DEPTH_BIAS_CLAMP',
48*61046927SAndroid Build Coastguard Worker    'SET_DEPTH_BOUNDS_M*',
49*61046927SAndroid Build Coastguard Worker    'SET_LINE_WIDTH_FLOAT',
50*61046927SAndroid Build Coastguard Worker    'SET_ALIASED_LINE_WIDTH_FLOAT',
51*61046927SAndroid Build Coastguard Worker    'SET_VIEWPORT_SCALE_*',
52*61046927SAndroid Build Coastguard Worker    'SET_VIEWPORT_OFFSET_*',
53*61046927SAndroid Build Coastguard Worker    'SET_VIEWPORT_CLIP_MIN_Z',
54*61046927SAndroid Build Coastguard Worker    'SET_VIEWPORT_CLIP_MAX_Z',
55*61046927SAndroid Build Coastguard Worker    'SET_Z_CLEAR_VALUE',
56*61046927SAndroid Build Coastguard Worker]
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard WorkerTEMPLATE_H = Template("""\
59*61046927SAndroid Build Coastguard Worker/* parsed class ${nvcl} */
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker#include "nvtypes.h"
62*61046927SAndroid Build Coastguard Worker#include "${clheader}"
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker#include <assert.h>
65*61046927SAndroid Build Coastguard Worker#include <stdio.h>
66*61046927SAndroid Build Coastguard Worker#include "util/u_math.h"
67*61046927SAndroid Build Coastguard Worker
68*61046927SAndroid Build Coastguard Worker%for mthd in mthddict:
69*61046927SAndroid Build Coastguard Workerstruct nv_${nvcl.lower()}_${mthd} {
70*61046927SAndroid Build Coastguard Worker  %for field_name in mthddict[mthd].field_name_start:
71*61046927SAndroid Build Coastguard Worker    uint32_t ${field_name.lower()};
72*61046927SAndroid Build Coastguard Worker  %endfor
73*61046927SAndroid Build Coastguard Worker};
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Workerstatic inline void
76*61046927SAndroid Build Coastguard Worker__${nvcl}_${mthd}(uint32_t *val_out, struct nv_${nvcl.lower()}_${mthd} st)
77*61046927SAndroid Build Coastguard Worker{
78*61046927SAndroid Build Coastguard Worker    uint32_t val = 0;
79*61046927SAndroid Build Coastguard Worker  %for field_name in mthddict[mthd].field_name_start:
80*61046927SAndroid Build Coastguard Worker    <%
81*61046927SAndroid Build Coastguard Worker        field_start = int(mthddict[mthd].field_name_start[field_name])
82*61046927SAndroid Build Coastguard Worker        field_end = int(mthddict[mthd].field_name_end[field_name])
83*61046927SAndroid Build Coastguard Worker        field_width = field_end - field_start + 1
84*61046927SAndroid Build Coastguard Worker    %>
85*61046927SAndroid Build Coastguard Worker    %if field_width == 32:
86*61046927SAndroid Build Coastguard Worker    val |= st.${field_name.lower()};
87*61046927SAndroid Build Coastguard Worker    %else:
88*61046927SAndroid Build Coastguard Worker    assert(st.${field_name.lower()} < (1ULL << ${field_width}));
89*61046927SAndroid Build Coastguard Worker    val |= st.${field_name.lower()} << ${field_start};
90*61046927SAndroid Build Coastguard Worker    %endif
91*61046927SAndroid Build Coastguard Worker  %endfor
92*61046927SAndroid Build Coastguard Worker    *val_out = val;
93*61046927SAndroid Build Coastguard Worker}
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker#define V_${nvcl}_${mthd}(val, args...) { ${bs}
96*61046927SAndroid Build Coastguard Worker  %for field_name in mthddict[mthd].field_name_start:
97*61046927SAndroid Build Coastguard Worker    %for d in mthddict[mthd].field_defs[field_name]:
98*61046927SAndroid Build Coastguard Worker    UNUSED uint32_t ${field_name}_${d} = ${nvcl}_${mthd}_${field_name}_${d}; ${bs}
99*61046927SAndroid Build Coastguard Worker    %endfor
100*61046927SAndroid Build Coastguard Worker  %endfor
101*61046927SAndroid Build Coastguard Worker  %if len(mthddict[mthd].field_name_start) > 1:
102*61046927SAndroid Build Coastguard Worker    struct nv_${nvcl.lower()}_${mthd} __data = args; ${bs}
103*61046927SAndroid Build Coastguard Worker  %else:
104*61046927SAndroid Build Coastguard Worker<% field_name = next(iter(mthddict[mthd].field_name_start)).lower() %>\
105*61046927SAndroid Build Coastguard Worker    struct nv_${nvcl.lower()}_${mthd} __data = { .${field_name} = (args) }; ${bs}
106*61046927SAndroid Build Coastguard Worker  %endif
107*61046927SAndroid Build Coastguard Worker    __${nvcl}_${mthd}(&val, __data); ${bs}
108*61046927SAndroid Build Coastguard Worker}
109*61046927SAndroid Build Coastguard Worker
110*61046927SAndroid Build Coastguard Worker%if mthddict[mthd].is_array:
111*61046927SAndroid Build Coastguard Worker#define VA_${nvcl}_${mthd}(i) V_${nvcl}_${mthd}
112*61046927SAndroid Build Coastguard Worker%else:
113*61046927SAndroid Build Coastguard Worker#define VA_${nvcl}_${mthd} V_${nvcl}_${mthd}
114*61046927SAndroid Build Coastguard Worker%endif
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker%if mthddict[mthd].is_array:
117*61046927SAndroid Build Coastguard Worker#define P_${nvcl}_${mthd}(push, idx, args...) do { ${bs}
118*61046927SAndroid Build Coastguard Worker%else:
119*61046927SAndroid Build Coastguard Worker#define P_${nvcl}_${mthd}(push, args...) do { ${bs}
120*61046927SAndroid Build Coastguard Worker%endif
121*61046927SAndroid Build Coastguard Worker  %for field_name in mthddict[mthd].field_name_start:
122*61046927SAndroid Build Coastguard Worker    %for d in mthddict[mthd].field_defs[field_name]:
123*61046927SAndroid Build Coastguard Worker    UNUSED uint32_t ${field_name}_${d} = ${nvcl}_${mthd}_${field_name}_${d}; ${bs}
124*61046927SAndroid Build Coastguard Worker    %endfor
125*61046927SAndroid Build Coastguard Worker  %endfor
126*61046927SAndroid Build Coastguard Worker    uint32_t nvk_p_ret; ${bs}
127*61046927SAndroid Build Coastguard Worker    V_${nvcl}_${mthd}(nvk_p_ret, args); ${bs}
128*61046927SAndroid Build Coastguard Worker    %if mthddict[mthd].is_array:
129*61046927SAndroid Build Coastguard Worker    nv_push_val(push, ${nvcl}_${mthd}(idx), nvk_p_ret); ${bs}
130*61046927SAndroid Build Coastguard Worker    %else:
131*61046927SAndroid Build Coastguard Worker    nv_push_val(push, ${nvcl}_${mthd}, nvk_p_ret); ${bs}
132*61046927SAndroid Build Coastguard Worker    %endif
133*61046927SAndroid Build Coastguard Worker} while(0)
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker%endfor
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Workerconst char *P_PARSE_${nvcl}_MTHD(uint16_t idx);
138*61046927SAndroid Build Coastguard Workervoid P_DUMP_${nvcl}_MTHD_DATA(FILE *fp, uint16_t idx, uint32_t data,
139*61046927SAndroid Build Coastguard Worker                              const char *prefix);
140*61046927SAndroid Build Coastguard Worker""")
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard WorkerTEMPLATE_C = Template("""\
143*61046927SAndroid Build Coastguard Worker#include "${header}"
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker#include <stdio.h>
146*61046927SAndroid Build Coastguard Worker
147*61046927SAndroid Build Coastguard Workerconst char*
148*61046927SAndroid Build Coastguard WorkerP_PARSE_${nvcl}_MTHD(uint16_t idx)
149*61046927SAndroid Build Coastguard Worker{
150*61046927SAndroid Build Coastguard Worker    switch (idx) {
151*61046927SAndroid Build Coastguard Worker%for mthd in mthddict:
152*61046927SAndroid Build Coastguard Worker  %if mthddict[mthd].is_array and mthddict[mthd].array_size == 0:
153*61046927SAndroid Build Coastguard Worker    <% continue %>
154*61046927SAndroid Build Coastguard Worker  %endif
155*61046927SAndroid Build Coastguard Worker  %if mthddict[mthd].is_array:
156*61046927SAndroid Build Coastguard Worker    %for i in range(mthddict[mthd].array_size):
157*61046927SAndroid Build Coastguard Worker    case ${nvcl}_${mthd}(${i}):
158*61046927SAndroid Build Coastguard Worker        return "${nvcl}_${mthd}(${i})";
159*61046927SAndroid Build Coastguard Worker    %endfor
160*61046927SAndroid Build Coastguard Worker  % else:
161*61046927SAndroid Build Coastguard Worker    case ${nvcl}_${mthd}:
162*61046927SAndroid Build Coastguard Worker        return "${nvcl}_${mthd}";
163*61046927SAndroid Build Coastguard Worker  %endif
164*61046927SAndroid Build Coastguard Worker%endfor
165*61046927SAndroid Build Coastguard Worker    default:
166*61046927SAndroid Build Coastguard Worker        return "unknown method";
167*61046927SAndroid Build Coastguard Worker    }
168*61046927SAndroid Build Coastguard Worker}
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Workervoid
171*61046927SAndroid Build Coastguard WorkerP_DUMP_${nvcl}_MTHD_DATA(FILE *fp, uint16_t idx, uint32_t data,
172*61046927SAndroid Build Coastguard Worker                         const char *prefix)
173*61046927SAndroid Build Coastguard Worker{
174*61046927SAndroid Build Coastguard Worker    uint32_t parsed;
175*61046927SAndroid Build Coastguard Worker    switch (idx) {
176*61046927SAndroid Build Coastguard Worker%for mthd in mthddict:
177*61046927SAndroid Build Coastguard Worker  %if mthddict[mthd].is_array and mthddict[mthd].array_size == 0:
178*61046927SAndroid Build Coastguard Worker    <% continue %>
179*61046927SAndroid Build Coastguard Worker  %endif
180*61046927SAndroid Build Coastguard Worker  %if mthddict[mthd].is_array:
181*61046927SAndroid Build Coastguard Worker    %for i in range(mthddict[mthd].array_size):
182*61046927SAndroid Build Coastguard Worker    case ${nvcl}_${mthd}(${i}):
183*61046927SAndroid Build Coastguard Worker    %endfor
184*61046927SAndroid Build Coastguard Worker  % else:
185*61046927SAndroid Build Coastguard Worker    case ${nvcl}_${mthd}:
186*61046927SAndroid Build Coastguard Worker  %endif
187*61046927SAndroid Build Coastguard Worker  %for field_name in mthddict[mthd].field_name_start:
188*61046927SAndroid Build Coastguard Worker    <%
189*61046927SAndroid Build Coastguard Worker        field_start = int(mthddict[mthd].field_name_start[field_name])
190*61046927SAndroid Build Coastguard Worker        field_end = int(mthddict[mthd].field_name_end[field_name])
191*61046927SAndroid Build Coastguard Worker        field_width = field_end - field_start + 1
192*61046927SAndroid Build Coastguard Worker    %>
193*61046927SAndroid Build Coastguard Worker    %if field_width == 32:
194*61046927SAndroid Build Coastguard Worker        parsed = data;
195*61046927SAndroid Build Coastguard Worker    %else:
196*61046927SAndroid Build Coastguard Worker        parsed = (data >> ${field_start}) & ((1u << ${field_width}) - 1);
197*61046927SAndroid Build Coastguard Worker    %endif
198*61046927SAndroid Build Coastguard Worker        fprintf(fp, "%s.${field_name} = ", prefix);
199*61046927SAndroid Build Coastguard Worker    %if len(mthddict[mthd].field_defs[field_name]):
200*61046927SAndroid Build Coastguard Worker        switch (parsed) {
201*61046927SAndroid Build Coastguard Worker      %for d in mthddict[mthd].field_defs[field_name]:
202*61046927SAndroid Build Coastguard Worker        case ${nvcl}_${mthd}_${field_name}_${d}:
203*61046927SAndroid Build Coastguard Worker            fprintf(fp, "${d}${bs}n");
204*61046927SAndroid Build Coastguard Worker            break;
205*61046927SAndroid Build Coastguard Worker      %endfor
206*61046927SAndroid Build Coastguard Worker        default:
207*61046927SAndroid Build Coastguard Worker            fprintf(fp, "0x%x${bs}n", parsed);
208*61046927SAndroid Build Coastguard Worker            break;
209*61046927SAndroid Build Coastguard Worker        }
210*61046927SAndroid Build Coastguard Worker    %else:
211*61046927SAndroid Build Coastguard Worker      %if mthddict[mthd].is_float:
212*61046927SAndroid Build Coastguard Worker        fprintf(fp, "%ff (0x%x)${bs}n", uif(parsed), parsed);
213*61046927SAndroid Build Coastguard Worker      %else:
214*61046927SAndroid Build Coastguard Worker        fprintf(fp, "(0x%x)${bs}n", parsed);
215*61046927SAndroid Build Coastguard Worker      %endif
216*61046927SAndroid Build Coastguard Worker    %endif
217*61046927SAndroid Build Coastguard Worker  %endfor
218*61046927SAndroid Build Coastguard Worker        break;
219*61046927SAndroid Build Coastguard Worker%endfor
220*61046927SAndroid Build Coastguard Worker    default:
221*61046927SAndroid Build Coastguard Worker        fprintf(fp, "%s.VALUE = 0x%x${bs}n", prefix, data);
222*61046927SAndroid Build Coastguard Worker        break;
223*61046927SAndroid Build Coastguard Worker    }
224*61046927SAndroid Build Coastguard Worker}
225*61046927SAndroid Build Coastguard Worker""")
226*61046927SAndroid Build Coastguard Worker
227*61046927SAndroid Build Coastguard WorkerTEMPLATE_RS = Template("""\
228*61046927SAndroid Build Coastguard Worker// parsed class ${nvcl}
229*61046927SAndroid Build Coastguard Worker
230*61046927SAndroid Build Coastguard Worker% if version is not None:
231*61046927SAndroid Build Coastguard Workerpub const ${version[0]}: u16 = ${version[1]};
232*61046927SAndroid Build Coastguard Worker% endif
233*61046927SAndroid Build Coastguard Worker""")
234*61046927SAndroid Build Coastguard Worker
235*61046927SAndroid Build Coastguard WorkerTEMPLATE_RS_MTHD = Template("""\
236*61046927SAndroid Build Coastguard Worker
237*61046927SAndroid Build Coastguard Worker// parsed class ${nvcl}
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Worker## Write out the methods in Rust
240*61046927SAndroid Build Coastguard Worker%for mthd_name, mthd in mthddict.items():
241*61046927SAndroid Build Coastguard Worker## Identify the field type.
242*61046927SAndroid Build Coastguard Worker<%
243*61046927SAndroid Build Coastguard Workerfor field_name, field_value in mthd.field_defs.items():
244*61046927SAndroid Build Coastguard Worker    if field_name == 'V' and len(field_value) > 0:
245*61046927SAndroid Build Coastguard Worker        mthd.field_rs_types[field_name] = to_camel(mthd_name) + 'V'
246*61046927SAndroid Build Coastguard Worker        mthd.field_is_rs_enum[field_name] = True
247*61046927SAndroid Build Coastguard Worker    elif len(field_value) > 0:
248*61046927SAndroid Build Coastguard Worker        assert(field_name != "")
249*61046927SAndroid Build Coastguard Worker        mthd.field_rs_types[field_name] = to_camel(mthd_name) + to_camel(field_name)
250*61046927SAndroid Build Coastguard Worker        mthd.field_is_rs_enum[field_name] = True
251*61046927SAndroid Build Coastguard Worker    elif mthd.is_float:
252*61046927SAndroid Build Coastguard Worker        mthd.field_rs_types[field_name] = "f32"
253*61046927SAndroid Build Coastguard Worker        mthd.field_is_rs_enum[field_name] = False
254*61046927SAndroid Build Coastguard Worker    else:
255*61046927SAndroid Build Coastguard Worker        mthd.field_rs_types[field_name] = "u32"
256*61046927SAndroid Build Coastguard Worker        mthd.field_is_rs_enum[field_name] = False
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker    # TRUE and FALSE are special cases.
259*61046927SAndroid Build Coastguard Worker    if len(field_value) == 2:
260*61046927SAndroid Build Coastguard Worker        for enumerant in field_value:
261*61046927SAndroid Build Coastguard Worker            if enumerant.lower() == 'true' or enumerant.lower() == 'false':
262*61046927SAndroid Build Coastguard Worker                mthd.field_rs_types[field_name] = "bool"
263*61046927SAndroid Build Coastguard Worker                mthd.field_is_rs_enum[field_name] = False
264*61046927SAndroid Build Coastguard Worker                break
265*61046927SAndroid Build Coastguard Worker%>
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker## If there are a range of values for a field, we define an enum.
268*61046927SAndroid Build Coastguard Worker%for field_name in mthd.field_defs:
269*61046927SAndroid Build Coastguard Worker    %if mthd.field_is_rs_enum[field_name]:
270*61046927SAndroid Build Coastguard Worker#[repr(u16)]
271*61046927SAndroid Build Coastguard Worker#[derive(Copy, Clone, Debug, PartialEq)]
272*61046927SAndroid Build Coastguard Workerpub enum ${mthd.field_rs_types[field_name]} {
273*61046927SAndroid Build Coastguard Worker    %for field_name, field_value in mthd.field_defs[field_name].items():
274*61046927SAndroid Build Coastguard Worker    ${to_camel(rs_field_name(field_name))} = ${field_value.lower()},
275*61046927SAndroid Build Coastguard Worker    %endfor
276*61046927SAndroid Build Coastguard Worker}
277*61046927SAndroid Build Coastguard Worker    %endif
278*61046927SAndroid Build Coastguard Worker%endfor
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker## We also define a struct with the fields for the mthd.
281*61046927SAndroid Build Coastguard Worker#[derive(Copy, Clone, Debug, PartialEq)]
282*61046927SAndroid Build Coastguard Workerpub struct ${to_camel(mthd_name)} {
283*61046927SAndroid Build Coastguard Worker  %for field_name in mthddict[mthd_name].field_name_start:
284*61046927SAndroid Build Coastguard Worker    pub ${rs_field_name(field_name.lower())}: ${mthd.field_rs_types[field_name]},
285*61046927SAndroid Build Coastguard Worker  %endfor
286*61046927SAndroid Build Coastguard Worker}
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker## Notice that the "to_bits" implementation is identical, so the first brace is
289*61046927SAndroid Build Coastguard Worker## not closed.
290*61046927SAndroid Build Coastguard Worker% if not mthd.is_array:
291*61046927SAndroid Build Coastguard Worker## This trait lays out how the conversion to u32 happens
292*61046927SAndroid Build Coastguard Workerimpl Mthd for ${to_camel(mthd_name)} {
293*61046927SAndroid Build Coastguard Worker    const ADDR: u16 = ${mthd.addr.replace('(', '').replace(')', '')};
294*61046927SAndroid Build Coastguard Worker    const CLASS: u16 = ${version[1].lower() if version is not None else nvcl.lower().replace("nv", "0x")};
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker%else:
297*61046927SAndroid Build Coastguard Workerimpl ArrayMthd for ${to_camel(mthd_name)} {
298*61046927SAndroid Build Coastguard Worker    const CLASS: u16 = ${version[1].lower() if version is not None else nvcl.lower().replace("nv", "0x")};
299*61046927SAndroid Build Coastguard Worker
300*61046927SAndroid Build Coastguard Worker    fn addr(i: usize) -> u16 {
301*61046927SAndroid Build Coastguard Worker        <% assert not ('i' in mthd.addr and 'j' in mthd.addr) %>
302*61046927SAndroid Build Coastguard Worker        (${mthd.addr.replace('j', 'i').replace('(', '').replace(')', '')}).try_into().unwrap()
303*61046927SAndroid Build Coastguard Worker    }
304*61046927SAndroid Build Coastguard Worker%endif
305*61046927SAndroid Build Coastguard Worker
306*61046927SAndroid Build Coastguard Worker    #[inline]
307*61046927SAndroid Build Coastguard Worker    fn to_bits(self) -> u32 {
308*61046927SAndroid Build Coastguard Worker        let mut val = 0;
309*61046927SAndroid Build Coastguard Worker        %for field_name in mthddict[mthd_name].field_name_start:
310*61046927SAndroid Build Coastguard Worker            <%
311*61046927SAndroid Build Coastguard Worker                field_start = int(mthd.field_name_start[field_name])
312*61046927SAndroid Build Coastguard Worker                field_end = int(mthd.field_name_end[field_name])
313*61046927SAndroid Build Coastguard Worker                field_width = field_end - field_start + 1
314*61046927SAndroid Build Coastguard Worker                field = rs_field_name(field_name.lower()) if mthd.field_rs_types[field_name] == "u32" else f"{rs_field_name(field_name)} as u32"
315*61046927SAndroid Build Coastguard Worker            %>
316*61046927SAndroid Build Coastguard Worker            %if field_width == 32:
317*61046927SAndroid Build Coastguard Worker        val |= self.${field};
318*61046927SAndroid Build Coastguard Worker            %else:
319*61046927SAndroid Build Coastguard Worker                %if "as u32" in field:
320*61046927SAndroid Build Coastguard Worker        assert!((self.${field}) < (1 << ${field_width}));
321*61046927SAndroid Build Coastguard Worker        val |= (self.${field}) << ${field_start};
322*61046927SAndroid Build Coastguard Worker                %else:
323*61046927SAndroid Build Coastguard Worker        assert!(self.${field} < (1 << ${field_width}));
324*61046927SAndroid Build Coastguard Worker        val |= self.${field} << ${field_start};
325*61046927SAndroid Build Coastguard Worker                %endif
326*61046927SAndroid Build Coastguard Worker            %endif
327*61046927SAndroid Build Coastguard Worker        %endfor
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker        val
330*61046927SAndroid Build Coastguard Worker    }
331*61046927SAndroid Build Coastguard Worker## Close the first brace.
332*61046927SAndroid Build Coastguard Worker}
333*61046927SAndroid Build Coastguard Worker%endfor
334*61046927SAndroid Build Coastguard Worker""")
335*61046927SAndroid Build Coastguard Worker
336*61046927SAndroid Build Coastguard Worker## A mere convenience to convert snake_case to CamelCase. Numbers are prefixed
337*61046927SAndroid Build Coastguard Worker## with "_".
338*61046927SAndroid Build Coastguard Workerdef to_camel(snake_str):
339*61046927SAndroid Build Coastguard Worker    result = ''.join(word.title() for word in snake_str.split('_'))
340*61046927SAndroid Build Coastguard Worker    return result if not result[0].isdigit() else '_' + result
341*61046927SAndroid Build Coastguard Worker
342*61046927SAndroid Build Coastguard Workerdef rs_field_name(name):
343*61046927SAndroid Build Coastguard Worker    name = name.lower()
344*61046927SAndroid Build Coastguard Worker
345*61046927SAndroid Build Coastguard Worker    # Fix up some Rust keywords
346*61046927SAndroid Build Coastguard Worker    if name == 'type':
347*61046927SAndroid Build Coastguard Worker        return 'type_'
348*61046927SAndroid Build Coastguard Worker    elif name == 'override':
349*61046927SAndroid Build Coastguard Worker        return 'override_'
350*61046927SAndroid Build Coastguard Worker    elif name[0].isdigit():
351*61046927SAndroid Build Coastguard Worker        return '_' + name
352*61046927SAndroid Build Coastguard Worker    else:
353*61046927SAndroid Build Coastguard Worker        return name
354*61046927SAndroid Build Coastguard Worker
355*61046927SAndroid Build Coastguard Workerdef glob_match(glob, name):
356*61046927SAndroid Build Coastguard Worker    if glob.endswith('*'):
357*61046927SAndroid Build Coastguard Worker        return name.startswith(glob[:-1])
358*61046927SAndroid Build Coastguard Worker    else:
359*61046927SAndroid Build Coastguard Worker        assert '*' not in glob
360*61046927SAndroid Build Coastguard Worker        return name == glob
361*61046927SAndroid Build Coastguard Worker
362*61046927SAndroid Build Coastguard Workerclass method(object):
363*61046927SAndroid Build Coastguard Worker    @property
364*61046927SAndroid Build Coastguard Worker    def array_size(self):
365*61046927SAndroid Build Coastguard Worker        for (glob, value) in METHOD_ARRAY_SIZES.items():
366*61046927SAndroid Build Coastguard Worker            if glob_match(glob, self.name):
367*61046927SAndroid Build Coastguard Worker                return value
368*61046927SAndroid Build Coastguard Worker        return 0
369*61046927SAndroid Build Coastguard Worker
370*61046927SAndroid Build Coastguard Worker    @property
371*61046927SAndroid Build Coastguard Worker    def is_float(self):
372*61046927SAndroid Build Coastguard Worker        for glob in METHOD_IS_FLOAT:
373*61046927SAndroid Build Coastguard Worker            if glob_match(glob, self.name):
374*61046927SAndroid Build Coastguard Worker                assert len(self.field_defs) == 1
375*61046927SAndroid Build Coastguard Worker                return True
376*61046927SAndroid Build Coastguard Worker        return False
377*61046927SAndroid Build Coastguard Worker
378*61046927SAndroid Build Coastguard Workerdef parse_header(nvcl, f):
379*61046927SAndroid Build Coastguard Worker    # Simple state machine
380*61046927SAndroid Build Coastguard Worker    # state 0 looking for a new method define
381*61046927SAndroid Build Coastguard Worker    # state 1 looking for new fields in a method
382*61046927SAndroid Build Coastguard Worker    # state 2 looking for enums for a fields in a method
383*61046927SAndroid Build Coastguard Worker    # blank lines reset the state machine to 0
384*61046927SAndroid Build Coastguard Worker
385*61046927SAndroid Build Coastguard Worker    version = None
386*61046927SAndroid Build Coastguard Worker    state = 0
387*61046927SAndroid Build Coastguard Worker    mthddict = {}
388*61046927SAndroid Build Coastguard Worker    curmthd = {}
389*61046927SAndroid Build Coastguard Worker    for line in f:
390*61046927SAndroid Build Coastguard Worker
391*61046927SAndroid Build Coastguard Worker        if line.strip() == "":
392*61046927SAndroid Build Coastguard Worker            state = 0
393*61046927SAndroid Build Coastguard Worker            if (curmthd):
394*61046927SAndroid Build Coastguard Worker                if not len(curmthd.field_name_start):
395*61046927SAndroid Build Coastguard Worker                    del mthddict[curmthd.name]
396*61046927SAndroid Build Coastguard Worker            curmthd = {}
397*61046927SAndroid Build Coastguard Worker            continue
398*61046927SAndroid Build Coastguard Worker
399*61046927SAndroid Build Coastguard Worker        if line.startswith("#define"):
400*61046927SAndroid Build Coastguard Worker            list = line.split();
401*61046927SAndroid Build Coastguard Worker            if "_cl_" in list[1]:
402*61046927SAndroid Build Coastguard Worker                continue
403*61046927SAndroid Build Coastguard Worker
404*61046927SAndroid Build Coastguard Worker            if not list[1].startswith(nvcl):
405*61046927SAndroid Build Coastguard Worker                if len(list) > 2 and list[2].startswith("0x"):
406*61046927SAndroid Build Coastguard Worker                    assert version is None
407*61046927SAndroid Build Coastguard Worker                    version = (list[1], list[2])
408*61046927SAndroid Build Coastguard Worker                continue
409*61046927SAndroid Build Coastguard Worker
410*61046927SAndroid Build Coastguard Worker            if list[1].endswith("TYPEDEF"):
411*61046927SAndroid Build Coastguard Worker                continue
412*61046927SAndroid Build Coastguard Worker
413*61046927SAndroid Build Coastguard Worker            if state == 2:
414*61046927SAndroid Build Coastguard Worker                teststr = nvcl + "_" + curmthd.name + "_" + curfield + "_"
415*61046927SAndroid Build Coastguard Worker                if ":" in list[2]:
416*61046927SAndroid Build Coastguard Worker                    state = 1
417*61046927SAndroid Build Coastguard Worker                elif teststr in list[1]:
418*61046927SAndroid Build Coastguard Worker                    curmthd.field_defs[curfield][list[1].removeprefix(teststr)] = list[2]
419*61046927SAndroid Build Coastguard Worker                else:
420*61046927SAndroid Build Coastguard Worker                    state = 1
421*61046927SAndroid Build Coastguard Worker
422*61046927SAndroid Build Coastguard Worker            if state == 1:
423*61046927SAndroid Build Coastguard Worker                teststr = nvcl + "_" + curmthd.name + "_"
424*61046927SAndroid Build Coastguard Worker                if teststr in list[1]:
425*61046927SAndroid Build Coastguard Worker                    if ("0x" in list[2]):
426*61046927SAndroid Build Coastguard Worker                        state = 1
427*61046927SAndroid Build Coastguard Worker                    else:
428*61046927SAndroid Build Coastguard Worker                        field = list[1].removeprefix(teststr)
429*61046927SAndroid Build Coastguard Worker                        bitfield = list[2].split(":")
430*61046927SAndroid Build Coastguard Worker                        curmthd.field_name_start[field] = bitfield[1]
431*61046927SAndroid Build Coastguard Worker                        curmthd.field_name_end[field] = bitfield[0]
432*61046927SAndroid Build Coastguard Worker                        curmthd.field_defs[field] = {}
433*61046927SAndroid Build Coastguard Worker                        curfield = field
434*61046927SAndroid Build Coastguard Worker                        state = 2
435*61046927SAndroid Build Coastguard Worker                else:
436*61046927SAndroid Build Coastguard Worker                    if not len(curmthd.field_name_start):
437*61046927SAndroid Build Coastguard Worker                        del mthddict[curmthd.name]
438*61046927SAndroid Build Coastguard Worker                        curmthd = {}
439*61046927SAndroid Build Coastguard Worker                    state = 0
440*61046927SAndroid Build Coastguard Worker
441*61046927SAndroid Build Coastguard Worker            if state == 0:
442*61046927SAndroid Build Coastguard Worker                if (curmthd):
443*61046927SAndroid Build Coastguard Worker                    if not len(curmthd.field_name_start):
444*61046927SAndroid Build Coastguard Worker                        del mthddict[curmthd.name]
445*61046927SAndroid Build Coastguard Worker                teststr = nvcl + "_"
446*61046927SAndroid Build Coastguard Worker                is_array = 0
447*61046927SAndroid Build Coastguard Worker                if (':' in list[2]):
448*61046927SAndroid Build Coastguard Worker                    continue
449*61046927SAndroid Build Coastguard Worker                name = list[1].removeprefix(teststr)
450*61046927SAndroid Build Coastguard Worker                if name.endswith("(i)"):
451*61046927SAndroid Build Coastguard Worker                    is_array = 1
452*61046927SAndroid Build Coastguard Worker                    name = name.removesuffix("(i)")
453*61046927SAndroid Build Coastguard Worker                if name.endswith("(j)"):
454*61046927SAndroid Build Coastguard Worker                    is_array = 1
455*61046927SAndroid Build Coastguard Worker                    name = name.removesuffix("(j)")
456*61046927SAndroid Build Coastguard Worker                x = method()
457*61046927SAndroid Build Coastguard Worker                x.name = name
458*61046927SAndroid Build Coastguard Worker                x.addr = list[2]
459*61046927SAndroid Build Coastguard Worker                x.is_array = is_array
460*61046927SAndroid Build Coastguard Worker                x.field_name_start = {}
461*61046927SAndroid Build Coastguard Worker                x.field_name_end = {}
462*61046927SAndroid Build Coastguard Worker                x.field_defs = {}
463*61046927SAndroid Build Coastguard Worker                x.field_rs_types = {}
464*61046927SAndroid Build Coastguard Worker                x.field_is_rs_enum = {}
465*61046927SAndroid Build Coastguard Worker                mthddict[x.name] = x
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker                curmthd = x
468*61046927SAndroid Build Coastguard Worker                state = 1
469*61046927SAndroid Build Coastguard Worker
470*61046927SAndroid Build Coastguard Worker    return (version, mthddict)
471*61046927SAndroid Build Coastguard Worker
472*61046927SAndroid Build Coastguard Workerdef convert_to_rust_constants(filename):
473*61046927SAndroid Build Coastguard Worker    with open(filename, 'r') as file:
474*61046927SAndroid Build Coastguard Worker        lines = file.readlines()
475*61046927SAndroid Build Coastguard Worker
476*61046927SAndroid Build Coastguard Worker    rust_items = []
477*61046927SAndroid Build Coastguard Worker    processed_constants = {}
478*61046927SAndroid Build Coastguard Worker    file_prefix = "NV" + os.path.splitext(os.path.basename(filename))[0].upper() + "_"
479*61046927SAndroid Build Coastguard Worker    file_prefix = file_prefix.replace('CL', '')
480*61046927SAndroid Build Coastguard Worker    for line in lines:
481*61046927SAndroid Build Coastguard Worker        match = re.match(r'#define\s+(\w+)\((\w+)\)\s+(.+)', line.strip())
482*61046927SAndroid Build Coastguard Worker        if match:
483*61046927SAndroid Build Coastguard Worker            name, arg, expr = match.groups()
484*61046927SAndroid Build Coastguard Worker            if name in processed_constants:
485*61046927SAndroid Build Coastguard Worker                processed_constants[name] += 1
486*61046927SAndroid Build Coastguard Worker                name += f"_{processed_constants[name]}"
487*61046927SAndroid Build Coastguard Worker            else:
488*61046927SAndroid Build Coastguard Worker                processed_constants[name] = 0
489*61046927SAndroid Build Coastguard Worker            name = name.replace(file_prefix, '')
490*61046927SAndroid Build Coastguard Worker            # convert to snake case
491*61046927SAndroid Build Coastguard Worker            name =  re.sub(r'(?<=[a-z])(?=[A-Z])', '_', name).lower()
492*61046927SAndroid Build Coastguard Worker            rust_items.append(f"#[inline]\npub fn {name}  ({arg}: u32) -> u32 {{ {expr.replace('(', '').replace(')', '')} }} ")
493*61046927SAndroid Build Coastguard Worker        else:
494*61046927SAndroid Build Coastguard Worker            match = re.match(r'#define\s+(\w+)\s+(?:MW\()?(\d+):(\d+)\)?', line.strip())
495*61046927SAndroid Build Coastguard Worker            if match:
496*61046927SAndroid Build Coastguard Worker                name, high, low = match.groups()
497*61046927SAndroid Build Coastguard Worker                high = int(high) + 1  # Convert to exclusive range
498*61046927SAndroid Build Coastguard Worker                if name in processed_constants:
499*61046927SAndroid Build Coastguard Worker                    processed_constants[name] += 1
500*61046927SAndroid Build Coastguard Worker                    name += f"_{processed_constants[name]}"
501*61046927SAndroid Build Coastguard Worker                else:
502*61046927SAndroid Build Coastguard Worker                    processed_constants[name] = 0
503*61046927SAndroid Build Coastguard Worker                # name = name.replace('__', '_').replace(file_prefix, '')
504*61046927SAndroid Build Coastguard Worker                name = name.replace(file_prefix, '')
505*61046927SAndroid Build Coastguard Worker                rust_items.append(f"pub const {name}: Range<u32> = {low}..{high};")
506*61046927SAndroid Build Coastguard Worker            else:
507*61046927SAndroid Build Coastguard Worker                match = re.match(r'#define\s+(\w+)\s+\(?0x(\w+)\)?', line.strip())
508*61046927SAndroid Build Coastguard Worker                if match:
509*61046927SAndroid Build Coastguard Worker                    name, value = match.groups()
510*61046927SAndroid Build Coastguard Worker                    if name in processed_constants:
511*61046927SAndroid Build Coastguard Worker                        processed_constants[name] += 1
512*61046927SAndroid Build Coastguard Worker                        name += f"_{processed_constants[name]}"
513*61046927SAndroid Build Coastguard Worker                    else:
514*61046927SAndroid Build Coastguard Worker                        processed_constants[name] = 0
515*61046927SAndroid Build Coastguard Worker                    name = name.replace(file_prefix, '')
516*61046927SAndroid Build Coastguard Worker                    rust_items.append(f"pub const {name}: u32 = 0x{value};")
517*61046927SAndroid Build Coastguard Worker                else:
518*61046927SAndroid Build Coastguard Worker                    match = re.match(r'#define\s+(\w+)\s+\(?(\d+)\)?', line.strip())
519*61046927SAndroid Build Coastguard Worker                    if match:
520*61046927SAndroid Build Coastguard Worker                        name, value = match.groups()
521*61046927SAndroid Build Coastguard Worker                        if name in processed_constants:
522*61046927SAndroid Build Coastguard Worker                            processed_constants[name] += 1
523*61046927SAndroid Build Coastguard Worker                            name += f"_{processed_constants[name]}"
524*61046927SAndroid Build Coastguard Worker                        else:
525*61046927SAndroid Build Coastguard Worker                            processed_constants[name] = 0
526*61046927SAndroid Build Coastguard Worker                        name = name.replace(file_prefix, '')
527*61046927SAndroid Build Coastguard Worker                        rust_items.append(f"pub const {name}: u32 = {value};")
528*61046927SAndroid Build Coastguard Worker
529*61046927SAndroid Build Coastguard Worker    return '\n'.join(rust_items)
530*61046927SAndroid Build Coastguard Worker
531*61046927SAndroid Build Coastguard Workerdef main():
532*61046927SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser()
533*61046927SAndroid Build Coastguard Worker    parser.add_argument('--out-h', required=False, help='Output C header.')
534*61046927SAndroid Build Coastguard Worker    parser.add_argument('--out-c', required=False, help='Output C file.')
535*61046927SAndroid Build Coastguard Worker    parser.add_argument('--out-rs', required=False, help='Output Rust file.')
536*61046927SAndroid Build Coastguard Worker    parser.add_argument('--out-rs-mthd', required=False,
537*61046927SAndroid Build Coastguard Worker                        help='Output Rust file for methods.')
538*61046927SAndroid Build Coastguard Worker    parser.add_argument('--in-h',
539*61046927SAndroid Build Coastguard Worker                        help='Input class header file.',
540*61046927SAndroid Build Coastguard Worker                        required=True)
541*61046927SAndroid Build Coastguard Worker    args = parser.parse_args()
542*61046927SAndroid Build Coastguard Worker
543*61046927SAndroid Build Coastguard Worker    clheader = os.path.basename(args.in_h)
544*61046927SAndroid Build Coastguard Worker    nvcl = clheader
545*61046927SAndroid Build Coastguard Worker    nvcl = nvcl.removeprefix("cl")
546*61046927SAndroid Build Coastguard Worker    nvcl = nvcl.removesuffix(".h")
547*61046927SAndroid Build Coastguard Worker    nvcl = nvcl.upper()
548*61046927SAndroid Build Coastguard Worker    nvcl = "NV" + nvcl
549*61046927SAndroid Build Coastguard Worker
550*61046927SAndroid Build Coastguard Worker    with open(args.in_h, 'r', encoding='utf-8') as f:
551*61046927SAndroid Build Coastguard Worker        (version, mthddict) = parse_header(nvcl, f)
552*61046927SAndroid Build Coastguard Worker
553*61046927SAndroid Build Coastguard Worker    environment = {
554*61046927SAndroid Build Coastguard Worker        'clheader': clheader,
555*61046927SAndroid Build Coastguard Worker        'nvcl': nvcl,
556*61046927SAndroid Build Coastguard Worker        'version': version,
557*61046927SAndroid Build Coastguard Worker        'mthddict': mthddict,
558*61046927SAndroid Build Coastguard Worker        'rs_field_name': rs_field_name,
559*61046927SAndroid Build Coastguard Worker        'to_camel': to_camel,
560*61046927SAndroid Build Coastguard Worker        'bs': '\\'
561*61046927SAndroid Build Coastguard Worker    }
562*61046927SAndroid Build Coastguard Worker
563*61046927SAndroid Build Coastguard Worker    try:
564*61046927SAndroid Build Coastguard Worker        if args.out_h is not None:
565*61046927SAndroid Build Coastguard Worker            environment['header'] = os.path.basename(args.out_h)
566*61046927SAndroid Build Coastguard Worker            with open(args.out_h, 'w', encoding='utf-8') as f:
567*61046927SAndroid Build Coastguard Worker                f.write(TEMPLATE_H.render(**environment))
568*61046927SAndroid Build Coastguard Worker        if args.out_c is not None:
569*61046927SAndroid Build Coastguard Worker            with open(args.out_c, 'w', encoding='utf-8') as f:
570*61046927SAndroid Build Coastguard Worker                f.write(TEMPLATE_C.render(**environment))
571*61046927SAndroid Build Coastguard Worker        if args.out_rs is not None:
572*61046927SAndroid Build Coastguard Worker            with open(args.out_rs, 'w', encoding='utf-8') as f:
573*61046927SAndroid Build Coastguard Worker                f.write(TEMPLATE_RS.render(**environment))
574*61046927SAndroid Build Coastguard Worker        if args.out_rs_mthd is not None:
575*61046927SAndroid Build Coastguard Worker            with open(args.out_rs_mthd, 'w', encoding='utf-8') as f:
576*61046927SAndroid Build Coastguard Worker                f.write("#![allow(non_camel_case_types)]\n")
577*61046927SAndroid Build Coastguard Worker                f.write("#![allow(non_snake_case)]\n")
578*61046927SAndroid Build Coastguard Worker                f.write("#![allow(non_upper_case_globals)]\n\n")
579*61046927SAndroid Build Coastguard Worker                f.write("use std::ops::Range;\n")
580*61046927SAndroid Build Coastguard Worker                f.write("use crate::Mthd;\n")
581*61046927SAndroid Build Coastguard Worker                f.write("use crate::ArrayMthd;\n")
582*61046927SAndroid Build Coastguard Worker                f.write("\n")
583*61046927SAndroid Build Coastguard Worker                f.write(convert_to_rust_constants(args.in_h))
584*61046927SAndroid Build Coastguard Worker                f.write("\n")
585*61046927SAndroid Build Coastguard Worker                f.write(TEMPLATE_RS_MTHD.render(**environment))
586*61046927SAndroid Build Coastguard Worker
587*61046927SAndroid Build Coastguard Worker    except Exception:
588*61046927SAndroid Build Coastguard Worker        # In the event there's an error, this imports some helpers from mako
589*61046927SAndroid Build Coastguard Worker        # to print a useful stack trace and prints it, then exits with
590*61046927SAndroid Build Coastguard Worker        # status 1, if python is run with debug; otherwise it just raises
591*61046927SAndroid Build Coastguard Worker        # the exception
592*61046927SAndroid Build Coastguard Worker        import sys
593*61046927SAndroid Build Coastguard Worker        from mako import exceptions
594*61046927SAndroid Build Coastguard Worker        print(exceptions.text_error_template().render(), file=sys.stderr)
595*61046927SAndroid Build Coastguard Worker        sys.exit(1)
596*61046927SAndroid Build Coastguard Worker
597*61046927SAndroid Build Coastguard Workerif __name__ == '__main__':
598*61046927SAndroid Build Coastguard Worker    main()
599