1*61046927SAndroid Build Coastguard Worker#! /usr/bin/env python3 2*61046927SAndroid Build Coastguard Worker# 3*61046927SAndroid Build Coastguard Worker# Copyright © 2024 Collabora Ltd. and Red Hat Inc. 4*61046927SAndroid Build Coastguard Worker# SPDX-License-Identifier: MIT 5*61046927SAndroid Build Coastguard Worker 6*61046927SAndroid Build Coastguard Workerimport argparse 7*61046927SAndroid Build Coastguard Workerimport os.path 8*61046927SAndroid Build Coastguard Workerimport re 9*61046927SAndroid Build Coastguard Workerimport sys 10*61046927SAndroid Build Coastguard Worker 11*61046927SAndroid Build Coastguard Workerfrom collections import namedtuple 12*61046927SAndroid Build Coastguard Workerfrom mako.template import Template 13*61046927SAndroid Build Coastguard Worker 14*61046927SAndroid Build Coastguard WorkerTEMPLATE_RS = Template("""\ 15*61046927SAndroid Build Coastguard Worker// Copyright © 2024 Collabora Ltd. and Red Hat Inc. 16*61046927SAndroid Build Coastguard Worker// SPDX-License-Identifier: MIT 17*61046927SAndroid Build Coastguard Worker 18*61046927SAndroid Build Coastguard Worker// This file is generated by struct_parser.py. DO NOT EDIT! 19*61046927SAndroid Build Coastguard Worker 20*61046927SAndroid Build Coastguard Worker#![allow(non_snake_case)] 21*61046927SAndroid Build Coastguard Worker 22*61046927SAndroid Build Coastguard Workeruse std::ops::Range; 23*61046927SAndroid Build Coastguard Worker 24*61046927SAndroid Build Coastguard Worker% for s in structs: 25*61046927SAndroid Build Coastguard Worker % for f in s.fields: 26*61046927SAndroid Build Coastguard Worker % if f.stride: 27*61046927SAndroid Build Coastguard Worker#[inline] 28*61046927SAndroid Build Coastguard Workerpub fn ${s.name}_${f.name}(i: usize) -> Range<usize> { 29*61046927SAndroid Build Coastguard Worker (i * ${f.stride} + ${f.lo})..(i * ${f.stride} + ${f.hi + 1}) 30*61046927SAndroid Build Coastguard Worker} 31*61046927SAndroid Build Coastguard Worker % else: 32*61046927SAndroid Build Coastguard Workerpub const ${s.name}_${f.name}: Range<usize> = ${f.lo}..${f.hi + 1}; 33*61046927SAndroid Build Coastguard Worker % endif: 34*61046927SAndroid Build Coastguard Worker % for e in f.enums: 35*61046927SAndroid Build Coastguard Workerpub const ${s.name}_${f.name}_${e.name}: u32 = ${e.value}; 36*61046927SAndroid Build Coastguard Worker % endfor 37*61046927SAndroid Build Coastguard Worker % endfor 38*61046927SAndroid Build Coastguard Worker% endfor 39*61046927SAndroid Build Coastguard Worker""") 40*61046927SAndroid Build Coastguard Worker 41*61046927SAndroid Build Coastguard WorkerSTRUCTS = [ 42*61046927SAndroid Build Coastguard Worker 'SPHV3', 43*61046927SAndroid Build Coastguard Worker 'SPHV4', 44*61046927SAndroid Build Coastguard Worker 'TEXHEADV2', 45*61046927SAndroid Build Coastguard Worker 'TEXHEADV3', 46*61046927SAndroid Build Coastguard Worker 'TEXHEAD_BL', 47*61046927SAndroid Build Coastguard Worker 'TEXHEAD_1D', 48*61046927SAndroid Build Coastguard Worker 'TEXHEAD_PITCH', 49*61046927SAndroid Build Coastguard Worker # This one goes last because it's a substring of the others 50*61046927SAndroid Build Coastguard Worker 'TEXHEAD', 51*61046927SAndroid Build Coastguard Worker 'TEXSAMP', 52*61046927SAndroid Build Coastguard Worker 'QMDV00_06', 53*61046927SAndroid Build Coastguard Worker 'QMDV01_06', 54*61046927SAndroid Build Coastguard Worker 'QMDV01_07', 55*61046927SAndroid Build Coastguard Worker 'QMDV02_01', 56*61046927SAndroid Build Coastguard Worker 'QMDV02_02', 57*61046927SAndroid Build Coastguard Worker 'QMDV02_03', 58*61046927SAndroid Build Coastguard Worker 'QMDV02_04', 59*61046927SAndroid Build Coastguard Worker 'QMDV03_00', 60*61046927SAndroid Build Coastguard Worker] 61*61046927SAndroid Build Coastguard Worker 62*61046927SAndroid Build Coastguard WorkerEnum = namedtuple('Enum', ['name', 'value']) 63*61046927SAndroid Build Coastguard Worker 64*61046927SAndroid Build Coastguard Workerclass Field(object): 65*61046927SAndroid Build Coastguard Worker def __init__(self, name, lo, hi, stride=0): 66*61046927SAndroid Build Coastguard Worker self.name = name 67*61046927SAndroid Build Coastguard Worker self.lo = lo 68*61046927SAndroid Build Coastguard Worker self.hi = hi 69*61046927SAndroid Build Coastguard Worker self.stride = stride 70*61046927SAndroid Build Coastguard Worker self.enums = [] 71*61046927SAndroid Build Coastguard Worker 72*61046927SAndroid Build Coastguard Worker def add_enum(self, name, value): 73*61046927SAndroid Build Coastguard Worker self.enums.append(Enum(name, value)) 74*61046927SAndroid Build Coastguard Worker 75*61046927SAndroid Build Coastguard Workerclass Struct(object): 76*61046927SAndroid Build Coastguard Worker def __init__(self, name): 77*61046927SAndroid Build Coastguard Worker self.name = name 78*61046927SAndroid Build Coastguard Worker self.fields = [] 79*61046927SAndroid Build Coastguard Worker 80*61046927SAndroid Build Coastguard Worker def add_field(self, name, lo, hi, stride=0): 81*61046927SAndroid Build Coastguard Worker self.fields.append(Field(name, lo, hi, stride)) 82*61046927SAndroid Build Coastguard Worker 83*61046927SAndroid Build Coastguard WorkerDRF_RE = re.compile(r'(?P<hi>[0-9]+):(?P<lo>[0-9]+)') 84*61046927SAndroid Build Coastguard WorkerFIELD_NAME_RE = re.compile(r'_?(?P<dw>[0-9]+)?_?(?P<name>.*)') 85*61046927SAndroid Build Coastguard WorkerMW_RE = re.compile(r'MW\((?P<hi>[0-9]+):(?P<lo>[0-9]+)\)') 86*61046927SAndroid Build Coastguard WorkerMW_ARR_RE = re.compile(r'MW\(\((?P<hi>\d+)\+\(i\)\*(?P<stride>\d+)\):\((?P<lo>[0-9]+)\+\(i\)\*(?P=stride)\)\)') 87*61046927SAndroid Build Coastguard Worker 88*61046927SAndroid Build Coastguard Workerdef parse_header(nvcl, file): 89*61046927SAndroid Build Coastguard Worker structs = {} 90*61046927SAndroid Build Coastguard Worker for line in file: 91*61046927SAndroid Build Coastguard Worker line = line.strip().split() 92*61046927SAndroid Build Coastguard Worker if not line: 93*61046927SAndroid Build Coastguard Worker continue 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Worker if line[0] != '#define': 96*61046927SAndroid Build Coastguard Worker continue 97*61046927SAndroid Build Coastguard Worker 98*61046927SAndroid Build Coastguard Worker if not line[1].startswith(nvcl): 99*61046927SAndroid Build Coastguard Worker continue 100*61046927SAndroid Build Coastguard Worker 101*61046927SAndroid Build Coastguard Worker name = line[1][(len(nvcl)+1):] 102*61046927SAndroid Build Coastguard Worker 103*61046927SAndroid Build Coastguard Worker struct = None 104*61046927SAndroid Build Coastguard Worker for s in STRUCTS: 105*61046927SAndroid Build Coastguard Worker if name.startswith(s): 106*61046927SAndroid Build Coastguard Worker if s not in structs: 107*61046927SAndroid Build Coastguard Worker structs[s] = Struct(s) 108*61046927SAndroid Build Coastguard Worker struct = structs[s] 109*61046927SAndroid Build Coastguard Worker name = name[len(s):] 110*61046927SAndroid Build Coastguard Worker break 111*61046927SAndroid Build Coastguard Worker 112*61046927SAndroid Build Coastguard Worker if struct is None: 113*61046927SAndroid Build Coastguard Worker continue 114*61046927SAndroid Build Coastguard Worker 115*61046927SAndroid Build Coastguard Worker name_m = FIELD_NAME_RE.match(name) 116*61046927SAndroid Build Coastguard Worker name = name_m.group('name') 117*61046927SAndroid Build Coastguard Worker 118*61046927SAndroid Build Coastguard Worker drf = DRF_RE.match(line[2]) 119*61046927SAndroid Build Coastguard Worker mw = MW_RE.match(line[2]) 120*61046927SAndroid Build Coastguard Worker mw_arr = MW_ARR_RE.match(line[2]) 121*61046927SAndroid Build Coastguard Worker if drf: 122*61046927SAndroid Build Coastguard Worker dw = int(name_m.group('dw')) 123*61046927SAndroid Build Coastguard Worker lo = int(drf.group('lo')) + dw * 32 124*61046927SAndroid Build Coastguard Worker hi = int(drf.group('hi')) + dw * 32 125*61046927SAndroid Build Coastguard Worker struct.add_field(name, lo, hi) 126*61046927SAndroid Build Coastguard Worker elif mw: 127*61046927SAndroid Build Coastguard Worker lo = int(mw.group('lo')) 128*61046927SAndroid Build Coastguard Worker hi = int(mw.group('hi')) 129*61046927SAndroid Build Coastguard Worker struct.add_field(name, lo, hi) 130*61046927SAndroid Build Coastguard Worker elif mw_arr: 131*61046927SAndroid Build Coastguard Worker lo = int(mw_arr.group('lo')) 132*61046927SAndroid Build Coastguard Worker hi = int(mw_arr.group('hi')) 133*61046927SAndroid Build Coastguard Worker stride = int(mw_arr.group('stride')) 134*61046927SAndroid Build Coastguard Worker assert name.endswith('(i)') 135*61046927SAndroid Build Coastguard Worker struct.add_field(name.removesuffix('(i)'), lo, hi, stride) 136*61046927SAndroid Build Coastguard Worker else: 137*61046927SAndroid Build Coastguard Worker for f in struct.fields: 138*61046927SAndroid Build Coastguard Worker if name.startswith(f.name + '_'): 139*61046927SAndroid Build Coastguard Worker name = name[(len(f.name)+1):] 140*61046927SAndroid Build Coastguard Worker f.add_enum(name, line[2]) 141*61046927SAndroid Build Coastguard Worker 142*61046927SAndroid Build Coastguard Worker return list(structs.values()) 143*61046927SAndroid Build Coastguard Worker 144*61046927SAndroid Build Coastguard WorkerNVCL_RE = re.compile(r'cl(?P<clsver>[0-9a-f]{4}).*') 145*61046927SAndroid Build Coastguard Worker 146*61046927SAndroid Build Coastguard Workerdef main(): 147*61046927SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 148*61046927SAndroid Build Coastguard Worker parser.add_argument('--out-rs', required=True, help='Output Rust file.') 149*61046927SAndroid Build Coastguard Worker parser.add_argument('--in-h', 150*61046927SAndroid Build Coastguard Worker help='Input class header file.', 151*61046927SAndroid Build Coastguard Worker required=True) 152*61046927SAndroid Build Coastguard Worker args = parser.parse_args() 153*61046927SAndroid Build Coastguard Worker 154*61046927SAndroid Build Coastguard Worker clheader = os.path.basename(args.in_h) 155*61046927SAndroid Build Coastguard Worker nvcl = NVCL_RE.match(clheader).group('clsver') 156*61046927SAndroid Build Coastguard Worker nvcl = nvcl.upper() 157*61046927SAndroid Build Coastguard Worker nvcl = "NV" + nvcl 158*61046927SAndroid Build Coastguard Worker 159*61046927SAndroid Build Coastguard Worker with open(args.in_h, 'r', encoding='utf-8') as f: 160*61046927SAndroid Build Coastguard Worker structs = parse_header(nvcl, f) 161*61046927SAndroid Build Coastguard Worker 162*61046927SAndroid Build Coastguard Worker try: 163*61046927SAndroid Build Coastguard Worker with open(args.out_rs, 'w', encoding='utf-8') as f: 164*61046927SAndroid Build Coastguard Worker f.write(TEMPLATE_RS.render(structs=structs)) 165*61046927SAndroid Build Coastguard Worker 166*61046927SAndroid Build Coastguard Worker except Exception: 167*61046927SAndroid Build Coastguard Worker # In the event there's an error, this imports some helpers from mako 168*61046927SAndroid Build Coastguard Worker # to print a useful stack trace and prints it, then exits with 169*61046927SAndroid Build Coastguard Worker # status 1, if python is run with debug; otherwise it just raises 170*61046927SAndroid Build Coastguard Worker # the exception 171*61046927SAndroid Build Coastguard Worker import sys 172*61046927SAndroid Build Coastguard Worker from mako import exceptions 173*61046927SAndroid Build Coastguard Worker print(exceptions.text_error_template().render(), file=sys.stderr) 174*61046927SAndroid Build Coastguard Worker sys.exit(1) 175*61046927SAndroid Build Coastguard Worker 176*61046927SAndroid Build Coastguard Workerif __name__ == '__main__': 177*61046927SAndroid Build Coastguard Worker main() 178