1 -- ----------------------------------------------------------------------------
3 -- (c) The University of Glasgow 2006
5 -- Fingerprints for recompilation checking and ABI versioning.
7 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/RecompilationAvoidance
9 -- ----------------------------------------------------------------------------
12 Fingerprint(..), fingerprint0,
18 ##include "HsVersions.h"
25 import Numeric ( readHex )
27 -- Using 128-bit MD5 fingerprints for now.
29 data Fingerprint = Fingerprint {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
33 fingerprint0 :: Fingerprint
34 fingerprint0 = Fingerprint 0 0
36 instance Outputable Fingerprint where
37 ppr (Fingerprint w1 w2) = text (printf "%016x%016x" i1 i2)
38 where i1 = fromIntegral w1 :: Integer
39 i2 = fromIntegral w2 :: Integer
40 -- printf in GHC 6.4.2 didn't have Word64 instances
42 -- useful for parsing the output of 'md5sum', should we want to do that.
43 readHexFingerprint :: String -> Fingerprint
44 readHexFingerprint s = Fingerprint w1 w2
45 where (s1,s2) = splitAt 16 s
46 [(w1,"")] = readHex s1
47 [(w2,"")] = readHex (take 16 s2)
49 peekFingerprint :: Ptr Word8 -> IO Fingerprint
50 peekFingerprint p = do
51 let peekW64 :: Ptr Word8 -> Int -> Word64 -> IO Word64
53 peekW64 _ 0 i = return i
56 peekW64 (p `plusPtr` 1) (n-1)
57 ((i `shiftL` 8) .|. fromIntegral w8)
60 low <- peekW64 (p `plusPtr` 8) 8 0
61 return (Fingerprint high low)
63 fingerprintData :: Ptr Word8 -> Int -> IO Fingerprint
64 fingerprintData buf len = do
65 allocaBytes (#const sizeof(struct MD5Context)) $ \pctxt -> do
67 c_MD5Update pctxt buf (fromIntegral len)
68 allocaBytes 16 $ \pdigest -> do
69 c_MD5Final pdigest pctxt
70 peekFingerprint (castPtr pdigest)
74 foreign import ccall unsafe "MD5Init"
75 c_MD5Init :: Ptr MD5Context -> IO ()
76 foreign import ccall unsafe "MD5Update"
77 c_MD5Update :: Ptr MD5Context -> Ptr Word8 -> CInt -> IO ()
78 foreign import ccall unsafe "MD5Final"
79 c_MD5Final :: Ptr Word8 -> Ptr MD5Context -> IO ()