module Text.XML.Expat.Internal.IO (
Parser, newParser,
parse, parse',
withParser,
ParserPtr, Parser_struct,
parseChunk,
Encoding(..),
XMLParseError(..),
getParseLocation,
XMLParseLocation(..),
XMLDeclarationHandler,
StartElementHandler,
EndElementHandler,
CharacterDataHandler,
ExternalEntityRefHandler,
SkippedEntityHandler,
StartCDataHandler,
EndCDataHandler,
CommentHandler,
ProcessingInstructionHandler,
setXMLDeclarationHandler,
setStartElementHandler,
setEndElementHandler,
setCharacterDataHandler,
setStartCDataHandler,
setEndCDataHandler,
setProcessingInstructionHandler,
setCommentHandler,
setExternalEntityRefHandler,
setSkippedEntityHandler,
setUseForeignDTD,
parseExternalEntityReference,
ExpatHandlers,
encodingToString
) where
import Control.Concurrent
import Control.Exception (bracket)
import Control.DeepSeq
import Control.Monad
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import Data.IORef
import Foreign
import Foreign.C
data Parser_struct
type ParserPtr = Ptr Parser_struct
data Parser = Parser
{ _parserObj :: ForeignPtr Parser_struct
, _xmlDeclarationHandler :: IORef CXMLDeclarationHandler
, _startElementHandler :: IORef CStartElementHandler
, _endElementHandler :: IORef CEndElementHandler
, _cdataHandler :: IORef CCharacterDataHandler
, _externalEntityRefHandler :: IORef (Maybe CExternalEntityRefHandler)
, _skippedEntityHandler :: IORef (Maybe CSkippedEntityHandler)
, _startCDataHandler :: IORef CStartCDataHandler
, _endCDataHandler :: IORef CEndCDataHandler
, _processingInstructionHandler :: IORef CProcessingInstructionHandler
, _commentHandler :: IORef CCommentHandler
}
instance Show Parser where
showsPrec _ (Parser fp _ _ _ _ _ _ _ _ _ _) = showsPrec 0 fp
data Encoding = ASCII | UTF8 | UTF16 | ISO88591
encodingToString :: Encoding -> String
encodingToString ASCII = "US-ASCII"
encodingToString UTF8 = "UTF-8"
encodingToString UTF16 = "UTF-16"
encodingToString ISO88591 = "ISO-8859-1"
withOptEncoding :: Maybe Encoding -> (CString -> IO a) -> IO a
withOptEncoding Nothing f = f nullPtr
withOptEncoding (Just enc) f = withCString (encodingToString enc) f
parserCreate :: Maybe Encoding -> IO (ParserPtr)
parserCreate a1 =
withOptEncoding a1 $ \a1' -> do
pp <- parserCreate'_ a1'
xmlSetUserData pp pp
return pp
newParser :: Maybe Encoding -> IO Parser
newParser enc = do
ptr <- parserCreate enc
fptr <- newForeignPtr parserFree ptr
nullXMLDeclH <- newIORef nullCXMLDeclarationHandler
nullStartH <- newIORef nullCStartElementHandler
nullEndH <- newIORef nullCEndElementHandler
nullCharH <- newIORef nullCCharacterDataHandler
extH <- newIORef Nothing
skipH <- newIORef Nothing
nullSCDataH <- newIORef nullCStartCDataHandler
nullECDataH <- newIORef nullCEndCDataHandler
nullPIH <- newIORef nullCProcessingInstructionHandler
nullCommentH <- newIORef nullCCommentHandler
return $ Parser fptr nullXMLDeclH nullStartH nullEndH nullCharH extH skipH
nullSCDataH nullECDataH nullPIH nullCommentH
setUseForeignDTD :: Parser -> Bool -> IO ()
setUseForeignDTD p b = withParser p $ \p' -> xmlUseForeignDTD p' b'
where
b' = if b then 1 else 0
withBStringLen :: BS.ByteString -> ((CString, CInt) -> IO a) -> IO a
withBStringLen bs f = do
BS.useAsCStringLen bs $ \(str, len) -> f (str, fromIntegral len)
unStatus :: CInt -> Bool
unStatus 0 = False
unStatus _ = True
parse :: Parser -> BSL.ByteString -> IO (Maybe XMLParseError)
parse parser bs = withParser parser $ \pp -> do
let
doParseChunks [] = doParseChunk pp BS.empty True
doParseChunks (c:cs) = do
ok <- doParseChunk pp c False
if ok
then doParseChunks cs
else return False
ok <- doParseChunks (BSL.toChunks bs)
if ok
then return Nothing
else Just `fmap` getError pp
parse' :: Parser -> BS.ByteString -> IO (Maybe XMLParseError)
parse' parser bs = withParser parser $ \pp -> do
ok <- doParseChunk pp bs True
if ok
then return Nothing
else Just `fmap` getError pp
parseExternalEntityReference :: Parser
-> CString
-> Maybe Encoding
-> CStringLen
-> IO Bool
parseExternalEntityReference parser context encoding (text,sz) =
withParser parser $ \pp -> do
extp <- withOptEncoding encoding $
xmlExternalEntityParserCreate pp context
e <- doParseChunk'_ extp text (fromIntegral sz) 1
parserFree' extp
return $ e == 1
parseChunk :: ParserPtr
-> BS.ByteString
-> Bool
-> IO (Maybe XMLParseError)
parseChunk pp xml final = do
ok <- doParseChunk pp xml final
if ok
then return Nothing
else Just `fmap` getError pp
getError :: ParserPtr -> IO XMLParseError
getError pp = do
code <- xmlGetErrorCode pp
cerr <- xmlErrorString code
err <- peekCString cerr
loc <- getParseLocation pp
return $ XMLParseError err loc
data ExpatHandlers = ExpatHandlers
(FunPtr CXMLDeclarationHandler)
(FunPtr CStartElementHandler)
(FunPtr CEndElementHandler)
(FunPtr CCharacterDataHandler)
(Maybe (FunPtr CExternalEntityRefHandler))
(Maybe (FunPtr CSkippedEntityHandler))
(FunPtr CStartCDataHandler)
(FunPtr CEndCDataHandler)
(FunPtr CProcessingInstructionHandler)
(FunPtr CCommentHandler)
withParser :: Parser
-> (ParserPtr -> IO a)
-> IO a
withParser parser@(Parser fp _ _ _ _ _ _ _ _ _ _) code = withForeignPtr fp $ \pp -> do
bracket
(unsafeSetHandlers parser pp)
unsafeReleaseHandlers
(\_ -> code pp)
where
unsafeSetHandlers :: Parser -> ParserPtr -> IO ExpatHandlers
unsafeSetHandlers (Parser _ xmlDeclRef startRef endRef charRef extRef skipRef
startCDataRef endCDataRef processingInstructionRef commentRef) pp =
do
cXMLDeclH <- mkCXMLDeclarationHandler =<< readIORef xmlDeclRef
cStartH <- mkCStartElementHandler =<< readIORef startRef
cEndH <- mkCEndElementHandler =<< readIORef endRef
cCharH <- mkCCharacterDataHandler =<< readIORef charRef
mExtH <- readIORef extRef >>=
maybe (return Nothing)
(\h -> liftM Just $ mkCExternalEntityRefHandler h)
mSkipH <- readIORef skipRef >>=
maybe (return Nothing)
(\h -> liftM Just $ mkCSkippedEntityHandler h)
cStartCDataH <- mkCStartCDataHandler =<< readIORef startCDataRef
cEndCDataH <- mkCEndCDataHandler =<< readIORef endCDataRef
cProcessingInstructionH <- mkCProcessingInstructionHandler =<< readIORef processingInstructionRef
cCommentH <- mkCCommentHandler =<< readIORef commentRef
xmlSetxmldeclhandler pp cXMLDeclH
xmlSetstartelementhandler pp cStartH
xmlSetendelementhandler pp cEndH
xmlSetcharacterdatahandler pp cCharH
xmlSetstartcdatahandler pp cStartCDataH
xmlSetendcdatahandler pp cEndCDataH
xmlSetprocessinginstructionhandler pp cProcessingInstructionH
xmlSetcommenthandler pp cCommentH
maybe (return ())
(xmlSetExternalEntityRefHandler pp)
mExtH
maybe (return ())
(xmlSetSkippedEntityHandler pp)
mSkipH
return $ ExpatHandlers cXMLDeclH cStartH cEndH cCharH mExtH mSkipH
cStartCDataH cEndCDataH cProcessingInstructionH cCommentH
unsafeReleaseHandlers :: ExpatHandlers -> IO ()
unsafeReleaseHandlers (ExpatHandlers cXMLDeclH cStartH cEndH cCharH mcExtH mcSkipH
cStartCDataH cEndCDataH cProcessingInstructionH cCommentH) = do
freeHaskellFunPtr cXMLDeclH
freeHaskellFunPtr cStartH
freeHaskellFunPtr cEndH
freeHaskellFunPtr cCharH
maybe (return ()) freeHaskellFunPtr mcExtH
maybe (return ()) freeHaskellFunPtr mcSkipH
freeHaskellFunPtr cStartCDataH
freeHaskellFunPtr cEndCDataH
freeHaskellFunPtr cProcessingInstructionH
freeHaskellFunPtr cCommentH
cFromBool :: Num a => Bool -> a
cFromBool = fromBool
doParseChunk :: ParserPtr -> BS.ByteString -> Bool -> IO (Bool)
doParseChunk = ensureBoundThread $ \a1 a2 a3 ->
withBStringLen a2 $ \(a2'1, a2'2) ->
let {a3' = cFromBool a3} in
doParseChunk'_ a1 a2'1 a2'2 a3' >>= \res ->
let {res' = unStatus res} in
return (res')
data WorkerIface = WorkerIface (MVar (ParserPtr, BS.ByteString, Bool)) (MVar Bool)
workerIfaceRef :: IORef (Maybe WorkerIface)
workerIfaceRef = unsafePerformIO $ newIORef Nothing
ensureBoundThread :: (ParserPtr -> BS.ByteString -> Bool -> IO Bool)
-> ParserPtr
-> BS.ByteString
-> Bool
-> IO Bool
ensureBoundThread doit p bs last = do
bound <- isCurrentThreadBound
if rtsSupportsBoundThreads && not bound
then delegate
else doit p bs last
where
delegate = do
mIface <- readIORef workerIfaceRef
case mIface of
Just iface -> pipeTo iface
Nothing -> do
inV <- newEmptyMVar
outV <- newEmptyMVar
let iface = WorkerIface inV outV
justSetItGlobally <- atomicModifyIORef workerIfaceRef $ \mIface ->
case mIface of
Just _ -> (mIface, False)
Nothing -> (Just iface, True)
if justSetItGlobally
then do
_ <- forkOS $ worker iface
pipeTo iface
else
delegate
pipeTo (WorkerIface inV outV) =
putMVar inV (p, bs, last) >> takeMVar outV
worker (WorkerIface inV outV) = forever $
putMVar outV =<< uncurry3 doit =<< takeMVar inV
where
uncurry3 f (a, b, c) = f a b c
data XMLParseError = XMLParseError String XMLParseLocation deriving (Eq, Show)
instance NFData XMLParseError where
rnf (XMLParseError msg loc) = rnf (msg, loc)
data XMLParseLocation = XMLParseLocation {
xmlLineNumber :: Int64,
xmlColumnNumber :: Int64,
xmlByteIndex :: Int64,
xmlByteCount :: Int64
}
deriving (Eq, Show)
instance NFData XMLParseLocation where
rnf (XMLParseLocation lin col ind cou) = rnf (lin, col, ind, cou)
getParseLocation :: ParserPtr -> IO XMLParseLocation
getParseLocation pp = do
line <- xmlGetCurrentLineNumber pp
col <- xmlGetCurrentColumnNumber pp
index <- xmlGetCurrentByteIndex pp
count <- xmlGetCurrentByteCount pp
return $ XMLParseLocation {
xmlLineNumber = fromIntegral line,
xmlColumnNumber = fromIntegral col,
xmlByteIndex = fromIntegral index,
xmlByteCount = fromIntegral count
}
type XMLDeclarationHandler = ParserPtr -> CString -> CString -> CInt -> IO Bool
type StartElementHandler = ParserPtr -> CString -> [(CString, CString)] -> IO Bool
type EndElementHandler = ParserPtr -> CString -> IO Bool
type CharacterDataHandler = ParserPtr -> CStringLen -> IO Bool
type StartCDataHandler = ParserPtr -> IO Bool
type EndCDataHandler = ParserPtr -> IO Bool
type ProcessingInstructionHandler = ParserPtr -> CString -> CString -> IO Bool
type CommentHandler = ParserPtr -> CString -> IO Bool
type ExternalEntityRefHandler = Parser
-> CString
-> CString
-> CString
-> CString
-> IO Bool
type SkippedEntityHandler = ParserPtr
-> CString
-> Int
-> IO Bool
type CXMLDeclarationHandler = ParserPtr -> CString -> CString -> CInt -> IO ()
nullCXMLDeclarationHandler :: CXMLDeclarationHandler
nullCXMLDeclarationHandler _ _ _ _ = return ()
foreign import ccall safe "wrapper"
mkCXMLDeclarationHandler :: CXMLDeclarationHandler
-> IO (FunPtr CXMLDeclarationHandler)
wrapXMLDeclarationHandler :: Parser -> XMLDeclarationHandler -> CXMLDeclarationHandler
wrapXMLDeclarationHandler parser handler = h
where
h pp ver enc sd | ver /= nullPtr = do
stillRunning <- handler pp ver enc sd
unless stillRunning $ stopp parser
h _ _ _ _ = return ()
setXMLDeclarationHandler :: Parser -> XMLDeclarationHandler -> IO ()
setXMLDeclarationHandler parser@(Parser _ xmlDeclRef _ _ _ _ _ _ _ _ _) handler =
writeIORef xmlDeclRef $ wrapXMLDeclarationHandler parser handler
type CStartElementHandler = ParserPtr -> CString -> Ptr CString -> IO ()
nullCStartElementHandler :: CStartElementHandler
nullCStartElementHandler _ _ _ = return ()
foreign import ccall safe "wrapper"
mkCStartElementHandler :: CStartElementHandler
-> IO (FunPtr CStartElementHandler)
wrapStartElementHandler :: Parser -> StartElementHandler -> CStartElementHandler
wrapStartElementHandler parser handler = h
where
h pp cname cattrs = do
cattrlist <- peekArray0 nullPtr cattrs
stillRunning <- handler pp cname (pairwise cattrlist)
unless stillRunning $ stopp parser
setStartElementHandler :: Parser -> StartElementHandler -> IO ()
setStartElementHandler parser@(Parser _ _ startRef _ _ _ _ _ _ _ _) handler =
writeIORef startRef $ wrapStartElementHandler parser handler
type CEndElementHandler = ParserPtr -> CString -> IO ()
nullCEndElementHandler :: CEndElementHandler
nullCEndElementHandler _ _ = return ()
foreign import ccall safe "wrapper"
mkCEndElementHandler :: CEndElementHandler
-> IO (FunPtr CEndElementHandler)
wrapEndElementHandler :: Parser -> EndElementHandler -> CEndElementHandler
wrapEndElementHandler parser handler = h
where
h pp cname = do
stillRunning <- handler pp cname
unless stillRunning $ stopp parser
setEndElementHandler :: Parser -> EndElementHandler -> IO ()
setEndElementHandler parser@(Parser _ _ _ endRef _ _ _ _ _ _ _) handler =
writeIORef endRef $ wrapEndElementHandler parser handler
type CCharacterDataHandler = ParserPtr -> CString -> CInt -> IO ()
nullCCharacterDataHandler :: CCharacterDataHandler
nullCCharacterDataHandler _ _ _ = return ()
foreign import ccall safe "wrapper"
mkCCharacterDataHandler :: CCharacterDataHandler
-> IO (FunPtr CCharacterDataHandler)
wrapCharacterDataHandler :: Parser -> CharacterDataHandler -> CCharacterDataHandler
wrapCharacterDataHandler parser handler = h
where
h pp cdata len = do
stillRunning <- handler pp (cdata, fromIntegral len)
unless stillRunning $ stopp parser
setCharacterDataHandler :: Parser -> CharacterDataHandler -> IO ()
setCharacterDataHandler parser@(Parser _ _ _ _ charRef _ _ _ _ _ _) handler =
writeIORef charRef $ wrapCharacterDataHandler parser handler
type CStartCDataHandler = ParserPtr -> IO ()
nullCStartCDataHandler :: CStartCDataHandler
nullCStartCDataHandler _ = return ()
foreign import ccall safe "wrapper"
mkCStartCDataHandler :: CStartCDataHandler
-> IO (FunPtr CStartCDataHandler)
wrapStartCDataHandler :: Parser -> StartCDataHandler -> CStartCDataHandler
wrapStartCDataHandler parser handler = h
where
h pp = do
stillRunning <- handler pp
unless stillRunning $ stopp parser
setStartCDataHandler :: Parser -> StartCDataHandler -> IO ()
setStartCDataHandler parser@(Parser _ _ _ _ _ _ _ startCData _ _ _) handler =
writeIORef startCData $ wrapStartCDataHandler parser handler
type CEndCDataHandler = ParserPtr -> IO ()
nullCEndCDataHandler :: CEndCDataHandler
nullCEndCDataHandler _ = return ()
foreign import ccall safe "wrapper"
mkCEndCDataHandler :: CEndCDataHandler
-> IO (FunPtr CEndCDataHandler)
wrapEndCDataHandler :: Parser -> EndCDataHandler -> CEndCDataHandler
wrapEndCDataHandler parser handler = h
where
h pp = do
stillRunning <- handler pp
unless stillRunning $ stopp parser
setEndCDataHandler :: Parser -> EndCDataHandler -> IO ()
setEndCDataHandler parser@(Parser _ _ _ _ _ _ _ _ endCData _ _) handler =
writeIORef endCData $ wrapEndCDataHandler parser handler
type CProcessingInstructionHandler = ParserPtr -> CString -> CString -> IO ()
nullCProcessingInstructionHandler :: CProcessingInstructionHandler
nullCProcessingInstructionHandler _ _ _ = return ()
foreign import ccall safe "wrapper"
mkCProcessingInstructionHandler :: CProcessingInstructionHandler
-> IO (FunPtr CProcessingInstructionHandler)
wrapProcessingInstructionHandler :: Parser -> ProcessingInstructionHandler -> CProcessingInstructionHandler
wrapProcessingInstructionHandler parser handler = h
where
h pp ctarget cdata = do
stillRunning <- handler pp ctarget cdata
unless stillRunning $ stopp parser
setProcessingInstructionHandler :: Parser -> ProcessingInstructionHandler -> IO ()
setProcessingInstructionHandler parser@(Parser _ _ _ _ _ _ _ _ _ piRef _) handler =
writeIORef piRef $ wrapProcessingInstructionHandler parser handler
type CCommentHandler = ParserPtr -> CString -> IO ()
nullCCommentHandler :: CCommentHandler
nullCCommentHandler _ _ = return ()
foreign import ccall safe "wrapper"
mkCCommentHandler :: CCommentHandler
-> IO (FunPtr CCommentHandler)
wrapCommentHandler :: Parser -> CommentHandler -> CCommentHandler
wrapCommentHandler parser handler = h
where
h pp cdata = do
stillRunning <- handler pp cdata
unless stillRunning $ stopp parser
setCommentHandler :: Parser -> CommentHandler -> IO ()
setCommentHandler parser@(Parser _ _ _ _ _ _ _ _ _ _ commentRef) handler =
writeIORef commentRef $ wrapCommentHandler parser handler
pairwise :: [a] -> [(a,a)]
pairwise (x1:x2:xs) = (x1,x2) : pairwise xs
pairwise _ = []
stopp :: Parser -> IO ()
stopp parser = withParser parser $ \p -> xmlStopParser p 0
foreign import ccall unsafe "XML_ParserCreate"
parserCreate'_ :: Ptr CChar -> IO ParserPtr
foreign import ccall unsafe "XML_SetUserData"
xmlSetUserData :: ParserPtr -> ParserPtr -> IO ()
foreign import ccall unsafe "XML_SetXmlDeclHandler"
xmlSetxmldeclhandler :: ParserPtr -> FunPtr CXMLDeclarationHandler -> IO ()
foreign import ccall unsafe "XML_SetStartElementHandler"
xmlSetstartelementhandler :: ParserPtr -> ((FunPtr (ParserPtr -> ((Ptr CChar) -> ((Ptr (Ptr CChar)) -> (IO ())))) -> (IO ())))
foreign import ccall unsafe "XML_SetEndElementHandler"
xmlSetendelementhandler :: ParserPtr -> ((FunPtr (ParserPtr -> ((Ptr CChar) -> (IO ()))) -> (IO ())))
foreign import ccall unsafe "XML_SetCharacterDataHandler"
xmlSetcharacterdatahandler :: ParserPtr -> ((FunPtr (ParserPtr -> ((Ptr CChar) -> (CInt -> (IO ())))) -> (IO ())))
foreign import ccall unsafe "XML_SetStartCdataSectionHandler"
xmlSetstartcdatahandler :: ParserPtr -> FunPtr CStartCDataHandler -> IO ()
foreign import ccall unsafe "XML_SetEndCdataSectionHandler"
xmlSetendcdatahandler :: ParserPtr -> FunPtr CStartCDataHandler -> IO ()
foreign import ccall unsafe "XML_SetCommentHandler"
xmlSetcommenthandler :: ParserPtr -> ((FunPtr (ParserPtr -> ((Ptr CChar) -> (IO ()))) -> (IO ())))
foreign import ccall unsafe "XML_SetProcessingInstructionHandler"
xmlSetprocessinginstructionhandler :: ParserPtr -> ((FunPtr (ParserPtr -> ((Ptr CChar) -> ((Ptr CChar) -> (IO ())))) -> (IO ())))
foreign import ccall safe "XML_Parse"
doParseChunk'_ :: ParserPtr -> ((Ptr CChar) -> (CInt -> (CInt -> (IO CInt))))
foreign import ccall unsafe "XML_UseForeignDTD"
xmlUseForeignDTD :: ParserPtr
-> CChar
-> IO ()
foreign import ccall "&XML_ParserFree" parserFree :: FunPtr (ParserPtr -> IO ())
foreign import ccall "XML_ParserFree" parserFree' :: ParserPtr -> IO ()
type CExternalEntityRefHandler = ParserPtr
-> Ptr CChar
-> Ptr CChar
-> Ptr CChar
-> Ptr CChar
-> IO ()
foreign import ccall unsafe "wrapper"
mkCExternalEntityRefHandler :: CExternalEntityRefHandler
-> IO (FunPtr CExternalEntityRefHandler)
foreign import ccall unsafe "XML_SetExternalEntityRefHandler"
xmlSetExternalEntityRefHandler :: ParserPtr
-> FunPtr CExternalEntityRefHandler
-> IO ()
foreign import ccall unsafe "XML_SetSkippedEntityHandler"
xmlSetSkippedEntityHandler :: ParserPtr
-> FunPtr CSkippedEntityHandler
-> IO ()
foreign import ccall unsafe "XML_ExternalEntityParserCreate"
xmlExternalEntityParserCreate :: ParserPtr
-> CString
-> CString
-> IO ParserPtr
type CSkippedEntityHandler = ParserPtr
-> CString
-> CInt
-> IO ()
foreign import ccall safe "wrapper"
mkCSkippedEntityHandler :: CSkippedEntityHandler
-> IO (FunPtr CSkippedEntityHandler)
wrapExternalEntityRefHandler :: Parser
-> ExternalEntityRefHandler
-> CExternalEntityRefHandler
wrapExternalEntityRefHandler parser handler = h
where
h _ context base systemID publicID = do
stillRunning <- handler parser context base systemID publicID
unless stillRunning $ stopp parser
wrapSkippedEntityHandler :: Parser
-> SkippedEntityHandler
-> CSkippedEntityHandler
wrapSkippedEntityHandler parser handler = h
where
h pp entityName i = do
stillRunning <- handler pp entityName (fromIntegral i)
unless stillRunning $ stopp parser
setExternalEntityRefHandler :: Parser -> ExternalEntityRefHandler -> IO ()
setExternalEntityRefHandler parser h =
writeIORef ref $ Just $ wrapExternalEntityRefHandler parser h
where
ref = _externalEntityRefHandler parser
setSkippedEntityHandler :: Parser -> SkippedEntityHandler -> IO ()
setSkippedEntityHandler parser h =
writeIORef ref $ Just $ wrapSkippedEntityHandler parser h
where
ref = _skippedEntityHandler parser
foreign import ccall unsafe "expat.h XML_GetErrorCode" xmlGetErrorCode
:: ParserPtr -> IO CInt
foreign import ccall unsafe "expat.h XML_GetCurrentLineNumber" xmlGetCurrentLineNumber
:: ParserPtr -> IO CULong
foreign import ccall unsafe "expat.h XML_GetCurrentColumnNumber" xmlGetCurrentColumnNumber
:: ParserPtr -> IO CULong
foreign import ccall unsafe "expat.h XML_GetCurrentByteIndex" xmlGetCurrentByteIndex
:: ParserPtr -> IO CLong
foreign import ccall unsafe "expat.h XML_GetCurrentByteCount" xmlGetCurrentByteCount
:: ParserPtr -> IO CInt
foreign import ccall unsafe "expat.h XML_ErrorString" xmlErrorString
:: CInt -> IO CString
foreign import ccall unsafe "expat.h XML_StopParser" xmlStopParser
:: ParserPtr -> CInt -> IO ()