From 753c190995e26666beaa4025689667c150775113 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jeremy@system76.com>
Date: Mon, 19 Jul 2021 10:04:29 -0600
Subject: [PATCH] Implement wctype.h

---
 src/header/wctype/alpha.rs | 190 +++++++++++++++++++++++++++++++++++++
 src/header/wctype/mod.rs   | 109 ++++++++++++++++++++-
 src/header/wctype/punct.rs | 156 ++++++++++++++++++++++++++++++
 3 files changed, 454 insertions(+), 1 deletion(-)
 create mode 100644 src/header/wctype/alpha.rs
 create mode 100644 src/header/wctype/punct.rs

diff --git a/src/header/wctype/alpha.rs b/src/header/wctype/alpha.rs
new file mode 100644
index 00000000..b7f3faba
--- /dev/null
+++ b/src/header/wctype/alpha.rs
@@ -0,0 +1,190 @@
+// From musl src/ctype/alpha.h
+// Licensed under the MIT license
+// Copyright 2005-2020 Rich Felker, et al.
+
+use crate::platform::types::*;
+
+pub fn is(wc: usize) -> c_uchar {
+    if wc < 0x20000 {
+        return (table[(table[wc>>8] as usize)*32+((wc&255)>>3)]>>(wc&7))&1;
+    }
+    if wc < 0x2fffe {
+        return 1;
+    }
+    return 0;
+}
+
+const table: [c_uchar; 3904] = [
+    18,17,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,17,34,35,36,17,37,38,39,40,
+    41,42,43,44,17,45,46,47,16,16,48,16,16,16,16,16,16,16,49,50,51,16,52,53,16,16,
+    17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,54,
+    17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+    17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+    17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+    17,17,17,55,17,17,17,17,56,17,57,58,59,60,61,62,17,17,17,17,17,17,17,17,17,17,
+    17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+    17,17,17,17,17,17,17,63,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,64,65,17,66,67,
+    68,69,70,71,72,73,74,17,75,76,77,78,79,80,81,16,82,83,84,85,86,87,88,89,90,91,
+    92,93,16,94,95,96,16,17,17,17,97,98,99,16,16,16,16,16,16,16,16,16,16,17,17,17,
+    17,100,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,101,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,17,17,102,103,16,16,104,105,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+    17,17,17,17,17,17,17,17,17,106,17,17,107,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,
+    108,109,16,16,16,16,16,16,16,16,16,110,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,111,112,113,114,16,16,16,16,16,16,16,16,115,116,
+    117,16,16,16,16,16,118,119,16,16,16,16,120,16,16,121,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,
+    16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,254,255,255,7,254,
+    255,255,7,0,0,0,0,0,4,32,4,255,255,127,255,255,255,127,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,195,255,3,0,31,80,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,223,188,64,215,255,255,
+    251,255,255,255,255,255,255,255,255,255,191,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,3,252,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,254,255,255,255,127,2,255,255,255,
+    255,255,1,0,0,0,0,255,191,182,0,255,255,255,135,7,0,0,0,255,7,255,255,255,255,
+    255,255,255,254,255,195,255,255,255,255,255,255,255,255,255,255,255,255,239,
+    31,254,225,255,
+    159,0,0,255,255,255,255,255,255,0,224,255,255,255,255,255,255,255,255,255,255,
+    255,255,3,0,255,255,255,255,255,7,48,4,255,255,255,252,255,31,0,0,255,255,255,
+    1,255,7,0,0,0,0,0,0,255,255,223,63,0,0,240,255,248,3,255,255,255,255,255,255,
+    255,255,255,239,255,223,225,255,207,255,254,255,239,159,249,255,255,253,197,
+    227,159,89,128,176,207,255,3,16,238,135,249,255,255,253,109,195,135,25,2,94,
+    192,255,63,0,238,191,251,255,255,253,237,227,191,27,1,0,207,255,0,30,238,159,
+    249,255,255,253,237,227,159,25,192,176,207,255,2,0,236,199,61,214,24,199,255,
+    195,199,29,129,0,192,255,0,0,239,223,253,255,255,253,255,227,223,29,96,7,207,
+    255,0,0,239,223,253,255,255,253,239,227,223,29,96,64,207,255,6,0,239,223,253,
+    255,255,255,255,231,223,93,240,128,207,255,0,252,236,255,127,252,255,255,251,
+    47,127,128,95,255,192,255,12,0,254,255,255,255,255,127,255,7,63,32,255,3,0,0,
+    0,0,214,247,255,255,175,255,255,59,95,32,255,243,0,0,0,
+    0,1,0,0,0,255,3,0,0,255,254,255,255,255,31,254,255,3,255,255,254,255,255,255,
+    31,0,0,0,0,0,0,0,0,255,255,255,255,255,255,127,249,255,3,255,255,255,255,255,
+    255,255,255,255,63,255,255,255,255,191,32,255,255,255,255,255,247,255,255,255,
+    255,255,255,255,255,255,61,127,61,255,255,255,255,255,61,255,255,255,255,61,
+    127,61,255,127,255,255,255,255,255,255,255,61,255,255,255,255,255,255,255,255,
+    7,0,0,0,0,255,255,0,0,255,255,255,255,255,255,255,255,255,255,63,63,254,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,159,255,255,254,255,255,7,255,255,255,255,255,255,255,255,
+    255,199,255,1,255,223,15,0,255,255,15,0,255,255,15,0,255,223,13,0,255,255,255,
+    255,255,255,207,255,255,1,128,16,255,3,0,0,0,0,255,3,255,255,255,255,255,255,
+    255,255,255,255,255,1,255,255,255,255,255,7,255,255,255,255,255,255,255,255,
+    63,
+    0,255,255,255,127,255,15,255,1,192,255,255,255,255,63,31,0,255,255,255,255,
+    255,15,255,255,255,3,255,3,0,0,0,0,255,255,255,15,255,255,255,255,255,255,255,
+    127,254,255,31,0,255,3,255,3,128,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,
+    255,239,255,239,15,255,3,0,0,0,0,255,255,255,255,255,243,255,255,255,255,255,
+    255,191,255,3,0,255,255,255,255,255,255,127,0,255,227,255,255,255,255,255,63,
+    255,1,255,255,255,255,255,231,0,0,0,0,0,222,111,4,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,
+    128,255,31,0,255,255,63,63,255,255,255,255,63,63,255,170,255,255,255,63,255,
+    255,255,255,255,255,223,95,220,31,207,15,255,31,220,31,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,2,128,0,0,255,31,0,0,0,0,0,0,0,0,0,0,0,0,132,252,47,62,80,189,255,243,
+    224,67,0,0,255,255,255,255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,255,255,255,255,255,255,3,0,
+    0,255,255,255,255,255,127,255,255,255,255,255,127,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,31,120,12,0,255,255,255,255,191,32,255,
+    255,255,255,255,255,255,128,0,0,255,255,127,0,127,127,127,127,127,127,127,127,
+    255,255,255,255,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,224,0,0,0,254,3,62,31,254,255,255,255,255,255,255,255,255,255,127,224,254,
+    255,255,255,255,255,255,255,255,255,255,247,224,255,255,255,255,255,254,255,
+    255,255,255,255,255,255,255,255,255,127,0,0,255,255,255,7,0,0,0,0,0,0,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,63,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,
+    0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,31,0,0,
+    0,0,0,0,0,0,255,255,255,255,255,63,255,31,255,255,255,15,0,0,255,255,255,255,
+    255,127,240,143,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,
+    0,128,255,252,255,255,255,255,255,255,255,255,255,255,255,255,249,255,255,255,
+    255,255,255,124,0,0,0,0,0,128,255,191,255,255,255,255,0,0,0,255,255,255,255,
+    255,255,15,0,255,255,255,255,255,255,255,255,47,0,255,3,0,0,252,232,255,255,
+    255,255,255,7,255,255,255,255,7,0,255,255,255,31,255,255,255,255,255,255,247,
+    255,0,128,255,3,255,255,255,127,255,255,255,255,255,255,127,0,255,63,255,3,
+    255,255,127,252,255,255,255,255,255,255,255,127,5,0,0,56,255,255,60,0,126,126,
+    126,0,127,127,255,255,255,255,255,247,255,0,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,7,255,3,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,15,0,255,255,127,248,255,255,255,255,
+    255,
+    15,255,255,255,255,255,255,255,255,255,255,255,255,255,63,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,3,0,0,0,0,127,0,248,224,255,253,127,95,219,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,3,0,0,0,248,255,255,255,
+    255,255,255,255,255,255,255,255,255,63,0,0,255,255,255,255,255,255,255,255,
+    252,255,255,255,255,255,255,0,0,0,0,0,255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,223,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,31,0,0,255,3,
+    254,255,255,7,254,255,255,7,192,255,255,255,255,255,255,255,255,255,255,127,
+    252,252,252,28,0,0,0,0,255,239,255,255,127,255,255,183,255,63,255,63,0,0,0,0,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,7,0,0,0,0,0,0,0,0,
+    255,255,255,255,255,255,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,255,255,255,31,255,255,255,255,255,255,1,0,0,0,0,
+    0,255,255,255,255,0,224,255,255,255,7,255,255,255,255,255,7,255,255,255,63,
+    255,255,255,255,15,255,62,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,63,255,3,255,255,255,255,15,255,255,255,
+    255,15,255,255,255,255,255,0,255,255,255,255,255,255,15,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,255,255,255,255,255,255,127,0,255,255,63,0,255,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,63,253,255,255,255,255,191,145,255,255,63,0,255,255,
+    127,0,255,255,255,127,0,0,0,0,0,0,0,0,255,255,55,0,255,255,63,0,255,255,255,3,
+    0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,192,0,0,0,0,0,0,0,0,111,240,239,
+    254,255,255,63,0,0,0,0,0,255,255,255,31,255,255,255,31,0,0,0,0,255,254,255,
+    255,31,0,0,0,255,255,255,255,255,255,63,0,255,255,63,0,255,255,7,0,255,255,3,
+    0,0,0,0,0,0,0,0,0,0,0,0,
+    0,255,255,255,255,255,255,255,255,255,1,0,0,0,0,0,0,255,255,255,255,255,255,7,
+    0,255,255,255,255,255,255,7,0,255,255,255,255,255,0,255,3,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,31,128,0,255,255,63,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,255,255,127,0,255,255,255,255,255,255,255,255,63,0,0,0,
+    192,255,0,0,252,255,255,255,255,255,255,1,0,0,255,255,255,1,255,3,255,255,255,
+    255,255,255,199,255,112,0,255,255,255,255,71,0,255,255,255,255,255,255,255,
+    255,30,0,255,23,0,0,0,0,255,255,251,255,255,255,159,64,0,0,0,0,0,0,0,0,127,
+    189,255,191,255,1,255,255,255,255,255,255,255,1,255,3,239,159,249,255,255,253,
+    237,227,159,25,129,224,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,
+    255,255,255,255,255,187,7,255,131,0,0,0,0,255,255,255,255,255,255,255,255,179,
+    0,255,3,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,63,127,0,0,0,63,0,0,
+    0,0,255,255,255,255,255,255,255,127,17,0,255,3,0,0,0,0,255,255,255,255,255,
+    255,63,1,255,3,0,0,0,0,0,0,255,255,255,231,255,7,255,3,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,1,0,0,0,0,0,0,0,0,0,0,0,
+    0,255,255,255,255,255,255,255,255,255,3,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,255,252,255,255,255,255,255,252,26,0,0,0,255,255,255,255,255,255,231,
+    127,0,0,255,255,255,255,255,255,255,255,255,32,0,0,0,0,255,255,255,255,255,
+    255,255,1,255,253,255,255,255,255,127,127,1,0,255,3,0,0,252,255,255,255,252,
+    255,255,254,127,0,0,0,0,0,0,0,0,0,127,251,255,255,255,255,127,180,203,0,255,3,
+    191,253,255,255,255,127,123,1,255,3,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,127,0,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,3,0,0,
+    0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,127,0,
+    0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+    255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+    255,255,255,255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,
+    255,255,255,255,255,255,1,255,255,255,127,255,3,0,0,0,0,0,0,0,0,0,0,0,0,255,
+    255,255,63,0,0,255,255,255,255,255,255,0,0,15,0,255,3,248,255,255,224,255,255,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,255,255,255,255,255,255,255,255,255,135,255,255,255,255,255,255,255,128,
+    255,255,0,0,0,0,0,0,0,0,11,0,0,0,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,7,0,255,255,255,127,0,0,0,0,0,
+    0,7,0,240,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,15,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,7,255,31,255,1,255,67,0,0,0,0,0,0,0,0,0,0,
+    0,0,255,255,255,255,255,255,255,255,255,255,223,255,255,255,255,255,255,255,
+    255,223,100,222,255,235,239,255,255,255,255,255,255,
+    255,191,231,223,223,255,255,255,123,95,252,253,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,63,255,255,255,
+    253,255,255,247,255,255,255,247,255,255,223,255,255,255,223,255,255,127,255,
+    255,255,127,255,255,255,253,255,255,255,253,255,255,247,207,255,255,255,255,
+    255,255,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,255,255,255,255,255,31,128,63,255,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,
+    15,255,3,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,31,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,
+    143,8,255,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,239,255,255,255,150,254,247,10,132,234,150,170,150,247,247,94,255,251,255,
+    15,238,251,255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,3,255,255,255,3,255,
+    255,255,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+];
diff --git a/src/header/wctype/mod.rs b/src/header/wctype/mod.rs
index d571aef1..33374237 100644
--- a/src/header/wctype/mod.rs
+++ b/src/header/wctype/mod.rs
@@ -2,11 +2,14 @@
 
 use crate::{
     c_str::CStr,
+    header::ctype,
     platform::types::*,
 };
