summaryrefslogtreecommitdiff
path: root/compiler/utils/Encoding.hs
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2009-02-27 18:00:29 +0000
committerIan Lynagh <igloo@earth.li>2009-02-27 18:00:29 +0000
commit911860671d3f35a52b54869a7a3e7730d7c631dd (patch)
tree58c1dcd74568ddf7f3c437fadf319d8b3c06a088 /compiler/utils/Encoding.hs
parent80b4eda6de2ea0f524e52b59415d84e04f7b1d5d (diff)
downloadhaskell-911860671d3f35a52b54869a7a3e7730d7c631dd.tar.gz
z-encode digits at the start of a symbol name; fixes trac #2997
Digits already have a couple of meanings in z-encoding (Z3T is a tuple, and z123U is a unicode character), so we encode digits as unicode characters to avoid trying to squeeze in another meaning. Also removed a little GHC < 6.2 compatibility hack.
Diffstat (limited to 'compiler/utils/Encoding.hs')
-rw-r--r--compiler/utils/Encoding.hs25
1 files changed, 16 insertions, 9 deletions
diff --git a/compiler/utils/Encoding.hs b/compiler/utils/Encoding.hs
index 33812650dd..35df00478c 100644
--- a/compiler/utils/Encoding.hs
+++ b/compiler/utils/Encoding.hs
@@ -29,9 +29,8 @@ module Encoding (
#include "HsVersions.h"
import Foreign
-import Data.Char ( ord, chr, isDigit, digitToInt, intToDigit,
- isHexDigit )
-import Numeric ( showIntAtBase )
+import Data.Char
+import Numeric
import Data.Bits
import GHC.Ptr ( Ptr(..) )
import GHC.Base
@@ -239,7 +238,9 @@ zEncodeString cs = case maybe_tuple cs of
Nothing -> go cs
where
go [] = []
- go (c:cs) = encode_ch c ++ go cs
+ go (c:cs) = encode_digit_ch c ++ go' cs
+ go' [] = []
+ go' (c:cs) = encode_ch c ++ go' cs
unencodedChar :: Char -> Bool -- True for chars that don't need encoding
unencodedChar 'Z' = False
@@ -248,6 +249,12 @@ unencodedChar c = c >= 'a' && c <= 'z'
|| c >= 'A' && c <= 'Z'
|| c >= '0' && c <= '9'
+-- If a digit is at the start of a symbol then we need to encode it.
+-- Otherwise package names like 9pH-0.1 give linker errors.
+encode_digit_ch :: Char -> EncodedString
+encode_digit_ch c | c >= '0' && c <= '9' = encode_as_unicode_char c
+encode_digit_ch c | otherwise = encode_ch c
+
encode_ch :: Char -> EncodedString
encode_ch c | unencodedChar c = [c] -- Common case first
@@ -279,16 +286,16 @@ encode_ch '/' = "zs"
encode_ch '*' = "zt"
encode_ch '_' = "zu"
encode_ch '%' = "zv"
-encode_ch c = 'z' : if isDigit (head hex_str) then hex_str
- else '0':hex_str
+encode_ch c = encode_as_unicode_char c
+
+encode_as_unicode_char :: Char -> EncodedString
+encode_as_unicode_char c = 'z' : if isDigit (head hex_str) then hex_str
+ else '0':hex_str
where hex_str = showHex (ord c) "U"
-- ToDo: we could improve the encoding here in various ways.
-- eg. strings of unicode characters come out as 'z1234Uz5678U', we
-- could remove the 'U' in the middle (the 'z' works as a separator).
- showHex = showIntAtBase 16 intToDigit
- -- needed because prior to GHC 6.2, Numeric.showHex added a "0x" prefix
-
zDecodeString :: EncodedString -> UserString
zDecodeString [] = []
zDecodeString ('Z' : d : rest)