@@ -151,29 +151,29 @@ showCStr s = '"' : foldr ((++) . showChar) "\"" s
151 -- Note: we need the double quotes around the codes because otherwise
151 -- Note: we need the double quotes around the codes because otherwise
152 -- "\n3" would get encoded as "\x0a3", which is incorrect.
152 -- "\n3" would get encoded as "\x0a3", which is incorrect.
153 -- Instead, we opt for "\x0a""3" and let the C compiler deal with it.
153 -- Instead, we opt for "\x0a""3" and let the C compiler deal with it.
154− | ord c < 0x10 = "\"\"\\x0" ++ showHex (ord c) "\"\""
155− | ord c < 0x20 = "\"\"\\x" ++ showHex (ord c) "\"\""
154+ | ord c < 0x20 = showUTF8 (ord c)
156 | ord c < 0x7f = [c] -- 0x7f = \DEL
155 | ord c < 0x7f = [c] -- 0x7f = \DEL
157 | otherwise = showHexes (utf8bytes (ord c))
156 | otherwise = showHexes (utf8bytes (ord c))
158+ showUTF8 c = "\"\"\\x" ++ pad (showHex c "") ++ "\"\""
159+ showHexes = foldr ((++) . showUTF8) ""
159 utf8bytes :: Int -> [Int]
161 utf8bytes :: Int -> [Int]
160− utf8bytes x = let (h : bytes) = split [] x in
162+ utf8bytes x
161− headHex h (length bytes) : map toHex bytes
163+ | x <= 0x7f = [x]
164+ | x <= 0x7ff = let (y : ys) = split [] 2 x in (y .|. 0xc0) : map (.|. 0x80) ys
165+ | x <= 0xffff = let (y : ys) = split [] 3 x in (y .|. 0xe0) : map (.|. 0x80) ys
166+ | x <= 0x10ffff = let (y : ys) = split [] 4 x in (y .|. 0xf0) : map (.|. 0x80) ys
167+ | otherwise = error $ "Invalid Unicode code point U+" ++ showHex x ""
163− split acc 0 = acc
169+ split acc 1 x = x : acc
164− split acc x = let xbits = x .&. 0x3f
170+ split acc i x = split (x .&. 0x3f : acc) (i - 1) (shiftR x 6)
165− xrest = shiftR x 6 in
171+
166− split (xbits : acc) xrest
172+ pad :: String -> String
167−
173+ pad s = case length s of
168− headHex h 1 = h + 0xc0
174+ 1 -> "0" ++ s
169− headHex h 2 = h + 0xe0
175+ 2 -> s
170− headHex h 3 = h + 0xf0
176+ _ -> error $ "Can't happen: String of invalid length " ++ show s
171− headHex h n = error "Can't happen: Invalid UTF8 character"
175− showHexes = foldr ((++) . showUTF8) ""
176− showUTF8 c = "\"\"\\x" ++ showHex c "\"\""
178bcc :: Int -> BC -> String
178bcc :: Int -> BC -> String
179bcc i (ASSIGN l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"
179bcc i (ASSIGN l r) = indent i ++ creg l ++ " = " ++ creg r ++ ";\n"