1bf215546Sopenharmony_ci#!/usr/bin/env python3 2bf215546Sopenharmony_ci# coding=utf-8 3bf215546Sopenharmony_ci########################################################################## 4bf215546Sopenharmony_ci# 5bf215546Sopenharmony_ci# enums2names - Parse and convert enums to translator code 6bf215546Sopenharmony_ci# (C) Copyright 2021 Matti 'ccr' Hämäläinen <ccr@tnsp.org> 7bf215546Sopenharmony_ci# 8bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a 9bf215546Sopenharmony_ci# copy of this software and associated documentation files (the 10bf215546Sopenharmony_ci# "Software"), to deal in the Software without restriction, including 11bf215546Sopenharmony_ci# without limitation the rights to use, copy, modify, merge, publish, 12bf215546Sopenharmony_ci# distribute, sub license, and/or sell copies of the Software, and to 13bf215546Sopenharmony_ci# permit persons to whom the Software is furnished to do so, subject to 14bf215546Sopenharmony_ci# the following conditions: 15bf215546Sopenharmony_ci# 16bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the 17bf215546Sopenharmony_ci# next paragraph) shall be included in all copies or substantial portions 18bf215546Sopenharmony_ci# of the Software. 19bf215546Sopenharmony_ci# 20bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21bf215546Sopenharmony_ci# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22bf215546Sopenharmony_ci# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23bf215546Sopenharmony_ci# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 24bf215546Sopenharmony_ci# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25bf215546Sopenharmony_ci# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26bf215546Sopenharmony_ci# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27bf215546Sopenharmony_ci# 28bf215546Sopenharmony_ci########################################################################## 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ciimport sys 31bf215546Sopenharmony_ciimport os.path 32bf215546Sopenharmony_ciimport re 33bf215546Sopenharmony_ciimport signal 34bf215546Sopenharmony_ciimport argparse 35bf215546Sopenharmony_ciimport textwrap 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ciassert sys.version_info >= (3, 6) 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci# 41bf215546Sopenharmony_ci# List of enums we wish to include in output. 42bf215546Sopenharmony_ci# NOTE: This needs to be updated if such enums are added. 43bf215546Sopenharmony_ci# 44bf215546Sopenharmony_cilst_enum_include = [ 45bf215546Sopenharmony_ci "pipe_texture_target", 46bf215546Sopenharmony_ci "pipe_shader_type", 47bf215546Sopenharmony_ci "pipe_shader_cap", 48bf215546Sopenharmony_ci "pipe_shader_ir", 49bf215546Sopenharmony_ci "pipe_cap", 50bf215546Sopenharmony_ci "pipe_capf", 51bf215546Sopenharmony_ci "pipe_compute_cap", 52bf215546Sopenharmony_ci "pipe_resource_param", 53bf215546Sopenharmony_ci "pipe_fd_type", 54bf215546Sopenharmony_ci] 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci### 58bf215546Sopenharmony_ci### Utility functions 59bf215546Sopenharmony_ci### 60bf215546Sopenharmony_ci## Fatal error handler 61bf215546Sopenharmony_cidef pkk_fatal(smsg): 62bf215546Sopenharmony_ci print("ERROR: "+ smsg) 63bf215546Sopenharmony_ci sys.exit(1) 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci## Handler for SIGINT signals 67bf215546Sopenharmony_cidef pkk_signal_handler(signal, frame): 68bf215546Sopenharmony_ci print("\nQuitting due to SIGINT / Ctrl+C!") 69bf215546Sopenharmony_ci sys.exit(1) 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci## Argument parser subclass 73bf215546Sopenharmony_ciclass PKKArgumentParser(argparse.ArgumentParser): 74bf215546Sopenharmony_ci def print_help(self): 75bf215546Sopenharmony_ci print("enums2names - Parse and convert enums to translator code\n" 76bf215546Sopenharmony_ci "(C) Copyright 2021 Matti 'ccr' Hämäläinen <ccr@tnsp.org>\n") 77bf215546Sopenharmony_ci super().print_help() 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci def error(self, msg): 80bf215546Sopenharmony_ci self.print_help() 81bf215546Sopenharmony_ci print(f"\nERROR: {msg}", file=sys.stderr) 82bf215546Sopenharmony_ci sys.exit(2) 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cidef pkk_get_argparser(): 86bf215546Sopenharmony_ci optparser = PKKArgumentParser( 87bf215546Sopenharmony_ci usage="%(prog)s [options] <infile|->\n" 88bf215546Sopenharmony_ci "example: %(prog)s ../../include/pipe/p_defines.h -C tr_util.c -H tr_util.h" 89bf215546Sopenharmony_ci ) 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci optparser.add_argument("in_file", 92bf215546Sopenharmony_ci type=str, 93bf215546Sopenharmony_ci metavar="infile", 94bf215546Sopenharmony_ci help="path to input header file p_defines.h (or '-' for stdin)") 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci optparser.add_argument("-C", 97bf215546Sopenharmony_ci type=str, 98bf215546Sopenharmony_ci metavar="outfile", 99bf215546Sopenharmony_ci dest="out_source", 100bf215546Sopenharmony_ci help="output C source file") 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci optparser.add_argument("-H", 103bf215546Sopenharmony_ci type=str, 104bf215546Sopenharmony_ci metavar="outfile", 105bf215546Sopenharmony_ci dest="out_header", 106bf215546Sopenharmony_ci help="output C header file") 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci optparser.add_argument("-I", 109bf215546Sopenharmony_ci type=str, 110bf215546Sopenharmony_ci metavar="include", 111bf215546Sopenharmony_ci dest="include_file", 112bf215546Sopenharmony_ci help="include file / path used for C source output") 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci return optparser 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ciclass PKKHeaderParser: 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci def __init__(self, nfilename): 120bf215546Sopenharmony_ci self.filename = nfilename 121bf215546Sopenharmony_ci self.enums = {} 122bf215546Sopenharmony_ci self.state = 0 123bf215546Sopenharmony_ci self.nline = 0 124bf215546Sopenharmony_ci self.mdata = [] 125bf215546Sopenharmony_ci self.start = 0 126bf215546Sopenharmony_ci self.name = None 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci def error(self, msg): 129bf215546Sopenharmony_ci pkk_fatal(f"{self.filename}:{self.nline} : {msg}") 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci def parse_line(self, sline): 132bf215546Sopenharmony_ci # A kingdom for Py3.8 := operator ... 133bf215546Sopenharmony_ci smatch = re.match(r'^enum\s+([A-Za-z0-9_]+)\s+.*;', sline) 134bf215546Sopenharmony_ci if smatch: 135bf215546Sopenharmony_ci pass 136bf215546Sopenharmony_ci else: 137bf215546Sopenharmony_ci smatch = re.match(r'^enum\s+([A-Za-z0-9_]+)', sline) 138bf215546Sopenharmony_ci if smatch: 139bf215546Sopenharmony_ci stmp = smatch.group(1) 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if self.state != 0: 142bf215546Sopenharmony_ci self.error(f"enum '{stmp}' starting inside another enum '{self.name}'") 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci self.name = stmp 145bf215546Sopenharmony_ci self.state = 1 146bf215546Sopenharmony_ci self.start = self.nline 147bf215546Sopenharmony_ci self.mdata = [] 148bf215546Sopenharmony_ci else: 149bf215546Sopenharmony_ci smatch = re.match(r'^}(\s*|\s*[A-Z][A-Z_]+\s*);', sline) 150bf215546Sopenharmony_ci if smatch: 151bf215546Sopenharmony_ci if self.state == 1: 152bf215546Sopenharmony_ci if self.name in self.enums: 153bf215546Sopenharmony_ci self.error("duplicate enum definition '{}', lines {} - {} vs {} - {}".format( 154bf215546Sopenharmony_ci self.name, self.enums[self.name]["start"], self.enums[self.name]["end"], 155bf215546Sopenharmony_ci self.start, self.nline)) 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci self.enums[self.name] = { 158bf215546Sopenharmony_ci "data": self.mdata, 159bf215546Sopenharmony_ci "start": self.start, 160bf215546Sopenharmony_ci "end": self.nline 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci self.state = 0 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci elif self.state == 1: 166bf215546Sopenharmony_ci smatch = re.match(r'([A-Za-z0-9_]+)\s*=\s*(.+)\s*,?', sline) 167bf215546Sopenharmony_ci if smatch: 168bf215546Sopenharmony_ci self.mdata.append(smatch.group(1)) 169bf215546Sopenharmony_ci else: 170bf215546Sopenharmony_ci smatch = re.match(r'([A-Za-z0-9_]+)\s*,?', sline) 171bf215546Sopenharmony_ci if smatch: 172bf215546Sopenharmony_ci self.mdata.append(smatch.group(1)) 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci def parse_file(self, fh): 175bf215546Sopenharmony_ci self.nline = 0 176bf215546Sopenharmony_ci for line in fh: 177bf215546Sopenharmony_ci self.nline += 1 178bf215546Sopenharmony_ci self.parse_line(line.strip()) 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci return self.enums 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_cidef pkk_output_header(fh): 184bf215546Sopenharmony_ci prototypes = [f"const char *\n" 185bf215546Sopenharmony_ci f"tr_util_{name}_name(enum {name} value);\n" for name in lst_enum_include] 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci print(textwrap.dedent("""\ 188bf215546Sopenharmony_ci /* 189bf215546Sopenharmony_ci * File generated with {program}, please do not edit manually. 190bf215546Sopenharmony_ci */ 191bf215546Sopenharmony_ci #ifndef {include_header_guard} 192bf215546Sopenharmony_ci #define {include_header_guard} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci #include "pipe/p_defines.h" 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci #ifdef __cplusplus 199bf215546Sopenharmony_ci extern "C" {{ 200bf215546Sopenharmony_ci #endif 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci {prototypes} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci #ifdef __cplusplus 205bf215546Sopenharmony_ci }} 206bf215546Sopenharmony_ci #endif 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci #endif /* {include_header_guard} */\ 209bf215546Sopenharmony_ci """).format( 210bf215546Sopenharmony_ci program=pkk_progname, 211bf215546Sopenharmony_ci include_header_guard=re.sub(r'[^A-Z]', '_', os.path.basename(pkk_cfg.out_header).upper()), 212bf215546Sopenharmony_ci prototypes="".join(prototypes) 213bf215546Sopenharmony_ci ), file=fh) 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cidef pkk_output_source(fh): 217bf215546Sopenharmony_ci if pkk_cfg.include_file == None: 218bf215546Sopenharmony_ci pkk_fatal("Output C source enabled, but include file is not set (-I option).") 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci print(textwrap.dedent("""\ 221bf215546Sopenharmony_ci /* 222bf215546Sopenharmony_ci * File generated with {program}, please do not edit manually. 223bf215546Sopenharmony_ci */ 224bf215546Sopenharmony_ci #include "{include_file}" 225bf215546Sopenharmony_ci """).format( 226bf215546Sopenharmony_ci program=pkk_progname, 227bf215546Sopenharmony_ci include_file=pkk_cfg.include_file, 228bf215546Sopenharmony_ci ), file=fh) 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci for name in lst_enum_include: 231bf215546Sopenharmony_ci cases = [f" case {eid}: return \"{eid}\";\n" 232bf215546Sopenharmony_ci for eid in enums[name]["data"]] 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci print(textwrap.dedent("""\ 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci const char * 237bf215546Sopenharmony_ci tr_util_{name}_name(enum {name} value) 238bf215546Sopenharmony_ci {{ 239bf215546Sopenharmony_ci switch (value) {{ 240bf215546Sopenharmony_ci {cases} 241bf215546Sopenharmony_ci default: return "{ucname}_UNKNOWN"; 242bf215546Sopenharmony_ci }} 243bf215546Sopenharmony_ci }} 244bf215546Sopenharmony_ci """).format( 245bf215546Sopenharmony_ci name=name, 246bf215546Sopenharmony_ci ucname=name.upper(), 247bf215546Sopenharmony_ci cases="".join(cases) 248bf215546Sopenharmony_ci ), file=fh) 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci### 251bf215546Sopenharmony_ci### Main program starts 252bf215546Sopenharmony_ci### 253bf215546Sopenharmony_ciif __name__ == "__main__": 254bf215546Sopenharmony_ci signal.signal(signal.SIGINT, pkk_signal_handler) 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci ### Parse arguments 257bf215546Sopenharmony_ci pkk_progname = sys.argv[0] 258bf215546Sopenharmony_ci optparser = pkk_get_argparser() 259bf215546Sopenharmony_ci pkk_cfg = optparser.parse_args() 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci ### Parse input 262bf215546Sopenharmony_ci hdrparser = PKKHeaderParser(pkk_cfg.in_file) 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci try: 265bf215546Sopenharmony_ci if pkk_cfg.in_file != "-": 266bf215546Sopenharmony_ci with open(pkk_cfg.in_file, "r", encoding="UTF-8") as fh: 267bf215546Sopenharmony_ci enums = hdrparser.parse_file(fh) 268bf215546Sopenharmony_ci else: 269bf215546Sopenharmony_ci enums = hdrparser.parse_file(sys.stdin) 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci except OSError as e: 272bf215546Sopenharmony_ci pkk_fatal(str(e)) 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci ### Check if any of the required enums are missing 275bf215546Sopenharmony_ci errors = False 276bf215546Sopenharmony_ci for name in lst_enum_include: 277bf215546Sopenharmony_ci if name not in enums: 278bf215546Sopenharmony_ci print(f"ERROR: Missing enum '{name}'!") 279bf215546Sopenharmony_ci errors = True 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if errors: 282bf215546Sopenharmony_ci pkk_fatal(f"Errors in input. Edit this script ({pkk_progname}) to add/remove included enums.") 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci ### Perform output 285bf215546Sopenharmony_ci if pkk_cfg.out_header: 286bf215546Sopenharmony_ci with open(pkk_cfg.out_header, "w", encoding="UTF-8") as fh: 287bf215546Sopenharmony_ci pkk_output_header(fh) 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci if pkk_cfg.out_source: 290bf215546Sopenharmony_ci with open(pkk_cfg.out_source, "w", encoding="UTF-8") as fh: 291bf215546Sopenharmony_ci pkk_output_source(fh) 292