1 ---------------------------------------------------------
2 -- The main program for the hpc-add tool, part of HPC.
4 ---------------------------------------------------------
6 module HpcCombine (combine_plugin) where
14 import qualified HpcSet as Set
15 import qualified HpcMap as Map
16 import System.Environment
18 ------------------------------------------------------------------------------
20 [ excludeOpt,includeOpt,outputOpt,combineFunOpt, combineFunOptInfo, postInvertOpt ]
22 combine_plugin = Plugin { name = "combine"
23 , usage = "[OPTION] .. <TIX_FILE> [<TIX_FILE> [<TIX_FILE> ..]]"
24 , options = combine_options
25 , summary = "Combine multiple .tix files in a single .tix files"
26 , implementation = combine_main
27 , init_flags = default_flags
28 , final_flags = default_final_flags
31 ------------------------------------------------------------------------------
33 combine_main :: Flags -> [String] -> IO ()
34 combine_main flags (first_file:more_files) = do
35 -- combine does not expand out the .tix filenames (by design).
37 let f = case combineFun flags of
39 SUB -> \ l r -> max 0 (l - r)
40 DIFF -> \ g b -> if g > 0 then 0 else min 1 b
43 Just tix <- readTix first_file
45 tix' <- foldM (mergeTixFile flags f)
49 let (Tix inside_tix') = tix'
52 let tix'' = if postInvert flags
53 then Tix [ TixModule m p i (map inv t)
54 | TixModule m p i t <- inside_tix'
58 case outputFile flags of
59 "-" -> putStrLn (show tix'')
60 out -> writeTix out tix''
62 mergeTixFile :: Flags -> (Integer -> Integer -> Integer) -> Tix -> String -> IO Tix
63 mergeTixFile flags fn tix file_name = do
64 Just new_tix <- readTix file_name
65 return $! strict $ mergeTix fn tix (filterTix flags new_tix)
67 -- could allow different numbering on the module info,
68 -- as long as the total is the same; will require normalization.
70 mergeTix :: (Integer -> Integer -> Integer) -> Tix -> Tix -> Tix
74 [ case (Map.lookup m fm1,Map.lookup m fm2) of
75 -- todo, revisit the semantics of this combination
76 (Just (TixModule _ hash1 len1 tix1),Just (TixModule _ hash2 len2 tix2))
78 || length tix1 /= length tix2
79 || len1 /= length tix1
80 || len2 /= length tix2
81 -> error $ "mismatched in module " ++ m
83 TixModule m hash1 len1 (zipWith f tix1 tix2)
84 (Just (TixModule _ hash1 len1 tix1),Nothing) ->
85 error $ "rogue module " ++ show m
86 (Nothing,Just (TixModule _ hash2 len2 tix2)) ->
87 error $ "rogue module " ++ show m
88 _ -> error "impossible"
89 | m <- Set.toList (m1s `Set.intersection` m2s)
92 m1s = Set.fromList $ map tixModuleName t1
93 m2s = Set.fromList $ map tixModuleName t2
95 fm1 = Map.fromList [ (tixModuleName tix,tix)
98 fm2 = Map.fromList [ (tixModuleName tix,tix)
103 -- What I would give for a hyperstrict :-)
104 -- This makes things about 100 times faster.
108 instance Strict Integer where
111 instance Strict Int where
114 instance Strict Hash where -- should be fine, because Hash is a newtype round an Int
117 instance Strict Char where
120 instance Strict a => Strict [a] where
121 strict (a:as) = (((:) $! strict a) $! strict as)
124 instance (Strict a, Strict b) => Strict (a,b) where
125 strict (a,b) = (((,) $! strict a) $! strict b)
127 instance Strict Tix where
131 instance Strict TixModule where
132 strict (TixModule m1 p1 i1 t1) =
133 ((((TixModule $! strict m1) $! strict p1) $! strict i1) $! strict t1)