diff --git a/Data/Graph/Inductive/Graphviz.hs b/Data/Graph/Inductive/Graphviz.hs
--- a/Data/Graph/Inductive/Graphviz.hs
+++ b/Data/Graph/Inductive/Graphviz.hs
@@ -57,11 +57,12 @@
 graphviz' g = graphviz g "fgl" (8.5,11.0) (1,1) Landscape
 
 sq :: String -> String
-sq ('"':s) | last s == '"'  = init s
-	   | otherwise	    = s
-sq ('\'':s) | last s == '\''	= init s
-	    | otherwise		= s
-sq s = s
+sq s@[c]                     = s
+sq ('"':s)  | last s == '"'  = init s
+	    | otherwise	     = s
+sq ('\'':s) | last s == '\'' = init s
+	    | otherwise	     = s
+sq s                         = s
 
 sl :: (Show a) => a -> String
 sl a =
diff --git a/Data/Graph/Inductive/PatriciaTree.hs b/Data/Graph/Inductive/PatriciaTree.hs
new file mode 100644
--- /dev/null
+++ b/Data/Graph/Inductive/PatriciaTree.hs
@@ -0,0 +1,191 @@
+-- |An efficient implementation of 'Data.Graph.Inductive.Graph.Graph'
+-- using big-endian patricia tree (i.e. "Data.IntMap").
+--
+-- This module provides the following specialised functions to gain
+-- more performance, using GHC's RULES pragma:
+--
+-- * 'Data.Graph.Inductive.Graph.insNode'
+--
+-- * 'Data.Graph.Inductive.Graph.insEdge'
+--
+-- * 'Data.Graph.Inductive.Graph.gmap'
+--
+-- * 'Data.Graph.Inductive.Graph.nmap'
+--
+-- * 'Data.Graph.Inductive.Graph.emap'
+
+module Data.Graph.Inductive.PatriciaTree
+    ( Gr
+    , UGr
+    )
+    where
+
+import           Data.Graph.Inductive.Graph
+import           Data.IntMap (IntMap)
+import qualified Data.IntMap as IM
+import           Data.List
+import           Data.Maybe
+
+
+data Gr a b = Gr (GraphRep a b)
+
+type GraphRep a b = IntMap (Context' a b)
+type Context' a b = (IntMap b, a, IntMap b)
+
+type UGr = Gr () ()
+
+
+instance Graph Gr where
+    -- required members
+    empty           = Gr IM.empty
+    isEmpty (Gr g)  = IM.null g
+    match           = matchGr
+    mkGraph vs es   = (insEdges' . insNodes vs) empty
+        where
+          insEdges' g = foldl' (flip insEdge) g es
+
+    labNodes (Gr g) = [ (node, label)
+                            | (node, (_, label, _)) <- IM.toList g ]
+
+    -- overriding members for efficiency
+    noNodes   (Gr g) = IM.size g
+    nodeRange (Gr g)
+        | IM.null g = (0, 0)
+        | otherwise = (ix (IM.minViewWithKey g), ix (IM.maxViewWithKey g))
+                  where
+                    ix = fst . fst . fromJust
+
+    labEdges (Gr g) = do (node, (_, _, s)) <- IM.toList g
+                         (next, label)     <- IM.toList s
+                         return (node, next, label)
+
+
+instance DynGraph Gr where
+    (p, v, l, s) & (Gr g)
+        = let !g1 = IM.insert v (fromAdj p, l, fromAdj s) g
+              !g2 = addSucc g1 v p
+              !g3 = addPred g2 v s
+          in
+            Gr g3
+
+
+matchGr :: Node -> Gr a b -> Decomp Gr a b
+matchGr node (Gr g)
+    = case IM.lookup node g of
+        Nothing
+            -> (Nothing, Gr g)
+
+        Just (p, label, s)
+            -> let !g1 = IM.delete node g
+                   !p' = IM.delete node p
+                   !s' = IM.delete node s
+                   !g2 = clearPred g1 node (IM.keys s')
+                   !g3 = clearSucc g2 node (IM.keys p')
+               in
+                 (Just (toAdj p', node, label, toAdj s), Gr g3)
+
+
+{-# RULES
+      "insNode/Data.Graph.Inductive.PatriciaTree"  insNode = fastInsNode
+  #-}
+fastInsNode :: LNode a -> Gr a b -> Gr a b
+fastInsNode (v, l) (Gr g) = g' `seq` Gr g'
+    where
+      g' = IM.insert v (IM.empty, l, IM.empty) g
+
+
+{-# RULES
+      "insEdge/Data.Graph.Inductive.PatriciaTree"  insEdge = fastInsEdge
+  #-}
+fastInsEdge :: LEdge b -> Gr a b -> Gr a b
+fastInsEdge (v, w, l) (Gr g) = g2 `seq` Gr g2
+    where
+      g1 = IM.adjust addSucc' v g
+      g2 = IM.adjust addPred' w g1
+
+      addSucc' (ps, l', ss) = (ps, l', IM.insert w l ss)
+      addPred' (ps, l', ss) = (IM.insert v l ps, l', ss)
+
+
+{-# RULES
+      "gmap/Data.Graph.Inductive.PatriciaTree"  gmap = fastGMap
+  #-}
+fastGMap :: forall a b c d. (Context a b -> Context c d) -> Gr a b -> Gr c d
+fastGMap f (Gr g) = Gr (IM.mapWithKey f' g)
+    where
+      f' :: Node -> Context' a b -> Context' c d
+      f' = ((fromContext . f) .) . toContext
+
+
+{-# RULES
+      "nmap/Data.Graph.Inductive.PatriciaTree"  nmap = fastNMap
+  #-}
+fastNMap :: forall a b c. (a -> c) -> Gr a b -> Gr c b
+fastNMap f (Gr g) = Gr (IM.map f' g)
+    where
+      f' :: Context' a b -> Context' c b
+      f' (ps, a, ss) = (ps, f a, ss)
+
+
+{-# RULES
+      "emap/Data.Graph.Inductive.PatriciaTree"  emap = fastEMap
+  #-}
+fastEMap :: forall a b c. (b -> c) -> Gr a b -> Gr a c
+fastEMap f (Gr g) = Gr (IM.map f' g)
+    where
+      f' :: Context' a b -> Context' a c
+      f' (ps, a, ss) = (IM.map f ps, a, IM.map f ss)
+
+
+toAdj :: IntMap b -> Adj b
+toAdj = map swap . IM.toList
+
+
+fromAdj :: Adj b -> IntMap b
+fromAdj = IM.fromList . map swap
+
+
+toContext :: Node -> Context' a b -> Context a b
+toContext v (ps, a, ss)
+    = (toAdj ps, v, a, toAdj ss)
+
+
+fromContext :: Context a b -> Context' a b
+fromContext (ps, _, a, ss)
+    = (fromAdj ps, a, fromAdj ss)
+
+
+swap :: (a, b) -> (b, a)
+swap (a, b) = (b, a)
+
+
+addSucc :: GraphRep a b -> Node -> [(b, Node)] -> GraphRep a b
+addSucc g _ []              = g
+addSucc g v ((l, p) : rest) = addSucc g' v rest
+    where
+      g' = IM.adjust f p g
+      f (ps, l', ss) = (ps, l', IM.insert v l ss)
+
+
+addPred :: GraphRep a b -> Node -> [(b, Node)] -> GraphRep a b
+addPred g _ []              = g
+addPred g v ((l, s) : rest) = addPred g' v rest
+    where
+      g' = IM.adjust f s g
+      f (ps, l', ss) = (IM.insert v l ps, l', ss)
+
+
+clearSucc :: GraphRep a b -> Node -> [Node] -> GraphRep a b
+clearSucc g _ []       = g
+clearSucc g v (p:rest) = clearSucc g' v rest
+    where
+      g' = IM.adjust f p g
+      f (ps, l, ss) = (ps, l, IM.delete v ss)
+
+
+clearPred :: GraphRep a b -> Node -> [Node] -> GraphRep a b
+clearPred g _ []       = g
+clearPred g v (s:rest) = clearPred g' v rest
+    where
+      g' = IM.adjust f s g
+      f (ps, l, ss) = (IM.delete v ps, l, ss)
diff --git a/Data/Graph/Inductive/Query/BCC.hs b/Data/Graph/Inductive/Query/BCC.hs
--- a/Data/Graph/Inductive/Query/BCC.hs
+++ b/Data/Graph/Inductive/Query/BCC.hs
@@ -25,14 +25,15 @@
                         lc'= map (\g->[ e | e <- s, gelem (snd e) g]) gs
 
 ------------------------------------------------------------------------------
--- Given a node v and a list of graphs, this functions returns the graph which
--- v belongs to.
+-- Given a node v and a list of graphs, this function returns the graph which
+-- v belongs to, together with a list of the remaining graphs.
 ------------------------------------------------------------------------------
-findGraph :: DynGraph gr => Node -> [gr a b] -> Decomp gr a b
+findGraph :: DynGraph gr => Node -> [gr a b] -> (Decomp gr a b, [gr a b])
 findGraph _ [] = error "findGraph: empty graph list"
 findGraph v (g:gs) = case match v g of
-                          (Nothing,  _) -> findGraph v gs
-                          (Just c,  g') -> (Just c, g')
+                          (Nothing,  g) -> let (d, gs') = findGraph v gs
+                                           in (d, g : gs')
+                          (Just c,  g') -> ((Just c, g'), gs)
 
 ------------------------------------------------------------------------------
 -- Given a graph g and its articulation points, this function disconnects g
@@ -40,12 +41,12 @@
 -- resulting disconnected graph.
 ------------------------------------------------------------------------------
 splitGraphs :: DynGraph gr => [gr a b] -> [Node] -> [gr a b]
-splitGraphs gs     []     = gs
-splitGraphs []	   _	  = error "splitGraphs: empty graph list"
-splitGraphs (g:gs) (v:vs) = splitGraphs (gs''++gs) vs 
-                            where gs''        = embedContexts c gs'
-                                  gs'         = gComponents g'
-                                  (Just c,g') = findGraph v (g:gs)
+splitGraphs gs []     = gs
+splitGraphs [] _      = error "splitGraphs: empty graph list"
+splitGraphs gs (v:vs) = splitGraphs (gs''++gs''') vs 
+                        where gs'' = embedContexts c gs'
+                              gs' = gComponents g'
+                              ((Just c,g'), gs''') = findGraph v gs
 
 {-|
 Finds the bi-connected components of an undirected connected graph.
diff --git a/doc/CHANGES b/doc/CHANGES
--- a/doc/CHANGES
+++ b/doc/CHANGES
@@ -1,5 +1,41 @@
-CHANGES (FGL/HASKELL, Version: June 2006)
---------------------------------------------
+CHANGES (FGL/HASKELL, Version: November 2008)
+---------------------------------------------
+
+
+November 2008
+-------------
+* Bugfix in Graphviz.sq
+
+
+June 2008
+---------
+* bug fix in bcc by Reid Barton
+* added new dynamic graph implementation: 
+  Data.Graph.Inductive.PatriciaTree (thanks to Pho)
+* added test/benchmark.hs: a benchmark to compare Tree and PatriciaTree
+  implementations (thanks to Pho)
+
+
+May 2008
+--------
+* added Setup.hs to tar file
+* reimplementation of Data.Graph.Inductive.Query.Dominators
+  by Bertram Felgenhauer:
+  It was buggy and very slow for large graphs. See
+      http://www.haskell.org/pipermail/haskell-cafe/2008-April/041739.html
+  This patch also adds a new function, iDom, that returns the immediate
+  dominators of the graph nodes.
+* Exported xdf*With functions from DFS.hs
+* many little cleanups thanks to many people 
+  (use 'darcs changes' to see the details)
+
+
+April 2007
+----------
+* changed the implementation for inspection functions (suc, pred, ...)
+  to correct the behavior in the presence of loops 
+  (thanks to Ralf Juengling for pointing out the inconsistency)
+
 
 June 2006
 ---------
diff --git a/fgl.cabal b/fgl.cabal
--- a/fgl.cabal
+++ b/fgl.cabal
@@ -1,5 +1,5 @@
 name:		fgl
-version:	5.4.2.0
+version:	5.4.2.2
 license:	BSD3
 license-file:	LICENSE
 author:	        Martin Erwig
@@ -7,7 +7,6 @@
 homepage:	http://web.engr.oregonstate.edu/~erwig/fgl/haskell
 category:	Data Structures
 synopsis:	Martin Erwig's Functional Graph Library
-description:    Martin Erwig's Functional Graph Library.
 exposed-modules:
 	Data.Graph.Inductive.Internal.FiniteMap,
 	Data.Graph.Inductive.Internal.Heap,
@@ -20,6 +19,7 @@
 	Data.Graph.Inductive.Graphviz,
 	Data.Graph.Inductive.Monad,
 	Data.Graph.Inductive.NodeMap,
+    Data.Graph.Inductive.PatriciaTree,
 	Data.Graph.Inductive.Query,
 	Data.Graph.Inductive.Tree,
 	Data.Graph.Inductive.Monad.IOArray,
@@ -37,6 +37,6 @@
 	Data.Graph.Inductive.Query.SP,
 	Data.Graph.Inductive.Query.TransClos,
 	Data.Graph.Inductive
-build-type:	Simple
 build-depends:	base, mtl, containers, array
-extensions: MultiParamTypeClasses, OverlappingInstances, FlexibleInstances
+extensions: MultiParamTypeClasses, OverlappingInstances, FlexibleInstances, ScopedTypeVariables
+build-type: Simple
diff --git a/setup/Main.hi b/setup/Main.hi
deleted file mode 100644
Binary files a/setup/Main.hi and /dev/null differ
diff --git a/setup/Main.o b/setup/Main.o
deleted file mode 100644
Binary files a/setup/Main.o and /dev/null differ
diff --git a/setup/setup b/setup/setup
deleted file mode 100644
# file too large to diff: setup/setup
diff --git a/test/bcc.hs b/test/bcc.hs
new file mode 100644
--- /dev/null
+++ b/test/bcc.hs
@@ -0,0 +1,16 @@
+module Main where
+
+import Data.Graph.Inductive
+import List
+
+mkUndirectedUGraph v e = mkUGraph v [ (x, y) | (x0, y0) <- e, (x, y) <- [(x0, y0), (y0, x0)] ]
+
+graph :: Gr () ()
+graph = mkUndirectedUGraph [1..5] [(1, 2), (2, 3), (2, 4), (3, 5)]
+
+bccEdges g = sort (concat $ map edges $ bcc g) == sort (edges g)
+
+prop_bcc = bccEdges graph
+
+main = do
+  print prop_bcc
diff --git a/test/benchmark.hs b/test/benchmark.hs
new file mode 100644
--- /dev/null
+++ b/test/benchmark.hs
@@ -0,0 +1,138 @@
+{-
+  Install microbench to build this program:
+  http://hackage.haskell.org/cgi-bin/hackage-scripts/package/microbench
+
+  % ghc -O --make benchmark
+  % ./benchmark
+  [1 of 1] Compiling Main             ( benchmark.hs, benchmark.o )
+  Linking benchmark ...
+  * insNode into AVL tree: ..................
+    8.877ns per iteration / 112655.53 per second.
+  * insNode into PATRICIA tree: .....................
+    1.788ns per iteration / 559342.86 per second.
+  * insEdge into AVL tree: ...........
+    2833.029ns per iteration / 352.98 per second.
+  * insEdge into PATRICIA tree: ...................
+    4.625ns per iteration / 216224.60 per second.
+  * gmap on AVL tree: ................
+    32.754ns per iteration / 30530.57 per second.
+  * gmap on PATRICIA tree: .....................
+    1.623ns per iteration / 616056.37 per second.
+  * nmap on AVL tree: ................
+    35.455ns per iteration / 28204.95 per second.
+  * nmap on PATRICIA tree: .....................
+    1.713ns per iteration / 583758.06 per second.
+  * emap on AVL tree: ...........
+    4416.303ns per iteration / 226.43 per second.
+  * emap on PATRICIA tree: ...................
+    4.532ns per iteration / 220663.09 per second.
+-}
+
+import Data.Graph.Inductive.Graph
+import qualified Data.Graph.Inductive.Tree as AVL
+import qualified Data.Graph.Inductive.PatriciaTree as Patricia
+import Microbench
+
+
+main :: IO ()
+main = do microbench "insNode into AVL tree" insNodeAVL
+          microbench "insNode into PATRICIA tree" insNodePatricia
+
+          microbench "insEdge into AVL tree" insEdgeAVL
+          microbench "insEdge into PATRICIA tree" insEdgePatricia
+
+          microbench "gmap on AVL tree" gmapAVL
+          microbench "gmap on PATRICIA tree" gmapPatricia
+
+          microbench "nmap on AVL tree" nmapAVL
+          microbench "nmap on PATRICIA tree" nmapPatricia
+
+          microbench "emap on AVL tree" emapAVL
+          microbench "emap on PATRICIA tree" emapPatricia
+
+
+insNodeAVL :: Int -> AVL.UGr
+insNodeAVL = insNodes' empty
+
+
+insNodePatricia :: Int -> Patricia.UGr
+insNodePatricia = insNodes' empty
+
+
+{-# INLINE insNodes' #-}
+insNodes' :: DynGraph gr => gr () b -> Int -> gr () b
+insNodes' g 0 = g
+insNodes' g n = let [v] = newNodes 1 g
+                    g'  = insNode (v, ()) g
+                in
+                  insNodes' g' (n - 1)
+
+
+insEdgeAVL :: Int -> AVL.UGr
+insEdgeAVL n = insEdges' (insNodeAVL n) n
+
+
+insEdgePatricia :: Int -> Patricia.UGr
+insEdgePatricia n = insEdges' (insNodePatricia n) n
+
+
+{-# INLINE insEdges' #-}
+insEdges' :: DynGraph gr => gr a () -> Int -> gr a ()
+insEdges' g 0 = g
+insEdges' g n = let g' = insEdge (1, n, ()) g
+                in
+                  insEdges' g' (n - 1)
+
+
+gmapAVL :: Int -> AVL.Gr Int ()
+gmapAVL n
+    = let g  = insNodeAVL n
+          g' = gmap f g
+          f (ps, v, _, ss) = (ps, v, v, ss)
+      in
+        g'
+
+
+gmapPatricia :: Int -> Patricia.Gr Int ()
+gmapPatricia n
+    = let g  = insNodePatricia n
+          g' = gmap f g
+          f (ps, v, _, ss) = (ps, v, v, ss)
+      in
+        g'
+
+
+nmapAVL :: Int -> AVL.Gr Int ()
+nmapAVL n
+    = let g   = insNodeAVL n
+          g'  = nmap f g
+          f _ = n
+      in
+        g'
+
+
+nmapPatricia :: Int -> Patricia.Gr Int ()
+nmapPatricia n
+    = let g   = insNodePatricia n
+          g'  = nmap f g
+          f _ = n
+      in
+        g'
+
+
+emapAVL :: Int -> AVL.Gr () Int
+emapAVL n
+    = let g   = insEdgeAVL n
+          g'  = emap f g
+          f _ = n
+      in
+        g'
+
+
+emapPatricia :: Int -> Patricia.Gr () Int
+emapPatricia n
+    = let g   = insEdgePatricia n
+          g'  = emap f g
+          f _ = n
+      in
+        g'
