diff --git a/cabal2nix.cabal b/cabal2nix.cabal
--- a/cabal2nix.cabal
+++ b/cabal2nix.cabal
@@ -1,5 +1,5 @@
 Name:                   cabal2nix
-Version:                1.10
+Version:                1.11
 Copyright:              (c) 2011 Peter Simons and Andres Loeh
 License:                BSD3
 License-File:           LICENSE
@@ -41,28 +41,43 @@
   Type:                 git
   Location:             git://github.com/haskell4nix/cabal2nix.git
 
+Library
+  Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal
+  hs-source-dirs:       src
+  Extensions:           PatternGuards
+  Ghc-Options:          -Wall
+  Exposed-Modules:      Distribution.NixOS.Derivation.Cabal
+                        Distribution.NixOS.Derivation.License
+                        Distribution.NixOS.Derivation.Meta
+  other-modules:        Distribution.NixOS.Derivation.PrettyPrinting
+
 Executable cabal2nix
   main-is:              Cabal2Nix.hs
   hs-source-dirs:       src
-  Build-Depends:        base >= 3 && < 5, Cabal, process, HTTP, pretty, filepath, directory
+  Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal,
+                        filepath, directory, process, HTTP
+  Extensions:           PatternGuards
   Ghc-Options:          -Wall
-  other-modules:        Cabal2Nix.Pretty
-                        Cabal2Nix.License
+  other-modules:        Cabal2Nix.CorePackages
+                        Cabal2Nix.Hackage
                         Cabal2Nix.Name
-                        Cabal2Nix.CorePackages
                         Cabal2Nix.Package
-                        Cabal2Nix.Hackage
+                        Distribution.NixOS.Derivation.Cabal
+                        Distribution.NixOS.Derivation.License
+                        Distribution.NixOS.Derivation.Meta
+                        Distribution.NixOS.Derivation.PrettyPrinting
 
 Executable hackage4nix
   main-is:              Hackage4Nix.hs
   hs-source-dirs:       src
-  Build-Depends:        base >= 3 && < 5, Cabal >= 1.8, pretty, filepath, directory,
-                        regex-posix, mtl, containers
+  Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal,
+                        mtl, containers, directory, filepath
   Extensions:           PatternGuards
-  other-modules:        Cabal2Nix.Pretty
-                        Cabal2Nix.License
+  Ghc-Options:          -Wall
+  other-modules:        Cabal2Nix.CorePackages
                         Cabal2Nix.Name
-                        Cabal2Nix.CorePackages
                         Cabal2Nix.Package
-                        Cabal2Nix.Hackage
-
+                        Distribution.NixOS.Derivation.Cabal
+                        Distribution.NixOS.Derivation.License
+                        Distribution.NixOS.Derivation.Meta
+                        Distribution.NixOS.Derivation.PrettyPrinting
diff --git a/src/Cabal2Nix.hs b/src/Cabal2Nix.hs
--- a/src/Cabal2Nix.hs
+++ b/src/Cabal2Nix.hs
@@ -1,19 +1,21 @@
 module Main ( main ) where
 
 import System.IO ( hPutStrLn, hFlush, stdout, stderr )
-import System.Environment ( getArgs )
+import System.Environment -- ( getArgs )
 import Control.Exception ( bracket )
 import System.Exit ( exitFailure )
 import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )
 import Distribution.PackageDescription ( package, packageDescription )
-import Distribution.Text ( simpleParse )
+import Distribution.Text
 import Data.List ( isPrefixOf )
 import Control.Monad ( when )
 import Network.HTTP ( simpleHTTP, getRequest, getResponseBody )
 import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )
 
-import Cabal2Nix.Package ( showNixPkg, cabal2nix )
+import Cabal2Nix.Package ( cabal2nix )
 import Cabal2Nix.Hackage ( hackagePath, Ext(..), hashPackage )
+import Distribution.NixOS.Derivation.Cabal
+import Distribution.NixOS.Derivation.Meta
 
 readCabalFile :: FilePath -> IO String
 readCabalFile path
@@ -60,11 +62,11 @@
   let uri         = args
       hash        = [ h | SHA256 h <- opts ]
       noHaddock   = NoHaddock `elem` opts
-      maintainers = [ m | Maintainer m <- opts ]
-      platforms'  = [ p | Platform p <- opts ]
-      platforms
-        | null platforms' = if not (null maintainers) then ["self.ghc.meta.platforms"] else []
-        | otherwise       = platforms'
+      maints      = [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | Maintainer m <- opts ]
+      plats'      = [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | Platform p <- opts ]
+      plats
+        | null plats' = if not (null maints) then ["self.ghc.meta.platforms"] else []
+        | otherwise   = plats'
 
   when (length uri /= 1) (cmdlineError "*** exactly one URI must be specified")
   when (length hash > 1) (cmdlineError "*** the --sha256 option may be specified only once")
@@ -78,6 +80,13 @@
 
   let packageId = package (packageDescription cabal)
 
