diff --git a/UMM.cabal b/UMM.cabal
--- a/UMM.cabal
+++ b/UMM.cabal
@@ -1,5 +1,5 @@
 Name:             UMM
-Version:          0.2.2
+Version:          0.3.0
 Homepage:         http://www.korgwal.com/umm/
 Author:           Uwe Hollerbach <uh@alumni.caltech.edu>
 Maintainer:       Uwe Hollerbach <uh@alumni.caltech.edu>
diff --git a/UMM.hs b/UMM.hs
--- a/UMM.hs
+++ b/UMM.hs
@@ -16,7 +16,7 @@
 along with umm; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-$Id: UMM.hs,v 1.67 2010/06/10 06:44:20 uwe Exp $ -}
+$Id: UMM.hs,v 1.69 2010/07/06 03:12:06 uwe Exp $ -}
 
 module Main where
 import Prelude hiding (putStr,putStrLn,print,readFile,getContents)
@@ -183,22 +183,30 @@
   where chk w1 w2 = w1 == w2 || w1 == COLAll
         sh = mapM_ print
 
+-- Generate the sum of a list of amounts, translating them
+-- into the default ccs to the extent possible
+
+genSum :: Name -> [Record] -> [Record] -> Date -> [CCSAmt] -> [CCSAmt]
+genSum dc ccs prices date vs =
+  let fp = map (\e -> reprice e dc ccs date prices) vs
+      gp = groupBy eqCCSAmtName (sortBy cmpCCSAmtName fp)
+  in filter (\e -> ccsA e /= 0) (map sumCCS gp)
+  where sumCCS cs =
+           CCSAmt (ccsN (head cs)) (Amount (roundP 2 (sum (map ccsA cs))))
+        ccsN (CCSAmt n _) = n
+        ccsA (CCSAmt _ (Amount a)) = a
+
 doBalance :: Bool -> Date -> [Name] -> Name -> [Record] ->
              [Record] -> [Record] -> [Record] -> IO ()
 doBalance ke date names dc ccs accts trans prices =
   do final <- getBalances startTime date Nothing False accts trans
      let fsel = selAccts ke names final
-         fp = map (\e -> reprice e dc ccs date prices) (concatMap tr3 fsel)
-         gp = groupBy eqCCSAmtName (sortBy cmpCCSAmtName fp)
-         sp = filter (\e -> ccsA e /= 0) (map sumCCS gp)
-     putStrLn ("Account balances as of " ++ show date)
+         sp = genSum dc ccs prices date (concatMap tr3 fsel)
+     putStrLn ("Account balances as of " ++ (gregorianDateToWDay date)
+              ++ " " ++ show date)
      mapM_ putStrLn (ppAccts (showPos dc ccs date prices fsel) 8)
      putStrLn ("Grand total: ~" ++ show sp)
-  where sumCCS cs =
-           CCSAmt (ccsN (head cs)) (Amount (roundP 2 (sum (map ccsA cs))))
-        ccsN (CCSAmt n _) = n
-        ccsA (CCSAmt _ (Amount a)) = a
-        tr3 (_,_,v) = v
+  where tr3 (_,_,v) = v
 
 doRegister :: Date -> Date -> [Name] -> Name -> [Record] ->
               [Record] -> [Record] -> [Record] -> Bool -> IO ()
@@ -263,12 +271,13 @@
          doList w dc ccs accts grps incs exps
        PlotCmd name date1 date2 (Name output) ->
          let crec = find (\r -> getRecName r == name) cd
+             gs = genSum1 dc ccs prices
          in if elem name (map getRecName cb)
                then putStrLn (show name ++ " is a base CCS!")
                else if isNothing crec
                        then if elem name (map getRecName accts)
                                then plotBalances date1 date2 name
-                                                 accts trans output
+                                                 accts trans output gs
                                else putStrLn (show name ++ " is unknown!")
                        else plotPrices name (getNB (fromJust crec))
                                        date1 date2 prices output
@@ -288,3 +297,7 @@
          getBalances startTime date Nothing False accts trans >> return ()
   where getNB (CCSRec _ _ _ nb) = nb
         getNB r = error ("internal error at main! got " ++ show r)
+        genSum1 dc ccs prices (r,bs) =
+          let date = getRecDate r
+          in (date, map ccsA (genSum dc ccs prices date bs))
+        ccsA (CCSAmt _ a) = a
diff --git a/UMMData.hs b/UMMData.hs
--- a/UMMData.hs
+++ b/UMMData.hs
@@ -16,7 +16,7 @@
 along with umm; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-$Id: UMMData.hs,v 1.56 2010/05/17 05:24:09 uwe Exp $ -}
