@@ -1,13 +1,16 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE NoMonomorphismRestriction #-}
4{-# LANGUAGE NoMonomorphismRestriction #-}
4{-# LANGUAGE NamedFieldPuns #-}
5{-# LANGUAGE NamedFieldPuns #-}
6+{-# OPTIONS_GHC -funbox-strict-fields -O #-}
5module Data.Terminfo.Parse ( module Data.Terminfo.Parse
7module Data.Terminfo.Parse ( module Data.Terminfo.Parse
6 , Text.ParserCombinators.Parsec.ParseError
8 , Text.ParserCombinators.Parsec.ParseError
10import Control.Monad ( liftM )
12import Control.Monad ( liftM )
13+import Control.Parallel.Strategies
12import Data.Array.Unboxed
15import Data.Array.Unboxed
13import Data.Monoid
16import Data.Monoid
@@ -20,33 +23,44 @@ type BytesOffset = Word8
20type CapBytes = UArray Word8 Word8
23type CapBytes = UArray Word8 Word8
22data CapExpression = CapExpression
25data CapExpression = CapExpression
23− { cap_ops :: CapOps
26+ { cap_ops :: !CapOps
24− , cap_bytes :: CapBytes
27+ , cap_bytes :: !CapBytes
25− , source_string :: String
28+ , source_string :: !String
26− , param_count :: Word
29+ , param_count :: !Word
27− , param_ops :: ParamOps
30+ , param_ops :: !ParamOps
33+instance NFData CapExpression where
34+ rnf (CapExpression ops !_bytes !_str !_c !_p_ops)
30type CapParam = Word
37type CapParam = Word
32type CapOps = [CapOp]
39type CapOps = [CapOp]
33data CapOp =
40data CapOp =
34− Bytes (BytesOffset, BytesLength)
41+ Bytes !BytesOffset !BytesLength
35− | DecOut
42+ | DecOut | CharOut
36 -- This stores a 0-based index to the parameter. However the operation that implies this op is
43 -- This stores a 0-based index to the parameter. However the operation that implies this op is
37 -- 1-based
44 -- 1-based
38− | PushParam !Word
45+ | PushParam !Word | PushValue !Word
39 -- The conditional parts are the sequence of (%t expression, %e expression) pairs.
46 -- The conditional parts are the sequence of (%t expression, %e expression) pairs.
40 -- The %e expression may be NOP
47 -- The %e expression may be NOP
41 | Conditional
48 | Conditional
42− { conditional_expr :: CapOps
49+ { conditional_expr :: !CapOps
43− , conditional_parts :: [(CapOps, CapOps)]
50+ , conditional_parts :: ![(CapOps, CapOps)]
45− | BitwiseOr
52+ | BitwiseOr | BitwiseXOr | BitwiseAnd
46− | CompareEq
54+ | CompareEq | CompareLt | CompareGt
48 deriving ( Show )
55 deriving ( Show )
57+instance NFData CapOp where
58+ rnf (Bytes offset c) = rnf offset >| rnf c
59+ rnf (PushParam !_pn) = ()
60+ rnf (PushValue !_v) = ()
61+ rnf (Conditional c_expr c_parts) = rnf c_expr >| rnf c_parts
50type ParamOps = [ParamOp]
64type ParamOps = [ParamOp]
51data ParamOp =
65data ParamOp =
52 IncFirstTwo
66 IncFirstTwo
@@ -61,16 +75,18 @@ parse_cap_expression cap_string =
61 in case v of
75 in case v of
62 Left e -> Left e
76 Left e -> Left e
63 Right build_results ->
77 Right build_results ->
64− Right $ CapExpression
78+ Right $! ( CapExpression
65− { cap_ops = out_cap_ops build_results
79+ { cap_ops = out_cap_ops build_results
66− -- The cap bytes are the lower 8 bits of the input string's characters.
80+ -- The cap bytes are the lower 8 bits of the input string's characters.
67− -- \todo Verify the input string actually contains an 8bit byte per character.
81+ -- \todo Verify the input string actually contains an 8bit byte per character.
68− , cap_bytes = listArray (0, toEnum $ length cap_string - 1)
82+ , cap_bytes = listArray (0, toEnum $ length cap_string - 1)
69− $ map (toEnum . fromEnum) cap_string
83+ $ map (toEnum . fromEnum) cap_string
70− , source_string = cap_string
84+ , source_string = cap_string
71− , param_count = out_param_count build_results
85+ , param_count = out_param_count build_results
72− , param_ops = out_param_ops build_results
86+ , param_ops = out_param_ops build_results
75type CapParser a = GenParser Char BuildState a
91type CapParser a = GenParser Char BuildState a
@@ -90,17 +106,20 @@ literal_percent_parser = do
91 start_offset <- getState >>= return . next_offset
107 start_offset <- getState >>= return . next_offset
92 inc_offset 1
108 inc_offset 1
93− return $ BuildResults 0 [Bytes (start_offset, 1)] []
109+ return $ BuildResults 0 [Bytes start_offset 1] []
95param_op_parser :: CapParser BuildResults
111param_op_parser :: CapParser BuildResults
96param_op_parser
112param_op_parser
97 = increment_op_parser
113 = increment_op_parser
98 <|> push_op_parser
114 <|> push_op_parser
99 <|> dec_out_parser
115 <|> dec_out_parser
100 <|> conditional_op_parser
117 <|> conditional_op_parser
101 <|> bitwise_op_parser
118 <|> bitwise_op_parser
102 <|> literal_int_op_parser
120 <|> literal_int_op_parser
103 <|> compare_op_parser
121 <|> compare_op_parser
122+ <|> char_const_parser
105increment_op_parser :: CapParser BuildResults
124increment_op_parser :: CapParser BuildResults
106increment_op_parser = do
125increment_op_parser = do
@@ -121,6 +140,12 @@ dec_out_parser = do
121 inc_offset 1
140 inc_offset 1
122 return $ BuildResults 0 [ DecOut ] []
141 return $ BuildResults 0 [ DecOut ] []
143+char_out_parser :: CapParser BuildResults
147+ return $ BuildResults 0 [ CharOut ] []
124conditional_op_parser :: CapParser BuildResults
149conditional_op_parser :: CapParser BuildResults
125conditional_op_parser = do
150conditional_op_parser = do
@@ -156,11 +181,11 @@ conditional_op_parser = do
156 return $ BuildResults n'' [ Conditional cond cond_parts ] p_ops
181 return $ BuildResults n'' [ Conditional cond cond_parts ] p_ops
159− many_p p end = choice
184+ many_p !p !end = choice
160 [ try end >> return []
185 [ try end >> return []
161− , do v <- p
186+ , do !v <- p
162− vs <- many_p p end
187+ !vs <- many_p p end
163− return $ v : vs
188+ return $! v : vs
165 many_expr end = liftM mconcat $ many_p ( param_escape_parser <|> bytes_op_parser ) end
190 many_expr end = liftM mconcat $ many_p ( param_escape_parser <|> bytes_op_parser ) end
@@ -180,8 +205,10 @@ conditional_end_parser = do
180 inc_offset 2
205 inc_offset 2
182bitwise_op_parser :: CapParser BuildResults
207bitwise_op_parser :: CapParser BuildResults
183−bitwise_op_parser = do
208+bitwise_op_parser
184− bitwise_or_parser
209+ = bitwise_or_parser
210+ <|> bitwise_and_parser
211+ <|> bitwise_xor_parser
186bitwise_or_parser :: CapParser BuildResults
213bitwise_or_parser :: CapParser BuildResults
187bitwise_or_parser = do
214bitwise_or_parser = do
@@ -189,22 +216,53 @@ bitwise_or_parser = do
189 inc_offset 1
216 inc_offset 1
190 return $ BuildResults 0 [ BitwiseOr ] [ ]
217 return $ BuildResults 0 [ BitwiseOr ] [ ]
219+bitwise_and_parser :: CapParser BuildResults
220+bitwise_and_parser = do
223+ return $ BuildResults 0 [ BitwiseAnd ] [ ]
225+bitwise_xor_parser :: CapParser BuildResults
226+bitwise_xor_parser = do
229+ return $ BuildResults 0 [ BitwiseXOr ] [ ]
231+arith_op_parser :: CapParser BuildResults
235+ return $ BuildResults 0 [ ArithPlus ] [ ]
192literal_int_op_parser :: CapParser BuildResults
237literal_int_op_parser :: CapParser BuildResults
193literal_int_op_parser = do
238literal_int_op_parser = do
195 inc_offset 1
240 inc_offset 1
196 n_str <- many1 digit
241 n_str <- many1 digit
197 inc_offset $ toEnum $ length n_str
242 inc_offset $ toEnum $ length n_str
198− let n = read n_str
243+ let n :: Word = read n_str
200 inc_offset 1
245 inc_offset 1
201− return $ BuildResults 0 [ LiteralInt n ] [ ]
246+ return $ BuildResults 0 [ PushValue n ] [ ]
203compare_op_parser :: CapParser BuildResults
248compare_op_parser :: CapParser BuildResults
204−compare_op_parser = do
249+compare_op_parser
205− char '='
255+ char '='
206− inc_offset 1
256+ inc_offset 1
207− return $ BuildResults 0 [ CompareEq ] [ ]
257+ return $ BuildResults 0 [ CompareEq ] [ ]
261+ return $ BuildResults 0 [ CompareLt ] [ ]
265+ return $ BuildResults 0 [ CompareGt ] [ ]
209bytes_op_parser :: CapParser BuildResults
267bytes_op_parser :: CapParser BuildResults
210bytes_op_parser = do
268bytes_op_parser = do
@@ -214,7 +272,15 @@ bytes_op_parser = do
214 !s <- getState
272 !s <- getState
215 let s' = s { next_offset = start_offset + c }
273 let s' = s { next_offset = start_offset + c }
216 setState s'
274 setState s'
217− return $ BuildResults 0 [Bytes (start_offset, c)] []
275+ return $ BuildResults 0 [Bytes start_offset c] []
277+char_const_parser :: CapParser BuildResults
278+char_const_parser = do
280+ char_value <- liftM (toEnum . fromEnum) anyChar
283+ return $ BuildResults 0 [ PushValue char_value ] [ ]
219data BuildState = BuildState
285data BuildState = BuildState
220 { next_offset :: Word8
286 { next_offset :: Word8
@@ -230,9 +296,9 @@ initial_build_state :: BuildState
230initial_build_state = BuildState 0
296initial_build_state = BuildState 0
232data BuildResults = BuildResults
298data BuildResults = BuildResults
233− { out_param_count :: Word
299+ { out_param_count :: !Word
234− , out_cap_ops :: CapOps
300+ , out_cap_ops :: !CapOps
235− , out_param_ops :: ParamOps
301+ , out_param_ops :: !ParamOps
238instance Monoid BuildResults where
304instance Monoid BuildResults where