{-# CFILES cbits/stub.c #-} ----------------------------------------------------------------------------- -- | -- Module : Text..Bibutils -- Copyright : (C) 2008 Andrea Rossato -- License : BSD3 -- -- Maintainer : vhaisman@gmail.com -- Stability : provisional -- Portability : portable -- -- Here is a simple program using hs-bibutils to conver a MODS -- collection into a bibtex file, sending the output to stdout: -- -- > import Text.Bibutils -- > -- > main :: IO () -- > main = do -- > bibl <- bibl_init -- > param <- bibl_initparams mods_in bibtex_out "mods2bibtex" -- > setFormatOpts param [bibout_brackets, bibout_uppercase] -- > setBOM param -- > setVerbose param -- > bibl_read param bibl "/path/to/bibtex.bib" -- > bibl_write param bibl "-" -- > bibl_free bibl -- > bibl_freeparams param -- ----------------------------------------------------------------------------- module Text.Bibutils ( -- * Basic Functions Bibl , Param (..) , bibl_init , bibl_initparams , bibl_read , bibl_write , bibl_readasis , bibl_addtoasis , bibl_readcorps , bibl_addtocorps , bibl_free , bibl_freeparams , bibl_reporterr -- * Auxiliary Functions , numberOfRefs , status -- ** Functions for Setting Parameters , setParam , setFormatOpts , setCharsetIn , setCharsetOut , setBOM , unsetBOM , setNoSplitTitle , unsetNoSplitTitle , setLatexOut , unsetLatexOut , setXmlOut , unsetXmlOut , setAddcount , unsetAddcount , setSinglerefperfile , unsetSinglerefperfile , setOutputRawOpts , setVerbose , setVerboseLevel , unsetVerbose -- * Input Formats , BiblioIn , mods_in , bibtex_in , ris_in , endnote_in , copac_in , isi_in , medline_in , biblatex_in , endnotexml_in , ebi_in , word_in , nbib_in -- * Output Formats , BiblioOut , mods_out , bibtex_out , ris_out , endnote_out , isi_out , word2007_out , adsab_out , nbib_out -- * Options for Specific Output Formats , FormatOpt , bibout_finalcomma , bibout_singledash , bibout_whitespace , bibout_brackets , bibout_uppercase , bibout_strictkey , bibout_shorttitle , bibout_dropkey , modsout_dropkey -- * Charsets , Charset , bibl_charset_unknown , bibl_charset_unicode , bibl_charset_gb18030 , bibl_charset_default , bibl_charset_utf8_default , bibl_charset_bom_default -- * Return Status , Status , bibl_ok , bibl_err_badinput , bibl_err_memerr , bibl_err_cantopen -- * Raw , Raw , bibl_raw_with_charset_convert , bibl_raw_with_make_ref_id ) where import Control.Monad import Foreign.C import Foreign -- | A type for storing the C struct with the bibliography data. -- Mostly opaque to the Haskell side. See 'numberOfRefs' to retrieve -- the number of references stored in the struct. newtype Bibl = Bibl { nrefs :: CLong } instance Storable Bibl where sizeOf _ = #{size bibl} alignment _ = #{alignment bibl} peek p = #{peek bibl, nrefs } p >>= return . Bibl poke p (Bibl n) = #{poke bibl, nrefs } p n -- | Initialize the 'Bibl' C struct. Usually the first function being -- called. bibl_init :: IO (ForeignPtr Bibl) bibl_init = alloca $ \p -> do c_bibl_init p newForeignPtr_ p -- | Free the 'Bibl' C struct. bibl_free :: ForeignPtr Bibl -> IO () bibl_free bibl = withForeignPtr bibl c_bibl_free -- | Retrieve the number of references from a 'Bibl' C struct. numberOfRefs :: ForeignPtr Bibl -> IO Int numberOfRefs b = withForeignPtr b $ \cb -> peek cb >>= return . fromIntegral . nrefs -- | A type for storing the Param C struct. It should be accessed with -- the functions provided, such as 'setCharsetIn', etc. data Param = Param { redaformat :: CInt , writeformat :: CInt , charsetin :: CInt , charsetin_src :: CUChar , latexin :: CUChar , utf8in :: CUChar , xmlin :: CUChar , nosplittitle :: CUChar , charsetout :: CInt , charsetout_src :: CUChar , latexout :: CUChar , utf8out :: CUChar , utf8bom :: CUChar , xmlout :: CUChar , format_opts :: CInt , addcount :: CInt , output_raw :: CUChar , verbose :: CUChar , singlerefperfile :: CUChar } deriving ( Show ) instance Storable Param where sizeOf _ = #{size param} alignment _ = #{alignment param} peek p = Param `fmap` #{peek param, readformat } p `ap` #{peek param, writeformat } p `ap` #{peek param, charsetin } p `ap` #{peek param, charsetin_src } p `ap` #{peek param, latexin } p `ap` #{peek param, utf8in } p `ap` #{peek param, xmlin } p `ap` #{peek param, nosplittitle } p `ap` #{peek param, charsetout } p `ap` #{peek param, charsetout_src } p `ap` #{peek param, latexout } p `ap` #{peek param, utf8out } p `ap` #{peek param, utf8bom } p `ap` #{peek param, xmlout } p `ap` #{peek param, format_opts } p `ap` #{peek param, addcount } p `ap` #{peek param, output_raw } p `ap` #{peek param, verbose } p `ap` #{peek param, singlerefperfile } p poke p (Param rf wf ci csi li ui xi nt co cso lo uo ub xo fo a raw v s) = do #{poke param, readformat } p rf #{poke param, writeformat } p wf #{poke param, charsetin } p ci #{poke param, charsetin_src } p csi #{poke param, latexin } p li #{poke param, utf8in } p ui #{poke param, xmlin } p xi #{poke param, nosplittitle } p nt #{poke param, charsetout } p co #{poke param, charsetout_src } p cso #{poke param, latexout } p lo #{poke param, utf8out } p uo #{poke param, utf8bom } p ub #{poke param, xmlout } p xo #{poke param, format_opts } p fo #{poke param, addcount } p a #{poke param, output_raw } p raw #{poke param, verbose } p v #{poke param, singlerefperfile } p s -- | Initialize the 'Param' C struct, given the input bibliographic -- format, the output bibliographic format, and the program name to -- be used for displaying debugging information. bibl_initparams :: BiblioIn -> BiblioOut -> String -> IO (ForeignPtr Param) bibl_initparams i o s = alloca $ \p -> withCString s $ \cs -> do c_bibl_initparams p (unBiblioIn i) (unBiblioOut o) cs newForeignPtr_ p -- | Free the 'Param' C struct. bibl_freeparams :: ForeignPtr Param -> IO () bibl_freeparams param = withForeignPtr param c_bibl_freeparams -- | Set fields of the 'Param' C struct directly. setParam :: ForeignPtr Param -> (Param -> Param) -> IO () setParam p f = withForeignPtr p $ \cp -> peek cp >>= poke cp . f -- | Set the input charset. Default is Latin-1 (ISO8859-1). See -- 'Charset'. setCharsetIn :: ForeignPtr Param -> Charset -> IO () setCharsetIn p c = setParam p $ \param -> param { charsetin = charset c } -- | Set the output charset. setCharsetOut :: ForeignPtr Param -> Charset -> IO () setCharsetOut p c = setParam p $ \param -> param { charsetout = charset c } -- | Set output format specific options. See 'FormatOpt'. setFormatOpts :: ForeignPtr Param -> [FormatOpt] -> IO () setFormatOpts p os = setParam p $ \param -> param { format_opts = unFormatOpt $ combineFormatOpts os } -- | Write utf8 byte-order-mark. setBOM :: ForeignPtr Param -> IO () setBOM p = setParam p $ \param -> param { utf8bom = 1 } unsetBOM :: ForeignPtr Param -> IO () unsetBOM p = setParam p $ \param -> param { utf8bom = 0 } -- | Do not split titles. setNoSplitTitle :: ForeignPtr Param -> IO () setNoSplitTitle p = setParam p $ \param -> param { nosplittitle = 1 } -- | Split titles. unsetNoSplitTitle :: ForeignPtr Param -> IO () unsetNoSplitTitle p = setParam p $ \param -> param { nosplittitle = 0 } -- | Write Latex codes. setLatexOut :: ForeignPtr Param -> IO () setLatexOut p = setParam p $ \param -> param { latexout = 1 } unsetLatexOut :: ForeignPtr Param -> IO () unsetLatexOut p = setParam p $ \param -> param { latexout = 0 } -- | Write characters in XML entities. setXmlOut :: ForeignPtr Param -> IO () setXmlOut p = setParam p $ \param -> param { xmlout = 1 } unsetXmlOut :: ForeignPtr Param -> IO () unsetXmlOut p = setParam p $ \param -> param { xmlout = 0 } -- | Add reference count to reference id. setAddcount :: ForeignPtr Param -> IO () setAddcount p = setParam p $ \param -> param { addcount = 1 } unsetAddcount :: ForeignPtr Param -> IO () unsetAddcount p = setParam p $ \param -> param { addcount = 0 } -- | Output a single reference for each file. setSinglerefperfile :: ForeignPtr Param -> IO () setSinglerefperfile p = setParam p $ \param -> param { singlerefperfile = 1 } unsetSinglerefperfile :: ForeignPtr Param -> IO () unsetSinglerefperfile p = setParam p $ \param -> param { singlerefperfile = 0 } -- | Set the output charset. setOutputRawOpts :: ForeignPtr Param -> [Raw] -> IO () setOutputRawOpts p os = setParam p $ \param -> param { output_raw = unRaw $ combineRawOpts os } -- | Verbose output. setVerbose :: ForeignPtr Param -> IO () setVerbose p = setParam p $ \param -> param { verbose = 1 } -- | Verbose output. setVerboseLevel :: ForeignPtr Param -> Int -> IO () setVerboseLevel p v = setParam p $ \param -> param { verbose = toEnum v } -- | Suppress verbose output. unsetVerbose :: ForeignPtr Param -> IO () unsetVerbose p = setParam p $ \param -> param { verbose = 0 } -- | Given a 'Param' C structure, a 'Bibl' C structure, the path to -- the input file (@\"-\"@ for the standard input), read the file, -- storing the data in the 'Bibl' struct, and report a 'Status'. bibl_read :: ForeignPtr Param -> ForeignPtr Bibl -> FilePath -> IO Status bibl_read param bibl path = withForeignPtr param $ \cparam -> withForeignPtr bibl $ \cbibl -> withCString path $ \cpath -> withCString "r" $ \cmode -> do cfile <- if path == "-" then return c_stdin else throwErrnoIfNull "fopen: " (fopen cpath cmode) cint <- c_bibl_read cbibl cfile cpath cparam when (path /= "-") $ fclose cfile >> return () return $ Status cint -- | Given a 'Param' C structure, a 'Bibl' C structure, the path to an -- output file (@\"-\"@ for the standard output), write the file -- returning a 'Status'. bibl_write :: ForeignPtr Param -> ForeignPtr Bibl -> FilePath -> IO Status bibl_write param bibl path = withForeignPtr param $ \cparam -> withForeignPtr bibl $ \cbibl -> withCString "w" $ \cmode -> do cfile <- if path == "-" then return c_stdout else withCString path $ throwErrnoIfNull "fopen: " . flip fopen cmode cint <- c_bibl_write cbibl cfile cparam when (path /= "-") $ fclose cfile >> return () return $ Status cint bibl_readasis :: ForeignPtr Param -> FilePath -> IO () bibl_readasis param path = withForeignPtr param $ \cparam -> withCString path $ \cpath -> do c_bibl_readasis cparam cpath bibl_addtoasis :: ForeignPtr Param -> String -> IO () bibl_addtoasis param entry = withForeignPtr param $ \cparam -> withCString entry $ \centry -> do c_bibl_addtoasis cparam centry bibl_readcorps :: ForeignPtr Param -> FilePath -> IO () bibl_readcorps param path = withForeignPtr param $ \cparam -> withCString path $ \cpath -> do c_bibl_readcorps cparam cpath bibl_addtocorps :: ForeignPtr Param -> String -> IO () bibl_addtocorps param entry = withForeignPtr param $ \cparam -> withCString entry $ \centry -> do c_bibl_addtocorps cparam centry bibl_reporterr :: Status -> IO () bibl_reporterr (Status n) = c_bibl_reporterr n newtype BiblioIn = BiblioIn { unBiblioIn :: CInt } deriving ( Eq ) #{enum BiblioIn, BiblioIn , mods_in = BIBL_MODSIN , bibtex_in = BIBL_BIBTEXIN , ris_in = BIBL_RISIN , endnote_in = BIBL_ENDNOTEIN , copac_in = BIBL_COPACIN , isi_in = BIBL_ISIIN , medline_in = BIBL_MEDLINEIN , endnotexml_in = BIBL_ENDNOTEXMLIN , biblatex_in = BIBL_BIBLATEXIN , ebi_in = BIBL_EBIIN , word_in = BIBL_WORDIN , nbib_in = BIBL_NBIBIN } newtype BiblioOut = BiblioOut { unBiblioOut :: CInt } deriving ( Eq ) #{enum BiblioOut, BiblioOut , mods_out = BIBL_MODSOUT , bibtex_out = BIBL_BIBTEXOUT , ris_out = BIBL_RISOUT , endnote_out = BIBL_ENDNOTEOUT , isi_out = BIBL_ISIOUT , word2007_out = BIBL_WORD2007OUT , adsab_out = BIBL_ADSABSOUT , nbib_out = BIBL_NBIBOUT } newtype FormatOpt = FormatOpt { unFormatOpt :: CInt } #include "bibutils.h" #{enum FormatOpt, FormatOpt , bibout_finalcomma = BIBL_FORMAT_BIBOUT_FINALCOMMA , bibout_singledash = BIBL_FORMAT_BIBOUT_SINGLEDASH , bibout_whitespace = BIBL_FORMAT_BIBOUT_WHITESPACE , bibout_brackets = BIBL_FORMAT_BIBOUT_BRACKETS , bibout_uppercase = BIBL_FORMAT_BIBOUT_UPPERCASE , bibout_strictkey = BIBL_FORMAT_BIBOUT_STRICTKEY , bibout_shorttitle = BIBL_FORMAT_BIBOUT_SHORTTITLE , bibout_dropkey = BIBL_FORMAT_BIBOUT_DROPKEY , modsout_dropkey = BIBL_FORMAT_MODSOUT_DROPKEY } newtype Status = Status { status :: CInt } deriving ( Eq, Show ) #{enum Status, Status , bibl_ok = BIBL_OK , bibl_err_badinput = BIBL_ERR_BADINPUT , bibl_err_memerr = BIBL_ERR_MEMERR , bibl_err_cantopen = BIBL_ERR_CANTOPEN } newtype Raw = Raw { unRaw :: CUChar } deriving ( Eq, Show ) #{enum Raw, Raw , bibl_raw_with_charset_convert = BIBL_RAW_WITHCHARCONVERT , bibl_raw_with_make_ref_id = BIBL_RAW_WITHMAKEREFID } newtype Charset = Charset { charset :: CInt } deriving ( Eq ) #{enum Charset, Charset , bibl_charset_unknown = BIBL_CHARSET_UNKNOWN , bibl_charset_unicode = BIBL_CHARSET_UNICODE , bibl_charset_gb18030 = BIBL_CHARSET_GB18030 , bibl_charset_default = BIBL_CHARSET_DEFAULT , bibl_charset_utf8_default = BIBL_CHARSET_UTF8_DEFAULT , bibl_charset_bom_default = BIBL_CHARSET_BOM_DEFAULT } -- Combine a list of output options into a single option, using bitwise (.|.) combineRawOpts :: [Raw] -> Raw combineRawOpts = Raw . foldr ((.|.) . unRaw) 0 -- Combine a list of options into a single option, using bitwise (.|.) combineFormatOpts :: [FormatOpt] -> FormatOpt combineFormatOpts = FormatOpt . foldr ((.|.) . unFormatOpt) 0 #include "bibutils.h" #include "bibl.h" #let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__) foreign import ccall unsafe "bibl_init" c_bibl_init :: Ptr Bibl -> IO () foreign import ccall unsafe "bibl_free" c_bibl_free :: Ptr Bibl -> IO () foreign import ccall unsafe "bibl_initparams" c_bibl_initparams :: Ptr Param -> CInt -> CInt -> CString -> IO () foreign import ccall unsafe "bibl_freeparams" c_bibl_freeparams :: Ptr Param -> IO () foreign import ccall unsafe "bibl_read" c_bibl_read :: Ptr Bibl -> Ptr CFile -> CString -> Ptr Param -> IO CInt foreign import ccall unsafe "bibl_write" c_bibl_write :: Ptr Bibl -> Ptr CFile -> Ptr Param -> IO CInt foreign import ccall unsafe "bibl_readasis" c_bibl_readasis :: Ptr Param -> CString -> IO () foreign import ccall unsafe "bibl_addtoasis" c_bibl_addtoasis :: Ptr Param -> CString -> IO () foreign import ccall unsafe "bibl_readcorps" c_bibl_readcorps :: Ptr Param -> CString -> IO () foreign import ccall unsafe "bibl_addtocorps" c_bibl_addtocorps :: Ptr Param -> CString -> IO () foreign import ccall unsafe "bibl_reporterr" c_bibl_reporterr :: CInt -> IO () foreign import ccall unsafe "fopen" fopen :: CString -> CString -> IO (Ptr CFile) foreign import ccall unsafe "fclose" fclose :: Ptr CFile -> IO CInt foreign import ccall unsafe "c_stdin" c_stdin :: Ptr CFile foreign import ccall unsafe "c_stdout" c_stdout :: Ptr CFile