+$Id: UMMData.hs,v 1.57 2010/07/06 03:12:08 uwe Exp $ -}
 
 module UMMData (Name(..), Date(..), Amount(..), startTime,
                 Command(..), CmdOpt(..), Record(..), genDate,
@@ -26,8 +26,9 @@
                 SN(..), Period(..), CCSAmt(..), cmpCCSAmtName,
                 eqCCSAmtName, AccountData, noName, todoName, joinDrop,
                 roundP, isLeap, validDate, julianDate, gregorianDate,
-                offsetDate, previousDate, nextDate,
-                trimspace, mylines, mergelines, uniqAdjBy, uniqAdj) where
+                offsetDate, previousDate, nextDate, julianDateToWDay,
+                gregorianDateToWDay, trimspace, mylines, mergelines,
+                uniqAdjBy, uniqAdj) where
 import Prelude
 import Data.Char
 import Data.List
@@ -465,6 +466,25 @@
 previousDate, nextDate :: Date -> Date
 previousDate d = offsetDate d (-1)
 nextDate d = offsetDate d 1
+
+-- Utility functions to get the day of the week
+-- from either a Julian or a Gregorian date
+
+julianDateToWDay :: Int -> String
+julianDateToWDay jd =
+  let jm = mod (jd + 1) 7
+  in case jm of
+       0 -> "Sun"
+       1 -> "Mon"
+       2 -> "Tue"
+       3 -> "Wed"
+       4 -> "Thu"
+       5 -> "Fri"
+       6 -> "Sat"
+       _ -> error ("internal error at julianDateToWDay! got " ++ show jm)
+
+gregorianDateToWDay :: Date -> String
+gregorianDateToWDay = julianDateToWDay . julianDate
 
 -- Remove leading and trailing whitespace from a string.
 
diff --git a/UMMEval.hs b/UMMEval.hs
--- a/UMMEval.hs
+++ b/UMMEval.hs
@@ -16,7 +16,7 @@
 along with umm; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-$Id: UMMEval.hs,v 1.48 2010/06/10 06:44:20 uwe Exp $ -}
+$Id: UMMEval.hs,v 1.50 2010/07/12 00:03:27 uwe Exp $ -}
 
 module UMMEval (validateRecs, validateCCS, validateAccts, classifyRecs,
                 validateTransPrices, generateImplicitPrices, getBalances,
@@ -361,14 +361,15 @@
      unless (null i) (putStrLn "Notes:" >> mapM_ ss i >> putStrLn "")
      return r
 
-plotBalances :: Date -> Date -> Name -> [Record] -> [Record] -> String -> IO ()
-plotBalances date1 date2 reg accts trans output =
+plotBalances :: Date -> Date -> Name -> [Record] -> [Record] ->
+                String -> ((Record, [CCSAmt]) -> (Date, [Amount])) -> IO ()
+plotBalances date1 date2 reg accts trans output gs =
   do let (_,i1,e) =
            runLedger (mkInit accts >>= appTr date2 (Just [reg]) False trans)
          i = dropWhile (\t -> getRecDate (fst t) < date1) i1
      unless (null e) (showErrs "processing errors" e)
-     unless (null i) (putStrLn "Notes:" >> mapM_ showTB i >> putStrLn "")
-     putStrLn ("gonna plot: " ++ output)
+     if null i then putStrLn ("No balances known for " ++ show reg)
+               else genPlot output reg date1 date2 (map gs i)
 
 -- For now, we don't generate "swap prices" internally, so unless the user
 -- enters some, we won't see any; see also generateImplicitPrices above.
@@ -402,10 +403,9 @@
   do let p1 = dropWhile (\t -> date2 < getRecDate t) prices
          p2 = takeWhile (\t -> date1 < getRecDate t) p1
          (_,i,e) = runLedger (getP nm dc p2)
-         pdata = map gp (reverse i)
      unless (null e) (putStrLn "There were swap \"prices\" which are ignored")
      if null i then putStrLn ("No prices known for " ++ show nm)
-               else genPlot output nm pdata
+               else genPlot output nm date1 date2 (map gp (reverse i))
   where gp (PriceRec d _ (CCSAmt _ (Amount a1)) (CCSAmt _ (Amount a2))) =
           (d, [Amount (a2/a1)])
         gp r = intErr "plotPrices" r
diff --git a/UMMHelp.hs b/UMMHelp.hs
--- a/UMMHelp.hs
+++ b/UMMHelp.hs
@@ -16,13 +16,13 @@
 along with umm; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-$Id: help-head.txt,v 1.4 2010/06/13 23:46:16 uwe Exp $ -}