-  sha256 <- if null hash then hashPackage packageId else return (head hash)
+  sha <- if null hash then hashPackage packageId else return (head hash)
 
-  putStr (showNixPkg (cabal2nix cabal sha256 noHaddock platforms maintainers))
+  let deriv  = (cabal2nix cabal) { sha256 = sha, runHaddock = not noHaddock }
+      deriv' = deriv { metaSection = (metaSection deriv)
+                                     { maintainers = maints
+                                     , platforms   = plats
+                                     }
+                     }
+
+  putStr (show (disp deriv'))
diff --git a/src/Cabal2Nix/License.hs b/src/Cabal2Nix/License.hs
deleted file mode 100644
--- a/src/Cabal2Nix/License.hs
+++ /dev/null
@@ -1,21 +0,0 @@
-module Cabal2Nix.License
-  (module Cabal2Nix.License, module Distribution.License)
-  where
-
-import Distribution.License
-import Distribution.Version
-
-showLic :: License -> String
-showLic (GPL Nothing)                     = show "GPL"
-showLic (GPL (Just (Version [2] [])))     = "self.stdenv.lib.licenses.gpl2"
-showLic (GPL (Just (Version [3] [])))     = "self.stdenv.lib.licenses.gpl3"
-showLic (LGPL Nothing)                    = show "LGPL"
-showLic (LGPL (Just (Version [2,1] [])))  = "self.stdenv.lib.licenses.lgpl21"
-showLic (LGPL (Just (Version [3] [])))    = "self.stdenv.lib.licenses.lgpl3"
-showLic BSD3                              = "self.stdenv.lib.licenses.bsd3"
-showLic BSD4                              = "self.stdenv.lib.licenses.bsd4"
-showLic MIT                               = "self.stdenv.lib.licenses.mit"
-showLic PublicDomain                      = "self.stdenv.lib.licenses.publicDomain"
-showLic AllRightsReserved                 = "self.stdenv.lib.licenses.proprietary"
-showLic OtherLicense                      = show "unknown"
-showLic l                                 = error $ "unknown license: " ++ show l
diff --git a/src/Cabal2Nix/Package.hs b/src/Cabal2Nix/Package.hs
--- a/src/Cabal2Nix/Package.hs
+++ b/src/Cabal2Nix/Package.hs
@@ -1,145 +1,55 @@
-module Cabal2Nix.Package
-  ( cabal2nix, showNixPkg
-  , PkgName, PkgVersion, PkgSHA256, PkgURL, PkgDescription, PkgLicense
-  , PkgIsLib, PkgIsExe, PkgDependencies, PkgBuildTools, PkgExtraLibs
-  , PkgPkgconfigDeps, PkgPlatforms, PkgMaintainers, PkgNoHaddock, Pkg(..)
-  )
-  where
+module Cabal2Nix.Package ( cabal2nix ) where
 
-import Data.List
 import Data.Maybe
 import Distribution.Compiler
-import Distribution.Package
-import Distribution.PackageDescription
+import qualified Distribution.Package as Cabal
+import qualified Distribution.PackageDescription as Cabal
 import Distribution.PackageDescription.Configuration
 import Distribution.System
 import Distribution.Version
-import Text.PrettyPrint
-import Data.Version ( showVersion )
-
-import Cabal2Nix.License
+import Distribution.NixOS.Derivation.Cabal
 import Cabal2Nix.Name
 import Cabal2Nix.CorePackages
-import Cabal2Nix.Pretty
-
-type PkgName          = String
-type PkgVersion       = String
-type PkgSHA256        = String
-type PkgURL           = String
-type PkgDescription   = String
-type PkgLicense       = String
-type PkgIsLib         = Bool
-type PkgIsExe         = Bool
-type PkgDependencies  = [Dependency] -- [CondTree ConfVar [Dependency] ()]
-type PkgBuildTools    = [Dependency]
-type PkgExtraLibs     = [String]
-type PkgPkgconfigDeps = [String]
-type PkgNoHaddock     = Bool
-type PkgPlatforms     = [String]
-type PkgMaintainers   = [String]
-
-data Pkg = Pkg PkgName
-               PkgVersion
-               PkgSHA256
-               PkgURL
-               PkgDescription
-               PkgLicense
-               PkgIsLib
-               PkgIsExe
-               PkgDependencies
-               PkgBuildTools
-               PkgExtraLibs
-               PkgPkgconfigDeps
-               PkgNoHaddock
-               PkgPlatforms
-               PkgMaintainers
-  deriving (Show)
-
-showNixPkg :: Pkg -> String
-showNixPkg (Pkg name ver sha256 url desc lic isLib isExe deps
-                tools libs pcs noHaddock platforms maintainers) =
-    render doc
-  where
-    doc = funargs (map text ("cabal" : pkgInputs)) $$
-          vcat [
-            text "",
-            text "cabal.mkDerivation" <+> lparen <> text "self" <>
-              colon <+> lbrace,
-            nest 2 $ vcat [
-              attr "pname"   $ string name,
-              attr "version" $ string ver,
-              attr "sha256"  $ string sha256,
-              boolattr "isLibrary"    (not isLib || isExe) isLib,
-              boolattr "isExecutable" (not isLib || isExe) isExe,
-              listattr "buildDepends"     pkgDeps,
-              listattr "buildTools"       pkgBuildTools,
-              listattr "extraLibraries"   pkgLibs,
-              listattr "pkgconfigDepends" pkgPCs,
-              boolattr "noHaddock"        noHaddock noHaddock,
-              vcat [
-                text "meta" <+> equals <+> lbrace,
-                nest 2 $ vcat [
-                  onlyIf url  $ attr "homepage"    $ string url,
-                  onlyIf desc $ attr "description" $ string desc,
-                  attr "license" $ text lic,
-                  onlyIf platforms $
-                    sep [
-                      text "platforms" <+> equals,
-                      nest 2 ((fsep $ punctuate (text " ++") $ map text platforms)) <> semi
-                    ],
-                  listattr "maintainers" maintainers
-                ],
-                rbrace <> semi
-              ]
-            ],
-            rbrace <> rparen,
-            text ""
-          ]
-    pkgLibs       = nub $ sort $ concatMap libNixName libs
-    pkgPCs        = nub $ sort $ concatMap libNixName pcs
-    pkgDeps       = nub $ sort $ map toNixName $
-                    filter (`notElem` (name : corePackages)) $ map unDep deps
-    pkgBuildTools = nub $ sort $ map toNixName $
-                    filter (`notElem` coreBuildTools) $ map unDep tools
-    pkgInputs     = nub $ pkgLibs ++ pkgPCs ++ pkgBuildTools ++ pkgDeps
-
+import Data.List
+import Data.Char
 
-cabal2nix :: GenericPackageDescription -> PkgSHA256 -> PkgNoHaddock -> PkgPlatforms -> PkgMaintainers -> Pkg
-cabal2nix cabal sha256 noHaddock platforms maintainers =
-    Pkg pkgname pkgver sha256 url desc lic
-      isLib isExe
-      (buildDepends tpkg)
-      tools
-      libs
-      pcs
-      noHaddock
-      [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | p <- platforms ]
-      [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | m <- maintainers ]
+cabal2nix :: Cabal.GenericPackageDescription -> Derivation
+cabal2nix cabal = MkDerivation
+  { pname        = Cabal.pkgName pkg
+  , version      = Cabal.pkgVersion pkg
+  , sha256       = "cabal2nix left the she256 field undefined"
+  , isLibrary    = isJust (Cabal.library tpkg)
+  , isExecutable = not (null (Cabal.executables tpkg))
+  , buildDepends = normalizeNixNames (filter (`notElem` (name : corePackages)) $ map unDep deps)
+  , buildTools   = normalizeNixNames (filter (`notElem` coreBuildTools) $ map unDep tools)
+  , extraLibs    = normalizeNixLibs libs
+  , pkgConfDeps  = normalizeNixLibs pcs
+  , runHaddock   = True
+  , metaSection  = Meta
+                   { homepage    = Cabal.homepage descr
+                   , description = normalizeDescription (Cabal.synopsis descr)
+                   , license     = fromCabalLicense (Cabal.license descr)
+                   , platforms   = []
+                   , maintainers = []
+                   }
+  }
   where
-    pkg = packageDescription cabal
-    PackageName pkgname = pkgName (package pkg)
-    pkgver = showVersion (pkgVersion (package pkg))
-    lic = showLic (license pkg)
-    url = homepage pkg
-    desc = normalizeDescription (synopsis pkg)
-    -- globalDeps = buildDepends pkg
-    -- Potentially dangerous: determine a default flattening of the
-    -- package description. Better approach: export the conditional
-    -- structure and reflect it in the generated file.
+    descr = Cabal.packageDescription cabal
+    pkg   = Cabal.package descr
+    Cabal.PackageName name  = Cabal.pkgName pkg
+    deps    = Cabal.buildDepends tpkg
+    libDeps = map Cabal.libBuildInfo (maybeToList (Cabal.library tpkg))
+    exeDeps = map Cabal.buildInfo (Cabal.executables tpkg)
+    tools   = concatMap Cabal.buildTools (libDeps ++ exeDeps)
+    libs    = concatMap Cabal.extraLibs (libDeps ++ exeDeps)
+    pcs     = map unDep (concatMap Cabal.pkgconfigDepends (libDeps ++ exeDeps))
     Right (tpkg, _) = finalizePackageDescription [] (const True)
-                        (Platform I386 Linux) -- shouldn't be hardcoded
-                        (CompilerId GHC (Version [7,0,4] [])) -- dito
+                        (Platform I386 Linux)                   -- shouldn't be hardcoded
+                        (CompilerId GHC (Version [7,0,4] []))   -- dito
                         [] cabal
-    isLib   = isJust (library tpkg)
-    isExe   = not (null (executables tpkg))
-    libDeps = map libBuildInfo $ maybeToList (library tpkg)
-    exeDeps = map    buildInfo $ executables tpkg
-    libs    =             concatMap extraLibs        (libDeps ++ exeDeps)
-    pcs     = map unDep $ concatMap pkgconfigDepends (libDeps ++ exeDeps)
-    tools   =             concatMap buildTools       (libDeps ++ exeDeps)
 
-unDep :: Dependency -> String
-unDep (Dependency (PackageName x) _) = x
+unDep :: Cabal.Dependency -> String
+unDep (Cabal.Dependency (Cabal.PackageName x) _) = x
 
 normalizeDescription :: String -> String
 normalizeDescription desc
@@ -150,3 +60,12 @@
 quote :: Char -> [Char]
 quote '"'  = "\\\""
 quote c    = [c]
+
+normalizeList :: [String] -> [String]
+normalizeList = nub . sortBy (\x y -> compare (map toLower x) (map toLower y))
+
+normalizeNixNames :: [String] -> [String]
+normalizeNixNames = normalizeList . map toNixName
+
+normalizeNixLibs :: [String] -> [String]
+normalizeNixLibs = normalizeList . concatMap libNixName
diff --git a/src/Cabal2Nix/Pretty.hs b/src/Cabal2Nix/Pretty.hs
deleted file mode 100644
--- a/src/Cabal2Nix/Pretty.hs
+++ /dev/null
@@ -1,42 +0,0 @@
-module Cabal2Nix.Pretty where
-
-import Text.PrettyPrint
-
--- Pretty-printing helpers for Nix expressions.
-
-attr :: String -> Doc -> Doc
-attr n v = text n <+> equals <+> v <> semi
-
-onlyIf :: [a] -> Doc -> Doc
-onlyIf p d = if not (null p) then d else empty
-
-boolattr :: String -> Bool -> Bool -> Doc
-boolattr n p v = if p then attr n (bool v) else empty
-
-listattr :: String -> [String] -> Doc
-listattr n vs = onlyIf vs $
-                sep [ text n <+> equals <+> lbrack,
-                      nest 2 $ fsep $ map text vs,
-                      rbrack <> semi
-                    ]
-
-bool :: Bool -> Doc
-bool True  = text "true"
-bool False = text "false"
-
-string :: String -> Doc
-string = doubleQuotes . text
-
-version :: [Int] -> Doc
-version = doubleQuotes . hcat . punctuate (text ".") . map int
-
-prepunctuate :: Doc -> [Doc] -> [Doc]
-prepunctuate _ []     = []
-prepunctuate p (d:ds) = d : map (p <>) ds
-
-funargs :: [Doc] -> Doc
-funargs xs = sep [
-               lbrace <+> (fcat $ prepunctuate (comma <> text " ") $
-                           map (nest 2) xs),
-               rbrace <> colon
-             ]
diff --git a/src/Distribution/NixOS/Derivation/Cabal.hs b/src/Distribution/NixOS/Derivation/Cabal.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/NixOS/Derivation/Cabal.hs
@@ -0,0 +1,106 @@
+{-# LANGUAGE PatternGuards #-}
+
+module Distribution.NixOS.Derivation.Cabal
+  ( Derivation(..)
+  , parseDerivation
+  , module Distribution.NixOS.Derivation.Meta
+  , Version(..), PackageName(..)
+  )
+  where
+
+import Distribution.NixOS.Derivation.PrettyPrinting
+import Distribution.NixOS.Derivation.Meta
+import Distribution.Package
+import Distribution.Text
+import Data.Version
+import Data.List
+import Data.Char
+import Text.PrettyPrint
+import Text.ParserCombinators.ReadP ( readP_to_S )
+import Text.Regex.Posix
+
+data Derivation = MkDerivation
+  { pname        :: PackageName
+  , version      :: Version
+  , sha256       :: String
+  , isLibrary    :: Bool
+  , isExecutable :: Bool
+  , buildDepends :: [String]
+  , buildTools   :: [String]
+  , extraLibs    :: [String]
+  , pkgConfDeps  :: [String]
+  , runHaddock   :: Bool
+  , metaSection  :: Meta
+  }
+  deriving (Show, Eq, Ord)
+
+instance Text Derivation where
+  disp  = renderDerivation
+  parse = error "parsing Distribution.NixOS.Derivation.Cabal.Derivation is not supported yet"
+
+renderDerivation :: Derivation -> Doc
+renderDerivation deriv = funargs (map text ("cabal" : inputs)) $$ vcat
+  [ text ""
+  , text "cabal.mkDerivation" <+> lparen <> text "self" <> colon <+> lbrace
+  , nest 2 $ vcat
+    [ attr "pname"   $ doubleQuotes (disp (pname deriv))
+    , attr "version" $ doubleQuotes (disp (version deriv))
+    , attr "sha256"  $ string (sha256 deriv)
+    , boolattr "isLibrary" (not (isLibrary deriv) || (isExecutable deriv)) (isLibrary deriv)
+    , boolattr "isExecutable" (not (isLibrary deriv) || (isExecutable deriv)) (isExecutable deriv)
+    , listattr "buildDepends" (buildDepends deriv)
+    , listattr "buildTools" (buildTools deriv)
+    , listattr "extraLibraries" (extraLibs deriv)
+    , listattr "pkgconfigDepends" (pkgConfDeps deriv)
+    , boolattr "noHaddock" (not (runHaddock deriv)) (not (runHaddock deriv))
+    , disp (metaSection deriv)
+    ]
+  , rbrace <> rparen
+  , text ""
+  ]
+  where
+    inputs = nub $ sortBy (\x y -> compare (map toLower x) (map toLower y)) $
+              filter (/="cabal") $ filter (/="Cabal") $
+                buildDepends deriv ++ buildTools deriv ++ extraLibs deriv ++ pkgConfDeps deriv
+
+parseDerivation :: String -> Maybe Derivation
+parseDerivation buf
+  | buf =~ "cabal.mkDerivation"
+  , [name]    <- buf `regsubmatch` "pname *= *\"([^\"]+)\""
+  , [vers]    <- buf `regsubmatch` "version *= *\"([^\"]+)\""
+  , [sha]     <- buf `regsubmatch` "sha256 *= *\"([^\"]+)\""
+  , plats     <- buf `regsubmatch` "platforms *= *([^;]+);"
+  , maint     <- buf `regsubmatch` "maintainers *= *\\[([^\"]+)]"
+  , noHaddock <- buf `regsubmatch` "noHaddock *= *(true|false) *;"
+              = Just $ MkDerivation
+                  { pname        = PackageName name
+                  , version      = readVersion vers
+                  , sha256       = sha
+                  , isLibrary    = False
+                  , isExecutable = False
+                  , buildDepends = []
+                  , buildTools   = []
+                  , extraLibs    = []
+                  , pkgConfDeps  = []
+                  , runHaddock   = case noHaddock of "true":[] -> False
+                                                     _         -> True
+                  , metaSection  = Meta
+                                   { homepage    = ""
+                                   , description = ""
+                                   , license     = Unknown Nothing
+                                   , maintainers = concatMap words maint
+                                   , platforms   = concatMap words (map (map (\c -> if c == '+' then ' ' else c)) plats)
+                                   }
+                  }
+  | otherwise = Nothing
+
+regsubmatch :: String -> String -> [String]
+regsubmatch buf patt = let (_,_,_,x) = f in x
+  where f :: (String,String,String,[String])
+        f = match (makeRegexOpts compExtended execBlank patt) buf
+
+readVersion :: String -> Version
+readVersion str =
+  case [ v | (v,[]) <- readP_to_S parseVersion str ] of
+    [ v' ] -> v'
+    _      -> error ("invalid version specifier " ++ show str)
diff --git a/src/Distribution/NixOS/Derivation/License.hs b/src/Distribution/NixOS/Derivation/License.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/NixOS/Derivation/License.hs
@@ -0,0 +1,54 @@
+module Distribution.NixOS.Derivation.License
+  ( License(..)
+  , fromCabalLicense
+  )
+  where
+
+import qualified Distribution.License as Cabal ( License(..) )
+import Data.Version ( Version(..) )
+import Distribution.Text
+import Text.PrettyPrint
+
+data License
+  = GPL2
+  | GPL3
+  | LGPL21
+  | LGPL3
+  | BSD3
+  | BSD4
+  | MIT
+  | PublicDomain
+  | Proprietary
+  | Unknown (Maybe String)
+  deriving (Eq, Ord)
+
+instance Show License where
+  show GPL2                     = "self.stdenv.lib.licenses.gpl2"
+  show GPL3                     = "self.stdenv.lib.licenses.gpl3"
+  show LGPL21                   = "self.stdenv.lib.licenses.lgpl21"
+  show LGPL3                    = "self.stdenv.lib.licenses.gpl3"
+  show BSD3                     = "self.stdenv.lib.licenses.bsd3"
+  show BSD4                     = "self.stdenv.lib.licenses.bsd4"
+  show MIT                      = "self.stdenv.lib.licenses.mit"
+  show PublicDomain             = "self.stdenv.lib.licenses.publicDomain"
+  show Proprietary              = "self.stdenv.lib.licenses.proprietary"
+  show (Unknown lic)            = show (maybe "unknown" id lic)
+
+instance Text License where
+  disp = text . show
+  parse = error "parsing Distribution.NixOS.Derivation.License is not supported yet"
+
+fromCabalLicense :: Cabal.License -> License
+fromCabalLicense (Cabal.GPL Nothing)                     = Unknown (Just "GPL")
+fromCabalLicense (Cabal.GPL (Just (Version [2] [])))     = GPL2
+fromCabalLicense (Cabal.GPL (Just (Version [3] [])))     = GPL3
+fromCabalLicense (Cabal.LGPL Nothing)                    = Unknown (Just "LGPL")
+fromCabalLicense (Cabal.LGPL (Just (Version [2,1] [])))  = LGPL21
+fromCabalLicense (Cabal.LGPL (Just (Version [3] [])))    = LGPL3
+fromCabalLicense Cabal.BSD3                              = BSD3
+fromCabalLicense Cabal.BSD4                              = BSD4
+fromCabalLicense Cabal.MIT                               = MIT
+fromCabalLicense Cabal.PublicDomain                      = PublicDomain
+fromCabalLicense Cabal.AllRightsReserved                 = Proprietary
+fromCabalLicense Cabal.OtherLicense                      = Unknown Nothing
+fromCabalLicense l                                       = error $ "Distribution.NixOS.Derivation.License.fromCabalLicense: unknown license " ++ show l
diff --git a/src/Distribution/NixOS/Derivation/Meta.hs b/src/Distribution/NixOS/Derivation/Meta.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/NixOS/Derivation/Meta.hs
@@ -0,0 +1,39 @@
+module Distribution.NixOS.Derivation.Meta
+  ( Meta(..)
+  , module Distribution.NixOS.Derivation.License
+  )
+  where
+
+import Distribution.NixOS.Derivation.PrettyPrinting
+import Distribution.NixOS.Derivation.License
+import Distribution.Text
+import Text.PrettyPrint
+
+data Meta = Meta
+  { homepage    :: String
+  , description :: String
+  , license     :: License
+  , platforms   :: [String]
+  , maintainers :: [String]
+  }
+  deriving (Show, Eq, Ord)
+
+instance Text Meta where
+  disp  = renderMeta
+  parse = error "parsing Distribution.NixOS.Derivation.Cabal.Meta is not supported yet"
+
+renderMeta :: Meta -> Doc
+renderMeta meta = vcat
+  [ text "meta" <+> equals <+> lbrace
+  , nest 2 $ vcat
+    [ onlyIf (homepage meta) $ attr "homepage" $ string (homepage meta)
+    , onlyIf (description meta) $ attr "description" $ string (description meta)
+    , attr "license" $ disp (license meta)
+    , onlyIf (platforms meta) $ sep
+      [ text "platforms" <+> equals
+      , nest 2 ((fsep $ punctuate (text " ++") $ map text (platforms meta))) <> semi
+      ]
+    , listattr "maintainers" (maintainers meta)
+    ]
+  , rbrace <> semi
+  ]
diff --git a/src/Distribution/NixOS/Derivation/PrettyPrinting.hs b/src/Distribution/NixOS/Derivation/PrettyPrinting.hs
new file mode 100644
--- /dev/null
+++ b/src/Distribution/NixOS/Derivation/PrettyPrinting.hs
@@ -0,0 +1,47 @@
+module Distribution.NixOS.Derivation.PrettyPrinting
+  ( onlyIf
+  , listattr
+  , boolattr
+  , attr
+  , string
+  , funargs
+  )
+  where
+
+import Text.PrettyPrint
+
+-- Pretty-printing helpers for Nix expressions.
+
+attr :: String -> Doc -> Doc
+attr n v = text n <+> equals <+> v <> semi
+
+onlyIf :: [a] -> Doc -> Doc
+onlyIf p d = if not (null p) then d else empty
+
+boolattr :: String -> Bool -> Bool -> Doc
+boolattr n p v = if p then attr n (bool v) else empty
+
+listattr :: String -> [String] -> Doc
+listattr n vs = onlyIf vs $
+                sep [ text n <+> equals <+> lbrack,
+                      nest 2 $ fsep $ map text vs,
+                      rbrack <> semi
+                    ]
+
+bool :: Bool -> Doc
+bool True  = text "true"
+bool False = text "false"
+
+string :: String -> Doc
+string = doubleQuotes . text
+
+prepunctuate :: Doc -> [Doc] -> [Doc]
+prepunctuate _ []     = []
+prepunctuate p (d:ds) = d : map (p <>) ds
+
+funargs :: [Doc] -> Doc
+funargs xs = sep [
+               lbrace <+> (fcat $ prepunctuate (comma <> text " ") $
+                           map (nest 2) xs),
+               rbrace <> colon
+             ]
diff --git a/src/Hackage4Nix.hs b/src/Hackage4Nix.hs
--- a/src/Hackage4Nix.hs
+++ b/src/Hackage4Nix.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE PatternGuards #-}
-
 module Main ( main ) where
 
 import System.IO
@@ -16,9 +14,15 @@
 import Text.ParserCombinators.ReadP ( readP_to_S )
 import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )
 import Distribution.PackageDescription ( GenericPackageDescription() )
+import Distribution.Text
 import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )
-import Cabal2Nix.Package ( cabal2nix, showNixPkg, PkgName, PkgVersion, PkgSHA256, PkgPlatforms, PkgMaintainers, PkgNoHaddock )
+import Cabal2Nix.Package
+import Distribution.NixOS.Derivation.Cabal
+import Distribution.NixOS.Derivation.Meta
 
+data Pkg = Pkg Derivation FilePath Bool
+  deriving (Show, Eq, Ord)
+
 type PkgSet = Set.Set Pkg
 
 data Configuration = Configuration
@@ -70,19 +74,15 @@
        (True,_)     -> return ()
        (False,_)    -> io (readDirectory dirOrFile) >>= mapM_ (discoverNixFiles yield . (dirOrFile </>))
 
-type Regenerate = Bool
-data Pkg = Pkg PkgName PkgVersion PkgSHA256 PkgNoHaddock PkgPlatforms PkgMaintainers FilePath Regenerate
-  deriving (Show, Eq, Ord)
-
-regsubmatch :: String -> String -> [String]
-regsubmatch buf patt = let (_,_,_,x) = f in x
-  where f :: (String,String,String,[String])
-        f = match (makeRegexOpts compExtended execBlank patt) buf
+regenerateDerivation :: Derivation -> String -> Bool
+regenerateDerivation deriv buf = not (display (pname deriv) `elem` patchedPackages) &&
+                                 not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase")
 
-normalizeMaintainer :: String -> String
-normalizeMaintainer x
-  | "self.stdenv.lib.maintainers." `isPrefixOf` x = drop 28 x
-  | otherwise                                     = x
+readVersion :: String -> Version
+readVersion str =
+  case [ v | (v,[]) <- readP_to_S parseVersion str ] of
+    [ v' ] -> v'
+    _      -> error ("invalid version specifier " ++ show str)
 
 parseNixFile :: FilePath -> String -> Hackage4Nix (Maybe Pkg)
 parseNixFile path buf
@@ -92,46 +92,24 @@
                = msgDebug ("ignore known bad package " ++ path) >> return Nothing
   | buf =~ "src = (fetchurl|fetchgit|sourceFromHead)"
                = msgDebug ("ignore non-hackage package " ++ path) >> return Nothing
-  | [name]  <- buf `regsubmatch` "name *= *\"([^\"]+)\""
-  , [vers]  <- buf `regsubmatch` "version *= *\"([^\"]+)\""
-  , [sha]   <- buf `regsubmatch` "sha256 *= *\"([^\"]+)\""
-  , plats   <- buf `regsubmatch` "platforms *= *([^;]+);"
-  , maint   <- buf `regsubmatch` "maintainers *= *\\[([^\"]+)]"
-  , haddock <- buf `regsubmatch` "noHaddock *= *(true|false) *;"
-              = let plats' = concatMap words (map (map (\c -> if c == '+' then ' ' else c)) plats)
-                    maint' = concatMap words maint
-                    noHaddock
-                      | "true":[] <- haddock = True
-                      | otherwise            = False
-                    regenerate = not (name `elem` patchedPackages) &&
-                                 not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase")
-                in
-                  return $ Just $ Pkg name vers sha noHaddock plats'
-                                      (map normalizeMaintainer maint')
-                                      path regenerate
+  | Just deriv <- parseDerivation buf
+               = return (Just (Pkg deriv path (regenerateDerivation deriv buf)))
   | otherwise = msgInfo ("failed to parse file " ++ path) >> return Nothing
 
-readVersion :: String -> Version
-readVersion str =
-  case [ v | (v,[]) <- readP_to_S parseVersion str ] of
-    [ v' ] -> v'
-    _      -> error ("invalid version specifier " ++ show str)
-
 selectLatestVersions :: PkgSet -> PkgSet
 selectLatestVersions = Set.fromList . nubBy f2 . sortBy f1 . Set.toList
   where
-    f1 (Pkg n1 v1 _ _ _ _ _ _) (Pkg n2 v2 _ _ _ _ _ _)
-      | n1 == n2  = compare v2 v1
-      | otherwise = compare n1 n2
-    f2 (Pkg n1 _ _ _ _ _ _ _) (Pkg n2 _ _ _ _ _ _ _)
-      = n1 == n2
+    f1 (Pkg deriv1 _ _) (Pkg deriv2 _ _)
+      | pname deriv1 == pname deriv2     = compare (version deriv2) (version deriv1)
+      | otherwise                        = compare (pname deriv1) (pname deriv2)
+    f2 (Pkg deriv1 _ _) (Pkg deriv2 _ _) = pname deriv1 == pname deriv2
 
-discoverUpdates :: PkgName -> PkgVersion -> Hackage4Nix [PkgVersion]
+discoverUpdates :: String -> String -> Hackage4Nix [String]
 discoverUpdates name vers = do
   hackage <- gets _hackageDb
   versionStrings <- io $ readDirectory (hackage </> name)
   let versions = map readVersion versionStrings
-  return (sort [ showVersion v | v <- versions, v > readVersion vers ])
+  return [ showVersion v | v <- versions, v > readVersion vers ]
 
 updateNixPkgs :: [FilePath] -> Hackage4Nix ()
 updateNixPkgs paths = do
@@ -140,45 +118,60 @@
     flip discoverNixFiles fileOrDir $ \file -> do
       nix' <- io (readFile file) >>= parseNixFile file
       flip (maybe (return ())) nix' $ \nix -> do
-        let Pkg name vers sha noHaddock plats maints path regenerate = nix
+        let Pkg deriv path regenerate = nix
+            maints = maintainers (metaSection deriv)
+            plats  = platforms (metaSection deriv)
+        when (null maints) (msgInfo ("no maintainers configured for " ++ path))
         modify $ \cfg -> cfg { _pkgset = Set.insert nix (_pkgset cfg) }
         when regenerate $ do
           msgDebug ("re-generate " ++ path)
-          let maints' = nub (sort (maints ++ ["andres","simons"]))
+          let maints' = nub (sort (maints ++ ["self.stdenv.lib.maintainers.andres","self.stdenv.lib.maintainers.simons"]))
               plats'
                 | null plats && not (null maints) = ["self.ghc.meta.platforms"]
                 | otherwise                       = plats
-          when (null maints) (msgInfo ("no maintainers configured for " ++ path))
-          pkg <- readCabalFile name vers
-          io $ writeFile path (showNixPkg (cabal2nix pkg sha noHaddock plats' maints'))
+          pkg <- readCabalFile (display (pname deriv)) (display (version deriv))
+          let deriv'  = (cabal2nix pkg) { sha256 = sha256 deriv, runHaddock = runHaddock deriv }
+              deriv'' = deriv' { metaSection = (metaSection deriv')
+                                               { maintainers = maints'
+                                               , platforms   = plats'
+                                               }
+                               }
+          io $ writeFile path (show (disp deriv''))
   pkgset <- gets (selectLatestVersions . _pkgset)
   updates' <- flip mapM (Set.elems pkgset) $ \pkg -> do
-    let Pkg name vers _ _ _ _ _ _ = pkg
-    updates <- discoverUpdates name vers
+    let Pkg deriv _ _ = pkg
+    updates <- discoverUpdates (display (pname deriv)) (display (version deriv))
     return (pkg,updates)
   let updates = [ u | u@(_,(_:_)) <- updates' ]
   when (not (null updates)) $ do
     msgInfo "The following updates are available:"
     flip mapM_ updates $ \(pkg,versions) -> do
-      let Pkg name vers _ noHaddock plats maints path regenerate = pkg
+      let Pkg deriv path regenerate = pkg
       msgInfo ""
-      msgInfo $ name ++ "-" ++ vers ++ ":"
+      msgInfo $ (display (pname deriv)) ++ "-" ++ (display (version deriv)) ++ ":"
       flip mapM_ versions $ \newVersion -> do
-        msgInfo $ "  " ++ genCabal2NixCmdline (Pkg name newVersion undefined noHaddock plats maints path regenerate)
+        let deriv' = deriv { version = readVersion newVersion }
+        msgInfo $ "  " ++ genCabal2NixCmdline (Pkg deriv' path regenerate)
   return ()
 
 genCabal2NixCmdline :: Pkg -> String
-genCabal2NixCmdline (Pkg name vers _ noHaddock plats maints path _) = unwords $ ["cabal2nix"] ++ opts ++ [">"++path']
-    where
-      opts = [cabal] ++ maints' ++ plats' ++ if noHaddock then ["--no-haddock"] else []
-      cabal = "cabal://" ++ name ++ "-" ++ vers
-      maints' = [ "--maintainer=" ++ m | m <- maints ]
-      plats'
-        | ["self.ghc.meta.platforms"] == plats = []
-        | otherwise                            =  [ "--platform=" ++ p | p <- plats ]
-      path'
-        | path =~ "/[0-9\\.]+\\.nix$" = replaceFileName path (vers <.> "nix")
-        | otherwise                   = path
+genCabal2NixCmdline (Pkg deriv path _) = unwords $ ["cabal2nix"] ++ opts ++ [">"++path']
+  where
+    meta = metaSection deriv
+    opts = [cabal] ++ maints' ++ plats' ++ if runHaddock deriv then [] else ["--no-haddock"]
+    cabal = "cabal://" ++ display (pname deriv) ++ "-" ++ display (version deriv)
+    maints' = [ "--maintainer=" ++ normalizeMaintainer m | m <- maintainers meta ]
+    plats'
+      | ["self.ghc.meta.platforms"] == platforms meta = []
+      | otherwise                                     =  [ "--platform=" ++ p | p <- platforms meta ]
+    path'
+      | path =~ "/[0-9\\.]+\\.nix$" = replaceFileName path (display (version deriv) <.> "nix")
+      | otherwise                   = path
+
+normalizeMaintainer :: String -> String
+normalizeMaintainer x
+  | "self.stdenv.lib.maintainers." `isPrefixOf` x = drop 28 x
+  | otherwise                                     = x
 
 data CliOption = PrintHelp | Verbose | HackageDB FilePath
   deriving (Eq)
