encoding/Data/Encoding/Preprocessor/Mapping.hs
Henning Guenther 73eefc2838 Removed obsolete import
Ignore-this: 1dbf628a27fb6b26d38dbf30e17f3a5e

darcs-hash:20090813024342-a4fee-54437c7ba6ea62ac454a6d1d4dc31c721b227d9f
2009-08-12 19:43:42 -07:00

140 lines
6.7 KiB
Haskell

module Data.Encoding.Preprocessor.Mapping where
import Distribution.Simple.PreProcess
import Distribution.Simple.Utils
import System.IO
import System.FilePath
import Data.List (intersperse,unfoldr)
import Data.Maybe
import Data.Char
import Data.Word
import Data.Ix
import Data.Bits
import Data.Array.Static.Builder
import Data.CharMap.Builder
data MappingType
= ISOMapping
| JISMapping
deriving (Eq,Ord,Show,Read)
readTranslation :: Int -> FilePath -> IO [(Integer,Maybe Char)]
readTranslation offset file = do
cont <- readFile file
return $ mapMaybe (\ln -> case drop offset ln of
[src] -> Just (src,Nothing)
[src,trg] -> Just (src,Just $ chr $ fromIntegral trg)
_ -> Nothing) (parseTranslationTable cont)
parseTranslationTable :: String -> [[Integer]]
parseTranslationTable cont = filter (not.null) (map (\ln -> map read (takeWhile ((/='#').head) (words ln))) (lines cont))
{-fillTranslations :: (Ix a,Show a) => a -> a -> [(a,Maybe Char)] -> [(a,Maybe Char)]
fillTranslations f t = merge (range (f,t))
where
merge xs [] = map (\x -> (x,Nothing)) xs
merge [] cs = error $ "Data.Encoding.Helper.Template.fillTranslations: Character translations out of range: " ++ show cs
merge (x:xs) (y:ys) = if x < fst y
then (x,Nothing):(merge xs (y:ys))
else y:(merge xs ys)-}
fillTranslations :: (Enum a,Eq a) => [(a,Maybe Char)] -> (a,a,[Maybe Char])
fillTranslations [] = error "fillTranslations: zero elements"
fillTranslations ((s,c):rest) = let (e,r) = fill' s rest
fill' cur [] = (cur,[])
fill' cur all@((n,c):rest2) = if succ cur == n
then (let (e',res) = fill' n rest2
in (e',c:res))
else (let (e',res) = fill' (succ cur) all
in (e',Nothing:res))
in (s,e,c:r)
validTranslations :: [(a,Maybe Char)] -> [(a,Char)]
validTranslations = mapMaybe (\(n,mc) -> case mc of
Nothing -> Nothing
Just c -> Just (n,c))
mappingPreprocessor :: PreProcessor
mappingPreprocessor = PreProcessor
{platformIndependent = True
,runPreProcessor = \(sbase,sfile) (tbase,tfile) verb -> do
let (dir,fn) = splitFileName sfile
let (bname,ext) = splitExtensions fn
let dirs = splitDirectories dir
let tp = case ext of
".mapping" -> ISOMapping
".mapping2" -> JISMapping
info verb (tfile++" generated from mapping "++sfile)
preprocessMapping tp (sbase </> sfile) (tbase </> tfile) dirs bname
}
preprocessMapping :: MappingType -> FilePath -> FilePath -> [String] -> String -> IO ()
preprocessMapping tp src trg mods name = do
trans <- readTranslation 0 src
let mod = concat $ intersperse "." (mods++[name])
let wsize = case tp of
ISOMapping -> 1
JISMapping -> 2
let bsize = show (wsize*8) ++ (if wsize > 1 then "be" else "")
--let (larr,off,arr) = staticArray32 trans
let (sarr,earr,els) = fillTranslations trans
{-let (lmp,idx,val) = staticMap wsize trans-}
let arrname = "decoding_array_"++name
let mpname = "encoding_map_"++name
let bcheck exp = if sarr/=0 || earr/=255
then ("(if "++
concat (intersperse "||" $ (if sarr/=0 then ["w<"++show sarr] else [])++(if earr/=255 then ["w>"++show earr] else []))++
" then throwException $ IllegalCharacter $ fromIntegral w else "++exp++")"
) else exp
let mp = buildCharMap (mapMaybe (\(i,c) -> do
rc <- c
return $ SingleMapping
rc
(reverse $ unfoldr (\(w,n) -> if n == 0
then Nothing
else Just (fromIntegral w,(w `shiftR` 8,n-1))) (i,wsize))
) trans
)
{-let mp = case wsize of
1 -> buildStaticMap (mapMaybe (\(i,c) -> case c of
Nothing -> Nothing
Just rc -> Just (rc,fromIntegral i::Word8)) trans)
2 -> buildStaticMap (mapMaybe (\(i,c) -> case c of
Nothing -> Nothing
Just rc -> Just (rc,fromIntegral i::Word16)) trans)-}
writeFile trg $ unlines $
["{-# LANGUAGE MagicHash,DeriveDataTypeable #-}"
,"module "++mod++"("++name++"(..)) where"
,""
,"import Data.Encoding.Base"
,"import Data.Encoding.ByteSource"
,"import Data.Encoding.ByteSink"
,"import Data.Encoding.Exception"
,"import Data.CharMap"
,"import Data.Array.Static"
,"import Data.Map.Static"
,"import Control.Throws"
,"import Prelude hiding (lookup)"
,"import Data.Word"
,""
,"import Data.Typeable"
,""
,"data "++name++" = "++name
," deriving (Show,Eq,Typeable)"
,""
,arrname++" = "++buildStaticArray (sarr,earr) els
,""
,mpname++" :: CharMap"
,mpname++" = "++mp
,""
,"instance Encoding "++name++" where"
," decodeChar _ = do"
," w <- fetchWord"++bsize
," "++bcheck "return ()"
," case "++arrname++"!w of"
," Nothing -> throwException $ IllegalCharacter $ fromIntegral w"
," Just c -> return c"
," encodeChar _ c = mapEncode c "++mpname
," encodeable _ c = mapMember c "++mpname
]