+$Id: help-head.txt,v 1.6 2010/07/12 00:26:27 uwe Exp $ -}
 
 module UMMHelp (writeHdr, usageMsg) where
 import Prelude
 
 version :: String
-version = "0.2.2"
+version = "0.3.0"
 
 writeHdr :: String
 writeHdr =
@@ -77,8 +77,6 @@
   "* 'plot' generates a plot of the price history of the specified\n" ++
   "  currency, commodity, or security, or of the value of the specified\n" ++
   "  account, in the given date range.\n" ++
-  "\n" ++
-  "  This is in progress, and only partially implemented.\n" ++
   "\n" ++
   "* 'price' shows the price history of the specified currency,\n" ++
   "  commodity, or security, in the given date range\n" ++
diff --git a/UMMPlot.hs b/UMMPlot.hs
--- a/UMMPlot.hs
+++ b/UMMPlot.hs
@@ -16,57 +16,124 @@
 along with umm; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
-$Id: UMMPlot.hs,v 1.3 2010/06/13 23:46:16 uwe Exp $ -}
+$Id: UMMPlot.hs,v 1.7 2010/07/12 00:26:26 uwe Exp $ -}
 
 module UMMPlot (genPlot) where
 import Prelude hiding (putStr, putStrLn, print)
 import Data.List
-import System.IO(openFile, IOMode(..), hClose)
+import System.IO(withFile, IOMode(..))
 import System.IO.UTF8
-import System.Process
+-- Just one of these is needed to build this; pick the appropriate one
+-- import System.Cmd	-- for ghc 6.8
+import System.Process	-- for ghc 6.10 (and newer? untested)
 import Control.Monad
 
 import UMMData
 
 -- TODO: a lot more work!
+-- Do we need the niceBounds stuff at all? Or can gnuplot handle it?
 
+-- Given a pair of numbers, return a set of nice bounds plus a number of
+-- sub-intervals into which those nice bounds should be divided:
+--
+--	niceBounds 23 65 -> (20.0,65.0,9)
+--
+-- meaning that the nice lower and upper bounds are 20 and 65, and that
+-- interval should be sub-divided into 9 sub-intervals which will thus
+-- each have length 5, and therefore tic-marks will be placed at nice
+-- round numbers: [20, 25, ..., 60, 65]
+--
+-- The original algorithm is not mine, but I don't now remember
+-- where it came from... I got it a long time ago.
+
+-- TODO: make this polymorphic, accepting Fractional or even Num?
+
+niceBounds :: Double -> Double -> (Double, Double, Int)
+niceBounds l h | l == h      = (l - 1, h + 1, 8)
+               | l > h       = nbw h l
+               | otherwise   = nbw l h
+  where nbw lo hi =
+          let sc = fsc (hi - lo) 1.0
+              los = lo*sc
+              his = hi*sc
+              tries = map (fn los his sc) [1.0, 0.5, 0.25, 0.2, 0.1, 0.05]
+          in head (dropWhile (\(_,_,n) -> n <= 6) tries)
+        fsc d s | d < 1       = fsc (10*d) (10*s)
+                | d > 10      = fsc (d/10) (s/10)
+                | otherwise   = s
+        fn lo hi sc e =
+          let fl = fromInteger (floor (lo/e))
+              ch = fromInteger (ceiling (hi/e))
+              n = ceiling (hi/e) - floor (lo/e)
+              es = e/sc
+          in (fl*es, ch*es, n)
+
+-- Various steps to take in subdividing a date range, used below
+
+data DateStep = Day | Month | YearM | YearQ | Year | DY Int deriving (Show)
+
+-- Given a pair of dates, return another pair of dates which are nice bounds
+-- plus a subdivision indicator: analogous to niceBounds, above, but
+-- specialized for dates, for which what's "nice" is slightly different
+-- than for generic numbers.
+
+niceDateBounds :: Date -> Date -> (Date, Date, DateStep)
+niceDateBounds l h = if l <= h then njbw l h else njbw h l
+  where njbw (Date yl ml _) (Date yh mh _) =
+          let dy = yh - yl
+              lo1 = nd yl ml 1
+              hi1 = nd yh (mh + 1) 0
+              lo2 = nd yl (ml - rem (ml - 1) 3) 1
+              hi2 = nd yh (mh + 3 - rem (mh - 1) 3) 0
+              lo3 = nd yl 1 1
+              hi3 = nd yh 12 31
+              (l4, h4, n4) =
+                niceBounds (fromIntegral yl) (fromIntegral (yh + 1))
+              lo4 = nd (fromInteger (round l4)) 1 1
+              hi4 = nd (fromInteger (round h4)) 1 0
+          in if dy <= 0
+                then (lo1, hi1, if ml == mh then Day else Month)
+                else if dy <= 2
+                        then (lo1, hi1, YearM)
+                        else if dy <= 5
+                                then (lo2, hi2, YearQ)
+                                else if dy <= 15
+                                        then (lo3, hi3, Year)
+                                        else (lo4, hi4, DY n4)
+-- The round-tripping of Date to Julian day back to Date may seem stupid,
+-- but it normalizes the date: for example, 2009-13-0 becomes 2009-12-31
+-- without having to worry about how many days there are in a given month
+        nd y m d = gregorianDate (julianDate (Date y m d))
+
 -- Adjust as needed: for example, for pgm output, use
 --  "set terminal pbm gray medium size 800,600\n" ++
 
