@@ -27,6 +27,10 @@ import Control.Monad.Failure
2727import Data.Typeable (Typeable)
2828import Control.Exception (Exception)
2929
30+import Data.Convertible
31+import Data.Text.Lazy (Text)
32+import Data.Object.Text ()
33+
3034data ParserStruct
3135type Parser = Ptr ParserStruct
3236parserSize :: Int
@@ -73,15 +77,32 @@ foreign import ccall unsafe "yaml_parser_parse"
7377foreign import ccall unsafe "yaml_event_delete"
7478 c_yaml_event_delete :: EventRaw -> IO ()
7579
76−foreign import ccall "print_parser_error"
77− c_print_parser_error :: Parser -> IO ()
80+foreign import ccall "get_parser_error_problem"
81+ c_get_parser_error_problem :: Parser -> IO (Ptr CUChar)
82+
83+foreign import ccall "get_parser_error_context"
84+ c_get_parser_error_context :: Parser -> IO (Ptr CUChar)
85+
86+foreign import ccall unsafe "get_parser_error_offset"
87+ c_get_parser_error_offset :: Parser -> IO CULong
7888
7989data YamlException =
80− YamlParserException String
81− | YamlEmitterException String
90+ YamlParserException
91+ { parserProblem :: String
92+ , parserContext :: String
93+ , parserOffset :: Int
94+ }
95+ | YamlEmitterException { emitterProblem :: String }
8296 deriving (Show, Typeable)
8397instance Exception YamlException
8498
99+makeString :: (a -> IO (Ptr CUChar)) -> a -> IO String
100+makeString f a = do
101+ cchar <- castPtr `fmap` f a
102+ len <- fromIntegral `fmap` B.c_strlen cchar
103+ bs <- B.create len $ \dest -> B.memcpy dest (castPtr cchar) (fromIntegral len)
104+ return $ (convertSuccess :: Text -> String) $ convertSuccess bs
105+
85106parserParseOne :: MonadFailure YamlException m
86107 => Parser
87108 -> IO (m Event)
@@ -89,8 +110,13 @@ parserParseOne parser = withEventRaw $ \er -> do
89110 res <- c_yaml_parser_parse parser er
90111 event <-
91112 if res == 0
92− then c_print_parser_error parser
93− >> return (failure $ YamlParserException "FIXME")
113+ then do
114+ problem <- makeString c_get_parser_error_problem parser
115+ context <- makeString c_get_parser_error_context parser
116+ offset <- fromIntegral `fmap`
117+ c_get_parser_error_offset parser
118+ return $ failure $
119+ YamlParserException problem context offset
94120 else return `fmap` getEvent er
95121 c_yaml_event_delete er
96122 return event
@@ -154,7 +180,7 @@ getEvent er = do
154180 YamlMappingStartEvent -> return EventMappingStart
155181 YamlMappingEndEvent -> return EventMappingEnd
156182
157−data YAttempt v = YSuccess v | YFailure YamlException -- FIXME use c-m-e?
183+data YAttempt v = YSuccess v | YFailure YamlException
158184instance Monad YAttempt where
159185 return = YSuccess
160186 YSuccess v >>= f = f v
@@ -237,8 +263,8 @@ withEmitter f = allocaBytes emitterSize $ \e -> do
237263foreign import ccall unsafe "yaml_emitter_emit"
238264 c_yaml_emitter_emit :: Emitter -> EventRaw -> IO CInt
239265
240−foreign import ccall unsafe "print_emitter_error"
241− c_print_emitter_error :: Emitter -> IO ()
266+foreign import ccall unsafe "get_emitter_error"
267+ c_get_emitter_error :: Emitter -> IO (Ptr CUChar)
242268
243269emitEvents :: MonadFailure YamlException m
244270 => Emitter
@@ -248,8 +274,9 @@ emitEvents _ [] = return $ return ()
248274emitEvents emitter (e:rest) = do
249275 res <- toEventRaw e $ c_yaml_emitter_emit emitter
250276 if res == 0
251− then c_print_emitter_error emitter
252− >> return (failure $ YamlEmitterException "FIXME")
277+ then do
278+ problem <- makeString c_get_emitter_error emitter
279+ return $ failure $ YamlEmitterException problem
253280 else emitEvents emitter rest
254281
255282foreign import ccall unsafe "yaml_stream_start_event_initialize"