#!/usr/bin/env python3 """Generate mpu-ctype-data.c from official Unicode 18.0.0 UCD files. This script is a maintainer tool. It is never run by Makefile/configure. Place these already-downloaded files beside the script or pass their paths: DerivedCoreProperties.txt DerivedGeneralCategory.txt """ import argparse import re from pathlib import Path BITS = { "Alphabetic": 0x01, "Uppercase": 0x02, "Lowercase": 0x04, "XID_Start": 0x10, "XID_Continue": 0x20, } DIGIT = 0x08 def parse_range(s): if ".." in s: a,b=s.split("..",1); return int(a,16),int(b,16) n=int(s,16); return n,n def apply(path, flags, wanted, general=False): version_ok=False with path.open(encoding="utf-8") as f: for raw in f: if "18.0.0" in raw[:80]: version_ok=True line=raw.split("#",1)[0].strip() if not line or ";" not in line: continue field, prop=(x.strip() for x in line.split(";",1)) bit = DIGIT if general and prop == "Nd" else wanted.get(prop) if bit is None: continue a,b=parse_range(field) if a > 0xffff: continue b=min(b,0xffff) for cp in range(a,b+1): flags[cp] |= bit if not version_ok: raise SystemExit(f"{path}: expected Unicode 18.0.0 data") def main(): ap=argparse.ArgumentParser() ap.add_argument("--core",default="DerivedCoreProperties.txt") ap.add_argument("--category",default="DerivedGeneralCategory.txt") ap.add_argument("--output",default="mpu-ctype-data.c") ns=ap.parse_args() flags=[0]*0x10000 apply(Path(ns.core),flags,BITS) apply(Path(ns.category),flags,{},general=True) for cp in range(0xd800,0xe000): flags[cp]=0 out=Path(ns.output) with out.open("w",encoding="utf-8") as f: f.write("/***************************************************************\n") f.write(" MPU-CTYPE-DATA.C\n\n") f.write(" Generated strict UCS-2 classification table.\n") f.write(" Unicode Character Database version: 18.0.0.\n") f.write(" ***************************************************************/\n\n") f.write("#include \n#include \n#include \n\n") f.write("__mpu_hidden_decl( __mpu_ucs2_ctype );\n\n") f.write("const unsigned char __mpu_ucs2_ctype[65536] =\n{\n") for base in range(0,0x10000,16): vals=", ".join("0x%02x"%flags[base+i] for i in range(16)) f.write(" %s, /* U+%04X..U+%04X */\n"%(vals,base,base+15)) f.write("};\n") if __name__ == "__main__": main()