-termo :: String -> String -> String
-termo output name =
+plot_cmds :: String -> String -> Date -> Date -> String
+plot_cmds output name lo hi =
   "set terminal postscript 'Times-Roman' 16\n" ++
   "set output '" ++ output ++ ".ps'\n" ++
   "set title 'Value of " ++ name ++ " over time'\n" ++
   "unset key\n" ++
+  "set xdata time\n" ++
+  "set timefmt \"%Y-%m-%d\"\n" ++
+  "set format x \"%Y-%m-%d\"\n" ++
+  "set xrange [\"" ++ show lo ++ "\":\"" ++ show hi ++ "\"]\n" ++
   "plot '" ++ output ++ ".dat' using 1:2 with lines\n"
 
-genPlot :: String -> Name -> [(Date, [Amount])] -> IO ()
-genPlot output name pts =
-  do fp <- openFile (output ++ ".plot") WriteMode
-     hPutStr fp (termo output (show name))
-     -- TODO: analyze input, generate nice xtics
-     hClose fp
-     fd <- openFile (output ++ ".dat") WriteMode
-     mapM_ (dP fd) pts
-     hClose fd
-     doit ("gnuplot " ++ output ++ ".plot")
+genPlot :: String -> Name -> Date -> Date -> [(Date, [Amount])] -> IO ()
+genPlot output name date1 date2 pts =
+  let pts1 = filter (not . null . snd) pts
+  in if null pts1
+        then putStrLn ("Nothing to show while trying to plot " ++ show name)
+        else do let (nlo, nhi, _) = niceDateBounds date1 date2
+                withFile (output ++ ".plot") WriteMode
+                  (\h -> hPutStr h (plot_cmds output (show name) nlo nhi))
+                withFile (output ++ ".dat") WriteMode
+                  (\h -> mapM_ (dP h) pts1)
+                doit ("gnuplot " ++ output ++ ".plot")
   where dP fp (d,vs) =
-          hPutStr fp (show (julianDate d)) >>
-            mapM_ (dY fp) vs >> hPutStrLn fp ""
+          hPutStr fp (show d) >> mapM_ (dY fp) vs >> hPutStrLn fp ""
         dY fp r = hPutStr fp (' ' : show r)
 
--- If you use the stupid version, you'll get a warning that nothing from
--- System.Process is used... that's ok.
-
 doit :: String -> IO ()
-
--- Stupid version that just says what the user needs to do next:
--- use this if you're using ghc 6.8.
-
--- doit cmd = putStrLn ("now you must run '" ++ cmd ++ "'")
-
--- Smart version that actually runs the command:
--- use this if you're using 6.10 or later.
-
 doit cmd = putStrLn ("running '" ++ cmd ++ "'") >> system cmd >> return ()
