packages feed

MissingH 0.18.6 → 1.0.0

raw patch · 30 files changed

+709/−686 lines, 30 filesdep +arraydep +containersdep +directorydep ~basesetup-changed

Dependencies added: array, containers, directory, old-locale, old-time, process, random, unix

Dependency ranges changed: base

Files

MissingH.cabal view
@@ -1,10 +1,9 @@--- arch-tag: MissingH main description file Name: MissingH-Version: 0.18.6+Version: 1.0.0 License: GPL Maintainer: John Goerzen <jgoerzen@complete.org> Author: John Goerzen-Copyright: Copyright (c) 2004-2007 John Goerzen+Copyright: Copyright (c) 2004-2008 John Goerzen license-file: COPYRIGHT extra-source-files: COPYING homepage: http://software.complete.org/missingh@@ -14,8 +13,16 @@  Haskell programmers.  It is written in pure Haskell and thus should  be extremely portable and easy to use. Stability: Beta-Hs-Source-Dirs: src-Exposed-Modules: Data.String, System.IO.Utils, System.IO.Binary, Data.List.Utils,+Build-Type: Simple+Cabal-Version: >=1.2++Flag splitBase+  description: Choose the new smaller, split-up base package.++Library+ Hs-Source-Dirs: src+ Exposed-Modules:+  Data.String.Utils, System.IO.Utils, System.IO.Binary, Data.List.Utils,   System.Daemon,   Text.ParserCombinators.Parsec.Utils,   Test.HUnit.Utils,@@ -34,6 +41,7 @@   Network.SocketServer,   Data.Either.Utils,   Data.Maybe.Utils,+  Data.Tuple.Utils,   Data.Bits.Utils,   Data.Hash.CRC32.Posix, Data.Hash.CRC32.GZip,    Data.Hash.MD5, Data.Hash.MD5.Zord64_HARD,@@ -48,17 +56,31 @@   System.Debian, System.Debian.ControlParser,   Data.MIME.Types,   System.Console.GetOpt.Utils-Extensions: ExistentialQuantification, OverlappingInstances, -   UndecidableInstances, CPP-Build-Depends: network, parsec, base,++ Extensions: ExistentialQuantification, OverlappingInstances,+   UndecidableInstances, CPP, Rank2Types,+   MultiParamTypeClasses, FlexibleInstances, FlexibleContexts+ -- Hack because ghc-6.6 and the Cabal the comes with ghc-6.8.1+ -- does not understand the PatternSignatures extension.+ -- The Cabal that comes with ghc-6.8.2 does understand it, so+ -- this hack can be dropped if we require Cabal-Version: >=1.2.3+ If impl(ghc >= 6.8)+   GHC-Options: -XPatternSignatures++ Build-Depends: network, parsec, base,                haskell98, mtl, HUnit, regex-compat, QuickCheck, filepath,                hslogger--- Cabal will automatically add unix here on non-Windows platforms-GHC-Options: -O2+ If flag(splitBase)+   Build-Depends: base >= 3, directory, random, process, old-time,+                             containers, old-locale, array+ Else+   Build-Depends: base < 3+ If ! os(windows)+   Build-Depends: unix -Executable: runtests-Buildable: False-Main-Is: runtests.hs-HS-Source-Dirs: testsrc, .-Extensions: ExistentialQuantification, OverlappingInstances,+Executable runtests+  Buildable: False+  Main-Is: runtests.hs+  HS-Source-Dirs: testsrc, .+  Extensions: ExistentialQuantification, OverlappingInstances,     UndecidableInstances, CPP
Setup.hs view
@@ -1,22 +1,5 @@ #!/usr/bin/env runhugs  import Distribution.Simple-import Distribution.PackageDescription-import Distribution.Simple.LocalBuildInfo-import Distribution.Version-import System.Info-import Data.Maybe-import System.Cmd -missingHooks = defaultUserHooks {confHook = customConfHook}--customConfHook descrip flags =-    let mydescrip = case System.Info.os of-                      "mingw32" -> descrip-                      _ -> descrip {buildDepends = -                                        (Dependency "unix" AnyVersion) :-                                        buildDepends descrip}-    in (confHook defaultUserHooks) mydescrip flags--main = defaultMainWithHooks missingHooks-+main = defaultMain
src/Data/CSV.hs view
@@ -30,14 +30,19 @@ Written by John Goerzen, jgoerzen\@complete.org -} -module Data.CSV(csvFile, genCsvFile) where+module Data.CSV (csvFile, genCsvFile) where import Text.ParserCombinators.Parsec-import Data.List+import Data.List (intersperse) +eol :: forall st. GenParser Char st String eol = (try $ string "\n\r") <|> (try $ string "\r\n") <|> string "\n" <|>       string "\r" <?> "End of line"++cell :: GenParser Char st String cell = quotedcell <|> many (noneOf ",\n\r")-quotedchar = noneOf "\"" ++quotedchar :: GenParser Char st Char+quotedchar = noneOf "\""              <|> (try $ do string "\"\""                            return '"'                  )@@ -46,6 +51,8 @@                 content <- many quotedchar                 char '"'                 return content++line :: GenParser Char st [String] line = sepBy cell (char ',')  {- | Parse a Comma-Separated Value (CSV) file.  The return value is a list of
src/Data/Either/Utils.hs view
@@ -34,7 +34,8 @@      maybeToEither,      forceEither,      forceEitherMsg,-     eitherToMonadError+     eitherToMonadError,+     fromLeft, fromRight, fromEither ) where import Control.Monad.Error @@ -71,3 +72,20 @@ eitherToMonadError :: MonadError e m => Either e a -> m a eitherToMonadError (Left x) = throwError x eitherToMonadError (Right x) = return x+++-- | Take a Left to a value, crashes on a Right+fromLeft :: Either a b -> a+fromLeft (Left a) = a+fromLeft _ = error "Data.Either.Utils.fromLeft: Right"++-- | Take a Right to a value, crashes on a Left+fromRight :: Either a b -> b+fromRight (Right a) = a+fromRight _ = error "Data.Either.Utils.fromRight: Left"++-- | Take an Either, and return the value inside it+fromEither :: Either a a -> a+fromEither (Left a) = a+fromEither (Right a) = a+
src/Data/List/Utils.hs view
@@ -59,9 +59,7 @@                      -- sub,                     ) where import Data.List(intersperse, concat, isPrefixOf, isSuffixOf, elemIndices,-                elemIndex, elemIndices, tails, find, findIndex)-import IO-import System.IO.Unsafe+                elemIndex, elemIndices, tails, find, findIndex, isInfixOf) import Control.Monad.State(State, get, put) import Data.Maybe(isJust) @@ -229,6 +227,7 @@ genericJoin :: Show a => String -> [a] -> String genericJoin delim l = join delim (map show l) +{-# DEPRECATED contains "Use Data.List.isInfixOf, will be removed in MissingH 1.1.0" #-} {- | Returns true if the given parameter is a sublist of the given list; false otherwise. @@ -236,10 +235,14 @@  > contains "Haskell" "I really like Haskell." -> True > contains "Haskell" "OCaml is great." -> False++This function was submitted to GHC and was applied as+'Data.List.isInfixOf'.  This function therefore is deprecated and will+be removed in future versions. -}  contains :: Eq a => [a] -> [a] -> Bool-contains substr str = isJust $ find (isPrefixOf substr) (tails str)+contains = isInfixOf  -- above function submitted to GHC as Data.List.isInfixOf on 8/31/2006 @@ -473,7 +476,7 @@ This function is not compatible with infinite lists. -} uniq :: Eq a => [a] -> [a] uniq [] = []-uniq (x:xs) = x : filter (/= x) (uniq xs)+uniq (x:xs) = x : uniq (filter (/= x) xs)  ----- same as --uniq (x:xs) = x : [y | y <- uniq xs, y /= x]
src/Data/MIME/Types.hs view
@@ -21,7 +21,7 @@    Copyright  : Copyright (C) 2004-2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -45,7 +45,6 @@ where  import qualified Data.Map as Map-import qualified System.Directory import Monad import System.IO import System.IO.Error@@ -55,10 +54,10 @@ import Data.Char  ------------------------------------------------------------------------- Basic type decl+-- Basic type declarations ---------------------------------------------------------------------- -data MIMETypeData = MIMETypeData +data MIMETypeData = MIMETypeData     {      -- | A mapping used to expand common suffixes into equivolent,      -- better-parsed versions.  For instance, ".tgz" would expand@@ -88,8 +87,6 @@  {- | Read the given mime.types file and add it to an existing object. Returns new object. -}-- readMIMETypes :: MIMETypeData            -- ^ Data to work with               -> Bool                    -- ^ Whether to work on strict data               -> FilePath               -- ^ File to read@@ -103,10 +100,10 @@                   -> Bool               -- ^ Whether to work on strict data                   -> Handle             -- ^ Handle to read from                   -> IO MIMETypeData       -- ^ New object-hReadMIMETypes mtd strict h = +hReadMIMETypes mtd strict h =     let parseline :: MIMETypeData -> String -> MIMETypeData         parseline obj line =-            let l1 = words line +            let l1 = words line                 procwords [] = []                 procwords (('#':_) :_) = []                 procwords (x:xs) = x : procwords xs@@ -119,29 +116,28 @@                        foldl (\o suff -> addType o strict thetype ('.' : suff)) obj suffixlist                 else obj         in-        do-        lines <- hGetLines h-        return (foldl parseline mtd lines)+          do+            lines <- hGetLines h+            return (foldl parseline mtd lines)  {- | Guess the type of a file given a filename or URL.  The file    is not opened; only the name is considered. -}- guessType :: MIMETypeData               -- ^ Source data for guessing              -> Bool                    -- ^ Whether to limit to strict data              -> String                  -- ^ File or URL name to consider              -> MIMEResults             -- ^ Result of guessing (see 'MIMEResults' for details on interpreting it)-guessType mtd strict fn = -    let mapext (base, ext) =-            case Map.lookup ext (suffixMap mtd) of-                Nothing -> (base, ext)+guessType mtd strict fn =+    let mapext (base, ex) =+            case Map.lookup ex (suffixMap mtd) of+                Nothing -> (base, ex)                 Just x -> mapext (splitExt (base ++ x))-        checkencodings (base, ext) =-            case Map.lookup ext (encodingsMap mtd) of-                 Nothing -> (base, ext, Nothing)+        checkencodings (base, ex) =+            case Map.lookup ex (encodingsMap mtd) of+                 Nothing -> (base, ex, Nothing)                  Just x -> (fst (splitExt base),                             snd (splitExt base),                             Just x)-        (base, ext, enc) = checkencodings . mapext $ splitExt fn+        (_, ext, enc) = checkencodings . mapext $ splitExt fn         typemap = getStrict mtd strict         in         case Map.lookup ext typemap of@@ -160,7 +156,7 @@                   -> Bool               -- ^ Whether to limit to strict data                   -> String             -- ^ MIME type to consider                   -> Maybe String       -- ^ Result of guessing, or Nothing if no match possible-guessExtension mtd strict fn = +guessExtension mtd strict fn =     case guessAllExtensions mtd strict fn of                                           [] -> Nothing                                           (x:_) -> Just x@@ -176,22 +172,21 @@         themap = getStrict mtd strict         in         flippedLookupM mimetype themap-        + {- | Adds a new type to the data structures, replacing whatever data    may exist about it already.  That is, it overrides existing information    about the given extension, but the same type may occur more than once. -}- addType :: MIMETypeData                 -- ^ Source data            -> Bool                      -- ^ Whether to add to strict data set            -> String                    -- ^ MIME type to add            -> String                    -- ^ Extension to add            -> MIMETypeData              -- ^ Result of addition-addType mtd strict thetype theext = +addType mtd strict thetype theext =     setStrict mtd strict (\m -> Map.insert theext thetype m)  {- | Default MIME type data to use -} defaultmtd :: MIMETypeData-defaultmtd = +defaultmtd =     MIMETypeData {suffixMap = default_suffix_map,                   encodingsMap = default_encodings_map,                   typesMap = default_types_map,@@ -202,7 +197,7 @@ readSystemMIMETypes :: MIMETypeData -> IO MIMETypeData readSystemMIMETypes mtd =     let tryread :: MIMETypeData -> String -> IO MIMETypeData-        tryread inputobj filename = +        tryread inputobj filename =             do             fn <- try (openFile filename ReadMode)             case fn of@@ -213,12 +208,11 @@                                return x         in         do-        foldM tryread mtd defaultfilelocations+          foldM tryread mtd defaultfilelocations  ---------------------------------------------------------------------- -- Internal utilities ----------------------------------------------------------------------- getStrict :: MIMETypeData -> Bool -> Map.Map String String getStrict mtd True = typesMap mtd getStrict mtd False = Map.union (typesMap mtd) (commonTypesMap mtd)@@ -230,7 +224,7 @@ ---------------------------------------------------------------------- -- Default data structures -----------------------------------------------------------------------+defaultfilelocations :: [String] defaultfilelocations =     [      "/etc/mime.types",@@ -240,13 +234,13 @@      "/usr/local/etc/mime.types"                -- Apache 1.3     ] -+default_encodings_map, default_suffix_map, default_types_map, default_common_types :: Map.Map String String default_encodings_map = Map.fromList [                                       (".Z", "compress"),                                       (".gz", "gzip"),                                       (".bz2", "bzip2")                                      ]-                               + default_suffix_map = Map.fromList [                                    (".tgz", ".tar.gz"),                                    (".tz", ".tar.gz"),
src/Data/Progress/Meter.hs view
@@ -21,7 +21,7 @@    Copyright  : Copyright (C) 2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -39,7 +39,7 @@                                addComponent,                                removeComponent,                                setWidth,-                               +                                -- * Rendering and Output                                renderMeter,                                displayMeter,@@ -50,17 +50,16 @@                                ) where  import Data.Progress.Tracker-import Control.Concurrent.MVar import Control.Concurrent-import Control.Monad(when)-import Data.String-import System.Time.Utils-import Data.Quantity+import Control.Monad (when)+import Data.String.Utils (join)+import System.Time.Utils (renderSecs)+import Data.Quantity (renderNums, binaryOpts) import System.IO-import Control.Monad(filterM)+import Control.Monad (filterM)  {- | The main data type for the progress meter. -}-data ProgressMeterR = +data ProgressMeterR =     ProgressMeterR {masterP :: Progress, -- ^ The master 'Progress' object for overall status                     components :: [Progress], -- ^ Individual component statuses                     width :: Int, -- ^ Width of the meter@@ -91,7 +90,7 @@           -> Int                -- ^ Width of the terminal -- usually 80           -> ([Integer] -> [String])-- ^ A function to render sizes           -> IO ProgressMeter-newMeter tracker u w rfunc = +newMeter tracker u w rfunc =     newMVar $ ProgressMeterR {masterP = tracker, components = [],                          width = w, renderer = rfunc, autoDisplayers = [],                          unit = u}@@ -102,7 +101,7 @@  {- | Add a new component to the list of components. -} addComponent :: ProgressMeter -> Progress -> IO ()-addComponent meter component = +addComponent meter component =     modifyMVar_ meter (\m -> return $ m {components = component : components m})  {- | Remove a component by name. -}@@ -116,9 +115,9 @@ setWidth :: ProgressMeter -> Int -> IO () setWidth meter w = modifyMVar_ meter (\m -> return $ m {width = w}) -{- | Like renderMeter, but prints it to the screen instead of returning it. +{- | Like renderMeter, but prints it to the screen instead of returning it. -This function will output CR, then the meter. +This function will output CR, then the meter.  Pass stdout as the handle for regular display to the screen. -} displayMeter :: Handle -> ProgressMeter -> IO ()@@ -130,15 +129,15 @@        -- lock the IO and prevent IO from stomping on each other.  {- | Clears the meter -- outputs CR, spaces equal to the width - 1,-then another CR. +then another CR.  Pass stdout as the handle for regular display to the screen. -} clearMeter :: Handle -> ProgressMeter -> IO ()-clearMeter h pm = withMVar pm $ \m -> +clearMeter h pm = withMVar pm $ \m ->                      do hPutStr h (clearmeterstr m)                         hFlush h -{- | Clears the meter, writes the given string, then restores the meter. +{- | Clears the meter, writes the given string, then restores the meter. The string is assumed to contain a trailing newline.  Pass stdout as the handle for regular display to the screen. -}@@ -150,11 +149,11 @@                                hPutStr h s                                hFlush h +clearmeterstr :: ProgressMeterR -> String clearmeterstr m = "\r" ++ replicate (width m - 1) ' ' ++ "\r" - {- | Starts a thread that updates the meter every n seconds by calling-the specified function.  Note: @displayMeter stdout@ +the specified function.  Note: @displayMeter stdout@ is an ideal function here.  Save this threadID and use it later to call 'stopAutoDisplayMeter'.@@ -185,7 +184,7 @@  You should probably call 'clearMeter' after a call to this. -} killAutoDisplayMeter :: ProgressMeter -> ThreadId -> IO ()-killAutoDisplayMeter pm t = +killAutoDisplayMeter pm t =     modifyMVar_ pm (\p -> return $ p {autoDisplayers = filter (/= t) (autoDisplayers p)})  {- | Render the current status. -}@@ -194,10 +193,10 @@  renderMeterR :: ProgressMeterR -> IO String renderMeterR meter =-    do overallpct <- renderpct (masterP meter)-       components <- mapM (rendercomponent (renderer meter))+    do overallpct <- renderpct $ masterP meter+       compnnts <- mapM (rendercomponent $ renderer meter)                      (components meter)-       let componentstr = case join " " components of+       let componentstr = case join " " compnnts of                             [] -> ""                             x -> x ++ " "        rightpart <- renderoverall (renderer meter) (masterP meter)@@ -206,25 +205,28 @@        if padwidth < 1           then return $ take (width meter - 1) $ leftpart ++ rightpart           else return $ leftpart ++ replicate padwidth ' ' ++ rightpart-       -    where renderpct pt = ++    where+      u = unit meter+      renderpct pt =               withStatus pt renderpctpts-          renderpctpts pts = +      renderpctpts pts =                   if (totalUnits pts == 0)                      then return "0%"                      else return $ show (((completedUnits pts) * 100) `div` (totalUnits pts)) ++ "%"-          rendercomponent :: ([Integer] -> [String]) -> Progress -> IO String-          rendercomponent rfunc pt = withStatus pt $ \pts ->+      rendercomponent :: ([Integer] -> [String]) -> Progress -> IO String+      rendercomponent rfunc pt = withStatus pt $ \pts ->               do pct <- renderpctpts pts-                 let u = unit meter                  let renders = rfunc [totalUnits pts, completedUnits pts]                  return $ "[" ++ trackerName pts ++ " " ++                      (renders !! 1) ++ u ++ "/" ++                      head renders ++ u ++ " " ++ pct ++ "]"-          renderoverall rfunc pt = withStatus pt $ \pts ->-              do etr <- getETR pts-                 speed <- getSpeed pts-                 return $ head (rfunc [floor speed]) ++ (unit meter) ++ -                            "/s " ++ renderSecs etr++      renderoverall :: (ProgressStatuses a (IO [Char])) => ([Integer] -> [[Char]]) -> a -> IO [Char]+      renderoverall rfunc pt = withStatus pt $ \pts ->+                                         do etr <- getETR pts+                                            speed <- getSpeed pts+                                            return $ head (rfunc [floor (speed :: Double)]) ++ u +++                                                       "/s " ++ renderSecs etr  
− src/Data/String.hs
@@ -1,100 +0,0 @@-{- arch-tag: String utilities main file-Copyright (C) 2004-2006 John Goerzen <jgoerzen@complete.org>--This program is free software; you can redistribute it and\/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--{- |-   Module     : Data.String-   Copyright  : Copyright (C) 2004-2006 John Goerzen-   License    : GNU GPL, version 2 or above--   Maintainer : John Goerzen <jgoerzen@complete.org>-   Stability  : provisional-   Portability: portable--This module provides various helpful utilities for dealing with strings.--Written by John Goerzen, jgoerzen\@complete.org--}--module Data.String-                       (-- * Whitespace Removal-                        strip, lstrip, rstrip,-                        -- * Tests-                        -- | Note: These functions are aliases for functions-                        -- in "Data.List.Utils".-                        startswith, endswith,-                        -- * Conversions-                        -- | Note: Some of these functions are aliases for functions-                        -- in "Data.List.Utils".-                        join, split, splitWs, replace, escapeRe-                       ) where-import Data.List.Utils(startswith, endswith, join, split, replace)-import Data.Char-import Text.Regex--wschars = " \t\r\n"--{- | Removes any whitespace characters that are present at the start-or end of a string. Does not alter the internal contents of a-string. If no whitespace characters are present at the start or end-of a string, returns the original string unmodified. Safe to use on-any string.--Note that this may differ from some other similar-functions from other authors in that:--1. If multiple whitespace-characters are present all in a row, they are all removed;--2. If no-whitespace characters are present, nothing is done.--}--strip :: String -> String-strip = lstrip . rstrip---- | Same as 'strip', but applies only to the left side of the string.-lstrip :: String -> String-lstrip s = case s of-                  [] -> []-                  (x:xs) -> if elem x wschars-                            then lstrip xs-                            else s---- | Same as 'strip', but applies only to the right side of the string.-rstrip :: String -> String-rstrip = reverse . lstrip . reverse--{- | Splits a string around whitespace.  Empty elements in the result-list are automatically removed. -}-splitWs :: String -> [String]-splitWs = filter (\x -> x /= []) . splitRegex (mkRegex "[ \t\n\r\v\f]+")--{- | Escape all characters in the input pattern that are not alphanumeric.--Does not make special allowances for NULL, which isn't valid in a-Haskell regular expression pattern. -}-escapeRe :: String -> String-escapeRe [] = []-escapeRe (x:xs)-    -- Chars that we never escape-    | x `elem` ['\'', '`'] = x : escapeRe xs-    -- General rules for chars we never escape-    | isDigit x || (isAscii x && isAlpha x) || x `elem` ['<', '>'] -        = x : escapeRe xs-    -- Escape everything else-    | otherwise = '\\' : x : escapeRe xs
+ src/Data/String/Utils.hs view
@@ -0,0 +1,101 @@+{- arch-tag: String utilities main file+Copyright (C) 2004-2006 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and\/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module     : Data.String.Utils+   Copyright  : Copyright (C) 2004-2008 John Goerzen+   License    : GNU GPL, version 2 or above++   Maintainer : John Goerzen <jgoerzen@complete.org>+   Stability  : provisional+   Portability: portable++This module provides various helpful utilities for dealing with strings.++Written by John Goerzen, jgoerzen\@complete.org+-}++module Data.String.Utils+                       (-- * Whitespace Removal+                        strip, lstrip, rstrip,+                        -- * Tests+                        -- | Note: These functions are aliases for functions+                        -- in "Data.List.Utils".+                        startswith, endswith,+                        -- * Conversions+                        -- | Note: Some of these functions are aliases for functions+                        -- in "Data.List.Utils".+                        join, split, splitWs, replace, escapeRe+                       ) where++import Data.List.Utils (startswith, endswith, join, split, replace)+import Data.Char (isAlpha, isAscii, isDigit)+import Text.Regex (mkRegex, splitRegex)++wschars :: String+wschars = " \t\r\n"++{- | Removes any whitespace characters that are present at the start+or end of a string. Does not alter the internal contents of a+string. If no whitespace characters are present at the start or end+of a string, returns the original string unmodified. Safe to use on+any string.++Note that this may differ from some other similar+functions from other authors in that:++1. If multiple whitespace+characters are present all in a row, they are all removed;++2. If no+whitespace characters are present, nothing is done.+-}+strip :: String -> String+strip = lstrip . rstrip++-- | Same as 'strip', but applies only to the left side of the string.+lstrip :: String -> String+lstrip s = case s of+                  [] -> []+                  (x:xs) -> if elem x wschars+                            then lstrip xs+                            else s++-- | Same as 'strip', but applies only to the right side of the string.+rstrip :: String -> String+rstrip = reverse . lstrip . reverse++{- | Splits a string around whitespace.  Empty elements in the result+list are automatically removed. -}+splitWs :: String -> [String]+splitWs = filter (\x -> x /= []) . splitRegex (mkRegex "[ \t\n\r\v\f]+")++{- | Escape all characters in the input pattern that are not alphanumeric.++Does not make special allowances for NULL, which isn't valid in a+Haskell regular expression pattern. -}+escapeRe :: String -> String+escapeRe [] = []+escapeRe (x:xs)+    -- Chars that we never escape+    | x `elem` ['\'', '`'] = x : escapeRe xs+    -- General rules for chars we never escape+    | isDigit x || (isAscii x && isAlpha x) || x `elem` ['<', '>']+        = x : escapeRe xs+    -- Escape everything else+    | otherwise = '\\' : x : escapeRe xs
+ src/Data/Tuple/Utils.hs view
@@ -0,0 +1,49 @@+{- arch-tag: Tuple utilities main file+Copyright (C) 2004-2006 John Goerzen <jgoerzen@complete.org>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module     : Data.Tuple.Utils+   Copyright  : Copyright (C) 2004-2008 John Goerzen+   License    : GNU GPL, version 2 or above++   Maintainer : John Goerzen <jgoerzen@complete.org> +   Stability  : provisional+   Portability: portable++This module provides various helpful utilities for dealing with lists.++Written by Neil Mitchell, <http://www.cs.york.ac.uk/~ndm/>+-}++module Data.Tuple.Utils(+    -- * Extraction+    fst3, snd3, thd3+    ) where+++-- | Take the first item out of a 3 element tuple+fst3 :: (a,b,c) -> a+fst3 (a,b,c) = a++-- | Take the second item out of a 3 element tuple+snd3 :: (a,b,c) -> b+snd3 (a,b,c) = b++-- | Take the third item out of a 3 element tuple+thd3 :: (a,b,c) -> c+thd3 (a,b,c) = c
src/Network/Email/Sendmail.hs view
@@ -22,7 +22,7 @@    Copyright  : Copyright (C) 2004-2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -45,6 +45,7 @@ import System.IO import System.IO.Error +sendmails :: [String] sendmails = ["/usr/sbin/sendmail",              "/usr/local/sbin/sendmail",              "/usr/local/bin/sendmail",@@ -90,12 +91,12 @@          -> IO () sendmail _ [] _ = fail "sendmail: no recipients specified" sendmail Nothing recipients msg = sendmail_worker recipients msg-sendmail (Just from) recipients msg = +sendmail (Just from) recipients msg =     sendmail_worker (("-f" ++ from) : recipients) msg-    + sendmail_worker :: [String] -> String -> IO () sendmail_worker args msg =-    let func h = hPutStr h msg +    let func h = hPutStr h msg         in         do         --pOpen WriteToPipe "/usr/sbin/sendmail" args func@@ -104,8 +105,8 @@             Right x -> return x             Left _ -> do                       sn <- findsendmail-                      rv <- pOpen WriteToPipe sn args func-                      return $! rv-                         +                      r <- pOpen WriteToPipe sn args func+                      return $! r+ #endif 
src/Network/Utils.hs view
@@ -15,13 +15,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -}- {- |    Module     : Network.Utils    Copyright  : Copyright (C) 2004-2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: systems with networking @@ -31,10 +30,10 @@  -} -module Network.Utils(niceSocketsDo, connectTCP, connectTCPAddr,-                        listenTCPAddr, showSockAddr-                       )-where+module Network.Utils (niceSocketsDo, connectTCP, connectTCPAddr,+                        listenTCPAddr, showSockAddr)+    where+ import Network import Network.Socket import Network.BSD@@ -43,11 +42,11 @@  {- | Sets up the system for networking.  Similar to the built-in withSocketsDo (and actually, calls it), but also sets the SIGPIPE-handler so that signal is ignored. +handler so that signal is ignored.  Example: -> main = niceSocketsDo $ do { ... } +> main = niceSocketsDo $ do { ... } -}  -- FIXME integrate with WebCont.Util.UDP@@ -56,7 +55,7 @@ niceSocketsDo func = do #ifndef mingw32_HOST_OS                 -- No signals on Windows anyway-                System.Posix.Signals.installHandler +                System.Posix.Signals.installHandler                       System.Posix.Signals.sigPIPE                       System.Posix.Signals.Ignore                       Nothing@@ -74,7 +73,7 @@                       s <- socket AF_INET Stream proto                       connect s addr                       return s-                      + listenTCPAddr :: SockAddr -> Int -> IO Socket listenTCPAddr addr queuelen = do                      proto <- getProtocolNumber "tcp"
src/System/Cmd/Utils.hs view
@@ -23,7 +23,7 @@    Copyright  : Copyright (C) 2004-2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable to platforms with POSIX process\/signal tools @@ -99,7 +99,7 @@                     pOpen, pOpen3, pOpen3Raw #endif #endif-		   )+                   ) where  -- FIXME - largely obsoleted by 6.4 - convert to wrappers.@@ -122,6 +122,7 @@  data PipeMode = ReadFromPipe | WriteToPipe +logbase :: String logbase = "System.Cmd.Utils"  {- | Return value from 'pipeFrom', 'pipeLinesFrom', 'pipeTo', or@@ -129,7 +130,7 @@ executed.  If you prefer not to use 'forceSuccess' on the result of one of these pipe calls, you can use (processID ph), assuming ph is your 'PipeHandle', as a parameter to 'System.Posix.Process.getProcessStatus'. -}-data PipeHandle = +data PipeHandle =     PipeHandle { processID :: ProcessID,                  phCommand :: FilePath,                  phArgs :: [String],@@ -152,7 +153,10 @@ #endif #endif +logRunning :: String -> FilePath -> [String] -> IO () logRunning func fp args = debugM (logbase ++ "." ++ func) (showCmd fp args)++warnFail :: [Char] -> FilePath -> [String] -> [Char] -> IO t warnFail funcname fp args msg =     let m = showCmd fp args ++ ": " ++ msg         in do warningM (logbase ++ "." ++ funcname) m@@ -170,7 +174,7 @@ Not available on Windows or with Hugs. -} hPipeFrom :: FilePath -> [String] -> IO (PipeHandle, Handle)-hPipeFrom fp args = +hPipeFrom fp args =     do pipepair <- createPipe        logRunning "pipeFrom" fp args        let childstuff = do dupTo (snd pipepair) stdOutput@@ -180,7 +184,7 @@        -- parent        pid <- case p of                   Right x -> return x-                  Left e -> warnFail "pipeFrom" fp args $ +                  Left e -> warnFail "pipeFrom" fp args $                             "Error in fork: " ++ show e        closeFd (snd pipepair)        h <- fdToHandle (fst pipepair)@@ -229,7 +233,7 @@        -- parent        pid <- case p of                    Right x -> return x-                   Left e -> warnFail "pipeTo" fp args $ +                   Left e -> warnFail "pipeTo" fp args $                              "Error in fork: " ++ show e        closeFd (fst pipepair)        h <- fdToHandle (snd pipepair)@@ -319,7 +323,7 @@ of the given process ID.  If the process terminated normally, does nothing. Otherwise, raises an exception with an appropriate error message. -This call will block waiting for the given pid to terminate. +This call will block waiting for the given pid to terminate.  Not available on Windows. -} forceSuccess :: PipeHandle -> IO ()@@ -329,12 +333,12 @@               case status of                 Nothing -> warnfail fp args $ "Got no process status"                 Just (Exited (ExitSuccess)) -> return ()-                Just (Exited (ExitFailure fc)) -> +                Just (Exited (ExitFailure fc)) ->                     cmdfailed funcname fp args fc-                Just (Terminated sig) -> +                Just (Terminated sig) ->                     warnfail fp args $ "Terminated by signal " ++ show sig-                Just (Stopped sig) -> -                    warnfail fp args $ "Stopped by signal " ++ show sig +                Just (Stopped sig) ->+                    warnfail fp args $ "Stopped by signal " ++ show sig #endif  {- | Invokes the specified command in a subprocess, waiting for the result.@@ -344,7 +348,7 @@ Implemented in terms of 'posixRawSystem' where supported, and System.Posix.rawSystem otherwise. -} safeSystem :: FilePath -> [String] -> IO ()-safeSystem command args = +safeSystem command args =     do debugM (logbase ++ ".safeSystem")                ("Running: " ++ command ++ " " ++ (show args)) #if defined(__HUGS__) || defined(mingw32_HOST_OS)@@ -381,7 +385,7 @@        oldset <- getSignalMask        blockSignals sigset        childpid <- forkProcess (childaction oldint oldquit oldset)-       +        mps <- getProcessStatus True False childpid        restoresignals oldint oldquit oldset        let retval = case mps of@@ -392,9 +396,9 @@               (program ++ ": exited with " ++ show retval)        return retval -    where childaction oldint oldquit oldset = +    where childaction oldint oldquit oldset =               do restoresignals oldint oldquit oldset-                 executeFile program True args Nothing +                 executeFile program True args Nothing           restoresignals oldint oldquit oldset =               do installHandler sigINT oldint Nothing                  installHandler sigQUIT oldquit Nothing@@ -418,14 +422,12 @@     do debugM (logbase ++ ".forkRawSystem")                ("Running: " ++ program ++ " " ++ (show args))        forkProcess childaction--    where childaction =-                 executeFile program True args Nothing +    where+      childaction = executeFile program True args Nothing  #endif #endif - cmdfailed :: String -> FilePath -> [String] -> Int -> IO a cmdfailed funcname command args failcode = do     let errormsg = "Command " ++ command ++ " " ++ (show args) ++@@ -452,12 +454,12 @@  Passes the handle on to the specified function. -The 'PipeMode' specifies what you will be doing.  That is, specifing 'ReadFromPipe' +The 'PipeMode' specifies what you will be doing.  That is, specifing 'ReadFromPipe' sets up a pipe from stdin, and 'WriteToPipe' sets up a pipe from stdout.  Not available on Windows.  -}-pOpen :: PipeMode -> FilePath -> [String] -> +pOpen :: PipeMode -> FilePath -> [String] ->          (Handle -> IO a) -> IO a pOpen pm fp args func =         do@@ -474,7 +476,7 @@                                         return $! x                          pOpen3 Nothing (Just (snd pipepair)) Nothing fp args                                 callfunc (closeFd (fst pipepair))-         WriteToPipe -> do +         WriteToPipe -> do                         let callfunc _ = do                                        closeFd (fst pipepair)                                        h <- fdToHandle (snd pipepair)@@ -488,7 +490,7 @@  #ifndef mingw32_HOST_OS #ifndef __HUGS__-{- | Runs a command, redirecting things to pipes. +{- | Runs a command, redirecting things to pipes.  Not available on Windows. @@ -503,7 +505,7 @@        -> (ProcessID -> IO a)           -- ^ Action to run in parent        -> IO ()                         -- ^ Action to run in child before execing (if you don't need something, set this to @return ()@) -- IGNORED IN HUGS        -> IO a-pOpen3 pin pout perr fp args func childfunc = +pOpen3 pin pout perr fp args func childfunc =     do pid <- pOpen3Raw pin pout perr fp args childfunc        retval <- func $! pid        let rv = seq retval retval@@ -514,7 +516,7 @@  #ifndef mingw32_HOST_OS #ifndef __HUGS__-{- | Runs a command, redirecting things to pipes. +{- | Runs a command, redirecting things to pipes.  Not available on Windows. @@ -554,7 +556,7 @@                      func p -}         in-        do +        do         p <- try (forkProcess childstuff)         pid <- case p of                 Right x -> return x@@ -564,7 +566,5 @@ #endif #endif - showCmd :: FilePath -> [String] -> String-showCmd fp args =-    fp ++ " " ++ show args+showCmd fp args = fp ++ " " ++ show args
src/System/Daemon.hs view
@@ -22,7 +22,7 @@    Copyright  : Copyright (C) 2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable to platforms with POSIX process\/signal tools @@ -47,8 +47,8 @@ #ifndef mingw32_HOST_OS         detachDaemon #endif-		   )-where+                   )+                       where #ifndef mingw32_HOST_OS  import System.Posix.Process@@ -58,6 +58,7 @@ import System.Exit  +trap :: IO a -> IO a trap = traplogging "System.Daemon" ERROR "detachDaemon"  {- | Detach the process from a controlling terminal and run it in the@@ -67,7 +68,7 @@   * The PID of the running process will change - * stdin, stdout, and stderr will not work (they'll be set to + * stdin, stdout, and stderr will not work (they'll be set to    \/dev\/null)   * CWD will be changed to \/@@ -76,10 +77,9 @@  Note that this is not intended for a daemon invoked from inetd(1). -}- detachDaemon :: IO ()-detachDaemon = trap $ -               do forkProcess child1 +detachDaemon = trap $+               do forkProcess child1                   exitImmediately ExitSuccess  child1 :: IO ()@@ -95,6 +95,4 @@        nullFd <- openFd "/dev/null" ReadWrite Nothing defaultFileFlags        mapM_ (dupTo nullFd) [stdInput, stdOutput, stdError]        closeFd nullFd-- #endif
src/System/Debian.hs view
@@ -21,7 +21,7 @@    Copyright  : Copyright (C) 2004 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -36,11 +36,9 @@                         -- * Version Number Utilities                         DebVersion, compareDebVersion, checkDebVersion                        )-where+    where+ import System.Cmd-import System.Debian.ControlParser-import System.Cmd.Utils-import Data.String import System.IO.Unsafe import System.Exit @@ -48,9 +46,6 @@ or any control-like file (such as the output from apt-cache show, etc.) -} type ControlFile = [(String, String)] -splitComma :: String -> [String]-splitComma = map strip . split ","- ---------------------------------------------------------------------- -- VERSION NUMBERS ----------------------------------------------------------------------@@ -60,7 +55,7 @@ data DebVersion = DebVersion String                 deriving (Eq) instance Ord DebVersion where-    compare (DebVersion v1) (DebVersion v2) = +    compare (DebVersion v1) (DebVersion v2) =         {- This is OK since compareDebVersion should always be the same. -}         unsafePerformIO $ compareDebVersion v1 v2 @@ -82,6 +77,6 @@                 -> IO Bool checkDebVersion v1 op v2 =     do ec <- rawSystem "dpkg" ["--compare-versions", v1, op, v2]-       case ec of +       case ec of                ExitSuccess -> return True                ExitFailure _ -> return False
src/System/Debian/ControlParser.hs view
@@ -21,7 +21,7 @@    Copyright  : Copyright (C) 2004 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -33,18 +33,20 @@  module System.Debian.ControlParser(control, depPart)     where+ import Text.ParserCombinators.Parsec-import Data.String+import Data.String.Utils (split) +eol, extline :: GenParser Char st String eol = (try (string "\r\n"))       <|> string "\n" <?> "EOL"  extline = try (do char ' '                   content <- many (noneOf "\r\n")                   eol-                  return content-              )+                  return content ) +entry :: GenParser Char st (String, String) entry = do key <- many1 (noneOf ":\r\n")            char ':'            val <- many (noneOf "\r\n")@@ -58,6 +60,7 @@              retval <- many entry              return retval +headerPGP, blankLine, header, headerHash :: GenParser Char st () headerPGP = do string "-----BEGIN PGP"                manyTill (noneOf "\r\n") eol                return ()@@ -69,9 +72,9 @@                 return () header = (try headerPGP) <|> (try blankLine) <|> (try headerHash) -{- | Dependency parser. +{- | Dependency parser. -Returns (package name, Maybe version, arch list+Returns (package name, Maybe version, arch list)  version is (operator, operand) -} depPart :: CharParser a (String, (Maybe (String, String)), [String])
src/System/FileArchive/GZip.hs view
@@ -46,17 +46,16 @@                                   read_header,                                   read_section                                  )-where+    where -import Data.Compression.Inflate-import Data.Hash.CRC32.GZip-import Data.List-import Data.Bits-import Control.Monad.Error-import Data.Char-import Data.Word-import Data.Bits.Utils-import System.IO+import Data.Compression.Inflate (inflate_string_remainder)+import Data.Hash.CRC32.GZip (update_crc)+import Data.Bits ((.&.))+import Control.Monad.Error -- (Error(), strMsg, throwError)+import Data.Char (ord)+import Data.Word (Word32())+import Data.Bits.Utils (fromBytes)+import System.IO (hGetContents, hPutStr, Handle())  data GZipError = CRCError               -- ^ CRC-32 check failed                | NotGZIPFile            -- ^ Couldn't find a GZip header@@ -69,14 +68,16 @@     strMsg = UnknownError  -- | First two bytes of file+magic :: String magic = "\x1f\x8b"  -- | Flags-fFTEXT = 1::Int-fFHCRC = 2::Int-fFEXTRA = 4::Int-fFNAME = 8::Int-fFCOMMENT = 16::Int+fFHCRC, fFEXTRA, fFNAME, fFCOMMENT :: Int+-- fFTEXT = 1 :: Int+fFHCRC = 2+fFEXTRA = 4+fFNAME = 8+fFCOMMENT = 16  {- | The data structure representing the GZip header.  This occurs at the beginning of each 'Section' on disk. -}@@ -117,7 +118,7 @@ hDecompress :: Handle                   -- ^ Input handle             -> Handle                   -- ^ Output handle             -> IO (Maybe GZipError)-hDecompress infd outfd = +hDecompress infd outfd =     do inc <- hGetContents infd        let (outstr, err) = decompress inc        hPutStr outfd outstr@@ -131,15 +132,15 @@ -} decompress :: String -> (String, Maybe GZipError) {--decompress s = +decompress s =     do x <- read_header s        let rem = snd x        return $ inflate_string rem -}-decompress s = +decompress s =     let procs :: [Section] -> (String, Bool)         procs [] = ([], True)-        procs ((_, content, foot):xs) = +        procs ((_, content, foot):xs) =             let (nexth, nextb) = procs xs in                 (content ++ nexth, (crc32valid foot) && nextb)         in case read_sections s of@@ -152,7 +153,7 @@                   return $ concatMap (\(_, x, _) -> x) x -} --- | Read all sections.  +-- | Read all sections. read_sections :: String -> Either GZipError [Section] read_sections [] = Right [] read_sections s =@@ -170,34 +171,34 @@ read_section s =         do x <- read_header s            let headerrem = snd x-           let (decompressed, crc32, remainder) = read_data headerrem-           let (crc32str, rem) = splitAt 4 remainder-           let (sizestr, rem2) = splitAt 4 rem+           let (decompressed, crc, remainder) = read_data headerrem+           let (crc32str, rm) = splitAt 4 remainder+           let (sizestr, rem2) = splitAt 4 rm            let filecrc32 = parseword crc32str            let filesize = parseword sizestr            return ((fst x, decompressed,                    Footer {size = filesize, crc32 = filecrc32,-                           crc32valid = filecrc32 == crc32})+                           crc32valid = filecrc32 == crc})                    ,rem2)  -- | Read the file's compressed data, returning -- (Decompressed, Calculated CRC32, Remainder) read_data :: String -> (String, Word32, String)-read_data x = +read_data x =     let (decompressed1, remainder) = inflate_string_remainder x         (decompressed, crc32) = read_data_internal decompressed1 0         in-        (decompressed, crc32, remainder)+          (decompressed, crc32, remainder)     where-    read_data_internal [] ck = ([], ck)-    read_data_internal (x:xs) ck =-        let newcrc = update_crc ck x-            n = newcrc `seq` read_data_internal xs newcrc+      read_data_internal [] ck = ([], ck)+      read_data_internal (y:ys) ck =+        let newcrc = update_crc ck y+            n = newcrc `seq` read_data_internal ys newcrc             in-            (x : fst n, snd n)-    +            (y : fst n, snd n)  + {- | Read the GZip header.  Return (Header, Remainder). -} read_header :: String -> Either GZipError (Header, String)@@ -217,22 +218,22 @@        let mtime = parseword mtimea        let (xfla, rem3b) = split1 rem3a        let xfl = ord xfla-       let (osa, rem3c) = split1 rem3b+       let (osa, _) = split1 rem3b        let os = ord osa        -- skip modtime (4), extraflag (1), and os (1)        let rem4 = drop 6 rem3-       -       let (extra, rem5) = ++       let (extra, rem5) =                if (flag .&. fFEXTRA /= 0)                -- Skip past the extra field if we have it.-                  then let (xlen_S, rem4a) = split1 rem4+                  then let (xlen_S, _) = split1 rem4                            (xlen2_S, rem4b) = split1 rem4                            xlen = (ord xlen_S) + 256 * (ord xlen2_S)                            (ex, rrem) = splitAt xlen rem4b                            in (Just ex, rrem)                   else (Nothing, rem4)-       -       let (filename, rem6) = ++       let (filename, rem6) =                if (flag .&. fFNAME /= 0)                -- Skip past the null-terminated filename                   then let fn = takeWhile (/= '\x00') rem5@@ -245,12 +246,12 @@                   then let cm = takeWhile (/= '\x00') rem6                            in (Just cm, drop ((length cm) + 1) rem6)                   else (Nothing, rem6)-       +        rem8 <- if (flag .&. fFHCRC /= 0)                   -- Skip past the header CRC                   then return $ drop 2 rem7                   else return rem7-                  +        return (Header {method = ord method,                       flags = flag,                       extra = extra,
src/System/IO/Binary.hs view
@@ -21,14 +21,14 @@    Copyright  : Copyright (C) 2004-2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable to platforms supporting binary I\/O  This module provides various helpful utilities for dealing with binary input and output. -You can use this module to deal with binary blocks of data as either Strings +You can use this module to deal with binary blocks of data as either Strings or lists of Word8.  The BinaryConvertible class provides this abstraction.  Wherever you see HVIO, you can transparently substite a regular Handle.@@ -44,7 +44,7 @@ is the support status:   * GHC 6.2 and above: yes- +  * GHC 6.x, earlier versions: unknown   * GHC 5.x: no@@ -80,17 +80,16 @@                        hFullBlockInteract, fullBlockInteract                         ) where -import Foreign.Ptr+import Data.Word (Word8())+import Foreign.C.String (peekCStringLen, withCString)+import Foreign.C.Types (CChar()) import Foreign.ForeignPtr-import Foreign.C.String-import Foreign.C.Types-import Foreign.Storable-import Foreign.Marshal.Array-import Data.Word-import System.IO.Unsafe+import Foreign.Marshal.Array (peekArray, withArray)+import Foreign.Ptr import System.IO-import System.IO.HVIO import System.IO.HVFS+import System.IO.HVIO+import System.IO.Unsafe (unsafeInterleaveIO)  {- | Provides support for handling binary blocks with convenient types.@@ -103,7 +102,7 @@  instance BinaryConvertible Char where     toBuf = withCString-    fromBuf len func = +    fromBuf len func =         do fbuf <- mallocForeignPtrArray (len + 1)            withForeignPtr fbuf handler         where handler ptr =@@ -120,19 +119,18 @@                      peekArray bytesread ptr  --- . **************************************************--- . Binary Files--- . **************************************************-+--  **************************************************+--  Binary Files+--  **************************************************  {- | As a wrapper around the standard function 'System.IO.hPutBuf', this function takes a standard Haskell 'String' instead of the far less-convenient 'Ptr a'.  The entire contents of the string will be written+convenient @Ptr a@.  The entire contents of the string will be written as a binary buffer using 'hPutBuf'.  The length of the output will be-the length of the passed String or list..+the length of the passed String or list.  If it helps, you can thing of this function as being of type-@Handle -> String -> IO ()@. -}+@Handle -> String -> IO ()@ -} hPutBufStr :: (HVIO a, BinaryConvertible b) => a -> [b] -> IO () hPutBufStr f s = toBuf s (\cs -> vPutBuf f cs (length s)) @@ -159,7 +157,7 @@ {- | Like 'hGetBufStr', but guarantees that it will only return fewer than the requested number of bytes when EOF is encountered. -} hFullGetBufStr :: (HVIO a, BinaryConvertible b) => a -> Int -> IO [b]-hFullGetBufStr f 0 = return []+hFullGetBufStr _ 0 = return [] hFullGetBufStr f count = do                          thisstr <- hGetBufStr f count                          if thisstr == []@@ -186,9 +184,9 @@                       hPutBufStr h x                       hPutBlocks h xs --- | An alias for 'hPutBlocks' 'stdout'+{- | An alias for 'hPutBlocks' 'stdout' putBlocks :: (BinaryConvertible b) => [[b]] -> IO ()-putBlocks = hPutBlocks stdout+putBlocks = hPutBlocks stdout -}  {- | Returns a lazily-evaluated list of all blocks in the input file, as read by 'hGetBufStr'.  There will be no 0-length block in this list.@@ -210,14 +208,13 @@  hGetBlocksUtil :: (HVIO a, BinaryConvertible b) => (a -> Int -> IO [b]) -> a -> Int -> IO [[b]] hGetBlocksUtil readfunc h count =-    unsafeInterleaveIO (do+    unsafeInterleaveIO $ do                        block <- readfunc h count                        if block == []                           then return []                           else do                                remainder <- hGetBlocksUtil readfunc h count                                return (block : remainder)-                       )  {- | Binary block-based interaction.  This is useful for scenarios that take binary blocks, manipulate them in some way, and then write them@@ -240,11 +237,11 @@ hFullBlockInteract = hBlockInteractUtil hFullGetBlocks  -- | An alias for 'hFullBlockInteract' over 'stdin' and 'stdout'-fullBlockInteract :: (BinaryConvertible b, BinaryConvertible c) => +fullBlockInteract :: (BinaryConvertible b, BinaryConvertible c) =>                      Int -> ([[b]] -> [[c]]) -> IO () fullBlockInteract x = hFullBlockInteract x stdin stdout -hBlockInteractUtil :: (HVIO a, HVIO d, BinaryConvertible b, BinaryConvertible c) => +hBlockInteractUtil :: (HVIO a, HVIO d, BinaryConvertible b, BinaryConvertible c) =>                       (a -> Int -> IO [[b]]) -> Int ->                       a -> d -> ([[b]] -> [[c]]) -> IO () hBlockInteractUtil blockreader blocksize hin hout func =@@ -253,7 +250,7 @@     hPutBlocks hout (func blocks)  {- | Copies everything from the input handle to the output handle using binary-blocks of the given size.  This was once the following +blocks of the given size.  This was once the following beautiful implementation:  > hBlockCopy bs hin hout = hBlockInteract bs hin hout id@@ -264,9 +261,8 @@ In more recent versions of MissingH, it uses a more optimized routine that avoids ever having to convert the binary buffer at all. -}- hBlockCopy :: (HVIO a, HVIO b) => Int -> a -> b -> IO ()-hBlockCopy bs hin hout = +hBlockCopy bs hin hout =     do (fbuf::ForeignPtr CChar) <- mallocForeignPtrArray (bs + 1)        withForeignPtr fbuf handler     where handler ptr =
src/System/IO/HVFS/Combinators.hs view
@@ -16,13 +16,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -}- {- |    Module     : System.IO.HVFS.Combinators    Copyright  : Copyright (C) 2004-2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -32,31 +31,25 @@  -} -module System.IO.HVFS.Combinators(-                                    -- * Restrictions+module System.IO.HVFS.Combinators ( -- * Restrictions                                     HVFSReadOnly(..),-                                    HVFSChroot, newHVFSChroot-                                   )-where+                                    HVFSChroot, newHVFSChroot)+    where -import System.IO.HVFS-import System.IO.HVIO-import System.IO.HVFS.InstanceHelpers import System.IO import System.IO.Error+import System.IO.HVFS+import System.IO.HVFS.InstanceHelpers (getFullPath) #ifndef mingw32_HOST_OS-import System.Posix.Files+import System.Posix.Files -- This actually needed? -Wall doesn't seem to think+                          -- so, but I'm not sure... #endif-import System.Posix.Types-import System.Time-import System.Directory-import System.Path-import System.Path.NameManip+import System.Path (secureAbsNormPath)+import System.Path.NameManip (normalise_path)  ---------------------------------------------------------------------- -- Providing read-only access ----------------------------------------------------------------------- {- | Restrict access to the underlying filesystem to be strictly read-only.  Any write-type operations will cause an error. @@ -68,7 +61,8 @@ withro :: HVFS a => (a -> b) -> HVFSReadOnly a -> b withro f (HVFSReadOnly x) = f x -roerror h = +roerror :: (HVFS a) => HVFSReadOnly a -> IO c+roerror h =     let err x = vRaiseError x permissionErrorType "Read-only virtual filesystem"                   Nothing         in withro err h@@ -92,14 +86,13 @@     vCreateLink h _ _ = roerror h  instance HVFSOpenable a => HVFSOpenable (HVFSReadOnly a) where-    vOpen fh fp mode = +    vOpen fh fp mode =         case mode of ReadMode -> withro (\h -> vOpen h fp mode) fh                      _ -> roerror fh  ---------------------------------------------------------------------- -- Restricting to a subdirectory ----------------------------------------------------------------------- {- | Access a subdirectory of a real filesystem as if it was the root of that filesystem. -} data HVFS a => HVFSChroot a = HVFSChroot String a@@ -121,16 +114,18 @@                  (Just full)  {- | Get the embedded object -}+dch :: (HVFS t) => HVFSChroot t -> t dch (HVFSChroot _ a) = a  {- | Convert a local (chroot) path to a full path. -}-dch2fp mainh@(HVFSChroot fp h) locfp = +dch2fp, fp2dch :: (HVFS t) => HVFSChroot t -> String -> IO String+dch2fp mainh@(HVFSChroot fp h) locfp =     do full <- case (head locfp) of                   '/' -> return (fp ++ locfp)-                  x -> do y <- getFullPath mainh locfp+                  _ -> do y <- getFullPath mainh locfp                           return $ fp ++ y        case secureAbsNormPath fp full of-           Nothing -> vRaiseError h doesNotExistErrorType  +           Nothing -> vRaiseError h doesNotExistErrorType                         ("Trouble normalizing path in chroot")                         (Just (fp ++ "," ++ full))            Just x -> return x@@ -149,9 +144,11 @@                else let newpath2 = drop (length fp) newpath                         in return $ normalise_path ("/" ++ newpath2) -dch2fph func fh@(HVFSChroot fp h) locfp =+dch2fph :: (HVFS t) => (t -> String -> IO t1) -> HVFSChroot t -> [Char] -> IO t1+dch2fph func fh@(HVFSChroot _ h) locfp =     do newfp <- dch2fp fh locfp        func h newfp+ instance HVFS a => HVFS (HVFSChroot a) where     vGetCurrentDirectory x = do fp <- vGetCurrentDirectory (dch x)                                 fp2dch x fp
src/System/IO/HVFS/InstanceHelpers.hs view
@@ -21,7 +21,7 @@    Copyright  : Copyright (C) 2004 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -41,20 +41,19 @@                                         MemoryEntry(..),                                         -- * Utilities                                         nice_slice, getFullPath,-                                        getFullSlice-                                       )-where+                                        getFullSlice)+    where++import Data.IORef (newIORef, readIORef, writeIORef, IORef())+import Data.List (genericLength)+import System.IO -- (ReadMode)+import System.IO.Error (doesNotExistErrorType, illegalOperationErrorType, permissionErrorType) import System.IO.HVFS-import Data.IORef-import Data.List-import System.Path-import System.Path.NameManip-import Control.Monad.Error-import System.IO.Error-import System.IO-import System.IO.HVIO+import System.IO.HVIO (newStreamReader)+import System.Path (absNormPath)+import System.Path.NameManip (slice_path) -{- | A simple "System.IO.HVFS.HVFSStat" +{- | A simple "System.IO.HVFS.HVFSStat" class that assumes that everything is either a file or a directory. -} data SimpleStat = SimpleStat {@@ -69,7 +68,6 @@ ---------------------------------------------------------------------- -- In-Memory Tree Types ----------------------------------------------------------------------- {- | The basic node of a 'MemoryVFS'.  The String corresponds to the filename, and the entry to the contents. -} type MemoryNode = (String, MemoryEntry)@@ -81,8 +79,7 @@  {- | An in-memory read\/write filesystem.  Think of it as a dynamically resizable ramdisk written in Haskell. -}--data MemoryVFS = MemoryVFS +data MemoryVFS = MemoryVFS                { content :: IORef [MemoryNode],                  cwd :: IORef FilePath                }@@ -124,7 +121,7 @@ getFullPath :: HVFS a => a -> String -> IO String getFullPath fs path =     do cwd <- vGetCurrentDirectory fs-       case absNormPath cwd path of+       case (absNormPath cwd path) of            Nothing -> vRaiseError fs doesNotExistErrorType                         ("Trouble normalizing path " ++ path) (Just (cwd ++ "/" ++ path))            Just newpath -> return newpath@@ -145,7 +142,7 @@         t = tail sliced1         newh = if (h /= "/") && head h == '/' then tail h else h         sliced2 = newh : t-                  +         -- Walk the tree         walk :: MemoryEntry -> [String] -> Either String MemoryEntry         -- Empty list -- return the item we have@@ -153,14 +150,14 @@         -- Root directory -- return the item we have         walk y ["/"] = Right y         -- File but stuff: error-        walk (MemoryFile _) (x : _) = -            Left $ "Attempt to look up name " ++ x ++ " in file"-        walk (MemoryDirectory y) (x : xs) =-            let newentry = case lookup x y of-                                Nothing -> Left $ "Couldn't find entry " ++ x-                                Just z -> Right z+        walk (MemoryFile _) (z : _) =+            Left $ "Attempt to look up name " ++ z ++ " in file"+        walk (MemoryDirectory y) (z : zs) =+            let newentry = case lookup z y of+                                Nothing -> Left $ "Couldn't find entry " ++ z+                                Just a -> Right a                 in do newobj <- newentry-                      walk newobj xs+                      walk newobj zs         in do            c <- readIORef $ content x            case walk (MemoryDirectory c) (sliced2) of@@ -169,7 +166,7 @@  -- | Find an element on the tree, normalizing the path first getMelem :: MemoryVFS -> String -> IO MemoryEntry-getMelem x s = +getMelem x s =     do base <- readIORef $ cwd x        case absNormPath base s of            Nothing -> vRaiseError x doesNotExistErrorType@@ -182,17 +179,17 @@         do curpath <- vGetCurrentDirectory x            -- Make sure new dir is valid            newdir <- getMelem x fp-           case newdir of -               (MemoryFile _) -> vRaiseError x doesNotExistErrorType +           case newdir of+               (MemoryFile _) -> vRaiseError x doesNotExistErrorType                                  ("Attempt to cwd to non-directory " ++ fp)                                  (Just fp)-               (MemoryDirectory _) -> +               (MemoryDirectory _) ->                    case absNormPath curpath fp of                        Nothing -> -- should never happen due to above getMelem call                                   vRaiseError x illegalOperationErrorType                                               "Bad internal error" (Just fp)                        Just y -> writeIORef (cwd x) y-    vGetFileStatus x fp = +    vGetFileStatus x fp =         do elem <- getMelem x fp            case elem of                      (MemoryFile y) -> return $ HVFSStatEncap $@@ -210,9 +207,9 @@                 MemoryDirectory c -> return $ map fst c  instance HVFSOpenable MemoryVFS where-    vOpen x fp (ReadMode) = +    vOpen x fp (ReadMode) =         do elem <- getMelem x fp-           case elem of +           case elem of                 MemoryDirectory _ -> vRaiseError x doesNotExistErrorType                                       "Can't open a directory"                                       (Just fp)
src/System/IO/HVIO.hs view
@@ -21,7 +21,7 @@    Copyright  : Copyright (C) 2004-2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -87,7 +87,7 @@  'MemoryBuffer' is a similar class, but with a different purpose.  It provides a full interface like Handle (it implements 'HVIOReader', 'HVIOWriter',-and 'HVIOSeeker').  However, it maintains an in-memory buffer with the +and 'HVIOSeeker').  However, it maintains an in-memory buffer with the contents of the file, rather than an actual on-disk file.  You can access the entire contents of this buffer at any time.  This can be quite useful for testing I\/O code, or for cases where existing APIs use I\/O, but you@@ -111,7 +111,7 @@ -}  module System.IO.HVIO(-- * Implementation Classes-                     HVIO(..), +                     HVIO(..),                      -- * Standard HVIO Implementations                       -- ** Handle@@ -121,7 +121,7 @@                      StreamReader, newStreamReader,                       -- ** Memory Buffer-                     MemoryBuffer, newMemoryBuffer, +                     MemoryBuffer, newMemoryBuffer,                      mbDefaultCloseFunc, getMemoryBuffer,                       -- ** Haskell Pipe@@ -155,9 +155,8 @@ Implementators of writable objects must provide at least 'vPutChar' and 'vIsWritable'. -Implementators of seekable objects must provide at least +Implementators of seekable objects must provide at least 'vIsSeekable', 'vTell', and 'vSeek'.- -} class (Show a) => HVIO a where     -- | Close a file@@ -201,12 +200,12 @@        a 'vGetChar' after a 'vGetContents' may return some undefined        result instead of the error you would normally get.  You should        use caution to make sure your code doesn't fall into that trap,-       or make sure to test your code with Handle or one of the +       or make sure to test your code with Handle or one of the        default instances defined in this module.  Also, some implementations        may essentially provide a complete close after a call to 'vGetContents'.        The bottom line: after a call to 'vGetContents', you should do nothing        else with the object save closing it with 'vClose'.-       +        For implementators, you are highly encouraged to provide a correct        implementation. -}     vGetContents :: a -> IO String@@ -225,7 +224,7 @@     -- | Write a string representation of the argument, plus a newline.     vPrint :: Show b => a -> b -> IO ()     -- | Flush any output buffers.-    -- Note: implementations should assure that a vFlush is automatically +    -- Note: implementations should assure that a vFlush is automatically     -- performed     -- on file close, if necessary to ensure all data sent is written.     vFlush :: a -> IO ()@@ -290,8 +289,8 @@      vIsReadable _ = return False -    vGetLine h = -        let loop accum = +    vGetLine h =+        let loop accum =                 let func = do c <- vGetChar h                               case c of                                      '\n' -> return accum@@ -306,7 +305,7 @@                    x -> loop [x]      vGetContents h =-        let loop = +        let loop =                 let func = do c <- vGetChar h                               next <- loop                               c `seq` return (c : next)@@ -315,7 +314,7 @@                     in catch func handler             in             do loop-           +     vReady h = do vTestEOF h                   return True @@ -329,7 +328,7 @@     vPutStrLn h s = vPutStr h (s ++ "\n")      vPrint h s = vPutStrLn h (show s)-                 +     vFlush = vTestOpen  @@ -341,13 +340,13 @@     vSeek h _ _ = vThrow h illegalOperationErrorType     vTell h = vThrow h illegalOperationErrorType     vGetChar h = vThrow h illegalOperationErrorType-     +     vPutBuf h buf len =         do str <- peekCStringLen (castPtr buf, len)            vPutStr h str -    vGetBuf h b l = +    vGetBuf h b l =         worker b l 0         where worker _ 0 accum = return accum               worker buf len accum =@@ -363,7 +362,6 @@ ---------------------------------------------------------------------- -- Handle instances ----------------------------------------------------------------------- instance HVIO Handle where     vClose = hClose     vIsEOF = hIsEOF@@ -393,7 +391,6 @@     vIsOpen = hIsOpen     vIsClosed = hIsClosed - ---------------------------------------------------------------------- -- VIO Support ----------------------------------------------------------------------@@ -414,7 +411,6 @@ ---------------------------------------------------------------------- -- Stream Readers ----------------------------------------------------------------------- {- | Simulate I\/O based on a string buffer.  When a 'StreamReader' is created, it is initialized based on the contents of@@ -434,7 +430,9 @@ newStreamReader s = do ref <- newIORef (True, s)                        return (StreamReader ref) +srv :: StreamReader -> VIOCloseSupport String srv (StreamReader x) = x+ instance Show StreamReader where     show _ = "<StreamReader>" @@ -451,7 +449,7 @@                     let retval = head c                     vioc_set (srv h) (tail c)                     return retval-    +     vGetContents h = do vTestEOF h                         c <- vioc_get (srv h)                         vClose h@@ -461,13 +459,12 @@ ---------------------------------------------------------------------- -- Buffers ----------------------------------------------------------------------- {- | A 'MemoryBuffer' simulates true I\/O, but uses an in-memory buffer instead of on-disk storage.  It provides a full interface like Handle (it implements 'HVIOReader', 'HVIOWriter',-and 'HVIOSeeker').  However, it maintains an in-memory buffer with the +and 'HVIOSeeker').  However, it maintains an in-memory buffer with the contents of the file, rather than an actual on-disk file.  You can access the entire contents of this buffer at any time.  This can be quite useful for testing I\/O code, or for cases where existing APIs use I\/O, but you@@ -501,9 +498,10 @@ mbDefaultCloseFunc :: String -> IO () mbDefaultCloseFunc _ = return () +vrv :: MemoryBuffer -> VIOCloseSupport (Int, String) vrv (MemoryBuffer _ x) = x -{- | Grab the entire contents of the buffer as a string. +{- | Grab the entire contents of the buffer as a string. Unlike 'vGetContents', this has no effect on the open status of the item, the EOF status, or the current position of the file pointer. -} getMemoryBuffer :: MemoryBuffer -> IO String@@ -546,9 +544,9 @@     vIsWritable _ = return True     vTell h = do v <- vioc_get (vrv h)                  return . fromIntegral $ (fst v)-    vSeek h seekmode seekposp = +    vSeek h seekmode seekposp =         do (pos, buf) <- vioc_get (vrv h)-           let seekpos = fromInteger seekposp +           let seekpos = fromInteger seekposp            let newpos = case seekmode of                              AbsoluteSeek -> seekpos                              RelativeSeek -> pos + seekpos@@ -562,7 +560,6 @@ ---------------------------------------------------------------------- -- Pipes ----------------------------------------------------------------------- {- | Create a Haskell pipe.  These pipes are analogous to the Unix@@ -574,9 +571,7 @@ pipes are implemented completely with existing Haskell threading primitives, and require no special operating system support.  Unlike Unix pipes, these pipes cannot be used across a fork().  Also unlike Unix pipes, these pipes-are portable and interact well with Haskell threads.--}-+are portable and interact well with Haskell threads. -} newHVIOPipe :: IO (PipeReader, PipeWriter) newHVIOPipe = do mv <- newEmptyMVar                  readerref <- newIORef (True, mv)@@ -584,7 +579,7 @@                  writerref <- newIORef (True, reader)                  return (reader, PipeWriter writerref) -data PipeBit = PipeBit Char +data PipeBit = PipeBit Char              | PipeEOF                deriving (Eq, Show) @@ -599,12 +594,13 @@ ------------------------------ -- Pipe Reader -------------------------------+prv :: PipeReader -> VIOCloseSupport (MVar PipeBit) prv (PipeReader x) = x  instance Show PipeReader where-    show x = "<PipeReader>"+    show _ = "<PipeReader>" +pr_getc :: PipeReader -> IO PipeBit pr_getc h = do mv <- vioc_get (prv h)                takeMVar mv @@ -618,11 +614,11 @@      vGetChar h = do vTestEOF h                     c <- pr_getc h-                    case c of +                    case c of                         PipeBit x -> return x                         -- vTestEOF should eliminate this case                         _ -> fail "Internal error in HVIOReader vGetChar"-    vGetContents h = +    vGetContents h =         let loop = do c <- pr_getc h                       case c of                           PipeEOF -> return []@@ -631,16 +627,17 @@         in do vTestEOF h               loop     vIsReadable _ = return True-                        + ------------------------------ -- Pipe Writer -------------------------------+pwv :: PipeWriter -> VIOCloseSupport PipeReader pwv (PipeWriter x) = x++pwmv :: PipeWriter -> IO (MVar PipeBit) pwmv (PipeWriter x) = do mv1 <- vioc_get x                          vioc_get (prv mv1) - instance Show PipeWriter where     show _ = "<PipeWriter>" @@ -659,7 +656,7 @@     vPutChar h c = do vTestOpen h                       child <- vioc_get (pwv h)                       copen <- vIsOpen child-                      if copen +                      if copen                          then do mv <- pwmv h                                  putMVar mv (PipeBit c)                          else fail "PipeWriter: Couldn't write to pipe because child end is closed"
src/System/IO/StatCompat.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE CPP #-}-{- +{- Copyright (C) 2005,2006 John Goerzen <jgoerzen@complete.org>  This program is free software; you can redistribute it and/or modify@@ -22,7 +22,7 @@    Copyright  : Copyright (C) 2005-2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -32,24 +32,22 @@ Copyright (c) 2005-2006 John Goerzen, jgoerzen\@complete.org -} -module System.IO.StatCompat +module System.IO.StatCompat where import System.Posix.Types import System.Posix.Consts #ifndef mingw32_HOST_OS import System.Posix.Files(intersectFileModes) #endif-import Data.Bits+import Data.Bits ((.&.))  #ifdef mingw32_HOST_OS type LinkCount = Int type UserID = Int type GroupID = Int- #endif --data FileStatusCompat = +data FileStatusCompat =     FileStatusCompat {deviceID :: DeviceID,                       fileID :: FileID,                       fileMode :: FileMode,@@ -62,10 +60,12 @@                       modificationTime :: EpochTime,                       statusChangeTime :: EpochTime                      }-    -sc_helper comp stat = ++sc_helper :: FileMode -> FileStatusCompat -> Bool+sc_helper comp stat =     (fileMode stat `intersectFileModes` fileTypeModes) == comp-                                      ++isBlockDevice,isCharacterDevice,isNamedPipe,isRegularFile,isDirectory,isSymbolicLink,isSocket :: FileStatusCompat -> Bool isBlockDevice = sc_helper blockSpecialMode isCharacterDevice = sc_helper characterSpecialMode isNamedPipe = sc_helper namedPipeMode
src/System/IO/Utils.hs view
@@ -21,11 +21,9 @@    Copyright  : Copyright (C) 2004-2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable--asdf. -}  module System.IO.Utils(-- * Entire File Handle Utilities@@ -46,15 +44,14 @@                        optimizeForBatch, optimizeForInteraction                         ) where -import System.IO.Unsafe+import System.IO.Unsafe (unsafeInterleaveIO) import System.IO-import Data.List+import Data.List (genericLength) import System.IO.HVIO  {- | Given a list of strings, output a line containing each item, adding newlines as appropriate.  The list is not expected to have newlines already. -}- hPutStrLns :: HVIO a => a -> [String] -> IO () hPutStrLns h = mapM_ $ vPutStrLn h @@ -72,17 +69,16 @@  -} --- FIXME does hGetContents h >>= return.lines not work?+-- FIXME: does hGetContents h >>= return . lines not work? hGetLines :: HVIO a => a -> IO [String] hGetLines h = unsafeInterleaveIO (do                                   ieof <- vIsEOF h-                                  if (ieof) +                                  if (ieof)                                      then return []                                      else do                                           line <- vGetLine h                                           remainder <- hGetLines h-                                          return (line : remainder)-                                 )+                                          return (line : remainder))   {- | This is similar to the built-in 'System.IO.interact', but works@@ -117,7 +113,7 @@  One could view this function like this: -> hLineInteract finput foutput func = +> hLineInteract finput foutput func = >     let newf = unlines . func . lines in >         hInteract finput foutput newf @@ -128,7 +124,6 @@ >     lines <- hGetLines finput >     hPutStrLns foutput (func lines) -}- hLineInteract :: (HVIO a, HVIO b) => a -> b -> ([String] -> [String]) -> IO () hLineInteract finput foutput func =     do@@ -146,8 +141,7 @@ {- | Copies from one handle to another in raw mode (using hGetContents). Takes a function to provide progress updates to the user. -}--hCopyProgress :: (HVIO b, HVIO c, Integral a) => +hCopyProgress :: (HVIO b, HVIO c, Integral a) =>                     b        -- ^ Input handle                  -> c              -- ^ Output handle                  -> (Maybe a -> Integer -> Bool -> IO ()) -- ^ Progress function -- the bool is always False unless this is the final call@@ -178,13 +172,11 @@  > hLineCopy hin hout = hLineInteract hin hout id -}- hLineCopy :: (HVIO a, HVIO b) => a -> b -> IO() hLineCopy hin hout = hLineInteract hin hout id  {- | Copies from 'stdin' to 'stdout' using lines.  An alias for 'hLineCopy' over 'stdin' and 'stdout'. -}- lineCopy :: IO () lineCopy = hLineCopy stdin stdout @@ -194,7 +186,6 @@ need to adjust them after the copy yourself.  This function is implemented using 'hLineCopy' internally. -}- copyFileLinesToFile :: FilePath -> FilePath -> IO () copyFileLinesToFile infn outfn = do                                  hin <- openFile infn ReadMode@@ -213,8 +204,7 @@                    hSetBuffering stdout (BlockBuffering (Just 4096))  {- | Sets stdin and stdout to be line-buffered.  This saves resources-on stdout, but not many on stdin, since it it still looking for newlines.--}+on stdout, but not many on stdin, since it it still looking for newlines. -} optimizeForInteraction :: IO () optimizeForInteraction = do                          hSetBuffering stdin LineBuffering
src/System/Path.hs view
@@ -22,7 +22,7 @@    Copyright  : Copyright (C) 2004-2005 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -59,11 +59,9 @@ {- | Splits a pathname into a tuple representing the root of the name and the extension.  The extension is considered to be all characters from the last dot after the last slash to the end.  Either returned string may be empty. -}---- FIXME - See 6.4 API when released.-+-- FIXME: See 6.4 API when released. splitExt :: String -> (String, String)-splitExt path = +splitExt path =     let dotindex = alwaysElemRIndex '.' path         slashindex = alwaysElemRIndex '/' path         in@@ -140,7 +138,7 @@ an exception. -} brackettmpdir :: String -> (String -> IO a) -> IO a brackettmpdir x action = do tmpdir <- mktmpdir x-                            finally (action tmpdir) +                            finally (action tmpdir)                                     (recursiveRemove SystemFS tmpdir)  {- | Changes the current working directory to the given path,
src/System/Path/Glob.hs view
@@ -20,7 +20,7 @@    Copyright  : Copyright (C) 2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -31,15 +31,16 @@  -} -module System.Path.Glob(glob, vGlob) where-import Data.List.Utils-import System.IO+module System.Path.Glob (glob, vGlob)+    where+import Data.List.Utils (hasAny) import System.IO.HVFS-import System.FilePath-import Control.Exception-import System.Path.WildMatch-import Data.List+import System.FilePath (splitFileName)+import Control.Exception (tryJust, ioErrors)+import System.Path.WildMatch (wildCheckCase)+import Data.List (isSuffixOf) +hasWild :: String -> Bool hasWild = hasAny "*?["  {- | Takes a pattern.  Returns a list of names that match that pattern.@@ -59,7 +60,7 @@ {- | Like 'glob', but works on both the system ("real") and HVFS virtual filesystems. -} vGlob :: HVFS a => a -> FilePath -> IO [FilePath]-vGlob fs fn = +vGlob fs fn =     if not (hasWild fn)           -- Don't try globbing if there are no wilds        then do de <- vDoesExist fs fn                if de@@ -79,17 +80,19 @@                          return $ concat r                  else do r <- mapM expandNormalBase dirlist                          return $ concat r-           +     where (dirnameslash, basename) = splitFileName fn           dirname = case dirnameslash of                       "/" -> "/"                       x -> if isSuffixOf "/" x                               then take (length x - 1) x                               else x+           expandWildBase :: FilePath -> IO [FilePath]           expandWildBase dname =               do dirglobs <- runGlob fs dname basename                  return $ map (\globfn -> dname ++ "/" ++ globfn) dirglobs+           expandNormalBase :: FilePath -> IO [FilePath]           expandNormalBase dname =               do isdir <- vDoesDirectoryExist fs dname@@ -103,7 +106,7 @@ runGlob fs "" patt = runGlob fs "." patt runGlob fs dirname patt =     do r <- tryJust ioErrors (vGetDirectoryContents fs dirname)-       case r of +       case r of          Left _ -> return []          Right names -> let matches = filter (wildCheckCase patt) $ names                         in if head patt == '.'
src/System/Path/NameManip.hs view
@@ -7,7 +7,7 @@    Copyright  : Copyright (C) 2004 Volker Wysk    License    : GNU LGPL, version 2.1 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -18,8 +18,8 @@  module System.Path.NameManip where -import Data.List-import System.Directory+import Data.List (intersperse)+import System.Directory (getCurrentDirectory)  {- | Split a path in components. Repeated \"@\/@\" characters don\'t lead to empty components. \"@.@\" path components are removed. If the path is absolute, the first component@@ -48,10 +48,10 @@                      (c:cs) -> (('/':c):cs)       _ -> slice_path' p    where-      slice_path' p = filter (\c -> c /= "" && c /= ".") (split p)+      slice_path' o = filter (\c -> c /= "" && c /= ".") (split o)        split ""      = []-      split ('/':p) = "" : split p+      split ('/':o) = "" : split o       split (x:xs)  = case split xs of                          [] -> [[x]]                          (y:ys) -> ((x:y):ys)@@ -371,7 +371,7 @@ -} absolute_path :: String         -- ^ The path to be made absolute               -> IO String      -- ^ Absulte path-absolute_path path@('/':p) = return path+absolute_path path@('/':_) = return path absolute_path path = do    cwd <- getCurrentDirectory    return (cwd ++ "/" ++ path)@@ -385,7 +385,7 @@ absolute_path_by :: String        -- ^ The directory relative to which the path is made absolute                  -> String        -- ^ The path to be made absolute                  -> String        -- ^ Absolute path-absolute_path_by dir path@('/':p) = path+absolute_path_by _ path@('/':_) = path absolute_path_by dir path = dir ++ "/" ++ path  @@ -399,7 +399,7 @@ absolute_path' :: String        -- ^ The path to be made absolute                -> String        -- ^ The directory relative to which the path is made absolute                -> String        -- ^ Absolute path-absolute_path' path@('/':p) dir = path+absolute_path' path@('/':_) _ = path absolute_path' path dir = dir ++ "/" ++ path  @@ -427,5 +427,5 @@ -} guess_dotdot :: String                  -- ^ Path to be normalised              -> Maybe String            -- ^ In case the path could be transformed, the normalised, @\"..\"@-component free form of the path.-guess_dotdot = +guess_dotdot =    fmap unslice_path . guess_dotdot_comps . slice_path
src/System/Path/WildMatch.hs view
@@ -20,7 +20,7 @@    Copyright  : Copyright (C) 2006 John Goerzen    License    : GNU GPL, version 2 or above -   Maintainer : John Goerzen <jgoerzen@complete.org> +   Maintainer : John Goerzen <jgoerzen@complete.org>    Stability  : provisional    Portability: portable @@ -61,15 +61,13 @@  module System.Path.WildMatch (-- * Wildcard matching                                 wildCheckCase,-                                wildToRegex-                               )--where+                                wildToRegex)+    where  import Text.Regex-import Data.String+import Data.String.Utils -{- | Convert a wildcard to an (uncompiled) regular expression. +{- | Convert a wildcard to an (uncompiled) regular expression.  -} wildToRegex :: String -> String@@ -88,7 +86,6 @@       Just _ -> True  -- This is SO MUCH CLEANER than the python implementation!- convwild :: String -> String convwild [] = [] convwild ('*':xs) = ".*" ++ convwild xs@@ -102,3 +99,4 @@ convpat ('\\':xs) = "\\\\" ++ convpat xs convpat (']':xs) = ']' : convwild xs convpat (x:xs) = x : convpat xs+convpat [] = []
src/System/Time/ParseDate.hs view
@@ -11,130 +11,126 @@ -} module System.Time.ParseDate (parseCalendarTime) where -import Control.Monad+import Control.Monad (liftM) import Data.Char (isSpace)-import Data.List (elemIndex)-import Data.Maybe (fromJust) import System.Locale import System.Time import Text.ParserCombinators.Parsec +{- | Parse a date string as formatted by 'formatCalendarTime'. --- | Parse a date string as formatted by 'formatCalendarTime'.------   The resulting 'CalendarTime' will only have those fields set that---   are represented by a format specifier in the format string, and those---   fields will be set to the values given in the date string.---   If the same field is specified multiple times, the rightmost---   occurence takes precedence.------   The resulting date is not neccessarily a valid date. For example,---   if there is no day of the week specifier in the format string,---   the value of 'ctWDay' will most likely be invalid.------   Format specifiers are % followed by some character. All other---   characters are treated literally. Whitespace in the format string---   matches zero or more arbitrary whitespace characters.------   Format specifiers marked with * are matched, but do not set any---   field in the output.------   Some of the format specifiers are marked as space-padded or ---   zero-padded. Regardless of this, space-padded, zero-padded ---   or unpadded inputs are accepted. Note that strings using ---   unpadded fields without separating the fields may cause---   strange parsing.------   Supported format specfiers:------    [%%]   a % character.------    [%a]   locale's abbreviated weekday name (Sun ... Sat)------    [%A]   locale's full weekday name (Sunday .. Saturday)------    [%b]   locale's abbreviated month name (Jan..Dec)------    [%B]   locale's full month name (January..December)------    [%c]   locale's date and time format (Thu Mar 25 17:47:03 CET 2004)------    [%C]   century [00-99]------    [%d]   day of month, zero padded (01..31)------    [%D]   date (%m\/%d\/%y)------    [%e]   day of month, space padded ( 1..31)------    [%h]   same as %b------    [%H]   hour, 24-hour clock, zero padded (00..23)------    [%I]   hour, 12-hour clock, zero padded (01..12)------    [%j]   day of the year, zero padded (001..366)------    [%k]   hour, 24-hour clock, space padded ( 0..23)------    [%l]   hour, 12-hour clock, space padded ( 1..12)------    [%m]   month, zero padded (01..12)------    [%M]   minute, zero padded (00..59)------    [%n]   a newline character------    [%p]   locale's AM or PM indicator------    [%r]   locale's 12-hour time format (hh:mm:ss AM\/PM)------    [%R]   hours and minutes, 24-hour clock (hh:mm)------    [%s]   * seconds since '00:00:00 1970-01-01 UTC'------    [%S]   seconds, zero padded (00..59)------    [%t]   a horizontal tab character------    [%T]   time, 24-hour clock (hh:mm:ss)------    [%u]   numeric day of the week (1=Monday, 7=Sunday)------    [%U]   * week number, weeks starting on Sunday, zero padded (01-53)------    [%V]   * week number (as per ISO-8601),---             week 1 is the first week with a Thursday,---             zero padded, (01-53)------    [%w]   numeric day of the week, (0=Sunday, 6=Monday)------    [%W]   * week number, weeks starting on Monday, zero padded (01-53)------    [%x]   locale's preferred way of printing dates (%m\/%d\/%y)------    [%X]   locale's preferred way of printing time. (%H:%M:%S)------    [%y]   year, within century, zero padded (00..99)------    [%Y]   year, including century. Not padded ---           (this is probably a bug, but formatCalendarTime does---           it this way). (0-9999)------    [%Z]   time zone abbreviation (e.g. CET) or RFC-822 style numeric ---           timezone (-0500)-parseCalendarTime :: +   The resulting 'CalendarTime' will only have those fields set that+   are represented by a format specifier in the format string, and those+   fields will be set to the values given in the date string.+   If the same field is specified multiple times, the rightmost+   occurence takes precedence.++   The resulting date is not neccessarily a valid date. For example,+   if there is no day of the week specifier in the format string,+   the value of 'ctWDay' will most likely be invalid.++   Format specifiers are % followed by some character. All other+   characters are treated literally. Whitespace in the format string+   matches zero or more arbitrary whitespace characters.++   Format specifiers marked with * are matched, but do not set any+   field in the output.++   Some of the format specifiers are marked as space-padded or+   zero-padded. Regardless of this, space-padded, zero-padded+   or unpadded inputs are accepted. Note that strings using+   unpadded fields without separating the fields may cause+   strange parsing.++   Supported format specfiers:++    [%%]   a % character.++    [%a]   locale's abbreviated weekday name (Sun ... Sat)++    [%A]   locale's full weekday name (Sunday .. Saturday)++    [%b]   locale's abbreviated month name (Jan..Dec)++    [%B]   locale's full month name (January..December)++    [%c]   locale's date and time format (Thu Mar 25 17:47:03 CET 2004)++    [%C]   century [00-99]++    [%d]   day of month, zero padded (01..31)++    [%D]   date (%m\/%d\/%y)++    [%e]   day of month, space padded ( 1..31)++    [%h]   same as %b++    [%H]   hour, 24-hour clock, zero padded (00..23)++    [%I]   hour, 12-hour clock, zero padded (01..12)++    [%j]   day of the year, zero padded (001..366)++    [%k]   hour, 24-hour clock, space padded ( 0..23)++    [%l]   hour, 12-hour clock, space padded ( 1..12)++    [%m]   month, zero padded (01..12)++    [%M]   minute, zero padded (00..59)++    [%n]   a newline character++    [%p]   locale's AM or PM indicator++    [%r]   locale's 12-hour time format (hh:mm:ss AM\/PM)++    [%R]   hours and minutes, 24-hour clock (hh:mm)++    [%s]   * seconds since '00:00:00 1970-01-01 UTC'++    [%S]   seconds, zero padded (00..59)++    [%t]   a horizontal tab character++    [%T]   time, 24-hour clock (hh:mm:ss)++    [%u]   numeric day of the week (1=Monday, 7=Sunday)++    [%U]   * week number, weeks starting on Sunday, zero padded (01-53)++    [%V]   * week number (as per ISO-8601),+             week 1 is the first week with a Thursday,+             zero padded, (01-53)++    [%w]   numeric day of the week, (0=Sunday, 6=Monday)++    [%W]   * week number, weeks starting on Monday, zero padded (01-53)++    [%x]   locale's preferred way of printing dates (%m\/%d\/%y)++    [%X]   locale's preferred way of printing time. (%H:%M:%S)++    [%y]   year, within century, zero padded (00..99)++    [%Y]   year, including century. Not padded+           (this is probably a bug, but formatCalendarTime does+           it this way). (0-9999)++    [%Z]   time zone abbreviation (e.g. CET) or RFC-822 style numeric+           timezone (-0500) -}+parseCalendarTime ::     TimeLocale            -- ^ Time locale     -> String             -- ^ Date format     -> String             -- ^ String to parse     -> Maybe CalendarTime -- ^ 'Nothing' if parsing failed.-parseCalendarTime l fmt s = +parseCalendarTime l fmt s =     case runParser parser epoch "<date string>" s of-         Left err -> Nothing-	 Right p -> Just p+         Left _ -> Nothing+         Right p -> Just p     where parser = pCalendarTime l fmt >> getState - -- FIXME: verify input -- FIXME: years outside 1000-9999 probably don't work -- FIXME: what about extra whitespace in input?@@ -159,7 +155,7 @@     doFmt ('%':c:cs) = decode c >> doFmt cs     doFmt (c:cs) = char c >> doFmt cs     doFmt "" = return ()-    +     decode '%' = char '%' >> return ()     decode 'a' = (parseEnum $ map snd $ wDays l) >>= setWDay     decode 'A' = (parseEnum $ map fst $ wDays l) >>= setWDay@@ -185,12 +181,12 @@     -- FIXME: strptime(3) accepts "arbitrary whitespace" for %n     decode 'n' = char '\n' >> return ()     decode 'p' = do-		 x <- (string am >> return 0) <|> (string pm >> return 12)-		 updateHour (\h -> x + h `rem` 12)-	where (am,pm) = amPm l +                 x <- (string am >> return 0) <|> (string pm >> return 12)+                 updateHour (\h -> x + h `rem` 12)+        where (am,pm) = amPm l     decode 'r' = doFmt (time12Fmt l)     decode 'R' = doFmt "%H:%M"-    -- FIXME: implement %s. +    -- FIXME: implement %s.     -- FIXME: implement %s in formatCalendarTime     decode 's' = int >> return ()     decode 'S' = read2 >>= setSec@@ -198,16 +194,16 @@     decode 't' = char '\t' >> return ()     decode 'T' = doFmt "%H:%M:%S"     decode 'u' = readN 1 >>= setWDay . toEnum . (\w -> if w == 7 then 0 else w)-    -- FIXME: implement %U. +    -- FIXME: implement %U.     decode 'U' = read2 >> return ()-    -- FIXME: implement %V. +    -- FIXME: implement %V.     decode 'V' = read2 >> return ()     decode 'w' = readN 1 >>= setWDay . toEnum     -- FIXME: implement %W.     decode 'W' = read2 >> return ()     decode 'x' = doFmt (dateFmt l)     decode 'X' = doFmt (timeFmt l)-    -- FIXME: should probably be zero padded, +    -- FIXME: should probably be zero padded,     --        need to change formatCalendarTime too     decode 'Y' = int >>= setYear     -- FIXME: maybe 04 should be 2004, not 1904?@@ -216,53 +212,56 @@     -- FIXME: set ctTZ when parsing timezone name and     --        ctTZName when parsing offset     decode 'Z' = tzname <|> tzoffset-	where tzname = many1 (oneOf ['A'..'Z']) >>= setTZName -	      tzoffset = do -			 s <- sign-			 h <- read2-			 m <- read2-			 setTZ (s * (h * 3600 + m * 60))+        where tzname = many1 (oneOf ['A'..'Z']) >>= setTZName+              tzoffset = do+                         s <- sign+                         h <- read2+                         m <- read2+                         setTZ (s * (h * 3600 + m * 60))     -- following the example of strptime(3),     -- whitespace matches zero or more whitespace     -- characters in the input string     decode c | isSpace c = spaces >> return ()     decode c = char c >> return () -- epoch :: CalendarTime epoch = CalendarTime {-		      ctYear = 1970,-		      ctMonth = January,-		      ctDay = 1,-		      ctHour = 0,-		      ctMin = 0,-		      ctSec = 0,-		      ctPicosec = 0,-		      ctWDay = Thursday,-		      ctYDay = 1,-		      ctTZName = "UTC",-		      ctTZ = 0,-		      ctIsDST = False-		     }+                      ctYear = 1970,+                      ctMonth = January,+                      ctDay = 1,+                      ctHour = 0,+                      ctMin = 0,+                      ctSec = 0,+                      ctPicosec = 0,+                      ctWDay = Thursday,+                      ctYDay = 1,+                      ctTZName = "UTC",+                      ctTZ = 0,+                      ctIsDST = False+                     }  parseEnum :: Enum a => [String] -> CharParser st a parseEnum ss = choice (zipWith tryString ss (enumFrom (toEnum 0)))     where tryString s x = try (string s) >> return x -+setYear,setDay,setHour,setHour12,setMin,setSec,setYDay,setTZ :: Int -> GenParser tok CalendarTime () setYear x   = updateState (\t -> t{ ctYear   = x })+setMonth :: Month -> GenParser tok CalendarTime () setMonth x  = updateState (\t -> t{ ctMonth  = x }) setDay x    = updateState (\t -> t{ ctDay    = x }) setHour x   = updateState (\t -> t{ ctHour   = x }) setMin x    = updateState (\t -> t{ ctMin    = x }) setSec x    = updateState (\t -> t{ ctSec    = x })+setWDay :: Day -> GenParser tok CalendarTime () setWDay x   = updateState (\t -> t{ ctWDay   = x }) setYDay x   = updateState (\t -> t{ ctYDay   = x })+setTZName :: String -> GenParser tok CalendarTime () setTZName x = updateState (\t -> t{ ctTZName = x }) setTZ x     = updateState (\t -> t{ ctTZ     = x }) +updateYear :: (Int -> Int) -> GenParser tok CalendarTime () updateYear f = updateState (\t -> t{ ctYear = f (ctYear t) })+updateHour :: (Int -> Int) -> GenParser tok CalendarTime () updateHour f = updateState (\t -> t{ ctHour = f (ctHour t) })  setHour12 x = updateHour (\h -> (h `quot` 12) * 12 + from12 x)@@ -272,10 +271,10 @@ read2 = readN 2 read3 = readN 3 --- | Read up to a given number of digits, optionally left-padded +-- | Read up to a given number of digits, optionally left-padded --   with whitespace and interpret them as an 'Int'. readN :: Int -> GenParser Char st Int-readN n = +readN n =     liftM read (spaces >> choice [try (count m digit) | m <- [n,n-1..1]])  int :: GenParser Char st Int
src/Test/HUnit/Utils.hs view
@@ -30,16 +30,14 @@ Written by John Goerzen, jgoerzen\@complete.org -} ---module Test.HUnit.Utils(assertRaises, mapassertEqual, qccheck, qctest) where+module Test.HUnit.Utils (assertRaises, mapassertEqual, qccheck, qctest)+    where import Test.HUnit import Test.QuickCheck as QC import qualified Control.Exception import System.Random  {- | Asserts that a specific exception is raised by a given action. -}- assertRaises :: Show a => String -> Control.Exception.Exception -> IO a -> IO () assertRaises msg selector action =     let thetest e = if e == selector then return ()@@ -49,18 +47,17 @@            r <- Control.Exception.try action            case r of                   Left e -> thetest e-                  Right x -> assertFailure $ msg ++ "\nReceived no exception, but was expecting exception: " ++ (show selector)+                  Right _ -> assertFailure $ msg ++ "\nReceived no exception, but was expecting exception: " ++ (show selector)  mapassertEqual :: (Show b, Eq b) => String -> (a -> b) -> [(a, b)] -> [Test]-mapassertEqual descrip func [] = []+mapassertEqual _ _ [] = [] mapassertEqual descrip func ((inp,result):xs) =     (TestCase $ assertEqual descrip result (func inp)) : mapassertEqual descrip func xs  -- * Turn QuickCheck tests into HUnit tests---- |qccheck turns the quickcheck test into an hunit test-qccheck :: (QC.Testable a) => -           Config -- ^ quickcheck config+-- | qccheck turns the quickcheck test into an hunit test+qccheck :: (QC.Testable a) =>+           QC.Config -- ^ quickcheck config         -> String -- ^ label for the property         -> a      -- ^ quickcheck property         -> Test@@ -69,14 +66,14 @@               do rnd <- newStdGen                  tests config (evaluate property) rnd 0 0 [] --- |qctest is equivalent to 'qccheck defaultConfig'+-- | qctest is equivalent to 'qccheck defaultConfig' qctest ::  (QC.Testable a) => String -> a -> Test-qctest lbl property = qccheck defaultConfig lbl property+qctest lbl = qccheck defaultConfig lbl --- |modified version of the tests function from Test.QuickCheck-tests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] -> IO () +-- | modified version of the tests function from Test.QuickCheck+tests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] -> IO () tests config gen rnd0 ntest nfail stamps-  | ntest == configMaxTest config = return () +  | ntest == configMaxTest config = return ()   | nfail == configMaxFail config = assertFailure $ "Arguments exhausted after " ++ show ntest ++ " tests."   | otherwise               =       do putStr (configEvery config ntest (arguments result))
− testsrc/runtests.hs
@@ -1,25 +0,0 @@-{- arch-tag: Test runner-Copyright (C) 2004 John Goerzen <jgoerzen@complete.org>--This program is free software; you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--module Main where --import Test.HUnit-import Tests--main = runTestTT tests-