diff --git a/Data/XCB.hs b/Data/XCB.hs
new file mode 100644
--- /dev/null
+++ b/Data/XCB.hs
@@ -0,0 +1,23 @@
+-- |
+-- Module    :  Data.XCB
+-- Copyright :  (c) Antoine Latter 2008
+-- License   :  BSD3
+--
+-- Maintainer:  Antoine Latter <aslatter@gmail.com>
+-- Stability :  provisional
+-- Portability: portable
+--
+-- The 'Data.XCB' module can parse the contents of the xcb-proto
+-- XML files into Haskell data structures.
+--
+-- Pretty-printers are provided to aid in the debugging - they do
+-- not pretty-print to XML, but to a custom human-readable format.
+module Data.XCB
+    (module Data.XCB.Types
+    ,module Data.XCB.FromXML
+    ,module Data.XCB.Pretty
+    ) where
+
+import Data.XCB.Types
+import Data.XCB.FromXML
+import Data.XCB.Pretty
diff --git a/Data/XCB/FromXML.hs b/Data/XCB/FromXML.hs
new file mode 100644
--- /dev/null
+++ b/Data/XCB/FromXML.hs
@@ -0,0 +1,401 @@
+-- |
+-- Module    :  Data.XCB.FromXML
+-- Copyright :  (c) Antoine Latter 2008
+-- License   :  BSD3
+--
+-- Maintainer:  Antoine Latter <aslatter@gmail.com>
+-- Stability :  provisional
+-- Portability: portable
+--
+-- Handls parsing the data structures from XML files.
+--
+-- In order to support copying events and errors across module
+-- boundaries, all modules which may have cross-module event copies and
+-- error copies must be parsed at once.
+--
+-- There is no provision for preserving the event copy and error copy
+-- declarations - the copies are handled during parsing.
+module Data.XCB.FromXML(fromFiles
+                       ,fromStrings
+                       ) where
+
+import Data.XCB.Types
+import Data.XCB.Pretty
+import Data.XCB.Utils
+
+import Text.XML.Light
+
+import Data.List as List
+import Data.Maybe
+import Data.Monoid
+
+import Control.Monad
+import Control.Monad.Reader
+
+import Control.Applicative
+
+-- |Process the listed XML files.
+-- Any files which fail to parse are silently dropped.
+-- Any declaration in an XML file which fail to parse are
+-- silently dropped.
+fromFiles :: [FilePath] -> IO [XHeader]
+fromFiles xs = do
+  strings <- sequence $ map readFile xs
+  return $ fromStrings strings
+
+-- |Process the strings as if they were XML files.
+-- Any files which fail to parse are silently dropped.
+-- Any declaration in an XML file which fail to parse are
+-- silently dropped.
+fromStrings :: [String] -> [XHeader]
+fromStrings xs =
+   let rs = mapAlt fromString xs
+       Just headers = runReaderT rs headers
+   in headers 
+
+-- The 'Parse' monad.  Provides the name of the
+-- current module, and a list of all of the modules.
+type Parse = ReaderT ([XHeader],Name) Maybe
+
+-- operations in the 'Parse' monad
+
+localName :: Parse Name
+localName = snd `liftM` ask
+
+allModules :: Parse [XHeader]
+allModules = fst `liftM` ask
+
+-- a generic function for looking up something from
+-- a named XHeader.
+--
+-- this implements searching both the current module and
+-- the xproto module if the name is not specified.
+lookupThingy :: ([XDecl] -> Maybe a)
+             -> (Maybe Name)
+             -> Parse (Maybe a)
+lookupThingy f Nothing = do
+  lname <- localName
+  liftM2 mplus (lookupThingy f $ Just lname)
+               (lookupThingy f $ Just "xproto") -- implicit xproto import
+lookupThingy f (Just mname) = do
+  xs <- allModules
+  return $ do
+    x <- findXHeader mname xs
+    f $ xheader_decls x
+
+-- lookup an event declaration by name.
+lookupEvent :: Maybe Name -> Name -> Parse (Maybe EventDetails)
+lookupEvent mname evname = flip lookupThingy mname $ \decls ->
+                 findEvent evname decls
+
+-- lookup an error declaration by name.
+lookupError :: Maybe Name -> Name -> Parse (Maybe ErrorDetails)
+lookupError mname ername = flip lookupThingy mname $ \decls ->
+                 findError ername decls
+
+findXHeader :: Name -> [XHeader] -> Maybe XHeader
+findXHeader name = List.find $ \ x -> xheader_header x == name
+
+findError :: Name -> [XDecl] -> Maybe ErrorDetails
+findError pname xs =
+      case List.find f xs of
+        Nothing -> Nothing
+        Just (XError name code elems) -> Just $ ErrorDetails name code elems
+    where  f (XError name _ _) | name == pname = True
+           f _ = False 
+                                       
+findEvent :: Name -> [XDecl] -> Maybe EventDetails
+findEvent pname xs = 
+      case List.find f xs of
+        Nothing -> Nothing
+        Just (XEvent name code elems) -> Just $ EventDetails name code elems
+   where f (XEvent name _ _) | name == pname = True
+         f _ = False 
+
+data EventDetails = EventDetails Name Int [StructElem]
+data ErrorDetails = ErrorDetails Name Int [StructElem]
+
+---
+
+-- extract a single XHeader from a single XML document
+fromString :: String -> ReaderT [XHeader] Maybe XHeader
+fromString str = do
+  el@(Element qname ats cnt _) <- lift $ parseXMLDoc str
+  guard $ el `named` "xcb"
+  header <- el `attr` "header"
+  let name = el `attr` "extension-name"
+      xname = el `attr` "extension-xname"
+      maj_ver = el `attr` "major-version" >>= readM
+      min_ver = el `attr` "minor-version" >>= readM
+      multiword = el `attr` "extension-multiword" >>= readM . ensureUpper
+  decls <- withReaderT (\r -> (r,header)) $ extractDecls cnt
+  return $ XHeader {xheader_header = header
+                   ,xheader_xname = xname
+                   ,xheader_name = name
+                   ,xheader_multiword = multiword
+                   ,xheader_major_version = maj_ver
+                   ,xheader_minor_version = min_ver
+                   ,xheader_decls = decls
+                   }
+
+-- attempts to extract declarations from XML content, discarding failures.
+extractDecls :: [Content] -> Parse [XDecl]
+extractDecls = mapAlt declFromElem . onlyElems
+
+-- attempt to extract a module declaration from an XML element
+declFromElem :: Element -> Parse XDecl
+declFromElem elem 
+    | elem `named` "request" = xrequest elem
+    | elem `named` "event"   = xevent elem
+    | elem `named` "eventcopy" = xevcopy elem
+    | elem `named` "error" = xerror elem
+    | elem `named` "errorcopy" = xercopy elem
+    | elem `named` "struct" = xstruct elem
+    | elem `named` "union" = xunion elem
+    | elem `named` "xidtype" = xidtype elem
+    | elem `named` "xidunion" = xidunion elem
+    | elem `named` "typedef" = xtypedef elem
+    | elem `named` "enum" = xenum elem
+    | elem `named` "import" = ximport elem
+    | otherwise = mzero
+
+
+ximport :: Element -> Parse XDecl
+ximport = return . XImport . strContent
+
+xenum :: Element -> Parse XDecl
+xenum elem = do
+  nm <- elem `attr` "name"
+  fields <- mapAlt enumField $ elChildren elem
+  guard $ not $ null fields
+  return $ XEnum nm fields
+
+enumField :: Element -> Parse EnumElem
+enumField elem = do
+  guard $ elem `named` "item"
+  name <- elem `attr` "name"
+  let expr = firstChild elem >>= expression
+  return $ EnumElem name expr
+
+xrequest :: Element -> Parse XDecl
+xrequest elem = do
+  nm <- elem `attr` "name"
+  code <- elem `attr` "opcode" >>= readM
+  fields <- mapAlt structField $ elChildren elem
+  let reply = getReply elem
+  guard $ not (null fields) || not (isNothing reply)
+  return $ XRequest nm code fields reply
+
+getReply :: Element -> Maybe XReply
+getReply elem = do
+  childElem <- unqual "reply" `findChild` elem
+  let fields = mapMaybe structField $ elChildren childElem
+  guard $ not $ null fields
+  return fields
+
+xevent :: Element -> Parse XDecl
+xevent elem = do
+  name <- elem `attr` "name"
+  number <- elem `attr` "number" >>= readM
+  fields <- mapAlt structField $ elChildren elem
+  guard $ not $ null fields
+  return $ XEvent name number fields
+
+xevcopy :: Element -> Parse XDecl
+xevcopy elem = do
+  name <- elem `attr` "name"
+  number <- elem `attr` "number" >>= readM
+  ref <- elem `attr` "ref"
+  -- do we have a qualified ref?
+  let (mname,evname) = splitRef ref
+  details <- lookupEvent mname evname 
+  return $ XEvent name number $ case details of
+               Nothing -> error $ "Unresolved event: " ++ show mname ++ " " ++ ref
+               Just (EventDetails _ _ x) -> x
+
+-- we need to do string processing to distinguish qualified from
+-- unqualified types.
+mkType :: String -> Type
+mkType str =
+    let (mname, name) = splitRef str
+    in case mname of
+         Just mod -> QualType mod name
+         Nothing  -> UnQualType name
+
+splitRef :: Name -> (Maybe Name, Name)
+splitRef ref = case split ':' ref of
+                 (x,"") -> (Nothing, x)
+                 (a, b) -> (Just a, b)
+
+-- |Neither returned string contains the first occurance of the
+-- supplied Char.
+split :: Char -> String -> (String, String)
+split c xs = go xs
+    where go [] = ([],[])
+          go (x:xs) | x == c = ([],xs)
+                    | otherwise = 
+                        let (lefts, rights) = go xs
+                        in (x:lefts,rights)
+                 
+
+xerror :: Element -> Parse XDecl
+xerror elem = do
+  name <- elem `attr` "name"
+  number <- elem `attr` "number" >>= readM
+  fields <- mapAlt structField $ elChildren elem
+  guard $ not $ null fields
+  return $ XError name number fields
+
+
+xercopy :: Element -> Parse XDecl
+xercopy elem = do
+  name <- elem `attr` "name"
+  number <- elem `attr` "number" >>= readM
+  ref <- elem `attr` "ref"
+  let (mname, ername) = splitRef ref
+  details <- lookupError mname ername
+  return $ XError name number $ case details of
+               Nothing -> error $ "Unresolved error: " ++ show mname ++ " " ++ ref
+               Just (ErrorDetails _ _ x) -> x
+
+xstruct :: Element -> Parse XDecl
+xstruct elem = do
+  name <- elem `attr` "name"
+  fields <- mapAlt structField $ elChildren elem
+  guard $ not $ null fields
+  return $ XStruct name fields
+
+xunion :: Element -> Parse XDecl
+xunion elem = do
+  name <- elem `attr` "name"
+  fields <- mapAlt structField $ elChildren elem
+  guard $ not $ null fields
+  return $ XUnion name fields
+
+xidtype :: Element -> Parse XDecl
+xidtype elem = liftM XidType $ elem `attr` "name"
+
+xidunion :: Element -> Parse XDecl
+xidunion elem = do
+  name <- elem `attr` "name"
+  let types = mapMaybe xidUnionElem $ elChildren elem
+  guard $ not $ null types
+  return $ XidUnion name types
+
+xidUnionElem :: Element -> Maybe XidUnionElem
+xidUnionElem elem = do
+  guard $ elem `named` "type"
+  return $ XidUnionElem $ mkType $ strContent elem
+
+xtypedef :: Element -> Parse XDecl
+xtypedef elem = do
+  oldtyp <- liftM mkType $ elem `attr` "oldname"
+  newname <- elem `attr` "newname"
+  return $ XTypeDef newname oldtyp
+
+
+structField :: MonadPlus m => Element -> m StructElem
+structField elem
+    | elem `named` "field" = do
+        typ <- liftM mkType $ elem `attr` "type"
+        name <- elem `attr` "name"
+        return $ SField name typ
+
+    | elem `named` "pad" = do
+        bytes <- elem `attr` "bytes" >>= readM
+        return $ Pad bytes
+
+    | elem `named` "list" = do
+        typ <- liftM mkType $ elem `attr` "type"
+        name <- elem `attr` "name"
+        let expr = firstChild elem >>= expression
+        return $ List name typ expr
+
+    | elem `named` "valueparam" = do
+        mask_typ <- liftM mkType $ elem `attr` "value-mask-type"
+        mask_name <- elem `attr` "value-mask-name"
+        list_name <- elem `attr` "value-list-name"
+        return $ ValueParam mask_typ mask_name list_name
+
+    | elem `named` "exprfield" = do
+        typ <- liftM mkType $ elem `attr` "type"
+        name <- elem `attr` "name"
+        expr <- firstChild elem >>= expression
+        return $ ExprField name typ expr
+
+    | elem `named` "reply" = fail "" -- handled separate
+
+    | otherwise = let name = elName elem
+                  in error $ "I don't know what to do with structelem "
+ ++ show name
+
+expression :: MonadPlus m => Element -> m Expression
+expression elem | elem `named` "fieldref"
+                    = return $ FieldRef $ strContent elem
+                | elem `named` "value"
+                    = Value `liftM` readM (strContent elem)
+                | elem `named` "bit"
+                    = Bit `liftM` do
+                        n <- readM (strContent elem)
+                        guard $ n >= 0
+                        return n
+                | elem `named` "op" = do
+                    binop <- elem `attr` "op" >>= toBinop
+                    [exprLhs,exprRhs] <- mapM expression $ elChildren elem
+                    return $ Op binop exprLhs exprRhs
+
+
+toBinop :: MonadPlus m => String -> m Binop
+toBinop "+"  = return Add
+toBinop "-"  = return Sub
+toBinop "*"  = return Mult
+toBinop "/"  = return Div
+toBinop "&"  = return And
+toBinop "&amp;" = return And
+toBinop ">>" = return RShift
+toBinop _ = mzero
+
+
+
+
+----
+----
+-- Utility functions
+----
+----
+
+firstChild :: MonadPlus m => Element -> m Element
+firstChild = listToM . elChildren
+
+listToM :: MonadPlus m => [a] -> m a
+listToM [] = mzero
+listToM (x:xs) = return x
+
+named :: Element -> String -> Bool
+named (Element qname _ _ _) name | qname == unqual name = True
+named _ _ = False
+
+attr :: MonadPlus m => Element -> String -> m String
+(Element _ xs _ _) `attr` name = case List.find p xs of
+      Just (Attr _ res) -> return res
+      _ -> mzero
+    where p (Attr qname _) | qname == unqual name = True
+          p _ = False
+
+-- adapted from Network.CGI.Protocol
+readM :: (MonadPlus m, Read a) => String -> m a
+readM = liftM fst . listToM . reads
+
+maybeRead :: Read a => String -> Maybe a
+maybeRead = readM
+
+-- In retorspect maybe I should've gone with MonadPlus, but the
+-- code is already written so I guess I need these instances.
+
+instance (Alternative f, Monad f) => Alternative (ReaderT r f) where
+    empty = ReaderT $ \r -> empty
+    m1 <|> m2 = ReaderT $ \r -> (runReaderT m1 r) <|> (runReaderT m2 r)
+
+instance (Applicative f, Monad f) => Applicative (ReaderT r f) where
+    pure a = ReaderT $ \_ -> pure a
+    mf <*> m = ReaderT $ \r -> (runReaderT mf r) <*> (runReaderT m r)
diff --git a/Data/XCB/Pretty.hs b/Data/XCB/Pretty.hs
new file mode 100644
--- /dev/null
+++ b/Data/XCB/Pretty.hs
@@ -0,0 +1,131 @@
+{-# LANGUAGE TypeSynonymInstances #-}
+
+-- |
+-- Module    :  Data.XCB.Pretty
+-- Copyright :  (c) Antoine Latter 2008
+-- License   :  BSD3
+--
+-- Maintainer:  Antoine Latter <aslatter@gmail.com>
+-- Stability :  provisional
+-- Portability: portable - requires TypeSynonymInstances
+--
+-- Pretty-printers for the tyes declared in this package.
+-- This does NOT ouput XML - it produces human-readable information
+-- intended to aid in debugging.
+module Data.XCB.Pretty where
+
+import Data.XCB.Types
+
+import Text.PrettyPrint.HughesPJ
+
+-- |Minimal complete definition:
+--
+-- One of 'pretty' or 'toDoc'.
+class Pretty a where
+    toDoc :: a -> Doc
+    pretty :: a -> String
+
+    pretty = show . toDoc
+    toDoc = text . pretty
+
+-- Builtin types
+
+instance Pretty String where
+    pretty = show
+
+instance Pretty Int where
+    pretty = show
+
+instance Pretty a => Pretty (Maybe a) where
+    toDoc Nothing = empty
+    toDoc (Just a) = toDoc a
+
+    pretty Nothing = ""
+    pretty (Just a) = pretty a
+
+-- Simple stuff
+
+instance Pretty XidUnionElem where
+    pretty = show
+
+instance Pretty Binop where
+    pretty Add  = "+"
+    pretty Sub  = "-"
+    pretty Mult = "*"
+    pretty Div  = "/"
+    pretty RShift = ">>"
+    pretty And = "&"
+
+instance Pretty EnumElem where
+    toDoc (EnumElem name expr)
+        = text name <> char ':' <+> toDoc expr
+
+instance Pretty Type where
+    toDoc (UnQualType name) = text name
+    toDoc (QualType mod name) = text mod <> char '.' <> text name
+
+-- More complex stuff
+
+instance Pretty Expression where
+    toDoc (Value n) = toDoc n
+    toDoc (Bit n) = text "2^" <> toDoc n
+    toDoc (FieldRef ref) = char '$' <> text ref
+    toDoc (Op binop exprL exprR)
+        = parens $ hsep [toDoc exprL
+                        ,toDoc binop
+                        ,toDoc exprR
+                        ]
+
+instance Pretty StructElem where
+    toDoc (Pad n) = braces $ toDoc n <+> text "bytes"
+    toDoc (List nm typ len)
+        = text nm <+> text "::" <+> brackets (toDoc typ) <+> toDoc len
+    toDoc (SField nm typ) = hsep [text nm
+                                 ,text "::"
+                                 ,toDoc typ
+                                 ]
+    toDoc (ExprField nm typ expr)
+          = parens (text nm <+> text "::" <+> toDoc typ)
+            <+> toDoc expr
+    toDoc (ValueParam typ mname lname)
+        = text "Valueparam" <+>
+          text "::" <+>
+          hsep (punctuate (char ',') [toDoc typ
+                                     ,text mname
+                                     ,text lname
+                                     ])
+
+instance Pretty XDecl where
+    toDoc (XStruct nm elems) =
+        hang (text "Struct:" <+> text nm) 2 $ vcat $ map toDoc elems
+    toDoc (XTypeDef nm typ) = hsep [text "TypeDef:"
+                                    ,text nm
+                                    ,text "as"
+                                    ,toDoc typ
+                                    ]
+    toDoc (XEvent nm n elems) =
+        hang (text "Event:" <+> text nm <> char ',' <> toDoc n) 2 $
+             vcat $ map toDoc elems
+    toDoc (XRequest nm n elems mrep) = 
+        (hang (text "Request:" <+> text nm <> char ',' <> toDoc n) 2 $
+             vcat $ map toDoc elems)
+         $$ case mrep of
+             Nothing -> empty
+             Just reply ->
+                 hang (text "Reply:" <+> text nm <> char ',' <> toDoc n) 2 $
+                      vcat $ map toDoc reply
+    toDoc (XidType nm) = text "XID:" <+> text nm
+    toDoc (XidUnion nm elems) = 
+        hang (text "XID" <+> text "Union:" <+> text nm) 2 $
+             vcat $ map toDoc elems
+    toDoc (XEnum nm elems) =
+        hang (text "Enum:" <+> text nm) 2 $ vcat $ map toDoc elems
+    toDoc (XUnion nm elems) = 
+        hang (text "Union:" <+> text nm) 2 $ vcat $ map toDoc elems
+    toDoc (XImport nm) = text "Import:" <+> text nm
+    toDoc (XError nm n elems) = 
+        hang (text "Error:" <+> text nm) 2 $ vcat $ map toDoc elems
+
+instance Pretty XHeader where
+    toDoc xhd = text (xheader_header xhd) $$
+                (vcat $ map toDoc (xheader_decls xhd))
diff --git a/Data/XCB/Types.hs b/Data/XCB/Types.hs
new file mode 100644
--- /dev/null
+++ b/Data/XCB/Types.hs
@@ -0,0 +1,99 @@
+
+-- |
+-- Module    :  Data.XCB.Types
+-- Copyright :  (c) Antoine Latter 2008
+-- License   :  BSD3
+--
+-- Maintainer:  Antoine Latter <aslatter@gmail.com>
+-- Stability :  provisional
+-- Portability: portable
+--
+-- Defines types inteneded to be equivalent to the schema used by
+-- the XCB project in their XML protocol description.
+--
+
+
+module Data.XCB.Types where
+
+
+import qualified Data.List as L
+import Control.Monad
+
+-- 'xheader_header' is the name gauranteed to exist, and is used in
+-- imports and in type qualifiers.
+--
+-- 'xheader_name' is the InterCaps name, and should be prefered in the naming
+-- of types, functions and haskell modules when available.
+-- |This is what a single XML file maps to.  It contains some meta-data
+-- then declarations.
+data XHeader = XHeader {xheader_header :: Name -- ^Name of module.  Used in the other modules as a reference.
+                       ,xheader_xname :: Maybe Name  -- ^Name used to indentify extensions between the X client and server.
+                       ,xheader_name :: Maybe Name -- ^InterCaps name.
+                       ,xheader_multiword :: Maybe Bool
+                       ,xheader_major_version :: Maybe Int
+                       ,xheader_minor_version :: Maybe Int
+                       ,xheader_decls :: [XDecl]  -- ^Declarations contained in this module.
+                       }
+ deriving (Show)
+
+-- |The different types of declarations which can be made in one of the
+-- XML files.
+data XDecl = XStruct  Name [StructElem]
+           | XTypeDef Name Type
+           | XEvent Name Int [StructElem]
+           | XRequest Name Int [StructElem] (Maybe XReply)
+           | XidType  Name
+           | XidUnion  Name [XidUnionElem]
+           | XEnum Name [EnumElem]
+           | XUnion Name [StructElem]
+           | XImport Name
+           | XError Name Int [StructElem]
+ deriving (Show)
+
+data StructElem = Pad Int
+                | List Name Type (Maybe Expression)
+                | SField Name Type
+                | ExprField Name Type Expression
+                | ValueParam Type MaskName ListName
+ deriving (Show)
+
+type Name = String
+type XReply = [StructElem]
+type Ref = String
+
+-- |Types may include a reference to the containing module.
+data Type = UnQualType Name
+          | QualType Name Name
+ deriving Show
+
+type MaskName = Name
+type ListName = Name
+
+data ExInfo = ExInfo Name Name Version
+ deriving (Show)
+
+type Version = (String,String)
+
+data XidUnionElem = XidUnionElem Type
+ deriving (Show)
+
+-- Should only ever have expressions of type 'Value' or 'Bit'.
+data EnumElem = EnumElem Name (Maybe Expression)
+ deriving (Show)
+
+-- |Declarations may contain expressions from this small language
+data Expression = Value Int  -- ^A literal value
+                | Bit Int    -- ^A log-base-2 literal value
+                | FieldRef String -- ^A reference to a field in the same declaration
+                | Op Binop Expression Expression -- ^A binary opeation
+ deriving (Show)
+
+-- |Supported Binary operations.
+data Binop = Add
+           | Sub
+           | Mult
+           | Div
+           | And
+           | RShift
+ deriving (Show)
+
diff --git a/Data/XCB/Utils.hs b/Data/XCB/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Data/XCB/Utils.hs
@@ -0,0 +1,18 @@
+module Data.XCB.Utils where
+
+-- random utility functions
+
+import Data.Char
+import Control.Applicative
+
+ensureUpper :: String -> String
+ensureUpper [] = []
+ensureUpper (x:xs) = (toUpper x) : xs
+
+-- |Like mapMaybe, but for any Alternative.
+-- Never returns 'empty', instead returns 'pure []'
+mapAlt :: Alternative f => (a -> f b) -> [a] -> f [b]
+mapAlt f xs = go xs
+ where go [] = pure []
+       go (y:ys) = pure (:) <*> f y <*> go ys
+               <|> go ys
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Antoine Latter 2008
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of the author nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/xcb-types.cabal b/xcb-types.cabal
new file mode 100644
--- /dev/null
+++ b/xcb-types.cabal
@@ -0,0 +1,37 @@
+Name:         xcb-types
+Version:      0.1.0
+Cabal-Version:  >= 1.2
+Synopsis:     Parses XML files used by the XCB project
+Description:   This package provides types which mirror the structures
+  used in the XCB code generation XML files.
+
+  See project http://xcb.freedesktop.org/ for more information about the XCB
+  project.
+
+  The XML files describe the data-types, events and requests used by the
+  X Protocol, and are used to auto-generate large parts of the XCB project.
+
+ This package parses these XML files into Haskell data structures.
+
+  If you want to do something with these XML descriptions but don't want
+  to learn XSLT, this package should help.
+
+License:      BSD3
+License-file: LICENSE
+Author:       Antoine Latter
+Maintainer:   Antoine Latter <aslatter@gmail.com>
+
+Build-type: Simple
+
+Category: Data
+
+Library
+
+ Build-depends: base, xml, pretty, mtl
+ Exposed-modules: Data.XCB,
+                  Data.XCB.Types,
+                  Data.XCB.Pretty,
+                  Data.XCB.FromXML
+
+ Other-modules:   Data.XCB.Utils
+