diff --git a/test/test1.dat b/test/test1.dat
new file mode 100644
--- /dev/null
+++ b/test/test1.dat
@@ -0,0 +1,179 @@
+todo 2009-1-1 Test 1: counting in different ways
+todo 2009-1-1 Run "umm test1.dat bal 2009-m-d" for different values of m and d
+todo 2009-1-1 This exercises "xfer" transactions
+
+todo 2009-1-1 You should see N dollars in accounts 1 & 3 on the Nth day of the
+todo 2009-1-1 year, and H_n dollars in account 2 on the Nth day of the year,
+todo 2009-1-1 where H_n is the nth harmonic number: H_19 = 275295799/77597520,
+todo 2009-1-1 H_20 = 55835135/15519504. Account 1 counts up to 60 on 2009-3-1,
+todo 2009-1-1 account 2 counts up to H_30 on 2009-1-30, and account 3 counts
+todo 2009-1-1 up to 365 on 2009-12-31. In account 4, start with 1/3 dollar,
+todo 2009-1-1 then add powers of 10 for a while, then subtract them again;
+todo 2009-1-1 should again end up with 1/3
+
+ccs $
+income in
+expense out
+
+account count1 "manually count $"
+account count2 "harmonic numbers"
+account count3 "automatically count $"
+account count4 "check bignums"
+
+xfer 2009-1-1 in count1 1
+xfer 2009-1-2 in count1 1
+xfer 2009-1-3 in count1 1
+xfer 2009-1-4 in count1 1
+xfer 2009-1-5 in count1 1
+xfer 2009-1-6 in count1 1
+xfer 2009-1-7 in count1 1
+xfer 2009-1-8 in count1 1
+xfer 2009-1-9 in count1 1
+xfer 2009-1-10 in count1 1
+xfer 2009-1-11 in count1 1
+xfer 2009-1-12 in count1 1
+xfer 2009-1-13 in count1 1
+xfer 2009-1-14 in count1 1
+xfer 2009-1-15 in count1 1
+xfer 2009-1-16 in count1 1
+xfer 2009-1-17 in count1 1
+xfer 2009-1-18 in count1 1
+xfer 2009-1-19 in count1 1
+xfer 2009-1-20 in count1 1
+xfer 2009-1-21 in count1 1
+xfer 2009-1-22 in count1 1
+xfer 2009-1-23 in count1 1
+xfer 2009-1-24 in count1 1
+xfer 2009-1-25 in count1 1
+xfer 2009-1-26 in count1 1
+xfer 2009-1-27 in count1 1
+xfer 2009-1-28 in count1 1
+xfer 2009-1-29 in count1 1
+xfer 2009-1-30 in count1 1
+xfer 2009-1-31 in count1 1
+xfer 2009-2-1 in count1 1
+xfer 2009-2-2 in count1 1
+xfer 2009-2-3 in count1 1
+xfer 2009-2-4 in count1 1
+xfer 2009-2-5 in count1 1
+xfer 2009-2-6 in count1 1
+xfer 2009-2-7 in count1 1
+xfer 2009-2-8 in count1 1
+xfer 2009-2-9 in count1 1
+xfer 2009-2-10 in count1 1
+xfer 2009-2-11 in count1 1
+xfer 2009-2-12 in count1 1
+xfer 2009-2-13 in count1 1
+xfer 2009-2-14 in count1 1
+xfer 2009-2-15 in count1 1
+xfer 2009-2-16 in count1 1
+xfer 2009-2-17 in count1 1
+xfer 2009-2-18 in count1 1
+xfer 2009-2-19 in count1 1
+xfer 2009-2-20 in count1 1
+xfer 2009-2-21 in count1 1
+xfer 2009-2-22 in count1 1
+xfer 2009-2-23 in count1 1
+xfer 2009-2-24 in count1 1
+xfer 2009-2-25 in count1 1
+xfer 2009-2-26 in count1 1
+xfer 2009-2-27 in count1 1
+xfer 2009-2-28 in count1 1
+xfer 2009-3-1 in count1 1
+
+xfer 2009-1-1 in count2 1/1
+xfer 2009-1-2 in count2 1/2
+xfer 2009-1-3 in count2 1/3
+xfer 2009-1-4 in count2 1/4
+xfer 2009-1-5 in count2 1/5
+xfer 2009-1-6 in count2 1/6
+xfer 2009-1-7 in count2 1/7
+xfer 2009-1-8 in count2 1/8
+xfer 2009-1-9 in count2 1/9
+xfer 2009-1-10 in count2 1/10
+xfer 2009-1-11 in count2 1/11
+xfer 2009-1-12 in count2 1/12
+xfer 2009-1-13 in count2 1/13
+xfer 2009-1-14 in count2 1/14
+xfer 2009-1-15 in count2 1/15
+xfer 2009-1-16 in count2 1/16
+xfer 2009-1-17 in count2 1/17
+xfer 2009-1-18 in count2 1/18
+xfer 2009-1-19 in count2 1/19
+xfer 2009-1-20 in count2 1/20
+xfer 2009-1-21 in count2 1/21
+xfer 2009-1-22 in count2 1/22
+xfer 2009-1-23 in count2 1/23
+xfer 2009-1-24 in count2 1/24
+xfer 2009-1-25 in count2 1/25
+xfer 2009-1-26 in count2 1/26
+xfer 2009-1-27 in count2 1/27
+xfer 2009-1-28 in count2 1/28
+xfer 2009-1-29 in count2 1/29
+xfer 2009-1-30 in count2 1/30
+
+recurring daily until 2009-12-31 xfer 2009-1-1 in count3 1
+
+xfer 2009-1-1 in count4  1/3
+xfer 2009-1-1 in count4  1
+xfer 2009-1-2 in count4  10
+xfer 2009-1-3 in count4  100
+xfer 2009-1-4 in count4  1000
+xfer 2009-1-5 in count4  10000
+xfer 2009-1-6 in count4  100000
+xfer 2009-1-7 in count4  1000000
+xfer 2009-1-8 in count4  10000000
+xfer 2009-1-9 in count4  100000000
+xfer 2009-1-10 in count4 1000000000
+xfer 2009-1-11 in count4 10000000000
+xfer 2009-1-12 in count4 100000000000
+xfer 2009-1-13 in count4 1000000000000
+xfer 2009-1-14 in count4 10000000000000
+xfer 2009-1-15 in count4 100000000000000
+xfer 2009-1-16 in count4 1000000000000000
+xfer 2009-1-17 in count4 10000000000000000
+xfer 2009-1-18 in count4 100000000000000000
+xfer 2009-1-19 in count4 1000000000000000000
+xfer 2009-1-20 in count4 10000000000000000000
+xfer 2009-1-21 in count4 100000000000000000000
+xfer 2009-1-22 in count4 1000000000000000000000
+xfer 2009-1-23 in count4 10000000000000000000000
+xfer 2009-1-24 in count4 100000000000000000000000
+xfer 2009-1-25 in count4 1000000000000000000000000
+xfer 2009-1-26 in count4 10000000000000000000000000
+xfer 2009-1-27 in count4 100000000000000000000000000
+xfer 2009-1-28 in count4 1000000000000000000000000000
+xfer 2009-1-29 in count4 10000000000000000000000000000
+xfer 2009-1-30 in count4 100000000000000000000000000000
+xfer 2009-1-31 in count4 1000000000000000000000000000000
+xfer 2009-2-1 count4 out  1
+xfer 2009-2-2 count4 out  100
+xfer 2009-2-3 count4 out  10000
+xfer 2009-2-4 count4 out  1000000
+xfer 2009-2-5 count4 out  100000000
+xfer 2009-2-6 count4 out  10000000000
+xfer 2009-2-7 count4 out  1000000000000
+xfer 2009-2-8 count4 out  100000000000000
+xfer 2009-2-9 count4 out  10000000000000000
+xfer 2009-2-10 count4 out 1000000000000000000
+xfer 2009-2-11 count4 out 100000000000000000000
+xfer 2009-2-12 count4 out 10000000000000000000000
+xfer 2009-2-13 count4 out 1000000000000000000000000
+xfer 2009-2-14 count4 out 100000000000000000000000000
+xfer 2009-2-15 count4 out 10000000000000000000000000000
+xfer 2009-2-16 count4 out 1000000000000000000000000000000
+xfer 2009-2-17 count4 out 100000000000000000000000000000
+xfer 2009-2-18 count4 out 1000000000000000000000000000
+xfer 2009-2-19 count4 out 10000000000000000000000000
+xfer 2009-2-20 count4 out 100000000000000000000000
+xfer 2009-2-21 count4 out 1000000000000000000000
+xfer 2009-2-22 count4 out 10000000000000000000
+xfer 2009-2-23 count4 out 100000000000000000
+xfer 2009-2-24 count4 out 1000000000000000
+xfer 2009-2-25 count4 out 10000000000000
+xfer 2009-2-26 count4 out 100000000000
+xfer 2009-2-27 count4 out 1000000000
+xfer 2009-2-28 count4 out 10000000
+xfer 2009-3-1 count4 out  100000
+xfer 2009-3-2 count4 out  1000
+xfer 2009-3-3 count4 out  10
diff --git a/test/test2.dat b/test/test2.dat
new file mode 100644
--- /dev/null
+++ b/test/test2.dat
@@ -0,0 +1,100 @@
+todo 2009-1-1 Test 2: more counting in different ways
+todo 2009-1-1 This exercises "buy", "sell", and "exch" transactions.
+todo 2009-1-1 Run "umm test1.dat bal 2009-m-d" for different values of m and d.
+
+todo 2009-1-1 You should see N units of J in account 1, balanced by -N $,
+todo 2009-1-1 for each day of January 2009; then in February and the first
+todo 2009-1-1 couple of days of March, the J get exchanged for $ again,
+todo 2009-1-1 and the positive balance of J and negative balance of $ should
+todo 2009-1-1 decrease again, until the account is empty.
+todo 2009-1-1 In account 2, units of J are bought in exchange for $, but
+todo 2009-1-1 automatically throughout the year: on the Nth day of the year,
+todo 2009-1-1 there should be N units of J balanced by -N $.
+todo 2009-1-1 Account 3 is the same as account 2, except that each J is
+todo 2009-1-1 exchanged for an S on the same day it is bought; thus
+todo 2009-1-1 there should be N units of S balanced by -N $. In account 3
+todo 2009-1-1 there will be two transactions each day, one showing the
+todo 2009-1-1 purchase of 1 unit of J and one showing the exchange of that
+todo 2009-1-1 unit of J for 1 unit of S.
+
+ccs $
+ccs J "junk"
+ccs S "s...tuff"
+
+account count1 "manually count $ & J"
+account count2 "automatically count $ & J"
+account count3 "automatically count $ & S"
+
+# manually accumulate junk
+
+buy 2009-1-1 count1 1 J 1
+buy 2009-1-2 count1 1 J 1
+buy 2009-1-3 count1 1 J 1
+buy 2009-1-4 count1 1 J 1
+buy 2009-1-5 count1 1 J 1
+buy 2009-1-6 count1 1 J 1
+buy 2009-1-7 count1 1 J 1
+buy 2009-1-8 count1 1 J 1
+buy 2009-1-9 count1 1 J 1
+buy 2009-1-10 count1 1 J 1
+buy 2009-1-11 count1 1 J 1
+buy 2009-1-12 count1 1 J 1
+buy 2009-1-13 count1 1 J 1
+buy 2009-1-14 count1 1 J 1
+buy 2009-1-15 count1 1 J 1
+buy 2009-1-16 count1 1 J 1
+buy 2009-1-17 count1 1 J 1
+buy 2009-1-18 count1 1 J 1
+buy 2009-1-19 count1 1 J 1
+buy 2009-1-20 count1 1 J 1
+buy 2009-1-21 count1 1 J 1
+buy 2009-1-22 count1 1 J 1
+buy 2009-1-23 count1 1 J 1
+buy 2009-1-24 count1 1 J 1
+buy 2009-1-25 count1 1 J 1
+buy 2009-1-26 count1 1 J 1
+buy 2009-1-27 count1 1 J 1
+buy 2009-1-28 count1 1 J 1
+buy 2009-1-29 count1 1 J 1
+buy 2009-1-30 count1 1 J 1
+buy 2009-1-31 count1 1 J 1
+sell 2009-2-1 count1 1 J 1
+sell 2009-2-2 count1 1 J 1
+sell 2009-2-3 count1 1 J 1
+sell 2009-2-4 count1 1 J 1
+sell 2009-2-5 count1 1 J 1
+sell 2009-2-6 count1 1 J 1
+sell 2009-2-7 count1 1 J 1
+sell 2009-2-8 count1 1 J 1
+sell 2009-2-9 count1 1 J 1
+sell 2009-2-10 count1 1 J 1
+sell 2009-2-11 count1 1 J 1
+sell 2009-2-12 count1 1 J 1
+sell 2009-2-13 count1 1 J 1
+sell 2009-2-14 count1 1 J 1
+sell 2009-2-15 count1 1 J 1
+sell 2009-2-16 count1 1 J 1
+sell 2009-2-17 count1 1 J 1
+sell 2009-2-18 count1 1 J 1
+sell 2009-2-19 count1 1 J 1
+sell 2009-2-20 count1 1 J 1
+sell 2009-2-21 count1 1 J 1
+sell 2009-2-22 count1 1 J 1
+sell 2009-2-23 count1 1 J 1
+sell 2009-2-24 count1 1 J 1
+sell 2009-2-25 count1 1 J 1
+sell 2009-2-26 count1 1 J 1
+sell 2009-2-27 count1 1 J 1
+sell 2009-2-28 count1 1 J 1
+sell 2009-3-1 count1 1 J 1
+sell 2009-3-2 count1 1 J 1
+sell 2009-3-3 count1 1 J 1
+
+# automatically accumulate junk
+
+recurring daily until 2009-12-31 buy 2009-1-1 count2 1 J 1
+
+# automatically accumulate junk, but exchange it for s...tuff
+
+recurring daily until 2009-12-31 buy 2009-1-1 count3 1 J 1
+recurring daily until 2009-12-31 exch 2009-1-1 count3 1 S 1 J
diff --git a/test/test3a.dat b/test/test3a.dat
new file mode 100644
--- /dev/null
+++ b/test/test3a.dat
@@ -0,0 +1,47 @@
+todo 2009-1-1 Test 3a: this exercises "split" transactions.
+todo 2009-1-1 Run "umm test3a.dat bal 2009-1-d" for different values of d.
+todo 2009-1-1 You should see 10^(N-1) dollars in the account on the Nth day
+todo 2009-1-1 of January 2009, from 1 up to 10^30.
+
+ccs J "junk"
+
+income in
+
+account count "generate powers of 10"
+
+# generate an initial amount in the account
+
+xfer 2009-1-1 in count 1 J
+
+# start splitting
+
+split 2009-1-2 J 10 1
+split 2009-1-3 J 10 1
+split 2009-1-4 J 10 1
+split 2009-1-5 J 10 1
+split 2009-1-6 J 10 1
+split 2009-1-7 J 10 1
+split 2009-1-8 J 10 1
+split 2009-1-9 J 10 1
+split 2009-1-10 J 10 1
+split 2009-1-11 J 10 1
+split 2009-1-12 J 10 1
+split 2009-1-13 J 10 1
+split 2009-1-14 J 10 1
+split 2009-1-15 J 10 1
+split 2009-1-16 J 10 1
+split 2009-1-17 J 10 1
+split 2009-1-18 J 10 1
+split 2009-1-19 J 10 1
+split 2009-1-20 J 10 1
+split 2009-1-21 J 10 1
+split 2009-1-22 J 10 1
+split 2009-1-23 J 10 1
+split 2009-1-24 J 10 1
+split 2009-1-25 J 10 1
+split 2009-1-26 J 10 1
+split 2009-1-27 J 10 1
+split 2009-1-28 J 10 1
+split 2009-1-29 J 10 1
+split 2009-1-30 J 10 1
+split 2009-1-31 J 10 1
diff --git a/test/test3b.dat b/test/test3b.dat
new file mode 100644
--- /dev/null
+++ b/test/test3b.dat
@@ -0,0 +1,47 @@
+todo 2009-1-1 Test 3b: this exercises "split" transactions.
+todo 2009-1-1 Run "umm test3b.dat bal 2009-1-d" for different values of d.
+todo 2009-1-1 You should see N dollars in the account on the Nth day
+todo 2009-1-1 of January 2009, from 1 up to 31.
+
+ccs J "junk"
+
+income in
+
+account count "again, count"
+
+# generate an initial amount in the accounts
+
+xfer 2009-1-1 in count 1 J
+
+# start splitting
+
+split 2009-1-2 J 2 1
+split 2009-1-3 J 3 2
+split 2009-1-4 J 4 3
+split 2009-1-5 J 5 4
+split 2009-1-6 J 6 5
+split 2009-1-7 J 7 6
+split 2009-1-8 J 8 7
+split 2009-1-9 J 9 8
+split 2009-1-10 J 10 9
+split 2009-1-11 J 11 10
+split 2009-1-12 J 12 11
+split 2009-1-13 J 13 12
+split 2009-1-14 J 14 13
+split 2009-1-15 J 15 14
+split 2009-1-16 J 16 15
+split 2009-1-17 J 17 16
+split 2009-1-18 J 18 17
+split 2009-1-19 J 19 18
+split 2009-1-20 J 20 19
+split 2009-1-21 J 21 20
+split 2009-1-22 J 22 21
+split 2009-1-23 J 23 22
+split 2009-1-24 J 24 23
+split 2009-1-25 J 25 24
+split 2009-1-26 J 26 25
+split 2009-1-27 J 27 26
+split 2009-1-28 J 28 27
+split 2009-1-29 J 29 28
+split 2009-1-30 J 30 29
+split 2009-1-31 J 31 30
