diff --git a/Data/ATerm/AbstractSyntax.hs b/Data/ATerm/AbstractSyntax.hs
new file mode 100644
--- /dev/null
+++ b/Data/ATerm/AbstractSyntax.hs
@@ -0,0 +1,27 @@
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (c) Joost Visser 2004
+-- License     :  LGPL
+-- 
+-- Maintainer  :  joost.visser@di.uminho.pt
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- This module is part of the ATerm library for Haskell. It defines
+-- the abstract syntax of ATerms as a Haskell datatype.
+--
+-----------------------------------------------------------------------------
+
+module Data.ATerm.AbstractSyntax (
+	ATerm(..)
+) where
+
+-----------------------------------------------------------------------------
+
+-- | The abstract syntax of ATerms.
+data ATerm = AAppl String [ATerm]	-- ^ Application
+           | AList [ATerm]		-- ^ Lists
+           | AInt Integer		-- ^ Integers
+           deriving (Read,Show,Eq,Ord)
+
+------------------------------------------------------------------------------
diff --git a/Data/ATerm/Conversion.hs b/Data/ATerm/Conversion.hs
new file mode 100644
--- /dev/null
+++ b/Data/ATerm/Conversion.hs
@@ -0,0 +1,131 @@
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (c) Joost Visser 2004
+-- License     :  LGPL
+-- 
+-- Maintainer  :  joost.visser@di.uminho.pt
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- This module is part of the ATerm library for Haskell. It provides the class
+-- ATermConvertible of types that are convertible to and from ATerms. Additionally,
+-- it provides default instances of this class for some predefined Prelude
+-- types.
+--
+-----------------------------------------------------------------------------
+
+module Data.ATerm.Conversion where
+
+import Data.ATerm.AbstractSyntax
+import Data.ATerm.ReadWrite
+import Data.Ratio
+import Data.Char
+
+-----------------------------------------------------------------------------
+-- * Conversion to and from ATerms
+
+class ATermConvertible t where
+  -- | Convert to an ATerm.
+  toATerm   :: t -> ATerm
+  -- | Convert from an ATerm.
+  fromATerm :: ATerm -> t 
+
+-- | Auxiliary function for reporting errors.
+fromATermError :: String -> ATerm -> a
+fromATermError t u 
+  = error ("Cannot convert ATerm to "++t++": "++(err u))
+    where err u = case u of 
+		  AAppl s _ -> '!':s
+		  AList _   -> "!AList"
+		  otherwise -> "!AInt"
+  
+-----------------------------------------------------------------------------
+-- * Conversion of ATerms to and from Strings
+
+-- | Convert to a textual ATerm representation without sharing (TXT format).
+toATermString 		:: ATermConvertible t => t -> String
+toATermString t		=  writeATerm (toATerm t)
+
+-- | Convert to a textual ATerm representation with full sharing (TAF format).
+toSharedATermString 	:: ATermConvertible t => t -> String
+toSharedATermString t	= writeSharedATerm (toATerm t)
+
+-- | Convert from a textual ATerm representation.
+fromATermString 	:: ATermConvertible t => String -> t
+fromATermString	s 	= fromATerm (readATerm s)
+
+-----------------------------------------------------------------------------
+-- * Instances for basic types
+                                                                      -- Lists
+instance ATermConvertible a => ATermConvertible [a] where
+  toATerm as 		= AList (map toATerm as)
+  fromATerm (AList as)	= map fromATerm as
+  fromATerm t		= fromATermError "Prelude.[]" t
+
+                                                                      -- Maybe
+instance ATermConvertible a => ATermConvertible (Maybe a) where
+  toATerm Nothing		= AAppl "None" []
+  toATerm (Just a)  		= AAppl "Just" [toATerm a]
+  fromATerm (AAppl "None" [])	= Nothing
+  fromATerm (AAppl "Some" [a])	= Just (fromATerm a)
+  fromATerm t			= fromATermError "Prelude.Maybe" t
+  
+                                                                   -- 2-Tuples
+instance (ATermConvertible a, ATermConvertible b) 
+      => ATermConvertible (a,b) where
+  toATerm (a,b)			    = AAppl "Tuple2" [toATerm a, toATerm b]
+  fromATerm (AAppl "Tuple2" [a,b])  = (fromATerm a,fromATerm b)
+  fromATerm t			    = fromATermError "Prelude.(,)" t
+  
+                                                                     -- Either
+instance (ATermConvertible a, ATermConvertible b) 
+      => ATermConvertible (Either a b) where
+  toATerm (Left a)		    = AAppl "Left" [toATerm a]
+  toATerm (Right b)		    = AAppl "Right" [toATerm b]
+  fromATerm (AAppl "Left" [a])      = Left (fromATerm a)
+  fromATerm (AAppl "Right" [b])     = Right (fromATerm b)
+  fromATerm t			    = fromATermError "Prelude.Either" t
+  
+                                                                     -- String
+instance ATermConvertible String where
+  toATerm s			= AAppl (show s) []
+  fromATerm (AAppl s [])  	= read s
+  fromATerm t			= fromATermError "Prelude.String" t
+
+                                                                   -- Integral
+instance Integral n => ATermConvertible n where
+  toATerm i			= AInt (toInteger i)
+  fromATerm (AInt i)  		= fromInteger i
+  fromATerm t			= fromATermError "Prelude.Integral" t
+
+                                                                       -- Bool
+instance ATermConvertible Bool where
+  toATerm True			= AAppl "True" []
+  toATerm False			= AAppl "False" []
+  fromATerm (AAppl "True" [])	= True
+  fromATerm (AAppl "False" [])	= False
+  fromATerm t			= fromATermError "Prelude.Bool" t
+                                                                       -- Bool
+
+instance ATermConvertible () where
+  toATerm ()			= AAppl "()" []
+  fromATerm (AAppl "()" [])	= ()
+  fromATerm t			= fromATermError "Prelude.()" t
+
+                                                                       -- Char
+instance ATermConvertible Char where
+  toATerm c			= AInt (toInteger . ord $ c)
+  fromATerm (AInt c)		= chr . fromInteger $ c
+  fromATerm t			= fromATermError "Prelude.Char" t
+
+                                                                      -- Ratio
+instance (Integral a, ATermConvertible a) 
+      => ATermConvertible (Ratio a) where
+  toATerm xy	= AAppl "Ratio" [toATerm (numerator xy), 
+                                 toATerm (denominator xy)]
+  fromATerm (AAppl "Ratio" [x,y])
+		= (fromATerm x)%(fromATerm y)
+  fromATerm t	= fromATermError "Ratio.Ratio" t
+  
+------------------------------------------------------------------------------
+  
diff --git a/Data/ATerm/IO.hs b/Data/ATerm/IO.hs
new file mode 100644
--- /dev/null
+++ b/Data/ATerm/IO.hs
@@ -0,0 +1,120 @@
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (c) Joost Visser 2004
+-- License     :  LGPL
+-- 
+-- Maintainer  :  joost.visser@di.uminho.pt
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- This module is part of the ATerm library for Haskell. This module
+-- provides wrapper functions that take care of IO.
+--
+-----------------------------------------------------------------------------
+
+module Data.ATerm.IO where
+
+import System.IO
+import System.Environment ( getArgs )
+import Data.ATerm.AbstractSyntax
+import Data.ATerm.Conversion 
+import Data.ATerm.ReadWrite
+import Data.Char
+
+-----------------------------------------------------------------------------
+-- * Transformation wrapper
+ 
+-- | Wrapper function to create a main function in the IO monad, given a
+--   program name and a monadic transformation function.
+atermIOwrap :: (ATermConvertible t, ATermConvertible a) 
+            => ProgramName -> (t -> IO a) -> IO ()
+atermIOwrap progName mtransform
+  = do args <- getArgs
+       opts <- return $ parseOptions progName args
+       sin  <- readStream (fin opts)
+       tin  <- return . fromATerm . dehyphenAST . readATerm $ sin
+       tout <- mtransform $ tin
+       sout <- return . toString (format opts) $ tout
+       writeStream (fout opts) sout 
+    where
+      readStream "#stdin#"	= getContents
+      readStream f		= readFile f
+      writeStream "#stdout#"	= putStr
+      writeStream f		= writeFile f
+      toString format 
+        = case format of 
+            "TEXT" -> toATermString
+	    "TAF"  -> toSharedATermString
+	    _      -> error $ "format unknown: "++"\n"++usage progName    
+	
+-----------------------------------------------------------------------------
+-- * Helpers
+
+type ProgramName = String
+
+-- | Turn hyphens in a String into underscores.
+dehyphen :: String -> String
+dehyphen str
+  = map aux str
+    where aux '-' = '_'
+          aux c   = c
+
+-- | Turn hyphens in AST into underscores except inside nodes
+--   that represent literals.
+dehyphenAST :: ATerm -> ATerm
+--dehyphenAST t@(AAppl "Sdf_Literal" ts) = t
+dehyphenAST (AAppl f ts)    = AAppl (dehyphenUnquoted f) (map dehyphenAST ts)
+dehyphenAST (AList ts)      = AList (map dehyphenAST ts)
+dehyphenAST t               = t
+
+-- | Turn hyphens in unquoted literal into underscores.
+dehyphenUnquoted s@('\"':_) = s
+dehyphenUnquoted s = dehyphen s
+
+-- | Turn the first character into upper case.       
+headToUpper 	   ::  String -> String
+headToUpper []     = []
+headToUpper (c:cs) = (toUpper c):cs
+
+-- | Make all AFun's start with an uppercase letter.
+afunCap :: ATerm -> ATerm
+afunCap (AAppl afun ts) = AAppl (headToUpper afun) (map afunCap ts)
+afunCap (AList ts)      = AList (map afunCap ts)
+afunCap t               = t
+
+-----------------------------------------------------------------------------
+-- * Option handling 
+
+data OptionsATermIO
+  = OptionsATermIO { fin :: String, fout :: String, format :: String }
+
+defaultOptionsATermIO :: OptionsATermIO
+defaultOptionsATermIO
+  = OptionsATermIO { fin = "#stdin#", fout = "#stdout#", format = "TEXT" }
+  
+parseOptions :: String -> [String] -> OptionsATermIO
+parseOptions programName args
+  = p args
+    where 
+      p []			= defaultOptionsATermIO
+      p ("-t":args)		= (p args){ format = "TEXT" }
+      p ("-s":args)		= (p args){ format = "TAF" }
+      p ("-b":args)		= err "BAF format not supported!"
+      p ("-i":fname:args)	= (p args){ fin = fname }
+      p ("-o":fname:args)	= (p args){ fout = fname }
+      p args			= err $ "Can't parse options: "++concat args
+      err msg			= error $ msg++"\n"++usage programName
+
+usage :: String -> String
+usage programName
+  = unlines ["Usage","",
+             "  "++programName++" [-i <fname>] [-o <fname>] [-t|-s]",
+             "",
+	     "Options","",
+	     "  -i <fname>    name of input file    (default: stdin)",
+	     "  -o <fname>    name of output file   (default: stdout)",
+	     "  -t            output format is TEXT (plain text)",
+	     "  -s            output format is TAF  (textual sharing)"
+	    ]	   
+    
+-------------------------------------------------------------------------------
diff --git a/Data/ATerm/Lib.hs b/Data/ATerm/Lib.hs
new file mode 100644
--- /dev/null
+++ b/Data/ATerm/Lib.hs
@@ -0,0 +1,31 @@
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (c) Joost Visser 2004
+-- License     :  LGPL
+-- 
+-- Maintainer  :  joost.visser@di.uminho.pt
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- This module is part of the ATerm library for Haskell. This 
+-- is the top module of the library. Most users only need to 
+-- import this module.
+--
+-----------------------------------------------------------------------------
+
+module Data.ATerm.Lib (
+
+	module Data.ATerm.AbstractSyntax,
+	module Data.ATerm.ReadWrite,
+	module Data.ATerm.Conversion,
+	module Data.ATerm.Lib,
+	module Data.ATerm.IO
+
+) where
+
+import Data.ATerm.AbstractSyntax
+import Data.ATerm.ReadWrite
+import Data.ATerm.Conversion
+import Data.ATerm.IO
+
+-------------------------------------------------------------------------------
diff --git a/Data/ATerm/ReadWrite.hs b/Data/ATerm/ReadWrite.hs
new file mode 100644
--- /dev/null
+++ b/Data/ATerm/ReadWrite.hs
@@ -0,0 +1,320 @@
+-----------------------------------------------------------------------------
+-- |
+-- Copyright   :  (c) Joost Visser 2004
+-- License     :  LGPL
+-- 
+-- Maintainer  :  joost.visser@di.uminho.pt
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- This module is part of the ATerm library for Haskell. It contains functions
+-- for reading and writing ATerms from and to Strings. Two ATerm formats are
+-- supported:
+--
+--      * AT:   plain (non-shared) textual ATerms
+--      
+--      * TAF:  shared textual ATerms
+--
+--  The binary ATerm format (BAF) is not supported.
+--
+--  Current limitations:
+--
+--      * BLOBS and place-holders are not supported.
+--      
+--      * Annotations are not supported.
+--
+-----------------------------------------------------------------------------
+
+module Data.ATerm.ReadWrite (
+        readATerm,
+        writeATerm,
+        writeSharedATerm
+) where
+
+import Data.ATerm.AbstractSyntax
+import Data.Map as FM
+import Data.Char
+
+-----------------------------------------------------------------------------
+-- * From String to ATerm
+
+-- | Parse the given string into an ATerm.
+readATerm               :: String -> ATerm
+readATerm ('!':str)     = let (t,_,_,_) = readTAF str emptyRT 0 in t
+readATerm str           = let (t,_)     = readAT str            in t
+
+                                                               -- non-shared --
+
+readAT ('[':str)        =  let (kids, str') = readATs (dropSpaces str)
+                           in (AList kids, str')
+readAT str@(c:cs)
+  | isIntHead c         =  let (i,str') = span isDigit cs
+                           in (AInt (read (c:i)),str')
+  | otherwise           =  let (c,str')      = readAFun str
+                               (kids, str'') = readParenATs (dropSpaces str')
+                           in (AAppl c kids, str'')
+
+readAFun ('"':str)      =  let (c,('"':str')) = spanNotQuote' str 
+                           in (quote c,str')
+readAFun str            =  spanAFunChar str
+
+readParenATs ('(':str)  =  readATs (dropSpaces str)
+readParenATs str        =  ([],str)
+
+
+readATs (')':str)       =  ([],str)
+readATs (']':str)       =  ([],str)
+readATs str             =  readATs1 str
+
+readATs1 str            =  let (t,str')   = readAT (dropSpaces str)
+                               (ts,str'') = readATs' (dropSpaces str')
+                           in (t:ts,str'')
+
+readATs' (',':str)      = readATs1 (dropSpaces str)
+readATs' (')':str)      = ([],str)
+readATs' (']':str)      = ([],str)
+
+                                                                   -- shared --
+                                                                   
+readTAF                 :: String -> ReadTable -> Int
+                        -> (ATerm,String,ReadTable,Int)
+readTAF ('#':str) tbl l =  let (i,str') = spanAbbrevChar str
+                           in (getElementRT (deAbbrev i) tbl, 
+                               str',tbl,l+(length i)+1)    
+readTAF ('[':str) tbl l =  let (kids, str',tbl',l') 
+                                  = readTAFs (dropSpaces str) tbl 1
+                               t  = AList kids
+                           in (t, str',condAddElementRT t l' tbl',l+l')
+readTAF str@(c:cs) tbl l
+  | isIntHead c         =  let (i,str') = span isDigit cs
+                               ci       = (c:i)
+                               l'       = length ci
+                               t        = AInt (read ci) 
+                               tbl'     = condAddElementRT t l' tbl
+                           in (t,str',tbl',l+l')
+  | otherwise           =  let (c,str') = readAFun str
+                               (kids, str'',tbl',l') 
+                                   = readParenTAFs (dropSpaces str') tbl 0
+                               t   = AAppl c kids
+                               lks = if Prelude.null kids then 0 else l'
+                               l'' = (length c) + lks
+                           in (t, str'',condAddElementRT t l'' tbl',l'')
+
+readParenTAFs ('(':str) tbl l   =  readTAFs (dropSpaces str) tbl l
+readParenTAFs str tbl l         =  ([],str,tbl,l)
+
+readTAFs (')':str) tbl l        =  ([],str,tbl,l+1)
+readTAFs (']':str) tbl l        =  ([],str,tbl,l+1)
+readTAFs str tbl l              =  readTAFs1 str tbl l
+
+readTAFs1 str tbl l     =  let (t,str',tbl',l')
+                                   = readTAF (dropSpaces str) tbl l
+                               (ts,str'',tbl'',l'') 
+                                   = readTAFs' (dropSpaces str') tbl' l'
+                           in (t:ts,str'',tbl'',l'')
+
+readTAFs' (',':str) tbl l       = readTAFs1 (dropSpaces str) tbl (l+1)
+readTAFs' (')':str) tbl l       = ([],str,tbl,l+1)
+readTAFs' (']':str) tbl l       = ([],str,tbl,l+1)
+
+                                                                  -- helpers --
+
+dropSpaces              = dropWhile isSpace
+spanAFunChar            = span isAFunChar
+isAFunChar c            = (isAlphaNum c) || (c `elem` "-_*+")
+spanNotQuote            = span (/='"')
+spanAbbrevChar          = span (`elem` toBase64)
+isIntHead c             = (isDigit c) || (c=='-')
+quote str               = ('"':str)++"\""
+
+spanNotQuote' []                = ([],[])
+spanNotQuote' xs@('"':xs')      = ([],xs)
+spanNotQuote' xs@('\\':'"':xs') = ('\\':'"':ys,zs) 
+                                  where (ys,zs) = spanNotQuote' xs'
+spanNotQuote' xs@('\\':'\\':xs')= ('\\':'\\':ys,zs) 
+                                  where (ys,zs) = spanNotQuote' xs'
+spanNotQuote' xs@(x:xs')        = (x:ys,zs) 
+                                  where (ys,zs) = spanNotQuote' xs'
+
+-----------------------------------------------------------------------------
+-- * From ATerm to String 
+
+-- | Write the given ATerm to non-shared textual representation (TXT format).
+writeATerm              :: ATerm -> String
+writeATerm t            = writeAT t
+
+-- | Write the given ATerm to fully shared textual representation (TAF format).
+writeSharedATerm        :: ATerm -> String
+writeSharedATerm t      = let (s,_) = writeTAF t emptyWT in ('!':s)
+
+                                                               -- non-shared --
+
+writeAT                 :: ATerm -> String
+writeAT (AAppl c ts)    =  writeATermAux c (Prelude.map writeAT ts)
+writeAT (AList ts)      =  bracket (commaSep (Prelude.map writeAT ts))
+writeAT (AInt i)        =  show i
+
+                                                                   -- shared --
+
+writeTAF                :: ATerm -> WriteTable -> (String,WriteTable)
+writeTAF t tbl          =  case getIndexWT t tbl of
+                             (Just i) -> (makeAbbrev i,tbl) 
+                             Nothing  -> (str, condAddElementWT t str tbl')
+                                         where (str,tbl') = writeTAF' t tbl
+
+writeTAF' (AAppl c ts) tbl      = let (kids,tbl') = writeTAFs ts tbl
+                                  in (writeATermAux c kids,tbl')
+writeTAF' (AList ts) tbl        = let (kids,tbl') = writeTAFs ts tbl
+                                  in (bracket (commaSep kids),tbl')
+writeTAF' (AInt i) tbl          = (show i,tbl)
+
+writeTAFs [] tbl                =  ([],tbl)
+writeTAFs (t:ts) tbl    =  let (str,tbl')   = writeTAF t tbl
+                               (strs,tbl'') = writeTAFs ts tbl'
+                           in ((str:strs),tbl'')
+
+                                                                  -- helpers --
+ 
+writeATermAux c []      =  c
+writeATermAux c ts      =  c++(parenthesise (commaSep ts))
+
+sepBy sep (x:y:ys)      =  x:sep:sepBy sep (y:ys)
+sepBy sep ys            =  ys
+
+commaSep strs           =  concat (sepBy "," strs)
+bracket str             = "["++str++"]"
+parenthesise str        = "("++str++")"
+
+-----------------------------------------------------------------------------
+-- * Tables of ATerms 
+
+                                                -- For reading (remove sharing)
+-- Using reversed List
+type ReadTable          = (Integer,[ATerm])
+emptyRT                 = (0,[])
+-- Hook to prevent expansion of productions. This is useful when reading
+-- huge AsFix files. 
+getElementRT' i tbl     = case getElementRT i tbl of
+                            (AAppl "prod" _) -> AAppl "#prod" []
+                            t -> t
+getElementRT  i tbl     = (snd tbl)!!!((fst tbl)-i-1)
+addElementRT a tbl      = ((fst tbl)+1,a:(snd tbl))
+sizeOfRT tbl            = fst tbl
+{--- Using Finite Map
+type ReadTable          = FiniteMap Integer ATerm
+emptyRT                 = emptyFM
+getElementRT  i tbl     = lookupWithDefaultFM tbl (error "getElement") i
+addElementRT a tbl      = addToFM tbl (sizeOfRT tbl) a
+sizeOfRT tbl            = toInteger (sizeFM tbl)
+-}
+{--- Using some imported Edison sequence
+type ReadTable          = T.Seq ATerm
+emptyRT                 = T.empty :: ReadTable
+getElementRT  i tbl     = T.lookup tbl (toInt i)
+addElementRT t tbl      = T.snoc tbl t
+sizeOfRT tbl            = T.size tbl
+-}
+
+condAddElementRT t l tbl
+  = if (length next_abbrev) < l then
+       addElementRT t tbl
+    else
+       tbl
+    --where next_abbrev = makeAbbrev (toInteger (sizeOfRT tbl)+1)
+    where next_abbrev = makeAbbrev (toInteger (sizeOfRT tbl))
+    
+condAddElementRT' t str tbl
+  = if (length next_abbrev) < (length str) then
+       addElementRT t tbl
+    else
+       tbl
+    where next_abbrev = makeAbbrev (toInteger (sizeOfRT tbl)+1)
+ 
+                                                -- For writing (create sharing)
+-- Using FiniteMap
+type WriteTable         = FM.Map ATerm Integer
+emptyWT                 = FM.empty
+getIndexWT    a tbl     = FM.lookup a tbl
+addElementWT a tbl      = FM.insert a (sizeOfWT tbl) tbl
+sizeOfWT tbl            = toInteger (FM.size tbl)
+
+condAddElementWT t str tbl
+  = if (length next_abbrev) < (length str) then
+       addElementWT t tbl
+    else
+       tbl
+    --where next_abbrev = makeAbbrev (toInteger (sizeOfWT tbl)+1)
+    where next_abbrev = makeAbbrev (toInteger (sizeOfWT tbl))
+
+-----------------------------------------------------------------------------
+-- * Base 64 encoding
+
+mkAbbrev x
+  | x == 0      = [toBase64!!0]
+  | otherwise   = reverse (mkAbbrevAux x)
+
+mkAbbrevAux x
+  | x == 0      = []
+  | x > 0       = (toBase64!!!m:mkAbbrevAux d) where (d,m) = divMod x 64
+
+deAbbrev x              =  deAbbrevAux (reverse x)
+
+deAbbrevAux []          =  0
+deAbbrevAux (c:cs)      =  let (Just i) = indexOf c toBase64
+                               r        = deAbbrevAux cs
+                           in (i + 64*r)
+
+toBase64 =
+  [ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' 
+  ]
+  
+makeAbbrev i = '#':mkAbbrev i
+
+-----------------------------------------------------------------------------
+-- * Helpers 
+
+indexOf t []            =  Nothing
+indexOf t (x:xs)        =  if t==x
+                           then (Just (0::Integer))
+                           else case indexOf t xs of
+                                 (Just i)   -> Just (i+1)
+                                 Nothing    -> Nothing
+(!!!)              :: [b] -> Integer -> b
+(x:_)  !!! 0       =  x
+(_:xs) !!! n | n>0 =  xs !!! (n-1)
+(_:_)  !!! _       =  error "!!!: negative index"
+[]     !!! _       =  error "!!!: index too large"
+
+-----------------------------------------------------------------------------
+-- * Future work
+
+{- The code could be made more readable by introducing
+   special monads that hide the consumed String/ATerm and the 
+   table that is built during reading/writing
+   
+newtype ReadMonad t     = RM { runRM :: String -> ReadTable 
+                                     -> (t,String,ReadTable) }
+instance Monad ReadMonad where
+  return t = RM $ \str tbl -> (t,str,tbl)
+  rm >>= f = RM $ \str tbl -> let (t,str',tbl') = runRM rm str tbl
+                              in runRM (f t) str' tbl'
+                              
+  I guess this should be a combined ParserMonad and StateMonad.                       
+-}
+
+-------------------------------------------------------------------------------
+-- * Testing
+
+-- | Test whether reading and writing to and from shared aterm representations
+--   (TAF format) deals correctly with the bounderies of the base-64 encoding.
+testAbbrevBoundaries :: Bool
+testAbbrevBoundaries 
+  = writeSharedATerm term == shared && readATerm shared == term
+  where
+    term = AList $ Prelude.map AInt ([100..164]++[100..164])
+    shared = "![100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,#A,#B,#C,#D,#E,#F,#G,#H,#I,#J,#K,#L,#M,#N,#O,#P,#Q,#R,#S,#T,#U,#V,#W,#X,#Y,#Z,#a,#b,#c,#d,#e,#f,#g,#h,#i,#j,#k,#l,#m,#n,#o,#p,#q,#r,#s,#t,#u,#v,#w,#x,#y,#z,#0,#1,#2,#3,#4,#5,#6,#7,#8,#9,#+,#/,164]"
+
+-------------------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,1 @@
+Does not exist.
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/Strafunski-ATermLib.cabal b/Strafunski-ATermLib.cabal
new file mode 100644
--- /dev/null
+++ b/Strafunski-ATermLib.cabal
@@ -0,0 +1,35 @@
+-- Initial ATermLib.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                Strafunski-ATermLib
+version:             1.6
+synopsis:            An abstract data type designed for the exchange of tree-like data structures
+description:         Library for dealing with ATerms (annotated terms) in Haskell. See https://github.com/cwi-swat/aterms for more information on ATerms.
+license:             BSD3
+license-file:        LICENSE
+author:              Ralf Laemmel, Joost Visser
+maintainer:          darmanithird@gmail.com
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.8
+source-repository head
+  type:              git
+  location:          https://github.com/jkoppel/Strafunski-ATermLib
+
+library
+
+  Extensions:
+    TypeSynonymInstances,
+    FlexibleInstances,
+    UndecidableInstances,
+    OverlappingInstances
+
+
+
+  exposed-modules:     Data.ATerm.AbstractSyntax,
+                       Data.ATerm.Conversion,
+                       Data.ATerm.IO,
+                       Data.ATerm.Lib,
+                       Data.ATerm.ReadWrite
+  -- other-modules:       
+  build-depends:       base ==4.5.*, containers ==0.4.*
