root/compiler/utils/Fingerprint.hsc

Revision 8f57a40b4bdd0c57419ce08f75a005ef7e67563f, 3.1 KB (checked in by Ian Lynagh <igloo@…>, 10 months ago)

Sync the typeable fingerprinting with base

  • Property mode set to 100644
Line 
1-- ----------------------------------------------------------------------------
2--
3--  (c) The University of Glasgow 2006
4--
5-- Fingerprints for recompilation checking and ABI versioning.
6--
7-- http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/RecompilationAvoidance
8--
9-- ----------------------------------------------------------------------------
10
11module Fingerprint (
12        Fingerprint(..), fingerprint0,
13        readHexFingerprint,
14        fingerprintData,
15        fingerprintString
16   ) where
17
18#include "md5.h"
19##include "HsVersions.h"
20
21import Outputable
22
23import Text.Printf
24import Numeric          ( readHex )
25
26##if __GLASGOW_HASKELL__ >= 701
27-- The MD5 implementation is now in base, to support Typeable
28import GHC.Fingerprint
29##endif
30
31##if __GLASGOW_HASKELL__ < 701
32import Data.Char
33import Foreign
34import Foreign.C
35import GHC.IO (unsafeDupablePerformIO)
36
37-- Using 128-bit MD5 fingerprints for now.
38
39data Fingerprint = Fingerprint {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
40  deriving (Eq, Ord)
41        -- or ByteString?
42
43fingerprint0 :: Fingerprint
44fingerprint0 = Fingerprint 0 0
45
46peekFingerprint :: Ptr Word8 -> IO Fingerprint
47peekFingerprint p = do
48      let peekW64 :: Ptr Word8 -> Int -> Word64 -> IO Word64
49          STRICT3(peekW64)
50          peekW64 _ 0 i = return i
51          peekW64 p n i = do
52                w8 <- peek p
53                peekW64 (p `plusPtr` 1) (n-1)
54                    ((i `shiftL` 8) .|. fromIntegral w8)
55
56      high <- peekW64 p 8 0
57      low  <- peekW64 (p `plusPtr` 8) 8 0
58      return (Fingerprint high low)
59
60fingerprintData :: Ptr Word8 -> Int -> IO Fingerprint
61fingerprintData buf len = do
62  allocaBytes (#const sizeof(struct MD5Context)) $ \pctxt -> do
63    c_MD5Init pctxt
64    c_MD5Update pctxt buf (fromIntegral len)
65    allocaBytes 16 $ \pdigest -> do
66      c_MD5Final pdigest pctxt
67      peekFingerprint (castPtr pdigest)
68
69-- This is duplicated in libraries/base/GHC/Fingerprint.hs
70fingerprintString :: String -> Fingerprint
71fingerprintString str = unsafeDupablePerformIO $
72  withArrayLen word8s $ \len p ->
73     fingerprintData p len
74    where word8s = concatMap f str
75          f c = let w32 :: Word32
76                    w32 = fromIntegral (ord c)
77                in [fromIntegral (w32 `shiftR` 24),
78                    fromIntegral (w32 `shiftR` 16),
79                    fromIntegral (w32 `shiftR` 8),
80                    fromIntegral w32]
81
82data MD5Context
83
84foreign import ccall unsafe "MD5Init"
85   c_MD5Init   :: Ptr MD5Context -> IO ()
86foreign import ccall unsafe "MD5Update"
87   c_MD5Update :: Ptr MD5Context -> Ptr Word8 -> CInt -> IO ()
88foreign import ccall unsafe "MD5Final"
89   c_MD5Final  :: Ptr Word8 -> Ptr MD5Context -> IO ()
90##endif
91
92instance Outputable Fingerprint where
93  ppr (Fingerprint w1 w2) = text (printf "%016x%016x" i1 i2)
94    where i1 = fromIntegral w1 :: Integer
95          i2 = fromIntegral w2 :: Integer
96          -- printf in GHC 6.4.2 didn't have Word64 instances
97
98-- useful for parsing the output of 'md5sum', should we want to do that.
99readHexFingerprint :: String -> Fingerprint
100readHexFingerprint s = Fingerprint w1 w2
101 where (s1,s2) = splitAt 16 s
102       [(w1,"")] = readHex s1
103       [(w2,"")] = readHex (take 16 s2)
Note: See TracBrowser for help on using the browser.