make-windows-h-wrapper.py (2938B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import re 6 import string 7 import textwrap 8 9 comment_re = re.compile(r"//[^\n]*\n|/\*.*\*/", re.S) 10 decl_re = re.compile( 11 r"""^(.+)\s+ # type 12 (\w+)\s* # name 13 (?:\((.*)\))?$ # optional param tys 14 """, 15 re.X | re.S, 16 ) 17 18 19 def read_decls(filename): 20 """Parse & yield C-style decls from an input file""" 21 with open(filename) as fd: 22 # Strip comments from the source text. 23 text = comment_re.sub("", fd.read()) 24 25 # Parse individual declarations. 26 raw_decls = [d.strip() for d in text.split(";") if d.strip()] 27 for raw in raw_decls: 28 match = decl_re.match(raw) 29 if match is None: 30 raise "Invalid decl: %s" % raw 31 32 ty, name, params = match.groups() 33 if params is not None: 34 params = [a.strip() for a in params.split(",") if a.strip()] 35 yield ty, name, params 36 37 38 def generate(fd, consts_path, unicodes_path, template_path, compiler): 39 # Parse the template 40 with open(template_path) as template_fd: 41 template = string.Template(template_fd.read()) 42 43 decls = "" 44 45 # Each constant should be saved to a temporary, and then re-assigned to a 46 # constant with the correct name, allowing the value to be determined by 47 # the actual definition. 48 for ty, name, args in read_decls(consts_path): 49 assert args is None, "parameters in const decl!" 50 51 decls += textwrap.dedent( 52 f""" 53 #ifdef {name} 54 constexpr {ty} _tmp_{name} = {name}; 55 #undef {name} 56 constexpr {ty} {name} = _tmp_{name}; 57 #endif 58 """ 59 ) 60 61 # Each unicode declaration defines a static inline function with the 62 # correct types which calls the 'A' or 'W'-suffixed versions of the 63 # function. Full types are required here to ensure that '0' to 'nullptr' 64 # coersions are preserved. 65 for ty, name, args in read_decls(unicodes_path): 66 assert args is not None, "argument list required for unicode decl" 67 68 # Parameter & argument string list 69 params = ", ".join("%s a%d" % (ty, i) for i, ty in enumerate(args)) 70 args = ", ".join("a%d" % i for i in range(len(args))) 71 72 decls += textwrap.dedent( 73 f""" 74 #ifdef {name} 75 #undef {name} 76 static inline {ty} WINAPI 77 {name}({params}) 78 #ifdef UNICODE 79 {{ 80 return {name}W({args}); 81 }} 82 #else 83 = delete; 84 #endif 85 #endif 86 """ 87 ) 88 89 # Write out the resulting file 90 fd.write(template.substitute(decls=decls))