+use self::casecmp::casemap;
 
+mod alpha;
 mod casecmp;
-use casecmp::casemap;
+mod punct;
 
 pub const WEOF: wint_t = 0xFFFF_FFFFu32;
 
@@ -23,6 +26,25 @@ pub const WCTYPE_SPACE: wctype_t = 10;
 pub const WCTYPE_UPPER: wctype_t = 11;
 pub const WCTYPE_XDIGIT: wctype_t = 12;
 
+#[no_mangle]
+pub extern "C" fn iswctype(wc: wint_t, desc: wctype_t) -> c_int {
+    match desc {
+        WCTYPE_ALNUM => iswalnum(wc),
+        WCTYPE_ALPHA => iswalpha(wc),
+        WCTYPE_BLANK => iswblank(wc),
+        WCTYPE_CNTRL => iswcntrl(wc),
+        WCTYPE_DIGIT => iswdigit(wc),
+        WCTYPE_GRAPH => iswgraph(wc),
+        WCTYPE_LOWER => iswlower(wc),
+        WCTYPE_PRINT => iswprint(wc),
+        WCTYPE_PUNCT => iswpunct(wc),
+        WCTYPE_SPACE => iswspace(wc),
+        WCTYPE_UPPER => iswupper(wc),
+        WCTYPE_XDIGIT => iswxdigit(wc),
+        _ => 0,
+    }
+}
+
 #[no_mangle]
 pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
     let name_cstr = CStr::from_ptr(name);
