zenc-0.1.2/0000755000000000000000000000000007346545000010642 5ustar0000000000000000zenc-0.1.2/LICENSE0000644000000000000000000000275707346545000011662 0ustar0000000000000000Copyright (c)2011, Jason Dagit All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Jason Dagit nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. zenc-0.1.2/README.md0000644000000000000000000000073507346545000012126 0ustar0000000000000000# Text.Encoding.Z ## The Z-encoding `zEncodeString` is a name-encoding and decoding function. It encodes any ascii string into a string that is acceptable as a C name. This is code was originally part of GHC and used right before emitting a symbol name into the compiled C or asm code. This library was created as this encoding is useful when working with GHC compiled code or generally when C-compatible name mangling is desired. `zDecodeString` is the inverse operation. zenc-0.1.2/Setup.hs0000644000000000000000000000005607346545000012277 0ustar0000000000000000import Distribution.Simple main = defaultMain zenc-0.1.2/Tests.hs0000644000000000000000000000063307346545000012302 0ustar0000000000000000module Main where import Hedgehog import qualified Hedgehog.Gen as Gen import qualified Hedgehog.Range as Range import Test.Hspec import Test.Hspec.Hedgehog import Text.Encoding.Z main :: IO () main = hspec $ do describe "Round trip" $ do it "self-inverse of arbitrary ascii" $ hedgehog $ do xs <- forAll $ Gen.string (Range.linear 0 100) Gen.ascii zDecodeString (zEncodeString xs) === xs zenc-0.1.2/Text/Encoding/0000755000000000000000000000000007346545000013314 5ustar0000000000000000zenc-0.1.2/Text/Encoding/Z.hs0000644000000000000000000001605007346545000014063 0ustar0000000000000000{-# LANGUAGE Safe #-} {- | The Z-encoding This is the main name-encoding and decoding function. It encodes any string into a string that is acceptable as a C name. This is code was originally part of GHC and used right before emitting a symbol name into the compiled C or asm code. This library was created as this encoding is useful when working with GHC compiled code or generally when C-compatible name mangling is desired. -} module Text.Encoding.Z ( zEncodeString, zDecodeString, UserString, EncodedString ) where import Data.Char import Numeric type UserString = String -- ^ As the user typed it type EncodedString = String -- ^ Encoded form -- | The basic encoding scheme is this: -- -- * Tuples (,,,) are coded as Z3T -- -- * Alphabetic characters (upper and lower) and digits -- all translate to themselves; -- except 'Z', which translates to 'ZZ' -- and 'z', which translates to 'zz' -- We need both so that we can preserve the variable/tycon distinction -- -- * Most other printable characters translate to 'zx' or 'Zx' for some -- alphabetic character x -- -- * The others translate as 'znnnU' where 'nnn' is the decimal number -- of the character -- -- @ -- Before After -- -------------------------- -- Trak Trak -- foo_wib foozuwib -- \> zg -- \>1 zg1 -- foo\# foozh -- foo\#\# foozhzh -- foo\#\#1 foozhzh1 -- fooZ fooZZ -- :+ ZCzp -- () Z0T 0-tuple -- (,,,,) Z5T 5-tuple -- (\# \#) Z1H unboxed 1-tuple (note the space) -- (\#,,,,\#) Z5H unboxed 5-tuple -- (NB: There is no Z1T nor Z0H.) -- @ zEncodeString :: UserString -> EncodedString zEncodeString cs = case maybe_tuple cs of Just n -> n -- Tuples go to Z2T etc Nothing -> go cs where go [] = [] 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 unencodedChar 'z' = False 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 -- Constructors encode_ch '(' = "ZL" -- Needed for things like (,), and (->) encode_ch ')' = "ZR" -- For symmetry with ( encode_ch '[' = "ZM" encode_ch ']' = "ZN" encode_ch ':' = "ZC" encode_ch 'Z' = "ZZ" -- Variables encode_ch 'z' = "zz" encode_ch '&' = "za" encode_ch '|' = "zb" encode_ch '^' = "zc" encode_ch '$' = "zd" encode_ch '=' = "ze" encode_ch '>' = "zg" encode_ch '#' = "zh" encode_ch '.' = "zi" encode_ch '<' = "zl" encode_ch '-' = "zm" encode_ch '!' = "zn" encode_ch '+' = "zp" encode_ch '\'' = "zq" encode_ch '\\' = "zr" encode_ch '/' = "zs" encode_ch '*' = "zt" encode_ch '_' = "zu" encode_ch '%' = "zv" 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). -- | The inverse of 'zEncodeString' zDecodeString :: EncodedString -> UserString zDecodeString [] = [] zDecodeString ('Z' : d : rest) | isDigit d = decode_tuple d rest | otherwise = decode_upper d : zDecodeString rest zDecodeString ('z' : d : rest) | isDigit d = decode_num_esc d rest | otherwise = decode_lower d : zDecodeString rest zDecodeString (c : rest) = c : zDecodeString rest decode_upper, decode_lower :: Char -> Char decode_upper 'L' = '(' decode_upper 'R' = ')' decode_upper 'M' = '[' decode_upper 'N' = ']' decode_upper 'C' = ':' decode_upper 'Z' = 'Z' decode_upper ch = {-pprTrace "decode_upper" (char ch)-} ch decode_lower 'z' = 'z' decode_lower 'a' = '&' decode_lower 'b' = '|' decode_lower 'c' = '^' decode_lower 'd' = '$' decode_lower 'e' = '=' decode_lower 'g' = '>' decode_lower 'h' = '#' decode_lower 'i' = '.' decode_lower 'l' = '<' decode_lower 'm' = '-' decode_lower 'n' = '!' decode_lower 'p' = '+' decode_lower 'q' = '\'' decode_lower 'r' = '\\' decode_lower 's' = '/' decode_lower 't' = '*' decode_lower 'u' = '_' decode_lower 'v' = '%' decode_lower ch = {-pprTrace "decode_lower" (char ch)-} ch -- Characters not having a specific code are coded as z224U (in hex) decode_num_esc :: Char -> EncodedString -> UserString decode_num_esc d rest = go (digitToInt d) rest where go n (c : rest) | isHexDigit c = go (16*n + digitToInt c) rest go n ('U' : rest) = chr n : zDecodeString rest go n other = error ("decode_num_esc: " ++ show n ++ ' ':other) decode_tuple :: Char -> EncodedString -> UserString decode_tuple d rest = go (digitToInt d) rest where -- NB. recurse back to zDecodeString after decoding the tuple, because -- the tuple might be embedded in a longer name. go n (c : rest) | isDigit c = go (10*n + digitToInt c) rest go 0 ('T':rest) = "()" ++ zDecodeString rest go n ('T':rest) = '(' : replicate (n-1) ',' ++ ")" ++ zDecodeString rest go 1 ('H':rest) = "(# #)" ++ zDecodeString rest go n ('H':rest) = '(' : '#' : replicate (n-1) ',' ++ "#)" ++ zDecodeString rest go n other = error ("decode_tuple: " ++ show n ++ ' ':other) {- Tuples are encoded as Z3T or Z3H for 3-tuples or unboxed 3-tuples respectively. No other encoding starts Z * "(# #)" is the tycon for an unboxed 1-tuple (not 0-tuple) There are no unboxed 0-tuples. * "()" is the tycon for a boxed 0-tuple. There are no boxed 1-tuples. -} maybe_tuple :: UserString -> Maybe EncodedString maybe_tuple "(# #)" = Just("Z1H") maybe_tuple ('(' : '#' : cs) = case count_commas (0::Int) cs of (n, '#' : ')' : _) -> Just ('Z' : shows (n+1) "H") _ -> Nothing maybe_tuple "()" = Just("Z0T") maybe_tuple ('(' : cs) = case count_commas (0::Int) cs of (n, ')' : _) -> Just ('Z' : shows (n+1) "T") _ -> Nothing maybe_tuple _ = Nothing count_commas :: Int -> String -> (Int, String) count_commas n (',' : cs) = count_commas (n+1) cs count_commas n cs = (n,cs) zenc-0.1.2/zenc.cabal0000644000000000000000000000250607346545000012570 0ustar0000000000000000Name: zenc Version: 0.1.2 Synopsis: GHC style name Z-encoding and Z-decoding Description: Implements GHC's name mangling. This code was taken directly from the GHC source. License: BSD3 License-file: LICENSE Author: GHC Team, Jason Dagit Maintainer: dagitj@gmail.com Copyright: GHC HQ Category: Text Build-type: Simple Cabal-version: >=1.10 extra-source-files: README.md Library -- Modules exported by the library. Exposed-modules: Text.Encoding.Z -- Packages needed in order to build this package. Build-depends: base >= 3 && <= 5 GHC-options: -O2 default-language: Haskell2010 -- Modules not exported by this package. -- Other-modules: -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source. -- Build-tools: test-suite tests type: exitcode-stdio-1.0 main-is: Tests.hs other-modules: Text.Encoding.Z build-depends: base >= 3 && <= 5 build-depends: hedgehog == 1.0.* build-depends: hspec == 2.8.* build-depends: hspec-hedgehog == 0.0.* default-language: Haskell2010 source-repository this type: git location: https://github.com/dagit/zenc.git tag: 0.1.2