@@ -43,6 +65,91 @@ pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
     }
 }
 
+#[no_mangle]
+pub extern "C" fn iswalnum(wc: wint_t) -> c_int {
+    c_int::from(iswdigit(wc) != 0 || iswalpha(wc) != 0)
+}
+
+#[no_mangle]
+pub extern "C" fn iswalpha(wc: wint_t) -> c_int {
+    c_int::from(alpha::is(wc as usize))
+}
+
+#[no_mangle]
+pub extern "C" fn iswblank(wc: wint_t) -> c_int {
+    ctype::isblank(wc as c_int)
+}
+
+#[no_mangle]
+pub extern "C" fn iswcntrl(wc: wint_t) -> c_int {
+    c_int::from(
+        wc < 32 ||
+        wc.wrapping_sub(0x7f) < 33 ||
+        wc.wrapping_sub(0x2028) < 2 ||
+        wc.wrapping_sub(0xfff9) < 3
+    )
+}
+
+#[no_mangle]
+pub extern "C" fn iswdigit(wc: wint_t) -> c_int {
+    c_int::from(wc.wrapping_sub('0' as wint_t) < 10)
+}
+
+#[no_mangle]
+pub extern "C" fn iswgraph(wc: wint_t) -> c_int {
+    c_int::from(iswspace(wc) == 0 && iswprint(wc) != 0)
+}
+
+#[no_mangle]
+pub extern "C" fn iswlower(wc: wint_t) -> c_int {
+    c_int::from(towupper(wc) != wc)
+}
+
+#[no_mangle]
+pub extern "C" fn iswprint(wc: wint_t) -> c_int {
+    if wc < 0xff {
+        c_int::from((wc+1 & 0x7f) >= 0x21)
+    } else if wc < 0x2028
+        || wc.wrapping_sub(0x202a) < 0xd800-0x202a
+        || wc.wrapping_sub(0xe000) < 0xfff9-0xe000 {
+        1
+    } else if wc.wrapping_sub(0xfffc) > 0x10ffff-0xfffc
+        || (wc&0xfffe)==0xfffe {
+        0
+    } else {
+        1
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn iswpunct(wc: wint_t) -> c_int {
+    c_int::from(punct::is(wc as usize))
+}
+
+#[no_mangle]
+pub extern "C" fn iswspace(wc: wint_t) -> c_int {
+    c_int::from([
+        ' ' as wint_t, '\t' as wint_t, '\n' as wint_t, '\r' as wint_t,
+        11, 12, 0x0085,
+        0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
+        0x2006, 0x2008, 0x2009, 0x200a,
+        0x2028, 0x2029, 0x205f, 0x3000
+    ].contains(&wc))
+}
+
+#[no_mangle]
+pub extern "C" fn iswupper(wc: wint_t) -> c_int {
+    c_int::from(towlower(wc) != wc)
+}
+
+#[no_mangle]
+pub extern "C" fn iswxdigit(wc: wint_t) -> c_int {
+    c_int::from(
+        wc.wrapping_sub('0' as wint_t) < 10 ||
+        (wc|32).wrapping_sub('a' as wint_t) < 6
+    )
+}
+
 #[no_mangle]
 pub extern "C" fn towlower(wc: wint_t) -> wint_t {
     casemap(wc, 0)
diff --git a/src/header/wctype/punct.rs b/src/header/wctype/punct.rs
new file mode 100644
index 00000000..f1098eb5
--- /dev/null
+++ b/src/header/wctype/punct.rs
@@ -0,0 +1,156 @@
+// From musl src/ctype/punct.h
+// Licensed under the MIT license
+// Copyright 2005-2020 Rich Felker, et al.
+
+use crate::platform::types::*;
+
+pub fn is(wc: usize) -> c_uchar {
+    if wc<0x20000 {
+        return (table[(table[wc>>8] as usize)*32+((wc&255)>>3)]>>(wc&7))&1;
+    }
+    return 0;
+}
+
+const table: [c_uchar; 4000] = [
+    18,16,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,16,16,34,35,16,36,37,38,39,
+    40,41,42,43,16,44,45,46,17,17,47,17,17,17,17,17,17,48,49,50,51,52,53,54,55,17,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,56,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,57,16,58,59,60,61,62,63,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,64,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,65,16,16,66,16,67,68,
+    69,16,70,71,72,16,73,16,16,74,75,76,77,78,16,79,80,81,82,83,84,85,86,87,88,89,
+    90,91,16,92,93,94,95,16,16,16,16,96,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,97,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,98,99,16,16,100,101,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,16,16,16,16,16,102,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+    16,16,16,103,104,105,106,16,16,107,108,17,17,109,16,16,16,16,16,16,110,111,16,
+    16,16,16,16,112,113,16,16,114,115,116,16,117,118,119,17,17,17,120,121,122,123,
+    124,16,16,16,16,
+    16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,254,255,0,252,1,0,0,248,1,
+    0,0,120,0,0,0,0,255,251,223,251,0,0,128,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,60,0,252,255,224,175,255,255,255,255,255,255,255,255,
+    255,255,223,255,255,255,255,255,32,64,176,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,252,0,0,0,0,0,230,254,255,255,255,0,64,73,0,0,0,0,0,24,0,255,255,0,216,
+    0,0,0,0,0,0,0,1,0,60,0,0,0,0,0,0,0,0,0,0,0,0,16,224,1,30,0,
+    96,255,191,0,0,0,0,0,0,255,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,207,
+    227,0,0,0,3,0,32,255,127,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,7,252,0,0,0,
+    0,0,0,0,0,0,16,0,32,30,0,48,0,1,0,0,0,0,0,0,0,0,16,0,32,0,0,0,0,252,111,0,0,0,
+    0,0,0,0,16,0,32,0,0,0,0,64,0,0,0,0,0,0,0,0,16,0,32,0,0,0,0,3,224,0,0,0,0,0,0,
+    0,16,0,32,0,0,0,0,253,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,255,7,16,0,0,0,0,0,0,0,0,
+    32,0,0,0,0,128,255,16,0,0,0,0,0,0,16,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,160,
+    0,127,0,0,255,3,0,0,0,0,0,0,0,0,0,4,0,0,0,0,16,0,0,0,0,0,0,128,0,128,192,223,
+    0,12,0,0,0,0,0,0,0,0,0,0,0,4,0,31,0,0,0,0,0,
+    0,254,255,255,255,0,252,255,255,0,0,0,0,0,0,0,0,252,0,0,0,0,0,0,192,255,223,
+    255,7,0,0,0,0,0,0,0,0,0,0,128,6,0,252,0,0,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,0,0,
+    0,0,8,0,0,0,0,0,0,0,0,0,0,0,224,255,255,255,31,0,0,255,3,0,0,0,0,0,0,0,0,0,0,
+    0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,96,0,0,1,0,0,24,0,0,0,0,0,0,0,0,0,56,0,0,0,0,16,0,0,0,112,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,254,127,47,0,0,255,3,255,127,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,49,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,196,255,255,255,
+    255,0,0,0,192,0,0,0,0,0,0,0,0,1,0,224,159,0,0,0,0,127,63,255,127,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,16,0,16,0,0,252,255,255,255,31,0,0,0,0,0,12,0,0,0,0,0,0,64,0,
+    12,240,0,0,0,0,0,0,128,248,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,0,255,0,255,255,
+    255,33,144,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,
+    127,0,224,251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,160,3,224,0,224,0,
+    224,0,96,128,248,255,255,255,252,255,255,255,255,255,127,223,255,241,127,255,
+    127,0,0,255,255,255,255,0,0,255,255,255,255,1,0,123,3,208,193,175,66,0,12,31,
+    188,255,255,0,0,0,0,0,14,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,127,0,0,0,255,7,0,0,255,255,255,255,255,255,255,255,255,
+    255,63,0,0,0,0,0,0,252,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,207,255,255,255,
+    63,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,135,3,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
+    128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,127,255,255,255,255,0,
+    0,0,0,0,0,255,255,255,251,255,255,255,255,255,255,255,255,255,255,15,0,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,63,0,0,0,255,15,30,255,255,255,1,252,193,224,0,0,0,0,
+    0,0,0,0,0,0,0,30,1,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    255,255,0,0,0,0,255,255,255,255,15,0,0,0,255,255,255,127,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,
+    255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,
+    255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,127,0,0,0,
+    0,0,0,192,0,224,0,0,0,0,0,0,0,0,0,0,0,128,15,112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    255,0,255,255,127,0,3,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    64,0,0,0,0,15,255,3,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,16,192,0,0,255,255,3,23,
+    0,0,0,0,0,248,0,0,0,0,8,128,0,0,0,0,0,0,0,0,0,0,8,0,255,63,0,192,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,240,0,0,128,3,0,0,0,0,0,0,0,128,2,0,0,192,0,0,67,0,0,0,0,0,
+    0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,
+    0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,2,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,252,255,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,255,255,255,3,255,255,255,255,255,255,247,
+    255,127,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,254,255,0,252,1,0,0,248,1,0,
+    0,248,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,127,0,48,135,255,255,255,255,255,
+    143,255,0,0,0,0,0,0,224,255,255,127,255,15,1,0,0,0,0,0,255,255,255,255,255,63,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,
+    15,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    128,255,0,0,128,255,0,0,0,0,128,255,0,0,0,0,0,0,0,0,0,248,0,0,192,143,0,0,0,
+    128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,255,255,252,255,255,255,255,255,0,0,0,0,
+    0,0,0,135,255,1,255,1,0,0,0,224,0,0,0,224,0,0,0,0,0,1,0,0,96,248,127,0,0,0,0,
+    0,0,0,0,254,0,0,0,255,0,0,0,255,0,0,0,30,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,0,0,0,0,0,0,0,0,0,0,0,
+    0,255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,224,127,0,0,0,192,255,255,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,192,63,252,255,63,0,0,128,3,0,0,0,0,0,0,254,3,32,0,0,0,0,0,0,0,
+    0,0,0,0,0,24,0,15,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,225,63,0,232,254,255,31,0,0,
+    0,0,0,0,0,96,63,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,
+    24,0,32,0,0,192,31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,
+    248,0,104,0,0,0,0,0,0,0,0,0,0,0,0,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,128,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,128,14,0,0,0,255,
+    31,0,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,8,0,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,7,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,24,128,255,0,0,0,0,0,
+    0,0,0,0,0,223,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,62,0,0,252,255,31,3,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,52,0,0,0,0,0,0,0,0,0,128,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,128,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,
+    255,3,
+    128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,63,0,0,0,0,0,0,0,255,255,48,0,0,248,
+    3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,
+    255,255,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,176,15,0,0,0,0,0,0,
+    0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,63,
+    0,255,255,255,255,127,254,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,1,0,0,255,255,255,255,255,255,255,255,
+    63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,15,0,255,255,255,255,255,255,
+    255,255,255,255,127,0,255,255,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,8,0,0,0,8,0,0,32,0,0,0,32,0,0,128,
+    0,0,0,128,0,0,0,2,0,0,0,2,0,0,8,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,255,255,15,0,248,254,255,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,127,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,
+    128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,255,127,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,112,7,0,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,254,255,255,255,255,255,255,255,31,0,0,0,0,0,0,0,0,0,254,255,
+    255,255,255,255,255,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,255,255,255,255,255,
+    15,255,255,255,255,255,255,255,255,255,255,255,255,15,0,255,127,254,255,254,
+    255,254,255,255,255,63,0,255,31,255,255,255,255,0,0,0,252,0,0,0,28,0,0,0,252,
+    255,255,255,31,0,0,0,0,0,0,192,255,255,255,7,0,255,255,255,255,255,15,255,1,3,
+    0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,255,63,0,255,31,255,7,255,255,255,255,255,255,255,255,
+    255,255,255,255,255,255,15,0,255,255,255,255,255,255,255,255,255,255,255,1,
+    255,15,0,0,255,15,255,255,255,255,255,255,255,0,255,3,255,255,255,255,255,0,
+    255,255,255,63,0,0,0,0,0,0,0,0,0,0,255,239,255,255,255,255,255,255,255,255,
+    255,255,255,255,123,252,255,255,255,255,231,199,255,255,255,231,255,255,255,
+    255,255,255,255,255,255,255,255,255,255,255,255,255,15,0,255,63,15,7,7,0,63,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,
+];
-- 
GitLab